mila-telegram
Enables running Claude Code sessions from Telegram with group auto-join, voice transcription, reply-quote context, and a restart-proof polling daemon.
README
Mila Telegram
Run your Claude Code session from Telegram — and keep it running.
This is an extended fork of the official Telegram channel plugin (Apache-2.0). The original connects a Telegram bot to a Claude Code session. This fork adds the things you start needing once you actually work that way every day: teams in group chats, voice notes, and a poller that doesn't lose your messages when the session restarts.
What this fork adds
A daemon that outlives the session. In the original, the Telegram poller lives inside the session process: restart Claude Code and every message sent in the meantime is gone. Here the poller runs as a long-lived daemon that appends events to a journal file, and the session replays them from a cursor on startup. Restart, crash, upgrade — incoming messages wait in the file and arrive when the session comes back.
Group auto-join with one-tap approval. Add the bot to a group and send /channel_join. The owner gets a four-button card in a private chat: reply to everyone, mention-only, listen-only (the bot hears the chat, but replies into it are blocked mechanically), or reject. Every decision — rejections included — is appended to an auth-log.jsonl journal, and each connected chat gets a context card in chats/<id>.md plus a generated CHATS.md registry. No numeric chat IDs, no editing JSON by hand; group messages can never change the allowlist themselves — approval only happens in the owner's private chat.
Voice transcription. Voice notes are handed to a transcription command of your choice (set TELEGRAM_VOICE_TRANSCRIBE_CMD), and the text reaches the assistant along with the audio. Unset means voice notes simply pass through untranscribed — no default, no vendor.
Reply-quote context. When someone replies to an earlier message, the quoted text travels with the new one, so the assistant answers about the message you actually pointed at instead of the last thing in the chat.
Disclosure by default. /whoami answers, in any chat and to anyone, that
they are talking to an AI, what it is connected to, and who is responsible for
it. No access check on that one: a person who finds a bot in their group is
entitled to know what it is, whether or not they are on the allowlist.
Everything from the original plugin still works: pairing, allowlists, mention detection, reply / react / edit_message, photos, attachments, typing indicators.
Security
Read this before you put it on a machine that matters.
Messages are untrusted input. Anything anyone sends the bot reaches your assistant as content. Someone in an allowlisted chat can try to instruct it. Treat the channel as a public door into a session that can read files and run commands.
Groups require a mention by default. An approved group is added with requireMention: true, so the bot only responds when addressed. Turning that off means every message from every member goes straight into the session — that is a real prompt-injection surface, not a theoretical one. Turn it off only for a chat where you trust every member.
Attachments can go out. The reply tool sends any absolute path the assistant passes it. That is deliberate — it's how you get files out of a session — but combined with the point above it is also an exfiltration path. Your permission settings, not this plugin, are what stand between a message and a file leaving your machine.
The event journal is a trust boundary. The daemon writes events to a file and the session replays them; whatever can write that file speaks with the voice of Telegram. The journal and its directory are created 0600/0700, and the bridge replays only an allowlist of two methods so a forged line cannot invoke arbitrary ones. Keep the state directory on a filesystem only you can write.
Your token lives in ~/.claude/channels/telegram/.env at 0600, and is stripped from error output before anything is logged.
Prerequisites
- Bun — the MCP server runs on Bun:
curl -fsSL https://bun.sh/install | bash
Setup
1. Create a bot. Message @BotFather, send /newbot, and copy the token it gives you (the whole thing, including the leading digits and colon).
2. Install the plugin. From a Claude Code session:
/plugin marketplace add shakhruz/mila-telegram
/plugin install mila-telegram@mila
3. Give the server the token.
/telegram:configure 123456789:AAHfiqksKZ8...
This writes TELEGRAM_BOT_TOKEN=... to ~/.claude/channels/telegram/.env. You can write that file yourself instead, or set the variable in your shell — the shell wins.
To run several bots on one machine, point
TELEGRAM_STATE_DIRat a different directory per instance.
4. Relaunch with the channel flag. The server won't connect without it:
claude --channels plugin:mila-telegram@mila
5. Pair. DM your bot; it replies with a 6-character code. In the session:
/telegram:access pair <code>
6. Lock it down. Pairing exists to capture your ID. Once you're in, switch to an allowlist so strangers stop getting pairing codes:
/telegram:access policy allowlist
Running the daemon
The daemon is what makes restarts free. Run receiver.ts as a service under your process supervisor of choice — launchd on macOS, systemd on Linux — with RECEIVER_DAEMON=1 in its environment:
RECEIVER_DAEMON=1 bun /path/to/plugin/receiver.ts
It writes events to $TELEGRAM_STATE_DIR/inbound/events.jsonl. When a session starts and finds the daemon alive, it reads from that journal instead of polling, so the two never fight over the Telegram API. With no daemon running, the session polls directly exactly as the original plugin does — the daemon is optional.
Configuration
| Variable | Purpose |
|---|---|
TELEGRAM_BOT_TOKEN |
Bot token from BotFather. Required. |
TELEGRAM_STATE_DIR |
State directory. Default ~/.claude/channels/telegram. |
TELEGRAM_VOICE_TRANSCRIBE_CMD |
Command that transcribes a voice file. Unset means no transcription. |
RECEIVER_DAEMON |
Set to 1 to run receiver.ts as the polling daemon. |
Access control
See ACCESS.md for DM policies, groups, mention detection, delivery config, skill commands, and the access.json schema.
IDs are numeric user IDs — get yours from @userinfobot. ackReaction only accepts Telegram's fixed emoji whitelist.
Tools exposed to the assistant
| Tool | Purpose |
|---|---|
reply |
Send to a chat. Takes chat_id + text, optionally reply_to for native threading and files (absolute paths) for attachments. Images send as photos, everything else as documents, 50MB each. Long text is chunked. Returns the sent message ID(s). |
react |
Add an emoji reaction by message ID. Telegram's fixed whitelist only (👍 👎 ❤ 🔥 👀 …). |
edit_message |
Edit a message the bot sent. Good for "working…" → result. Own messages only. |
download_attachment |
Fetch a file by file_id from an inbound message and return its local path. |
Inbound messages trigger a typing indicator automatically.
No history, no search
Telegram's Bot API exposes neither. The bot only sees messages as they arrive — there is no way to fetch a chat's past. If the assistant needs earlier context it has to ask you for it. This is a limit of Telegram, not of this plugin, and it is why photos are downloaded eagerly on arrival.
License and attribution
Apache-2.0. This is a modified fork of the telegram channel plugin from anthropics/claude-plugins-official, copyright Anthropic, PBC. See NOTICE for the list of changes.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。