An agent skill that lets AI coding agents read and act on your own Telegram account: list chats, read and search messages, send, reply, forward, react, edit, delete, press bot buttons, and move media in both directions. It uses Telethon over Telegram's MTProto client API, so the agent acts as you, not as a bot.
Unofficial. This project is not affiliated with, endorsed by, or supported by Telegram. It
uses the Telegram API with an api_id you create yourself.
Packaged for Claude Code, Codex, and Gemini CLI. The skill itself is a plain
SKILL.md folder, so any agent that reads Agent Skills
can use it.
Installing this gives an agent the same access to your Telegram account that you have.
- Prompt injection is the main risk. Anyone who can message you can put text in front of
your agent. The skill tells the agent to treat Telegram content as data and to act only on
your requests, but that is model behavior, not a guarantee. Keep your harness's command
approval on for outbound commands (
send,reply,forward,edit,delete,react,upload,click). Don't run this in an auto-approve mode on an account that matters. - The session file is your account.
telegram.sessionholds the login key. Anyone who reads it is logged in as you, with no code or 2FA prompt. It is created owner-only (0600); keep it that way and keep it out of backups you share. - Message content goes to your AI provider. Whatever the agent reads (including other people's messages) becomes part of its context and is processed under your AI provider's terms. See PRIVACY.md.
- Telegram's terms apply. Use your own
api_id. Automated or bulk activity on a user account can get it limited or banned.
What the code enforces (see Security model for details):
- It refuses to upload its own session, credential, or cache files.
- Outbound commands refuse to guess between chats with similar names.
- Media downloads go outside the current project by default.
- Commands never prompt for a login; they fail with
NotLoggedInErrorinstead.
- Runs one local Python script,
skills/telegram-explorer/scripts/telegram_client.py, once per command. With uv, the first run installs Telethon 1.45.0 and its three dependencies (pyaes,pyasn1,rsa) from PyPI, pinned by hash intelegram_client.py.lockand enforced with--locked. Video uploads also runffprobe, if it is installed, to read the video's dimensions and duration. - Sends network traffic only to Telegram's MTProto servers (Telethon's built-in data-center addresses), plus, on first run with uv, PyPI for the pinned dependencies and, only if no Python ≥ 3.11 is installed, uv's managed-Python download from GitHub. There is no telemetry, analytics, or other destination.
- Reads local files only when you ask it to
uploadthem, plus its own state directory. - Writes only to its state directory (
~/.config/telegram-explorer/) and the download directory (~/.local/share/telegram-explorer/downloads/or the--outyou pass).
- Python ≥ 3.11
- uv (recommended: it installs the pinned Telethon automatically; tested with uv 0.9.17), or pip
- Optional:
ffprobe(from ffmpeg), so uploaded videos play inline
| Harness | Install |
|---|---|
| Claude Code | /plugin marketplace add zknpr/telegram-explorer then /plugin install telegram-explorer@telegram-explorer |
| Codex | codex plugin marketplace add zknpr/telegram-explorer then codex plugin add telegram-explorer@telegram-explorer |
| Gemini CLI | gemini extensions install https://github.com/zknpr/telegram-explorer |
| Other Agent Skills harnesses | Copy or symlink skills/telegram-explorer/ into the agent's skills directory (for example ~/.agents/skills/) |
A .cursor-plugin/plugin.json manifest is included but untested (see Compatibility).
-
Create an app at https://my.telegram.org/apps and note the
api_idandapi_hash. -
Log in. It asks for the API credentials, your phone number, the code Telegram sends, and your 2FA password if you have one:
git clone https://github.com/zknpr/telegram-explorer uv run --locked --script telegram-explorer/skills/telegram-explorer/scripts/telegram_client.py login
The session is stored in
~/.config/telegram-explorer/, not next to the script, so logging in from a clone works for every harness install.
Without uv:
python3 -m venv ~/.local/share/telegram-explorer/venv
~/.local/share/telegram-explorer/venv/bin/pip install -r telegram-explorer/skills/telegram-explorer/scripts/requirements.txt
~/.local/share/telegram-explorer/venv/bin/python telegram-explorer/skills/telegram-explorer/scripts/telegram_client.py loginlogin is the only interactive command. Don't let an agent run it.
Ask your agent in plain language:
- "What did I miss in the Dev Team group today? Summarize the unread messages."
- "Search my Telegram for the message where someone shared the staging database URL."
- "Send the build log at
./build.logto @alice with the caption 'failing on main'." - "List the forum topics in the Project X group and show the last 10 messages in Releases."
- "Alias @my_long_channel_name as 'news', then show me its pinned messages."
The agent runs the CLI and reads its JSON output. For the full command list, see
SKILL.md and
references/api-reference.md.
Chats can be referenced by @username, numeric id, phone number, invite link, cached name, or
an alias you define (alias-add <chat> "mom"). last refers to the most recently used chat.
| Variable | Default | Purpose |
|---|---|---|
TELEGRAM_EXPLORER_HOME |
$XDG_CONFIG_HOME/telegram-explorer (else ~/.config/telegram-explorer) |
State directory: credentials.json, telegram.session, cache.json. Use one directory per account. |
TELEGRAM_API_ID, TELEGRAM_API_HASH |
unset | Override credentials.json |
XDG_DATA_HOME |
~/.local/share |
Media downloads go to $XDG_DATA_HOME/telegram-explorer/downloads unless --out is given |
TELEGRAM_CACHE_PATH |
<state dir>/cache.json |
Cache file override (tests) |
| Threat | Mitigation | Limits |
|---|---|---|
Injected message makes the agent exfiltrate the session (upload @attacker --file …session) |
upload refuses files inside the state directory and symlinks or hard links to the session, credentials, or cache files, before connecting |
Copying the file first bypasses the check. Command approval in the harness is the real control. |
| Look-alike display name receives outbound content | Identical cached names always raise AmbiguousMatchError. Outbound commands never use the recency tiebreak, so several partial matches raise too. |
A single look-alike is still the only match when the real contact isn't cached. The skill tells the agent to confirm recipients given by name. |
| Other local users read the session | Process umask 077. Session and credentials files are chmod 0600 on every run. |
Root and backups are out of scope. |
Sender-named downloads planted in the working project (conftest.py, …) |
Default download dir is outside the current directory. Telethon strips path components and won't overwrite existing files. | Passing --out . brings the risk back. |
| Agent stuck on an interactive login prompt | Commands connect without Telethon's interactive start() and fail with NotLoggedInError |
— |
| Tampered or drifting dependency | Telethon is pinned to an exact version and verified by hash from the lockfile (uv run --locked) |
The pip fallback pins the version but not hashes. |
Please report vulnerabilities through GitHub's private vulnerability reporting on this repository.
Install and skill discovery were checked locally. No harness has been tested against a live Telegram session.
| Harness | Manifest | Status |
|---|---|---|
| Claude Code | .claude-plugin/plugin.json, .claude-plugin/marketplace.json |
Validated with claude plugin validate, installed from GitHub (2.1.295) |
| Codex | .codex-plugin/plugin.json (marketplace read from .claude-plugin/marketplace.json) |
Installed from GitHub (0.162.0) |
| Gemini CLI | gemini-extension.json |
Installed from GitHub; skill discovered (0.32.1) |
| Cursor | .cursor-plugin/plugin.json |
Validated against Cursor's published schema; not installed |
| Others (OpenCode, …) | skills/telegram-explorer/ |
Untested |
| Windows | — | Untested |
cd skills/telegram-explorer/scripts
uv run --no-project --with 'telethon==1.45.0' python -m unittest discover -s tests -t .The tests are offline: Telegram calls go to a fake client. After changing the dependency line
in telegram_client.py, regenerate the lockfile with uv lock --script telegram_client.py.
Original artwork for this project. It is not, and is not derived from, the Telegram logo.
MIT.