{"id":50514154,"url":"https://github.com/b1rd33/tg-cli","last_synced_at":"2026-06-02T22:31:34.753Z","repository":{"id":356501415,"uuid":"1232814800","full_name":"b1rd33/tg-cli","owner":"b1rd33","description":"Agent-friendly Telegram CLI built on Telethon — read, write, archive your Telegram from the terminal with safety gates for autonomous-agent use.","archived":false,"fork":false,"pushed_at":"2026-05-08T11:18:19.000Z","size":304,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-08T11:40:39.451Z","etag":null,"topics":["agent","ai-agent","archiver","automation","cli","mtproto","python","sdk","telegram","telethon","terminal"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/b1rd33.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-08T09:51:18.000Z","updated_at":"2026-05-08T11:29:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/b1rd33/tg-cli","commit_stats":null,"previous_names":["b1rd33/tg-cli"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/b1rd33/tg-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b1rd33%2Ftg-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b1rd33%2Ftg-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b1rd33%2Ftg-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b1rd33%2Ftg-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/b1rd33","download_url":"https://codeload.github.com/b1rd33/tg-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b1rd33%2Ftg-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33840213,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","ai-agent","archiver","automation","cli","mtproto","python","sdk","telegram","telethon","terminal"],"created_at":"2026-06-02T22:31:29.637Z","updated_at":"2026-06-02T22:31:34.742Z","avatar_url":"https://github.com/b1rd33.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tgctl\n\n[![PyPI](https://img.shields.io/pypi/v/tgctl.svg)](https://pypi.org/project/tgctl/)\n[![CI](https://github.com/b1rd33/tg-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/b1rd33/tg-cli/actions/workflows/ci.yml)\n[![Python](https://img.shields.io/pypi/pyversions/tgctl.svg)](https://pypi.org/project/tgctl/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Docs](https://img.shields.io/badge/docs-b1rd33.github.io/tg--cli-blue)](https://b1rd33.github.io/tg-cli/)\n\n📖 **Documentation:** \u003chttps://b1rd33.github.io/tg-cli/\u003e\n\n**Agent-friendly Telegram CLI** built on [Telethon](https://github.com/LonamiWebs/Telethon). Read, write, archive,\nand listen to your own Telegram account from the terminal with JSON output,\nidempotency, audit logging, multi-account stores, and explicit safety gates\nfor autonomous-agent use.\n\n`tgctl` is for developers and local agents that need a predictable Telegram\nsurface without running a bot account or handing control to a GUI client. It\nuses your normal Telegram account through Telethon and stores a local SQLite\ncache for fast offline queries.\n\n\u003e **Names:** the PyPI distribution is `tgctl` (in the `kubectl`/`flyctl`\n\u003e family — Telegram control). The binary on `PATH` is `tg`. The Python\n\u003e import is `from tgcli import Client`. The GitHub repo is `tg-cli`.\n\n## Quick start\n\n```bash\npip install tgctl\necho \"TG_API_ID=12345678\" \u003e .env\necho \"TG_API_HASH=abcdef0123456789abcdef0123456789\" \u003e\u003e .env\ntg login\ntg stats\n```\n\nGet `TG_API_ID` and `TG_API_HASH` from https://my.telegram.org/apps.\n\n## CLI examples\n\n```bash\n# Sync chat metadata (no messages, fast)\ntg discover\n\n# Backfill messages from your top 10 chats\ntg backfill --max-chats 10 --per-chat 200\n\n# Search cached messages\ntg search \"shipping\" --json\n\n# Show recent messages from a specific chat\ntg show @username --limit 20\n\n# Send a message (--allow-write required for any Telegram write)\ntg send @username \"hello from tg-cli\" --allow-write\n\n# Format messages as HTML or Markdown\ntg send @username \"\u003cb\u003ehello\u003c/b\u003e from \u003ci\u003etgctl\u003c/i\u003e\" --parse-mode html --allow-write\ntg send @username \"**bold** and \\`code\\`\" --parse-mode md --allow-write\n\n# Pipe stdin as the message body\necho \"multi-line\\nbody\" | tg send @username - --allow-write\n\n# Reply to a specific message\ntg send @username \"thanks!\" --reply-to 12345 --allow-write\n\n# Listen for incoming messages — streams JSON envelopes to stdout\ntg listen\n\n# Forum topics\ntg topic-create -1001234567890 \"Q1 planning\" --allow-write\ntg send -1001234567890 \"kickoff\" --topic 42 --allow-write\n\n# Destructive ops require typed --confirm matching the resolved chat id\ntg delete-msg @username 99 100 --allow-write --confirm 12345\n\n# Health check\ntg doctor --json\n```\n\nEvery command supports `--json` for clean agent integration. `--read-only` (or `TG_READONLY=1`) globally rejects writes for a hardened script.\n\n## Features\n\n- 62 commands covering read, write, media, folder, topic, account, admin, and destructive operations\n- Multi-account mode with isolated session, database, and audit paths per account\n- JSON envelope output for clean agent integration\n- Local SQLite cache for fast reads and archival workflows\n- Write safety through `--allow-write`, `--dry-run`, idempotency keys, and append-only audit logs\n- Destructive safety through typed `--confirm \u003cid\u003e` checks\n- Read-only mode for trusted inspection with `--read-only` or `TG_READONLY=1`\n\n## Commands at a glance\n\n| Command | Purpose |\n| --- | --- |\n| `account-sessions` | List authenticated Telegram sessions |\n| `accounts-add` | Create a local account store |\n| `accounts-list` | List local account stores |\n| `accounts-remove` | Delete a local account store |\n| `accounts-show` | Show current account paths |\n| `accounts-use` | Switch the default local account |\n| `backfill` | Pull historical messages into SQLite |\n| `block-user` | Block a user or bot |\n| `chats-info` | Show cached chat metadata |\n| `contacts` | List synced contacts |\n| `delete-msg` | Delete one or more messages |\n| `discover` | Scan dialogs without fetching messages |\n| `doctor` | Diagnose env, session, DB, schema, and optional live API |\n| `edit-msg` | Edit one of your own text messages |\n| `folder-add-chat` | Add a chat to a Telegram folder |\n| `folder-create` | Create a Telegram folder |\n| `folder-delete` | Delete a Telegram folder |\n| `folder-edit` | Edit a Telegram folder |\n| `folder-remove-chat` | Remove a chat from a Telegram folder |\n| `folder-show` | Show one Telegram folder |\n| `folders-list` | List Telegram folders |\n| `folders-reorder` | Reorder Telegram folders |\n| `forward` | Forward one cached message |\n| `get-msg` | Get one cached message by id |\n| `leave-chat` | Leave a group, supergroup, or channel |\n| `list-msgs` | List cached messages from one chat |\n| `listen` | Capture new incoming messages forever |\n| `login` | Run one-time interactive auth |\n| `mark-read` | Mark all messages in a chat as read |\n| `me` | Print authenticated user info |\n| `pin-msg` | Pin a message |\n| `react` | Add a reaction to a message |\n| `search` | Search cached messages in one chat |\n| `send` | Send a text message |\n| `show` | Print messages from one chat |\n| `stats` | Show a database summary |\n| `sync-contacts` | Pull phone-book contacts from Telegram |\n| `terminate-session` | Terminate a Telegram session |\n| `topic-create` | Create a forum topic |\n| `topic-edit` | Edit a forum topic |\n| `topic-pin` | Pin a forum topic |\n| `topic-unpin` | Unpin a forum topic |\n| `topics-list` | List forum topics in a supergroup |\n| `unblock-user` | Unblock a user or bot |\n| `unpin-msg` | Unpin a message |\n| `unread` | List chats with unread messages |\n\n## Why tg-cli?\n\nTelegram tooling usually optimizes for one of four shapes: interactive TUIs,\nfile-transfer utilities, bot APIs, or MCP servers. `tg-cli` is narrower and\nmore scriptable: a local user-account CLI with stable exit codes, JSON output,\nSQLite-backed reads, an audit trail, and explicit write gates. It is designed\nfor shell scripts and coding agents that need to inspect or operate on the\nuser's own Telegram account while keeping every write intentional.\n\n## Configuration\n\nPaths and credentials can be provided through environment variables or a local\n`.env` file.\n\n| Variable | Purpose |\n| --- | --- |\n| `TG_API_ID` | Telegram API id from my.telegram.org |\n| `TG_API_HASH` | Telegram API hash from my.telegram.org |\n| `TG_SESSION_PATH` | Telethon session file path |\n| `TG_DB_PATH` | SQLite cache path |\n| `TG_AUDIT_PATH` | Append-only audit log path |\n| `TG_MEDIA_DIR` | Media output directory |\n| `TG_ACCOUNT` | Active local account name |\n| `TG_READONLY` | Reject Telegram-side and local DB writes when set to `1` |\n| `TG_ALLOW_WRITE` | Allow writes without passing `--allow-write` each time |\n\n## Multi-account\n\n```bash\ntg accounts-add work\ntg --account work login\ntg accounts-use work\ntg accounts-show\n```\n\nEach account stores its own session, database, and audit log under\n`accounts/\u003cNAME\u003e/`. The default account remains `default`.\n\n## Safety\n\nWrites are blocked unless you pass `--allow-write` or set `TG_ALLOW_WRITE=1`.\nDestructive commands also require a typed `--confirm \u003cid\u003e` value matched against\nthe resolved chat, user, message, folder, or session id. `--dry-run` reports\nwhat would happen without calling Telegram. `--read-only` and `TG_READONLY=1`\nreject both Telegram-side writes and local DB writers.\n\nEvery invocation appends audit entries to `audit.log`. Write commands record\npre-call and post-call entries with the same `request_id`; idempotency keys can\nreplay a cached successful envelope instead of calling Telegram again.\n\n## Architecture\n\n`tgcli.__main__` builds the argparse surface and dispatches into command modules\nunder `tgcli/commands/`. Commands share the same output envelope, resolver,\nsafety, idempotency, and audit helpers. Telethon handles Telegram API access;\nSQLite stores chats, messages, contacts, folders, topics, and idempotency state.\n\n```text\ntg command\n  -\u003e argparse\n  -\u003e command runner\n  -\u003e safety gates + resolver + audit\n  -\u003e Telethon and/or SQLite\n  -\u003e JSON envelope or human output\n```\n\n## Python SDK\n\nFor in-process use from another Python app — skip the subprocess overhead:\n\n```python\nfrom tgcli import Client\n\nc = Client()                                  # default account\n\n# Read paths\nme = c.me()\nsummary = c.stats(min_msgs=10)\nhistory = c.messages.show(chat_id=12345, limit=50)\n\n# Write paths reuse the CLI's safety gates\nresult = c.messages.send(\n    chat=12345,\n    text=\"hello\",\n    allow_write=True,                         # required, mirrors --allow-write\n    idempotency_key=\"abc123\",                 # optional replay protection\n)\n\n# Dry-run any write to preview without calling Telegram\npreview = c.messages.send(\n    chat=12345, text=\"hi\", allow_write=True, dry_run=True\n)\nassert preview[\"dry_run\"] is True\n```\n\nThe SDK reuses the CLI's safety gates — calling a write method without\n`allow_write=True` raises `tgcli.safety.WriteDisallowed`. Destructive\nadmin methods accept `confirm=\u003cresolved-id\u003e` matching the CLI\n`--confirm` flag.\n\n**Multi-account:** v0.4.0 SDK is single-account-per-process. Set\n`TG_ACCOUNT=\u003cname\u003e` BEFORE importing tgcli, then construct\n`Client(account=\"\u003cname\u003e\")`. Mismatched constructions raise\n`RuntimeError`. For concurrent multi-account work, run one process\nper account.\n\nThe SDK exposes a curated subset of runners (`me`, `stats`,\n`messages.send`, `messages.show`, `admin.chat_title`) for v1.0. All\n62 commands remain available through the CLI surface; open an issue\nif you need a specific runner exposed in the SDK.\n\n## Contributing\n\nSee [AGENTS.md](AGENTS.md) for the project's working conventions and the\n[git commit history](https://github.com/b1rd33/tg-cli/commits/main) for the\ndesign progression.\n\n## License\n\nMIT - see [LICENSE](LICENSE).\n\n## Credits\n\nBuilt on [Telethon](https://github.com/LonamiWebs/Telethon), the pure-Python\nMTProto client by Lonami, distributed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb1rd33%2Ftg-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb1rd33%2Ftg-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb1rd33%2Ftg-cli/lists"}