A minimal Python CLI that wraps Telethon (MTProto) so Claude Code can read your Telegram groups on your behalf — list groups, fetch recent messages, search within a group, and pull reply threads.
Bundled with a Claude Code skill (skill/SKILL.md) that documents the
CLI for the model so it does not have to guess command names or flags.
Telegram's Bot API cannot read group history — a bot only sees messages
explicitly addressed to it. MTProto (the user-account API) is the only
way to search past group conversations. tg-cli uses Telethon to speak
MTProto with your own account.
Security note: the session file at
~/.config/tg-cli/session.sessiongrants full access to your Telegram account. Treat it like a credential: do not commit it, share it, or paste it into chats. The skill is strictly read-only; nothing in this repo sends messages or mutates state.
Requires Python 3.10+.
# install from a local checkout
git clone <repo-url> ~/src/tg-cli
cd ~/src/tg-cli
uv tool install . # or: pipx install .This exposes a tg command on your PATH.
- Register a personal app at https://my.telegram.org/apps to obtain
api_id(int) andapi_hash(str). This is free and one-time. - Create
~/.config/tg-cli/config.toml:Override the directory withapi_id = 1234567 api_hash = "abcdef0123456789abcdef0123456789"
TG_CLI_CONFIG_DIR=/some/pathif needed. - Authenticate:
Prompts for phone number (unless
tg login # interactive: phone prompt + login code tg login --phone +15551234567 # skip the phone prompt
--phoneis given), login code, and (if enabled) 2FA password. The session persists at~/.config/tg-cli/session.sessionso subsequent commands run non-interactively.
All commands emit JSON to stdout on success and a JSON error object to
stderr (with non-zero exit) on failure. Add --pretty for indented
output.
List your dialogs.
tg groups --type group | jq '.[] | .title'Example element:
{
"id": -1001234567890,
"title": "My Dev Group",
"type": "supergroup",
"username": "mydevgroup",
"member_count": 42
}Fetch recent messages from <group>, oldest first.
tg messages "My Dev Group" --since 24h
tg messages @mydevgroup --since 7d --limit 200
tg messages --since 2026-04-15T10:00 -- -1001234567890<group> accepts a numeric id, @username, or a case-insensitive
substring of the title (errors on ambiguous match).
Negative numeric ids. Raw supergroup/channel ids start with
-(e.g.-1001234567890), which the CLI parser mistakes for an option and rejects withNo such option: -1.... Pass options first and put the id after a--separator, or use the@username/ title form instead. The same applies totg searchandtg thread.
Migrated basic chats. Legacy basic-chat ids (and old title substrings) are transparently redirected to the supergroup they were migrated to, so an id you copy-pasted from an older listing keeps working. This applies equally to numeric ids,
@username, and title substrings, and coverstg messages,tg search, andtg thread. Thegroup_idfield on returned messages reflects the resolved supergroup's-100…id, not the id you passed on the command line.
TIME accepts 24h, 7d, 2026-04-15, or 2026-04-15T10:00 (UTC).
Full-text search within <group>, newest matches first.
tg search "My Dev Group" "deploy" --since 30dFetch a root message and its replies. The root message is returned first, then replies in chronological (oldest-first) order.
tg thread "My Dev Group" 12345{
"id": 12345,
"date": "2026-04-17T10:23:45+00:00",
"sender_id": 98765,
"sender_name": "Alice",
"text": "hello world",
"reply_to_id": null,
"group_id": -1001234567890
}{"error": "Not logged in. Run `tg login` first.", "type": "AuthError"}The skill/ directory contains a Claude Code skill (SKILL.md) that
tells Claude when and how to use tg. Install it as a symlink:
./scripts/install-skill.shThis links skill/ to ~/.claude/skills/telegram/. The script is
idempotent and refuses to clobber an existing file. Restart your Claude
Code session after installing so the skill is picked up.
See skill/SKILL.md for the full skill contents
(command reference, workflows, and notes Claude follows when calling
tg).
FloodWaitError: retry after N seconds. Telegram rate-limited the
account. Wait the reported number of seconds before retrying. Reduce
--limit or avoid tight loops across many groups.
**AuthError: Not logged in. Run \tg login` first..** Session is missing or was invalidated (password change, security event, or explicit logout). Run tg login` again.
Session corruption / database is locked. A stale session file can
linger after a crash. Remove it and re-login:
rm ~/.config/tg-cli/session.session
tg loginConfigError. Config file missing or malformed. Recreate
~/.config/tg-cli/config.toml per the setup section above.
AmbiguousGroupError. The title substring matched more than one
dialog. Use the numeric id from tg groups instead.
MessageNotFoundError. The message id does not exist in the given
group. Confirm via tg messages or tg search.
uv sync --all-extras # install dev deps
uv run pytest -v # run the test suite
uv run pytest --cov=tg_cli # coverage
uv run ruff check src tests # lint
shellcheck scripts/install-skill.shTests mock TelegramClient; no live API calls are made from the test
suite. For end-to-end verification, use the commands against a
throwaway group from a shell after tg login.
MIT.