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 --json before 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.
- Treat
tg guard start with write access enabled as continuous remote-mutation automation. Review its enabled groups, rules, and policies and obtain explicit authorization before starting an armed Guard; with write access disabled, Telegram write actions are recorded as dry runs.
- Never provide, solicit in plain text, or automate an ownership-transfer password.
group admin transfer-owner prompts 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 commit DATA_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 --markdown for finite commands. Use JSON or YAML for automation and stable ok/error fields; Markdown is human-facing and may omit structured failure details. Non-TTY output otherwise defaults to YAML. listen excludes these flags.
- Check the process exit status and structured
ok. For automated archive partial-failure accounting, use JSON/YAML and inspect error.code plus error.details.completed, error.details.failed, and error.details.warnings; never report complete success when any chat or media failed.
- Structured envelopes use
schema_version: "2". Message rows expose content, reply_to_msg_id, media_group_id, and ordered lowercase attachments[]; do not expect legacy singular attachment or 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, repair |
yes |
writes local SQLite DB; repair --dry-run only previews gaps |
| Archive chats as Markdown |
archive |
yes |
writes account-local archive files |
| Query/export/delete stored messages |
search, recent, today, stats, top, timeline, filter, export, purge |
no |
export may write a file; purge deletes matching local rows |
| 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 |
| Browse local messages and trigger read-only sync |
web |
local HTTP plus optional Telegram sync |
local server and SQLite writes; no Telegram mutation |
| Watch incoming messages |
listen |
yes, long-running |
none by default; --save writes SQLite; --auto-download writes files |
| Run rule-based group automation |
guard start |
yes, long-running |
local Guard records; remote actions when write access is enabled |
| Change Telegram state |
send, edit, delete, notification/folder/group/Guard writes |
yes |
real external write |
Read references/command-reference.md before composing an exact command, downloading media, starting Web or Guard, 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 --json and use an explicit account.
- Route by source and persistence:
search uses synchronized SQLite; search-online and transient read use Telegram; history/sync/repair persist into SQLite. Do not copy read time flags to history/sync, which use limit/delay controls.
- Treat
inbox as read-only discovery; never assume it marks messages read.
- Resolve chats with
chats --json and folders with folder 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
refresh and inspect data.failures; sync-all omits that field.
- Immediately before a remote write, verify the target, check write-access status, and obtain explicit authorization for that mutation. Starting an armed Guard authorizes an ongoing class of configured actions, so summarize its enabled scope before requesting authorization.
Common mistakes
pnpm dev -- ...: remove the extra separator.
- Assuming
sync --limit 5000 backfills a new chat: first sync is capped at 500; use history for deeper history.
- Expecting
repair --dry-run to write data: remove --dry-run after reviewing the gap table.
- Expecting
sync-all to expose partial failures: use refresh and inspect data.failures.
- Reusing an old database after a breaking media schema change: run
tg data reset --yes, then sync again.
- Expecting
listen --no-media to suppress --save or --auto-download: it only hides rendered media rows; the explicit save and download flags still write their respective data.
- Starting Guard with write access enabled merely to inspect it: an armed Guard can immediately execute saved rules; inspect with write access off, then obtain authorization before enabling writes and restarting it.
- Using an ambiguous chat name: retry with its numeric chat ID.
- Looking up an uncached numeric non-contact with
contact info <user-id> alone: add --chat <group> or use contact info <group> <user-id> so Telegram can resolve the user from group message context.
- 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
send to appear immediately in local search: synchronize afterward.
1---2name: using-telegram-cli3description: Use when an agent needs to install or operate @will-17173/telegram-cli for Telegram accounts, chats, messages, media downloads, Web UI, Guard automation, contacts, folders, notifications, archives, listening, or group administration.4---56# Using Telegram CLI78## Overview910Use `tg` as an account-aware Telegram client and local SQLite message index. Choose commands by data source, persistence, and whether they mutate Telegram.1112## Mandatory rules1314- 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.15- Check `tg config write-access status --json` before 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.16- Treat `tg guard start` with write access enabled as continuous remote-mutation automation. Review its enabled groups, rules, and policies and obtain explicit authorization before starting an armed Guard; with write access disabled, Telegram write actions are recorded as dry runs.17- Never provide, solicit in plain text, or automate an ownership-transfer password. `group admin transfer-owner` prompts for it securely in an interactive TTY after `--yes`; it is not suitable for non-interactive CI.18- 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 commit `DATA_DIR`.19- Select an account explicitly with `--account <name>` in automation. Do not change the current account merely to run one command.20- Select exactly one of `--json`, `--yaml`, or `--markdown` for finite commands. Use JSON or YAML for automation and stable `ok`/error fields; Markdown is human-facing and may omit structured failure details. Non-TTY output otherwise defaults to YAML. `listen` excludes these flags.21- Check the process exit status and structured `ok`. For automated archive partial-failure accounting, use JSON/YAML and inspect `error.code` plus `error.details.completed`, `error.details.failed`, and `error.details.warnings`; never report complete success when any chat or media failed.22- Structured envelopes use `schema_version: "2"`. Message rows expose `content`, `reply_to_msg_id`, `media_group_id`, and ordered lowercase `attachments[]`; do not expect legacy singular `attachment` or raw parser fields.2324## Ensure the executable is available2526When 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.2728For 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.2930If `tg` is installed, do not reinstall or upgrade it automatically. Verify the installed executable and inspect live help:3132```sh33tg --version34tg --help35tg <command> --help36```3738If `tg` is missing, check the runtime first:3940```sh41node --version42npm --version43```4445Continue 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.4647Install the published package, then continue the original task:4849```sh50npm install --global @will-17173/telegram-cli51```5253Never 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:5455```sh56npm install --global --prefix "$HOME/.local" @will-17173/telegram-cli57export PATH="$HOME/.local/bin:$PATH"58```5960Do not modify a shell startup file without authorization. After installation, require these checks to succeed before running Telegram commands:6162```sh63hash -r64command -v tg65tg --version66tg --help67```6869If the binary is still missing, inspect the npm global prefix and `PATH`, report the failure, and stop before running Telegram commands.7071## Choose the operation7273| Need | Command family | Network | Side effect |74| --- | --- | --- | --- |75| Authenticate/select/logout accounts | `account` | login/logout | session/registry; messages retained on logout/login |76| Unread overview or transient online reads | `inbox`, `read`, `search-online` | yes | none; `inbox` does not mark messages read |77| Discover contacts/chats/groups | `contact`, `chats`, `info`, `group list` | yes | none |78| Persist Telegram history | `history`, `sync`, `sync-all`, `refresh`, `repair` | yes | writes local SQLite DB; `repair --dry-run` only previews gaps |79| Archive chats as Markdown | `archive` | yes | writes account-local archive files |80| Query/export/delete stored messages | `search`, `recent`, `today`, `stats`, `top`, `timeline`, `filter`, `export`, `purge` | no | export may write a file; purge deletes matching local rows |81| Reset local data after breaking storage upgrades | `data reset` | no | deletes account DB/default archive files |82| Inspect/mutate notifications or folders | `notification`, `folder` | yes | `mute`/`unmute` and `folder chat add/remove` mutate Telegram |83| Browse local messages and trigger read-only sync | `web` | local HTTP plus optional Telegram sync | local server and SQLite writes; no Telegram mutation |84| Watch incoming messages | `listen` | yes, long-running | none by default; `--save` writes SQLite; `--auto-download` writes files |85| Run rule-based group automation | `guard start` | yes, long-running | local Guard records; remote actions when write access is enabled |86| Change Telegram state | `send`, `edit`, `delete`, notification/folder/group/Guard writes | yes | real external write |8788Read [references/command-reference.md](references/command-reference.md) before composing an exact command, downloading media, starting Web or Guard, handling automation output, managing groups, or troubleshooting authentication and flood limits.8990## Operating workflow91921. Run the relevant `--help`; prefer it over memorized flags.932. For account-dependent work, inspect `tg account list --json` and use an explicit account.943. Route by source and persistence: `search` uses synchronized SQLite; `search-online` and transient `read` use Telegram; `history`/`sync`/`repair` persist into SQLite. Do not copy `read` time flags to `history`/`sync`, which use limit/delay controls.954. Treat `inbox` as read-only discovery; never assume it marks messages read.965. Resolve chats with `chats --json` and folders with `folder list --json`; prefer numeric IDs after discovery because names/titles may be ambiguous.976. Parse structured envelopes rather than terminal tables. For batch sync failures use `refresh` and inspect `data.failures`; `sync-all` omits that field.987. Immediately before a remote write, verify the target, check write-access status, and obtain explicit authorization for that mutation. Starting an armed Guard authorizes an ongoing class of configured actions, so summarize its enabled scope before requesting authorization.99100## Common mistakes101102- `pnpm dev -- ...`: remove the extra separator.103- Assuming `sync --limit 5000` backfills a new chat: first sync is capped at 500; use `history` for deeper history.104- Expecting `repair --dry-run` to write data: remove `--dry-run` after reviewing the gap table.105- Expecting `sync-all` to expose partial failures: use `refresh` and inspect `data.failures`.106- Reusing an old database after a breaking media schema change: run `tg data reset --yes`, then sync again.107- Expecting `listen --no-media` to suppress `--save` or `--auto-download`: it only hides rendered media rows; the explicit save and download flags still write their respective data.108- Starting Guard with write access enabled merely to inspect it: an armed Guard can immediately execute saved rules; inspect with write access off, then obtain authorization before enabling writes and restarting it.109- Using an ambiguous chat name: retry with its numeric chat ID.110- Looking up an uncached numeric non-contact with `contact info <user-id>` alone: add `--chat <group>` or use `contact info <group> <user-id>` so Telegram can resolve the user from group message context.111- Using Markdown for archive automation: it does not preserve full partial-failure details; use JSON/YAML.112- Passing a 2FA password in arguments, environment variables, stdin automation, chat, or logs: ownership transfer accepts only its secure interactive prompt.113- Expecting `send` to appear immediately in local search: synchronize afterward.