Complete guide to setting up Claude Code Rust Telegram (CTM) from scratch.
graph LR
RUST[Rust 1.75+] --> BUILD[cargo build]
TMUX[tmux] --> INJECT[Input injection]
TELEGRAM[Telegram Account] --> BOT[Bot creation]
CLAUDE[Claude Code CLI] --> HOOKS[Hook integration]
style RUST fill:#f96,stroke:#333
style TMUX fill:#9f6,stroke:#333
style TELEGRAM fill:#69f,stroke:#333
style CLAUDE fill:#f9f,stroke:#333
| Requirement | Purpose | Check |
|---|---|---|
| Rust 1.75+ | Build CTM binary | rustc --version |
| tmux | Bidirectional CLI communication | tmux -V |
| Claude Code | The CLI being mirrored | claude --version |
| Telegram account | Mobile control interface | - |
git clone https://github.com/DreamLab-AI/Claude-Code-Rust-Telegram.git
cd Claude-Code-Rust-Telegram
cargo build --releaseThe binary is at target/release/ctm. Optionally install it:
cp target/release/ctm ~/.local/bin/
# or
sudo cp target/release/ctm /usr/local/bin/sequenceDiagram
participant You
participant BotFather as @BotFather
participant Bot as Your New Bot
You->>BotFather: /newbot
BotFather->>You: Choose a name
You->>BotFather: Claude Mirror Bot
BotFather->>You: Choose a username
You->>BotFather: claude_mirror_bot
BotFather->>You: Bot token: 123456:ABC...
You->>BotFather: /mybots
You->>BotFather: Select bot -> Settings
You->>BotFather: Group Privacy -> Turn OFF
Note over You,BotFather: Privacy mode must be OFF<br/>for the bot to see all messages
- Open Telegram (desktop app or mobile — not a self-chat)
- Use the search bar to find
BotFather— select the one with the blue verified checkmark - Start a direct chat with @BotFather and send
/newbot - BotFather will ask for a display name (e.g. "Claude Mirror") and a username (must end in
bot, e.g.claude_mirror_bot) - Copy the bot token it gives you (format:
123456789:ABCdefGHIjklMNOpqrsTUVwxyz) - Disable privacy mode:
/mybots-> Select bot -> Bot Settings -> Group Privacy -> Turn off
Note: @BotFather is a real Telegram bot you message directly — it is not a settings page or a chat with yourself.
graph TB
CREATE[Create Telegram Group] --> ADD[Add your bot]
ADD --> SETTINGS[Group Settings]
SETTINGS --> TOPICS[Enable Topics/Forums]
TOPICS --> ADMIN[Make bot an Admin]
ADMIN --> PERMS[Grant permissions]
PERMS --> P1[Manage Topics]
PERMS --> P2[Post Messages]
PERMS --> P3[Delete Messages]
- Create a new group in Telegram
- Add your bot during group creation: in the "Add Members" screen, search for your bot's username (e.g.
TheDreamLabBot) and select it - Go to Group Settings -> Enable Topics to convert it to a forum supergroup
- Make the bot an Administrator with these permissions:
- Manage Topics
- Post Messages
- Delete Messages (optional, for topic cleanup)
Telegram Web limitation: Enabling Topics (converting a group to a forum) may not be available in Telegram Web. Use the Telegram desktop app or mobile app to enable Topics in group settings. Once enabled, the forum works fine in Telegram Web.
Adding the bot: If the group already exists, open the group -> click the group name header -> Add Members -> search for your bot username.
The chat ID identifies your supergroup. Supergroup IDs start with -100.
- Send any message in the group where your bot is a member
- Run this command (replace
YOUR_TOKENwith your bot token):
curl -s "https://api.telegram.org/botYOUR_TOKEN/getUpdates" | python3 -m json.tool- Look for
"chat": {"id": -100XXXXXXXXXX}in the response — that negative number is your chat ID
./scripts/get-chat-id.sh YOUR_BOT_TOKENTip: If
getUpdatesreturns an empty result, make sure you've sent a message in the group after adding the bot. The bot only sees messages sent after it joined.
Create ~/.config/claude-telegram-mirror/config.json:
mkdir -p ~/.config/claude-telegram-mirror
chmod 700 ~/.config/claude-telegram-mirror{
"bot_token": "123456789:ABCdefGHIjklMNOpqrsTUVwxyz",
"chat_id": -1001234567890,
"enabled": true,
"approvals": true,
"use_threads": true,
"rate_limit": 20,
"session_timeout": 1800,
"auto_delete_topics": false
}chmod 600 ~/.config/claude-telegram-mirror/config.jsonOr use the interactive wizard which validates your token and chat ID:
ctm setupCreate ~/.telegram-env:
export TELEGRAM_BOT_TOKEN="123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
export TELEGRAM_CHAT_ID="-1001234567890"
export TELEGRAM_MIRROR=trueSource it in your shell profile (~/.bashrc or ~/.zshrc):
[[ -f ~/.telegram-env ]] && source ~/.telegram-envNote: Environment variables take precedence over the config file. You can mix both — use the config file for stable settings and env vars for overrides.
graph TD
subgraph "Required"
TOKEN[TELEGRAM_BOT_TOKEN]
CHATID[TELEGRAM_CHAT_ID]
MIRROR[TELEGRAM_MIRROR=true]
end
subgraph "Optional"
VERBOSE[TELEGRAM_MIRROR_VERBOSE<br/>default: false]
THREADS[TELEGRAM_USE_THREADS<br/>default: true]
AUTODEL[TELEGRAM_AUTO_DELETE_TOPICS<br/>default: false]
DELAY[TELEGRAM_TOPIC_DELETE_DELAY<br/>default: 5 minutes]
SOCKET[TELEGRAM_BRIDGE_SOCKET<br/>default: auto]
end
TOKEN --> CONFIG[Config]
CHATID --> CONFIG
MIRROR --> CONFIG
VERBOSE --> CONFIG
THREADS --> CONFIG
AUTODEL --> CONFIG
DELAY --> CONFIG
SOCKET --> CONFIG
| Variable | Required | Default | Description |
|---|---|---|---|
TELEGRAM_BOT_TOKEN |
Yes | - | Bot API token from @BotFather |
TELEGRAM_CHAT_ID |
Yes | - | Supergroup chat ID (starts with -100) |
TELEGRAM_MIRROR |
Yes | false |
Enable the bridge |
TELEGRAM_MIRROR_VERBOSE |
No | false |
Show tool start/result messages |
TELEGRAM_USE_THREADS |
No | true |
Create forum topics per session |
TELEGRAM_AUTO_DELETE_TOPICS |
No | false |
Delete topics when sessions end |
TELEGRAM_TOPIC_DELETE_DELAY |
No | 5 |
Minutes before topic deletion |
TELEGRAM_BRIDGE_SOCKET |
No | auto | Custom socket path |
Add to ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [{ "hooks": [{ "type": "command", "command": "ctm hook", "timeout": 5000 }] }],
"PostToolUse": [{ "hooks": [{ "type": "command", "command": "ctm hook", "timeout": 5000 }] }],
"UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "ctm hook", "timeout": 5000 }] }],
"SessionStart": [{ "hooks": [{ "type": "command", "command": "ctm hook", "timeout": 5000 }] }],
"SessionEnd": [{ "hooks": [{ "type": "command", "command": "ctm hook", "timeout": 5000 }] }],
"Notification": [{ "hooks": [{ "type": "command", "command": "ctm hook", "timeout": 5000 }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "ctm hook", "timeout": 5000 }] }]
}
}graph LR
subgraph "Claude Code Hooks"
PRE[PreToolUse]
POST[PostToolUse]
NOTIF[Notification]
STOP[Stop]
USER[UserPromptSubmit]
SSTART[SessionStart]
SEND[SessionEnd]
end
subgraph "CTM Handler"
HOOK[ctm hook<br/>reads stdin JSON]
end
subgraph "Bridge"
SOCKET[Unix Socket]
end
PRE -->|stdin| HOOK
POST -->|stdin| HOOK
NOTIF -->|stdin| HOOK
STOP -->|stdin| HOOK
USER -->|stdin| HOOK
SSTART -->|stdin| HOOK
SEND -->|stdin| HOOK
HOOK -->|NDJSON| SOCKET
HOOK -->|stdout passthrough| PRE
Each hook:
- Receives JSON on stdin from Claude Code
- Parses the event and forwards to the bridge via unix socket
- Passes through the original JSON on stdout (so Claude Code is unaffected)
# Start in foreground
ctm start
# Or in a tmux window
tmux new-window -n ctm 'ctm start'ctm doctorExpected output:
Claude Telegram Mirror - Doctor
================================
[1/6] Binary...
OK: ctm binary running
[2/6] Config directory...
OK: Config directory exists with secure permissions
[3/6] Environment variables...
OK: All environment variables set
[4/6] tmux...
OK: tmux is available
OK: tmux session detected: workspace:0.0
[5/6] Socket...
OK: Bridge socket exists at ~/.config/claude-telegram-mirror/bridge.sock
[6/6] Database...
OK: Database accessible (0 sessions, 0 approvals)
================================
All checks passed!
# Start Claude Code in tmux
tmux new -s claude
claudeNow any Claude Code activity will be mirrored to your Telegram supergroup. Reply in the forum topic to send input back to Claude.
For running as a managed service:
[program:ctm]
command=/usr/local/bin/ctm start
directory=/home/devuser
user=devuser
autostart=true
autorestart=true
environment=TELEGRAM_MIRROR="true",RUST_LOG="info"
stdout_logfile=/home/devuser/.config/claude-telegram-mirror/supervisor.log
stdout_logfile_maxbytes=10MBgraph TB
subgraph "System A"
BOT_A[Bot A Token]
DAEMON_A[ctm start]
BOT_A --> DAEMON_A
end
subgraph "System B"
BOT_B[Bot B Token]
DAEMON_B[ctm start]
BOT_B --> DAEMON_B
end
subgraph "Telegram"
GROUP[Shared Supergroup]
TOPIC_A[System A Topics]
TOPIC_B[System B Topics]
GROUP --> TOPIC_A
GROUP --> TOPIC_B
end
DAEMON_A -->|creates & manages| TOPIC_A
DAEMON_B -->|creates & manages| TOPIC_B
Each system needs its own bot token (Telegram only allows one polling connection per token). All bots share the same supergroup, and each daemon only manages topics it created.