--- name: tgcli description: > Use when user wants to read/search/send/analyze Telegram messages via tgcli CLI. Trigger on requests about channel/chat history, digests/news, mentions, files, topics, contacts, groups, tags, media downloads, and archive/sync status. Also covers group admin (rename, members, invite links, join/leave). For edit/delete/reactions/inline buttons, use telegram-mcp instead. --- # tgcli Telegram CLI skill for AI agents. ## Install Install this skill from GitHub: ```bash npx skills add dapi/tgcli --skill tgcli --agent '*' -g -y ``` Install CLI: ```bash npm install -g @dapi/tgcli ``` Authenticate once: ```bash tgcli auth ``` ## Tool Boundary: tgcli vs telegram-mcp | Use tgcli for | Use telegram-mcp for | |-|-| | Read/search/archive messages | edit/delete/forward | | Send text/photo/files and topic posts | reactions | | Forum topics listing/search | inline bot buttons | | Download media from messages | advanced interactive actions | | Group admin (rename, members, invite, join/leave) | ban/kick/promote with granular permissions | | Channel/contact tags and metadata | | | Sync jobs and archive monitoring | | | JSON output for automation | | ## Execution Rules - If `tgcli` is not found, install it: `npm install -g @dapi/tgcli` then run `tgcli auth` for first-time login. - `tgcli auth` only authenticates the Telegram session. Use `tgcli sync --once` or `tgcli sync --follow` to seed/archive dialogs. - Always add `--json` for agent workflows. - Add `--timeout 30s` by default; use `--timeout 90s` for heavy archive fallback reads. - Prefer explicit `--source archive|live|both` instead of relying on defaults. - Never use `--since`; tgcli uses `--after` and `--before` with ISO timestamps. - Never use `tgcli sync --chat ...`; top-level `sync` only runs workers via `--once` / `--follow`. - To sync a specific chat: `tgcli channels sync --chat --enable` and/or `tgcli sync jobs add --chat `, then run `tgcli sync --once` or `tgcli sync --follow`. - If command shape is uncertain, verify it first with `tgcli --help` instead of guessing flags. - For sending format control: - `--parse-mode markdown|html|none` (case-insensitive) - for `send photo` and `send file`, `--parse-mode` requires `--caption` - `--reply-to ` replies to a specific message; if both `--reply-to` and `--topic` are passed, `--reply-to` wins - `--silent` sends without notification sound - `--no-forwards` protects message from forwarding/saving - `--schedule ` schedules message for future delivery (ISO 8601, must be in the future, within 365 days) - `--caption-above` shows caption above media (`send photo`/`send file`, requires `--caption`) - `--spoiler` blurs media until tapped (`send photo`/`send file`) - `--retries ` retries transient network/transport failures for `send photo` - `--retry-backoff ` controls retry delay for `send photo` - `--force-document` sends photo/video as uncompressed document (`send file` only) - `--retries ` retry on failure with exponential backoff (default 0); JSON output includes `retry_log` and `attempts` when retries occurred - Telegram markdown formatting (when `--parse-mode markdown`): - Bold: `**text**` - Italic: `__text__` (double underscores, NOT single `_`) - Bold+Italic: `**__text__**` (bold wraps italic) - Single `_text_` does NOT work for italic — renders as literal underscores - Single `*text*` does NOT work for bold — renders as literal asterisks - Monospace inline: `` `text` `` - Code block: triple backticks - Telegram markdown differs from standard Markdown — always use double markers - Never delete lock files (`LOCK`, `database is locked`): wait and retry. ## Core Command Patterns ### Read ```bash tgcli messages list --chat --limit 50 --source archive --json --timeout 30s tgcli messages list --chat --chat --limit 50 --source archive --json --timeout 30s tgcli messages list --chat --topic --after 2025-01-01T00:00:00Z --limit 100 --source archive --json --timeout 30s tgcli messages show --chat --id --source archive --json --timeout 30s tgcli messages context --chat --id --before 5 --after 5 --source archive --json --timeout 30s ``` Never use `--since` here; the correct flag is `--after`. ### Search ```bash tgcli messages search "Claude Code" --chat --source archive --json --timeout 30s tgcli messages search --query "Claude Code" --chat --source archive --json --timeout 30s tgcli messages search --regex "claude\\s+(code|agent)" --chat --source archive --json --timeout 30s tgcli messages search --tag ai --chat --source archive --json --timeout 30s tgcli messages search --tags "ai,dev" --chat --source archive --json --timeout 30s tgcli messages search "release" --chat --after 2025-06-01T00:00:00Z --before 2025-06-30T00:00:00Z --source archive --json --timeout 30s tgcli messages search "Release" --case-sensitive --chat --source archive --json --timeout 30s ``` Both positional query and `--query` flag work. `--chat` accepts multiple values. Use `--regex` for pattern matching, `--tag`/`--tags` to filter by channel tags, `--after`/`--before` for date range, `--case-sensitive` to disable case-insensitive search. ### Send Text/Photo/File **⚠ `send` uses `--to` (alias `--chat`) for the destination; then `--message` (alias `--text`) for text body, `--photo` for photo uploads, and `--file` for generic files.** ```bash tgcli send text --to --message "Hello" --json --timeout 30s tgcli send text --to --topic --message "**Hello**" --parse-mode markdown --json --timeout 30s tgcli send text --to --message "Done" --reply-to --json --timeout 30s tgcli send text --to --message "https://example.com check this" --no-preview --json --timeout 30s tgcli send text --to --message "Nightly report" --silent --json --timeout 30s tgcli send text --to --message "Confidential" --no-forwards --json --timeout 30s tgcli send text --to --message "Good morning!" --schedule "2025-01-15T09:00:00+03:00" --json --timeout 30s tgcli send text --to --message "Hello" --retries 3 --json --timeout 30s tgcli send photo --to --photo /path/to/image.png --caption "Report" --json --timeout 30s tgcli send photo --to --photo /path/to/image.png --caption "**Report**" --parse-mode markdown --json --timeout 30s tgcli send photo --to --photo /path/to/image.png --reply-to --json --timeout 30s tgcli send photo --to --photo /path/to/image.png --caption "Breaking news" --caption-above --json --timeout 30s tgcli send photo --to --photo /path/to/image.png --spoiler --json --timeout 30s tgcli send photo --to --photo /path/to/image.png --retries 3 --retry-backoff exponential --json --timeout 30s tgcli send file --to --file /path/to/file --caption "Report" --json --timeout 30s tgcli send file --to --file /path/to/file --caption "Report" --parse-mode html --json --timeout 30s tgcli send file --to --file /path/to/file --filename custom-name.pdf --json --timeout 30s tgcli send file --to --file /path/to/file --reply-to --json --timeout 30s tgcli send file --to --file /path/to/file --caption "Breaking news" --caption-above --json --timeout 30s tgcli send file --to --file /path/to/photo.jpg --spoiler --json --timeout 30s tgcli send file --to --file /path/to/photo.jpg --force-document --json --timeout 30s ``` ### Photo Preview vs Document Upload - Use `tgcli send photo` for local PNG/JPG when Telegram should render a photo preview. - Use `tgcli send file` for generic uploads and explicit document-style attachments. - For draft/approval flow, send to Saved Messages first, review in Telegram, then resend to the target chat. ### Media Download ```bash tgcli media download --chat --id --json --timeout 30s tgcli media download --chat --id --output /path/to/save --json --timeout 30s ``` ### Channels ```bash tgcli channels list --query "ai" --limit 20 --json --timeout 30s tgcli channels show --chat --json --timeout 30s tgcli channels sync --chat --enable --json --timeout 30s tgcli channels sync --chat --disable --json --timeout 30s ``` ### Topics ```bash tgcli topics list --chat --limit 50 --json --timeout 30s tgcli topics search --chat --query "release" --limit 20 --json --timeout 30s ``` ### Contacts ```bash tgcli contacts search "alex" --limit 20 --json --timeout 30s tgcli contacts show --user --json --timeout 30s tgcli contacts alias set --user --alias "Alex" --json --timeout 30s tgcli contacts alias rm --user --json --timeout 30s tgcli contacts tags add --user --tag coworker --tag ai --json --timeout 30s tgcli contacts tags rm --user --tag ai --json --timeout 30s tgcli contacts notes set --user --notes "Met at meetup" --json --timeout 30s ``` ### Groups ```bash tgcli groups list --query "dev" --limit 20 --json --timeout 30s tgcli groups info --chat --json --timeout 30s tgcli groups rename --chat --name "New Name" --json --timeout 30s tgcli groups members add --chat --user --user --json --timeout 30s tgcli groups members remove --chat --user --json --timeout 30s tgcli groups invite get --chat --json --timeout 30s tgcli groups invite revoke --chat --json --timeout 30s tgcli groups join --code --json --timeout 30s tgcli groups leave --chat --json --timeout 30s ``` ### Tags (Channel Classification) ```bash tgcli tags list --chat --json --timeout 30s tgcli tags set --chat --tag ai --tag dev --json --timeout 30s tgcli tags search --tag ai --limit 20 --json --timeout 30s tgcli tags auto --limit 50 --json --timeout 90s # AI-powered: generates tags from channel metadata/content tgcli tags auto --chat --source manual --json --timeout 90s tgcli tags auto --limit 50 --no-refresh-metadata --json --timeout 90s ``` ### Metadata (Channel Cache) ```bash tgcli metadata get --chat --json --timeout 30s tgcli metadata refresh --chat --force --json --timeout 30s tgcli metadata refresh --only-missing --limit 50 --json --timeout 90s ``` ### Folders ```bash tgcli folders list --json --timeout 30s tgcli folders show --json --timeout 30s tgcli folders show --resolve --json --timeout 30s tgcli folders create --title "Name" --emoji "🤖" --json --timeout 30s tgcli folders edit --title "New Name" --json --timeout 30s tgcli folders delete --json --timeout 30s tgcli folders order --json --timeout 30s tgcli folders add-chat --chat --json --timeout 30s tgcli folders remove-chat --chat --json --timeout 30s tgcli folders join --link "https://t.me/addlist/slug" --json --timeout 30s ``` Use `--resolve` with `folders show` to resolve peer IDs to readable channel/user names (slower, requires API calls per peer). Without `--resolve`, peers are shown as typed IDs (e.g., `channel:123`). ### Sync Jobs ```bash tgcli sync status --json --timeout 30s tgcli sync jobs list --json --timeout 30s tgcli sync jobs list --status error --json --timeout 30s tgcli sync jobs list --channel --json --timeout 30s tgcli sync jobs add --chat --depth 500 --json --timeout 30s tgcli sync jobs add --chat --min-date 2025-01-01T00:00:00Z --json --timeout 30s tgcli sync jobs retry --all-errors --json --timeout 30s tgcli sync jobs retry --job-id --json --timeout 30s tgcli sync jobs retry --channel --json --timeout 30s tgcli sync jobs cancel --job-id --json --timeout 30s tgcli sync jobs cancel --channel --json --timeout 30s ``` Do not write `tgcli sync --chat ...`; queue work with `sync jobs add --chat ...`, then process it with `tgcli sync --once` or `tgcli sync --follow`. ### Service (Background Sync Daemon) ```bash tgcli service status --json --timeout 30s tgcli service install --json --timeout 30s tgcli service start --json --timeout 30s tgcli service stop --json --timeout 30s tgcli service logs --json --timeout 30s ``` ### Config & Auth ```bash tgcli auth --json --timeout 30s tgcli auth --qr --json --timeout 30s tgcli auth status --json --timeout 30s tgcli auth logout --json --timeout 30s tgcli config list --json --timeout 30s tgcli config get --json --timeout 30s tgcli config set --json --timeout 30s tgcli config unset --json --timeout 30s tgcli doctor --json --timeout 30s tgcli doctor --connect --json --timeout 30s ``` ## Archive + Analysis Workflow For tasks like "analyze chat history", "what happened this week", "digest/news": 1. Resolve chat: - `tgcli channels list --query "" --json --timeout 30s` - optionally `tgcli groups list --query "" --json --timeout 30s` 2. Ensure archive flow: - `tgcli channels sync --chat --enable` - `tgcli sync jobs add --chat --depth 500` - `tgcli service status --json --timeout 30s` — check if running - `tgcli service install --json --timeout 30s` — if not installed yet - `tgcli service start --json --timeout 30s` — start daemon 3. Read archive first: - `tgcli messages list --chat --source archive --limit 500 --json --timeout 30s` 4. If archive is still empty, fallback to live: - `tgcli messages list --chat --source live --limit 500 --json --timeout 90s` 5. Build digest/synthesis from JSON payload. ## Continuous Sync Workflow For tasks like "monitor these channels", "keep syncing my subscriptions": Architecture: `channels sync --enable` marks channels for watching → `sync jobs add` creates backfill tasks → `service start` runs a persistent daemon that processes jobs and pulls realtime updates. 1. Enable sync for each channel: - `tgcli channels sync --chat --enable --json --timeout 30s` - repeat for each channel to monitor 2. Add backfill jobs (optional, pulls history): - `tgcli sync jobs add --chat --depth 1000 --json --timeout 30s` 3. Start the background daemon: - `tgcli service install --json --timeout 30s` — first time only - `tgcli service start --json --timeout 30s` 4. Verify it's running: - `tgcli service status --json --timeout 30s` - `tgcli sync status --json --timeout 30s` — shows per-channel sync progress 5. Check for errors: - `tgcli sync jobs list --status error --json --timeout 30s` - `tgcli sync jobs retry --all-errors --json --timeout 30s` 6. Stop monitoring a channel: - `tgcli channels sync --chat --disable --json --timeout 30s` Alternative without systemd service (one-shot or foreground): - `tgcli sync --once` — run one sync pass and exit - `tgcli sync --follow` — keep syncing in foreground (ctrl-c to stop) - `tgcli sync --follow --idle-exit 5m` — auto-exit after 5 minutes idle ## Sync Semantics - "My channels/subscriptions" -> `tgcli channels list ...` - "Monitored/synced channels" -> `tgcli sync status --json --timeout 30s` ## Trigger Examples ### Should trigger - "read messages in " - "search telegram for " - "send this text/file to telegram" - "download file from telegram message" - "summarize what was discussed this week" - "what's new in ?" - "show my mentions in " - "tag channels by topic" - "add user to telegram group" - "get invite link for group" - "reply to a specific telegram message" - "start syncing this channel" - "monitor my telegram channels" - "прочитай сообщения в канале" - "найди в телеграме про релиз" - "отправь сообщение в канал" - "дай сводку по чату" - "скачай файл из сообщения" - "опубликуй пост с картинкой" - "отправь фото с подписью в канал" - "post with cover image" ### Should not trigger - "edit/delete/forward telegram message" - "react with emoji to message" - "click inline button in bot" - "ban/kick/promote user with granular permissions" Use `telegram-mcp` for those operations.