Full Telegram account control from the terminal. Agent-friendly, daemon-based, with webhook event push.
pip install tlgr
For agents: Authentication requires human interaction (phone code, 2FA). Run
tlgr account addyourself first, then hand the CLI to your agent. See AGENT.md for the full agent reference.
tlgr config init # create config files
tlgr login +15551234567 # authenticate (shortcut for account add)
tlgr daemon start # start background daemon
tlgr send @username "Hello from tlgr" # send a message
tlgr chats --limit 20 # list your chats
tlgr status # check daemon statusEvery Telegram operation available as a single command. Three output modes: human-readable tables (default), JSON (--json) for agents, and plain TSV (--plain) for piping.
flowchart LR
USER["You / Agent"] --> CLI["tlgr CLI"]
CLI -->|"direct"| TG["Telegram API"]
CLI -->|"IPC socket"| DAEMON["tlgr daemon"]
DAEMON --> TG
Common operations are available as top-level commands for quick access:
tlgr send <chat> <text> # message send
tlgr login <phone> # account add
tlgr logout <alias> # account remove
tlgr status # daemon status
tlgr chats # chat list
tlgr contacts # contact list
tlgr dl <chat> <msg_id> # media download
tlgr up <chat> <path> # media uploadtlgr message send <chat> <text> # --file, --caption, --reply-to, --silent
tlgr message list <chat> # --limit, --sender, --media, --reactions
tlgr message get <chat> <msg_id> # full metadata
tlgr message delete <chat> <ids...>
tlgr message search <chat> <query> # --local for regex, --regex <pattern>
tlgr message pin <chat> <msg_id>
tlgr message react <chat> <id> <emoji>msg is an alias for message (e.g. tlgr msg send @user "hello").
tlgr chat list # --type, --search, --limit
tlgr chat get <chat>
tlgr chat create <name> # --type group|channel, --members
tlgr chat archive <chat>
tlgr chat mute <chat> [duration]
tlgr chat leave <chat>tlgr contact list
tlgr contact add <phone> [name]
tlgr contact remove <user>
tlgr contact search <query>tlgr media download <chat> <msg_id> # --out-dir
tlgr media upload <chat> <path> # --captiontlgr profile get
tlgr profile update # --first-name, --last-name, --bio, --phototlgr account add <phone> # authenticate a new account
tlgr account list # (* = default)
tlgr account switch <alias>
tlgr account remove <alias>
tlgr account rename <old> <new>
tlgr account info [alias]tlgr daemon start # --foreground
tlgr daemon stop
tlgr daemon status
tlgr daemon logs # --follow--json JSON to stdout (for scripting and agents)
--plain Stable TSV for piping
-a, --account TEXT Account alias to use
--results-only In JSON mode, strip envelope and emit only the primary result
--select FIELDS In JSON mode, project comma-separated fields (supports dot paths)
--enable-commands Comma-separated allowlist of enabled commands (sandboxing)
-n, --dry-run Preview destructive operations without executing
-y, --force Skip confirmations
--no-input Never prompt; fail instead (CI/agent mode)
-v, --verbose Verbose logging to stderr
--version / --help
All global flags can be set via environment variables:
| Variable | Equivalent |
|---|---|
TLGR_JSON=1 |
--json |
TLGR_PLAIN=1 |
--plain |
TLGR_ACCOUNT=alias |
--account alias |
TLGR_ENABLE_COMMANDS=cmd1,cmd2 |
--enable-commands cmd1,cmd2 |
TLGR_AUTO_JSON=1 |
Auto-switch to JSON when stdout is piped (non-TTY) |
tlgr pushes Telegram events to an external HTTP endpoint in real time. Designed for agentic interfaces like OpenClaw where an agent receives events and calls tlgr CLI commands to act.
flowchart LR
TG["Telegram"] --> DAEMON["tlgr daemon"]
DAEMON -->|"POST /hooks/agent"| AGENT["Your Agent"]
AGENT -->|"tlgr --json message send ..."| CLI["tlgr CLI"]
CLI --> TG
Configure in ~/.tlgr/webhook.toml:
[webhook]
enabled = true
url = "http://127.0.0.1:18789/hooks/agent"
token = "shared-secret"
events = ["new_message", "message_edited", "message_deleted"]
[webhook.retry]
enabled = true
max_attempts = 3
backoff_base = 2
[webhook.filters]
chats = ["@important_channel"]Events arrive as JSON with Authorization: Bearer <token>:
{
"event_type": "new_message",
"timestamp": "2025-03-06T12:00:00Z",
"account": "main",
"data": { "..." }
}tlgr also ships with a deterministic, always-on Gateway that runs background jobs on your Telegram account. Define declarative pipelines in ~/.tlgr/jobs.yaml that automatically react to incoming messages -- auto-reply, auto-forward, filter by chat type, time of day, content, and more.
flowchart LR
TG["Telegram event"] --> F["Filters"]
F -->|"passed"| P["Processors"]
P --> A["Actions"]
A --> R["reply / forward / ..."]
A few examples of what you can do:
jobs:
# Auto-reply to all private messages
- name: private-bot
account: main
filters:
chat_type: private
actions:
- reply: "shut up i'm just a bot!"
# Forward breaking news to your archive
- name: news-forward
account: main
filters:
chat_id: "@raw_feed"
types: [text, photo]
contains: [breaking]
actions:
- forward:
to: ["@clean_feed", "@archive"]
processors: [strip_formatting]
# Night-mode auto-reply
- name: night-mode
account: main
filters:
chat_type: private
time_of_day: "23:00-07:00"
actions:
- reply: "I'm sleeping. Will reply tomorrow."Filters support full AND / OR / NOT composition, 20+ built-in filter types, 7 text processors, and a registry pattern for adding your own.
For the full Gateway reference -- filters, processors, actions, composition, extensibility -- see Gateway documentation.
tlgr is designed to be consumed by LLM agents and automation pipelines.
tlgr schema # full CLI schema as JSON
tlgr schema message send # schema for a specific commandAgents can discover all commands, flags, positionals, types, and defaults without parsing --help.
tlgr exit-codes # print the exit code table
tlgr --json agent exit-codes # as JSON| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Generic failure |
| 2 | Usage / parse error |
| 3 | Empty results |
| 4 | Auth required |
| 5 | Not found |
| 6 | Permission denied |
| 7 | Rate limited |
| 8 | Retryable error |
| 10 | Config error |
| 11 | Daemon error |
| 12 | IPC error |
| 130 | Interrupted (SIGINT) |
Restrict which commands an agent can run:
tlgr --enable-commands="message,chat,schema" send @user "hi" # allowed
tlgr --enable-commands="message,chat,schema" account remove foo # blocked (exit 2)Or via environment: TLGR_ENABLE_COMMANDS=message,chat,schema.
tlgr --json --results-only chat list # strip pagination/envelope, emit only the chat array
tlgr --json --select "id,name" chat list # project specific fieldsSet TLGR_AUTO_JSON=1 and tlgr automatically outputs JSON whenever stdout is piped (non-TTY), without requiring --json.
Errors include actionable recovery hints:
Error: No session found for account 'main'
Session expired. Run: tlgr account add <phone>
Config files live in ~/.tlgr/:
| File | Format | Purpose |
|---|---|---|
config.toml |
TOML | App defaults, daemon, accounts |
jobs.yaml |
YAML | Gateway job definitions |
webhook.toml |
TOML | Outbound webhook push |
tlgr config init # create defaults
tlgr config validate # check syntax + validate filter/action names
tlgr config path # print config directory
tlgr config keys # list all known config keys
tlgr config list # show current values
tlgr config get <key> # get a single value
tlgr config set <key> <value> # set a value
tlgr config unset <key> # reset to default[defaults]
output = "human"
[accounts]
default = "main"
[daemon]
auto_start = true
log_level = "info"tlgr account add +15551234567 --alias personal
tlgr account add +15559876543 --alias work
tlgr -a personal message send @friend "Hi"Jobs can reference different accounts:
jobs:
- name: work-forward
account: work
# ...See LICENSE for license details.