Custom Telegram MCP server + TUI auto-responder for running Claude Code as an autonomous Telegram agent
Project description
claude-code-telegrammer
Custom Telegram MCP server + TUI auto-responder for running Claude Code as an autonomous Telegram agent
Documentation ยท
pip install claude-code-telegrammer
Problem
The official plugin:telegram@claude-plugins-official has several unresolved issues that make it unusable for production autonomous agents:
- #851 --
STATE_DIRnot respected; access.json path hardcoded - #1075 -- 409 Conflict errors when multiple instances poll the same bot
- #1146 -- Zombie CPU consumption after session ends
Additionally, Claude Code sessions running unattended will stall at permission prompts or idle states with no way to recover.
Solution
Two subsystems that replace and extend the official plugin:
-
Custom Telegram MCP Server (
ts/) -- A self-contained MCP server that fixes all three official plugin issues: configurable state directory viaCLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR, PID-based single-instance lock, and clean shutdown on stdin close/SIGTERM. Provides 10 MCP tools (vs 3 in the official plugin), SQLite message persistence, allowlist-based access control, and inbound reaction (message_reaction) delivery. Incoming messages are acknowledged with a ๐ฉ reaction. -
TUI Watchdog (
lib/) -- Polls a GNU Screen session, detects Claude Code's TUI state via pattern matching, and sends keystrokes to keep the agent running unattended (auto-accepts permission prompts, re-engages on idle). Throttled with burst limits to prevent runaway responses. Orchestration and lifecycle management is handled by scitex-agent-container.
MCP Tools (10)
| Tool | Description |
|---|---|
reply |
Reply on Telegram. Supports threading (reply_to), auto-marks inbound as read. Inbound reply-to-message references are tracked and forwarded. |
react |
Add an emoji reaction to a message. Inbound reactions (message_reaction) are also delivered as channel notifications. |
edit_message |
Edit a previously sent bot message. |
get_history |
Retrieve message history for a chat from local SQLite. |
get_unread |
List unread inbound messages, optionally filtered by chat_id. |
mark_read |
Mark messages as read by chat_id or message_ids. |
download_attachment |
Download a Telegram file by file_id, returns local path. |
send_document |
Upload a local file to a Telegram chat. |
search_messages |
Text search across stored messages. |
get_context |
Recent conversation formatted as compact text for LLM context. |
Installation
Prerequisites
- Python >= 3.10 and GNU Screen (for watchdog/CLI)
- Bun >= 1.0 (for the MCP server)
Install
pip install claude-code-telegrammer
Or from source:
git clone https://github.com/ywatanabe1989/claude-code-telegrammer.git
cd claude-code-telegrammer
pip install -e .
# Install TypeScript dependencies for the MCP server
cd ts && bun install
Quickstart
Get a Telegram Bot Token
- Open Telegram and message @BotFather
- Send
/newbot, then enter a name (e.g.,Claude Code Telegrammer) and a username (e.g.,ClaudeCodeTelegrammerBot) - BotFather replies with your token:
123456789:AAH... - Verify your token works:
curl -s "https://api.telegram.org/bot<YOUR_TOKEN>/getMe" # Should return {"ok":true,"result":{"is_bot":true,...}}
- Open your bot (e.g., t.me/ClaudeCodeTelegrammerBot) and send any message to start a conversation
Register MCP Server with Claude Code
Copy the example and fill in your values (.mcp.json is gitignored):
{
"mcpServers": {
"claude-code-telegrammer": {
"type": "stdio",
"command": "bun",
"args": ["run", "/path/to/claude-code-telegrammer/ts/telegram-server.ts"],
"env": {
"CLAUDE_CODE_TELEGRAMMER_TELEGRAM_BOT_TOKEN": "123456789:AAH...",
"CLAUDE_CODE_TELEGRAMMER_TELEGRAM_ALLOWED_USERS": "YOUR_TELEGRAM_USER_ID",
"CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR": "~/.claude-code-telegrammer"
}
}
}
}
cp .mcp.json.example .mcp.json
# Edit .mcp.json with your token, user ID, and paths
Find your Telegram user ID by messaging @userinfobot.
Run
claude \
--dangerously-skip-permissions \
--dangerously-load-development-channels server:claude-code-telegrammer
For full agent orchestration (screen sessions, watchdog, YAML configs), see scitex-agent-container.
Interfaces
MCP Server -- for AI Agents
Start command:
bun run ts/telegram-server.ts
10 tools exposed via MCP stdio protocol. See MCP Tools above. The server's MCP instructions include a responsiveness policy that directs the agent to acknowledge messages immediately and delegate heavy work to background subagents.
Skills -- for AI Agent Discovery
Skills are bundled at src/claude_code_telegrammer/_skills/claude-code-telegrammer/SKILL.md.
Architecture
User (Telegram)
|
| Bot API (getUpdates long-polling)
v
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Custom Telegram MCP Server (ts/telegram-server.ts) โ
โ Bun + @modelcontextprotocol/sdk โ
โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โ โ Poller โ โ Store โ โ Tools โ โ Attachmentsโ โ
โ โ (long โ โ (SQLite โ โ (10 MCP โ โ (download โ โ
โ โ poll) โ โ WAL) โ โ tools) โ โ queue) โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ Access โ โ Config โ โ Lock โ โ
โ โ (allow- โ โ (env โ โ (PID โ โ
โ โ list) โ โ vars) โ โ file) โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MCP stdio
v
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Claude Code (in GNU Screen session) โ
โ --mcp-config points to the custom MCP server โ
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ screen buffer
v
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Watchdog (claude-code-telegrammer-watchdog) โ
โ Polls screen buffer every 1.5s โ
โ Detects: y/n prompt -> "1", y/y/n -> "2", idle -> cmd โ
โ Throttled: burst limit, same-state delay, min interval โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
State Detection
| State | Pattern | Response |
|---|---|---|
running |
(esc to interrupt), tokens ยท, ing... |
No action |
y_n |
1. Yes + 3. No (two-choice prompt) |
Send 1 (accept) |
y_y_n |
2. Yes, and... / 2. Yes, allow... / 2. Yes, don't ask... |
Send 2 (accept all) |
waiting |
Cooking puns (Crafted for, etc.), empty > prompt, idle hints |
Send configurable command |
Response throttling: minimum interval between responses, burst limit (10 in 3s window), same-state delay.
Configuration (Environment Variables)
MCP Server:
| Variable | Required | Default | Description |
|---|---|---|---|
CLAUDE_CODE_TELEGRAMMER_TELEGRAM_BOT_TOKEN |
Yes | -- | Telegram Bot API token |
CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR |
No | ~/.claude-code-telegrammer |
Directory for SQLite DB, access.json, lock file |
CLAUDE_CODE_TELEGRAMMER_TELEGRAM_ALLOWED_USERS |
No | -- | Comma-separated Telegram user IDs for DM allowlist |
CLAUDE_CODE_TELEGRAMMER_TELEGRAM_HOST_NAME |
No | os.hostname() |
Hostname stored with each message |
CLAUDE_CODE_TELEGRAMMER_TELEGRAM_PROJECT |
No | process.cwd() |
Project path stored with each message |
CLAUDE_CODE_TELEGRAMMER_TELEGRAM_AGENT_ID |
No | 'telegram' |
Agent identifier stored with each message |
Watchdog:
| Variable | Default | Description |
|---|---|---|
CLAUDE_CODE_TELEGRAMMER_SESSION |
claude-code-telegrammer |
GNU Screen session name |
CLAUDE_CODE_TELEGRAMMER_WATCHDOG_INTERVAL |
1.5 |
Poll interval in seconds |
CLAUDE_CODE_TELEGRAMMER_RESP_Y_N |
1 |
Response for y/n prompts |
CLAUDE_CODE_TELEGRAMMER_RESP_Y_Y_N |
2 |
Response for y/y/n prompts |
CLAUDE_CODE_TELEGRAMMER_RESP_WAITING |
/speak-and-call |
Response when idle/waiting |
SQLite Schema (v2)
All messages persisted in $CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR/messages.db using WAL mode.
messages table: direction, chat_id, message_id, user_id, username, text, timestamps (telegram_ts, received_at, read_at, replied_at), threading (reply_to_message_id, reply_to_row_id), identity (host, project, agent_id, bot_token_hash), raw_json.
attachments table: message_row_id (FK), kind, file_id, file_name, mime_type, file_size, local_path, downloaded_at.
meta table: key-value store for schema_version, update_offset.
Integration with scitex-agent-container
For YAML-based agent orchestration (screen sessions, watchdog lifecycle, restart policies), see scitex-agent-container.
Access Control
Managed via access.json in $CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR:
{
"dmPolicy": "allowlist",
"allowFrom": ["123456789"],
"groups": {
"-100123456": {
"requireMention": true,
"allowFrom": ["123456789"]
}
}
}
Merged with CLAUDE_CODE_TELEGRAMMER_TELEGRAM_ALLOWED_USERS env var at runtime. Mtime-based caching means edits take effect without restart.
Part of SciTeX
claude-code-telegrammer is part of SciTeX. It provides the Telegram communication layer and TUI watchdog used by scitex-agent-container for autonomous agent operation.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ scitex-orochi โ agent definitions, dashboard โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
v
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ scitex-agent-container โ lifecycle, health, restart โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
v
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ claude-code-telegrammer <-- YOU ARE HERE โ
โ MCP server: Telegram API, message DB, 10 tools โ
โ Watchdog: TUI auto-response, screen polling โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
References
- Claude Code Channels -- Official documentation for Claude Code's channel system
- Official Telegram Plugin -- The
plugin:telegram@claude-plugins-officialsource code - #851: STATE_DIR not respected -- Hardcoded access.json path
- #1075: 409 Conflict errors -- Multiple instances polling the same bot
- #1146: Zombie CPU consumption -- Runaway process after session ends
- Telegram BotFather -- Create and manage Telegram bots
- Telegram Bot API -- Official Bot API documentation
- MCP Specification -- Model Context Protocol standard
- claude-code-telegrammer Issues -- Bug reports and feature requests
- claude-code-telegrammer Pull Requests -- Contributions
Four Freedoms for Research
- The freedom to run your research anywhere -- your machine, your terms.
- The freedom to study how every step works -- from raw data to final manuscript.
- The freedom to redistribute your workflows, not just your papers.
- The freedom to modify any module and share improvements with the community.
AGPL-3.0 -- because we believe research infrastructure deserves the same freedoms as the software it runs on.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claude_code_telegrammer-0.4.0.tar.gz.
File metadata
- Download URL: claude_code_telegrammer-0.4.0.tar.gz
- Upload date:
- Size: 519.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c2f588c216ddc4719ce7cc4bd9275f9915eed025b1142386ce450c000a4b7a6
|
|
| MD5 |
43530a92953835f31391968b17b37d14
|
|
| BLAKE2b-256 |
0c62e9958d8f98aaf789be4de3bd7b1b1158ee7a45c136d3d695253adb6171c8
|
Provenance
The following attestation bundles were made for claude_code_telegrammer-0.4.0.tar.gz:
Publisher:
publish-pypi.yml on ywatanabe1989/claude-code-telegrammer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_code_telegrammer-0.4.0.tar.gz -
Subject digest:
9c2f588c216ddc4719ce7cc4bd9275f9915eed025b1142386ce450c000a4b7a6 - Sigstore transparency entry: 1271320739
- Sigstore integration time:
-
Permalink:
ywatanabe1989/claude-code-telegrammer@ab2f887c5f6301442214d45cf5cd7b1ff5d1739b -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ywatanabe1989
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@ab2f887c5f6301442214d45cf5cd7b1ff5d1739b -
Trigger Event:
push
-
Statement type:
File details
Details for the file claude_code_telegrammer-0.4.0-py3-none-any.whl.
File metadata
- Download URL: claude_code_telegrammer-0.4.0-py3-none-any.whl
- Upload date:
- Size: 20.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a0e1e4ebc96871c25c0281929144927a6e27ece3fee33006a397b080dd3b2df
|
|
| MD5 |
f45abd25dee732f639553080cc6cbb3b
|
|
| BLAKE2b-256 |
e9f733aa764a6324ab67b920a54e08de372e6f31102a6d16a62abe6d885b0391
|
Provenance
The following attestation bundles were made for claude_code_telegrammer-0.4.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on ywatanabe1989/claude-code-telegrammer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_code_telegrammer-0.4.0-py3-none-any.whl -
Subject digest:
1a0e1e4ebc96871c25c0281929144927a6e27ece3fee33006a397b080dd3b2df - Sigstore transparency entry: 1271320781
- Sigstore integration time:
-
Permalink:
ywatanabe1989/claude-code-telegrammer@ab2f887c5f6301442214d45cf5cd7b1ff5d1739b -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ywatanabe1989
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@ab2f887c5f6301442214d45cf5cd7b1ff5d1739b -
Trigger Event:
push
-
Statement type: