Using Telegram CLI
Overview
Use tg as an account-aware Telegram client and local SQLite message index. Choose commands by data source, persistence, and whether they mutate Telegram.
Mandatory rules
- Request explicit user authorization before either enabling write access or executing any remote mutation. Authorization to enable writes is not authorization for a mutation. Several mutations have no built-in confirmation.
- Check
tg config write-access status --jsonbefore a planned mutation. The gate covers remote mutations only; read-only Telegram calls, local SQLite/file operations, account lifecycle, and configuration remain available while it is off. - Never provide, solicit in plain text, or automate an ownership-transfer password.
group admin transfer-ownerprompts for it securely in an interactive TTY after--yes; it is not suitable for non-interactive CI. - Treat API hashes, proxy URLs, sessions, account metadata, exported messages, and databases as secrets. Never print
config list --show-secrets, expose a credential-bearing proxy, or commitDATA_DIR. - Select an account explicitly with
--account <name>in automation. Do not change the current account merely to run one command. - Select exactly one of
--json,--yaml, or--markdownfor finite commands. Use JSON or YAML for automation and stableok/error fields; Markdown is human-facing and may omit structured failure details. Non-TTY output otherwise defaults to YAML.listenexcludes these flags. - Check the process exit status and structured
ok. For automated archive partial-failure accounting, use JSON/YAML and inspecterror.codepluserror.details.completed,error.details.failed, anderror.details.warnings; never report complete success when any chat or media failed. - Structured envelopes use
schema_version: "2". Message rows exposecontent,reply_to_msg_id,media_group_id, and ordered lowercaseattachments[]; do not expect legacy singularattachmentor raw parser fields.
Ensure the executable is available
When developing or testing this repository's current source, skip global package installation. Require Node.js 22 or later, run pnpm install, and use pnpm dev <args>, for example pnpm dev search --help. Do not insert an extra --; pnpm dev -- search ... passes that token to the CLI and can fail.
For any other user-requested tg task, first run command -v tg. If the user asks only for instructions, explain the setup without changing their system.
If tg is installed, do not reinstall or upgrade it automatically. Verify the installed executable and inspect live help:
tg --version
tg --help
tg <command> --help
If tg is missing, check the runtime first:
node --version
npm --version
Continue only when both commands succeed and Node.js is version 22 or later. If Node.js is missing or too old, use an existing user-managed version manager when available; ask before installing or changing a system-level runtime or package manager.
Install the published package, then continue the original task:
npm install --global @will-17173/telegram-cli
Never retry a permission failure with sudo. Prefer an existing user-managed Node.js installation; otherwise install to a user-owned prefix for the current shell:
npm install --global --prefix "$HOME/.local" @will-17173/telegram-cli
export PATH="$HOME/.local/bin:$PATH"
Do not modify a shell startup file without authorization. After installation, require these checks to succeed before running Telegram commands:
hash -r
command -v tg
tg --version
tg --help
If the binary is still missing, inspect the npm global prefix and PATH, report the failure, and stop before running Telegram commands.
Choose the operation
| Need | Command family | Network | Side effect |
|---|---|---|---|
| Authenticate/select/logout accounts | account | login/logout | session/registry; messages retained on logout/login |
| Unread overview or transient online reads | inbox, read, search-online | yes | none; inbox does not mark messages read |
| Discover contacts/chats/groups | contact, chats, info, group list | yes | none |
| Persist Telegram history | history, sync, sync-all, refresh | yes | writes local SQLite DB |
| Archive chats as Markdown | archive | yes | writes account-local archive files |
| Query/export stored messages | search, recent, today, stats, top, timeline, filter, export | no | export may write a file |
| Reset local data after breaking storage upgrades | data reset | no | deletes account DB/default archive files |
| Inspect/mutate notifications or folders | notification, folder | yes | mute/unmute and folder chat add/remove mutate Telegram |
| Watch incoming messages | listen | yes, long-running | persists normalized attachments; optional downloads |
| Change Telegram state | send, edit, delete, notification/folder/group writes | yes | real external write |
Read references/command-reference.md before composing an exact command, handling automation output, managing groups, or troubleshooting authentication and flood limits.
Operating workflow
- Run the relevant
--help; prefer it over memorized flags. - For account-dependent work, inspect
tg account list --jsonand use an explicit account. - Route by source and persistence:
searchuses synchronized SQLite;search-onlineand transientreaduse Telegram;history/syncpersist into SQLite. Do not copyreadtime flags tohistory/sync, which use limit/delay controls. - Treat
inboxas read-only discovery; never assume it marks messages read. - Resolve chats with
chats --jsonand folders withfolder list --json; prefer numeric IDs after discovery because names/titles may be ambiguous. - Parse structured envelopes rather than terminal tables. For batch sync failures use
refreshand inspectdata.failures;sync-allomits that field. - Immediately before a remote write, verify the target, check write-access status, and obtain explicit authorization for that mutation.
Common mistakes
pnpm dev -- ...: remove the extra separator.- Assuming
sync --limit 5000backfills a new chat: first sync is capped at 500; usehistoryfor deeper history. - Expecting
sync-allto expose partial failures: userefreshand inspectdata.failures. - Reusing an old database after a breaking media schema change: run
tg data reset --yes, then sync again. - Expecting
listen --no-mediato suppress persistence/downloads: it only hides rendered media rows; normalizedattachments[]remain persisted and usable. - Using an ambiguous chat name: retry with its numeric chat ID.
- Using Markdown for archive automation: it does not preserve full partial-failure details; use JSON/YAML.
- Passing a 2FA password in arguments, environment variables, stdin automation, chat, or logs: ownership transfer accepts only its secure interactive prompt.
- Expecting
sendto appear immediately in local search: synchronize afterward.