Configuration¶
The config file describes your whole bot: the Telegram
connection, who may use it, the button menu, and logging.
You pass it with --config to the commands that read it — run, validate,
fmt, and list-functions (see CLI).
All keys use lower_snake_case. Unknown keys are rejected, so a typo is an
error you will see immediately when you validate.
Required means validation fails if the field is missing or empty after
defaults are applied.
Optional fields may be omitted; the Default column shows what is used then.
New to the project? Start with Run in CLI, which walks through building a first config. See Concepts for the vocabulary used below.
A minimal config¶
Only telegram (with a token and one allowed user)
and menu are required. Everything else has a default:
Start with one allowed user and one button
The config-examples/ folder in the release includes both a minimal and a full
example.
Root fields¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
telegram |
object | yes | — | Telegram settings (see below) |
menu |
list | yes | — | Menu tree; at least one node |
function_directory |
string | no | unset | Custom function YAML directory (see rules below) |
shell |
string | no | /bin/bash |
Shell used as shell -c "<command>" |
timeout |
duration | no | 60s |
Default command timeout |
max_output_bytes |
int | no | 524288 |
Max output kept per command (see How much command output you see) |
workdir |
string | no | process cwd | Default working directory for commands |
env |
map | no | empty | Extra environment variables for commands |
menu_columns |
int | no | 2 |
Item buttons per row under the message box |
page_size |
int | no | 8 |
Items per page before pagination |
confirm_ttl |
duration | no | 5m |
How long a confirmation prompt stays valid |
enable_run_command |
bool | no | false |
Show a $ >_ Run Command button that runs the next message as a shell command. Off by default. Anyone who can use the bot can then run any command on the host, so only turn this on if you trust every allowed user. Putting this key under telegram is invalid. |
logging |
object | no | built-in default logger | Named loggers (see below) |
What if I omit shell?
You can omit it. The bot uses /bin/bash. Same for timeout, page_size,
and other optional root fields: omit them and defaults apply. You only need
to set them when you want a non-default value (for example
shell: /bin/sh).
How much command output you see¶
Two limits apply, one after the other. max_output_bytes is your limit and
comes on top of a Telegram limit you cannot change.
1. Your limit: max_output_bytes (default 524288, so 512 KB)
While a command runs, the bot keeps at most this much of its output, counted
separately for normal output and error output. Anything past that is dropped,
but the command itself keeps running until it finishes or hits its timeout.
When this happens, the result starts with (output truncated).
2. Telegram's limit: one message holds at most 4096 bytes
This one is fixed by Telegram. If the result is longer than a single message, the bot splits it into several messages. Each part is sent as a reply to the part before it, so they stay together and in order, and the menu buttons appear on the last part. The split happens on line boundaries whenever possible, so lines are not cut in half.
If the result is still very long after splitting, the bot stops after 10
messages and the last one ends with a note like
(output too long; showing first N bytes), where N is how much of the output
you actually received.
So raising max_output_bytes lets the bot keep more output, but you still see
at most about ten messages of it. For output that long, it is usually better to
shorten the command itself (for example journalctl -u nginx | tail -n 50) or
write the full output to a file on the server.
function_directory rules¶
| Situation | Result |
|---|---|
| Key missing | Info log; built-in functions only |
Key present but empty ("") |
Info log; built-in functions only |
| Key set to a path that does not exist or is not accessible | Hard error; process stops |
| Path exists but directory is empty | OK |
A wrong path stops the bot
If function_directory points to a folder that does not exist or cannot be
read, the program stops with an error instead of starting without your
custom functions.
telegram¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
bot_token |
string | yes | — | Bot token from BotFather |
allowed_users |
list of string | yes | — | Allowed users |
api |
string | no | https://api.telegram.org |
Bot API base URL |
proxy.enabled |
bool | no | false |
Use proxy for Telegram API |
proxy.url |
string | conditional | — | Required when proxy.enabled is true |
insecure |
bool | no | false |
Skip TLS verify (not recommended) |
Unauthorized users receive a message with their user_id and username so they can ask an admin for access. This is also how you find your own id the first time — see Run in CLI → Step 5.
Connect through a proxy
To let allowed users type a shell command from Telegram, set this at the root of the file (not under telegram):
Menu¶
This section is the field reference. For a guided explanation with examples, see Menu. Each button or category node:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Display name (unique among siblings, case-insensitive) |
type |
category | button |
yes | Node kind |
items |
list | yes if category |
Children; category must have at least one |
function |
string | yes if button |
Function name |
command |
string | yes if function: command |
Shell command for built-in command |
path |
string | yes if function: script |
Script path for built-in script |
icon |
string | no | Optional emoji prefix |
id |
string | no | Optional id for this node. You can omit it |
confirm |
bool | no | Ask for confirmation before run (default false) |
timeout |
duration | no | Override global timeout |
workdir |
string | no | Override working directory |
env |
map | no | Extra env for this button |
columns |
int | no | Override columns for this category |
args |
string | no | Optional args for script |
| Any declared parameter name | scalar | as declared by the function | Value passed to the selected function, for example url, host, unit, or lines |
On a button, any other scalar key is treated as a function parameter.
Its name must match a parameter declared by the selected function. Unknown
parameter names fail validate. Values declared as int or
bool are also checked. Strings, numbers, and booleans can be written directly
as YAML values; numbers do not need quotes.
On a category, any key outside the category fields above is an error. Categories do not run functions, so they cannot have parameter keys.
command, path, and args are shortcut fields that fill parameters with the
same names. Other parameter names are written directly
on the button. Do not place button values inside a nested params: map. See
Functions → Passing values from a button.
logging¶
Optional. If omitted, a default console logger on stderr at info is used.
Named loggers:
Write normal logs and an audit file
Supported outputs: stdout, stderr, file, discard.
The audit logger shown above records every command run (who, which button,
exit code, duration). See Audit log.
Related pages¶
- Run in CLI — build and run a first config
- Menu — the menu tree in depth
- Functions — what
function,command,path, andargsmean - CLI — validate and run with your config