claude-telegram-mirror
v0.2.17
Published
Bidirectional Telegram integration for Claude Code CLI - monitor and control your Claude Code sessions from Telegram
Maintainers
Readme
Claude Code Telegram Mirror
Bidirectional communication between Claude Code CLI and Telegram. Control your Claude Code sessions from your phone.
Supported platforms: Linux x64, Linux arm64, macOS ARM64, macOS Intel x64
Installation
npm install -g claude-telegram-mirror
ctm setup # Interactive setup wizardThis installs a native Rust binary (ctm) via platform-specific optional packages. No Node.js runtime is needed to run the binary itself — Node.js 18+ is only required as the npm distribution mechanism.
Features
- CLI to Telegram: Mirror Claude's responses, tool usage, and notifications
- Telegram to CLI: Send prompts from Telegram directly to Claude Code
- Tool Summarizer: Human-readable summaries for 30+ command patterns ("Running tests" instead of "Running: Bash")
- AskUserQuestion Rendering: Inline buttons for Claude's interactive questions
- Photo & Document Upload: Send images/files from Telegram, path injected into Claude
- Stop/Interrupt: Type
stopto send Escape,killto send Ctrl-C - Session Threading: Each Claude session gets its own Forum Topic
- Session Rename:
/renamesyncs with Claude Code's session title - Multi-System Support: Run separate daemons on multiple machines
- Compaction Notifications: Get notified when Claude summarizes context
- Governor Rate Limiting: MessageQueue with retry and exponential backoff
- Doctor Auto-Fix:
ctm doctor --fixauto-remediates common issues - Token Scrubbing: Global regex-based scrubbing prevents bot tokens from leaking to logs
- Atomic PID Locking:
flock(2)prevents duplicate daemon instances - Path Traversal Protection: Transcript paths validated and canonicalized before file access
- Char-Boundary Safe: Unicode-safe message chunking and string truncation throughout
Quick Start
# 1. Install globally
npm install -g claude-telegram-mirror
# 2. Run interactive setup (creates bot, configures everything)
ctm setup
# 3. Start the daemon
ctm start
# 4. Run Claude in tmux
tmux new -s claude
claudeCLI Commands
# Setup & diagnostics
ctm setup # Interactive setup wizard
ctm doctor # Diagnose configuration issues
ctm doctor --fix # Auto-fix detected issues
# Daemon control
ctm start # Start daemon (foreground mode)
ctm stop # Stop running daemon
ctm stop --force # Force stop if graceful shutdown fails
ctm restart # Restart daemon
ctm status # Show daemon status, config, and hooks
ctm config --test # Test Telegram connection
ctm toggle # Toggle mirroring on/off
ctm toggle --on # Force mirroring ON
ctm toggle --off # Force mirroring OFF
# Hook management
ctm install-hooks # Install global hooks
ctm install-hooks -p # Install to current project's .claude/
ctm uninstall-hooks # Remove hooks
ctm hooks # Show hook status
# OS service management (optional, for auto-start on boot)
ctm service install # Install as systemd/launchd service
ctm service uninstall # Remove system service
ctm service start # Start via service manager
ctm service stop # Stop via service manager
ctm service restart # Restart via service manager
ctm service status # Show service statusNote: ctm stop and ctm restart auto-detect whether the daemon is running directly or via a system service and use the appropriate method.
Telegram Commands
| Command | Action |
|---------|--------|
| Any text | Sends to Claude as input |
| stop | Sends Escape to pause Claude |
| kill | Sends Ctrl-C to exit Claude entirely |
| cc <cmd> | Sends /<cmd> as a slash command to Claude |
| /status | Show active sessions and mirroring state |
| /sessions | List active sessions with age and project dir |
| /rename <name> | Rename session (syncs with Claude Code) |
| /attach <id> | Attach to a session for updates |
| /detach | Detach from current session |
| /mute / /unmute | Suppress/resume agent response notifications |
| /toggle | Toggle mirroring on/off |
| /abort | Abort the attached session |
| /ping | Measure round-trip latency |
| /help | Show all commands |
See docs/ARCHITECTURE.md for additional details and command aliases.
Tool Approval Buttons
When Claude requests to use a tool that requires permission (Write, Edit, Bash with non-safe commands), you'll see approval buttons in Telegram:
| Button | Action | |--------|--------| | Approve | Allow the tool to execute | | Reject | Deny this specific tool execution | | Abort | Stop the entire Claude session | | Details | View full tool input parameters |
Approval buttons only appear in normal mode, not with --dangerously-skip-permissions. If you don't respond within 5 minutes, Claude falls back to CLI approval.
Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Claude Code │────▶│ ctm daemon │────▶│ Telegram │
│ CLI │◀────│ (Rust binary) │◀────│ Bot │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
│ hooks │ Unix socket
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ ctm hook │────▶│ Socket Server │
│ (same binary, │◀────│ (bidirectional)│
│ hook mode) │ │ │
└─────────────────┘ └─────────────────┘Flow:
- Claude Code hooks invoke
ctm hook, which reads the event from stdin - PreToolUse: sends approval request via socket, waits for Telegram response
- Other hooks: sends JSON to daemon via socket and exits immediately
- Daemon forwards messages to Telegram Forum Topic with summarized tool actions
- Telegram replies are injected into CLI via
tmux send-keys - Stop/kill commands send Escape or Ctrl-C to interrupt Claude
Multi-System Architecture
When running Claude Code on multiple machines, each system needs its own bot to avoid Telegram API conflicts (error 409: only one polling connection per bot token is allowed).
The model:
- One daemon per host - Each machine runs its own bridge daemon
- One bot per daemon - Each daemon uses a unique Telegram bot
- Multiple sessions per host - One daemon handles all Claude sessions on that machine
- Shared supergroup - All bots post to the same Telegram supergroup
Setup for Multiple Systems
- Create one bot per system via @BotFather
- Add all bots to the same supergroup with admin permissions
- Configure each system with its own bot token:
# On System A (~/.telegram-env) export TELEGRAM_BOT_TOKEN="token-for-system-a-bot" export TELEGRAM_CHAT_ID="-100shared-group-id" # On System B (~/.telegram-env) export TELEGRAM_BOT_TOKEN="token-for-system-b-bot" export TELEGRAM_CHAT_ID="-100shared-group-id" # Same group! - Each daemon creates topics for its sessions - Messages route correctly because each daemon only processes topics it created.
Prerequisites
- Node.js 18+ (for npm installation only)
- Claude Code CLI
- tmux (for bidirectional communication)
- Telegram account
Telegram Setup
1. Create a Bot
- Message @BotFather ->
/newbot - Choose name and username (must end in
bot) - Save the API token
2. Create Supergroup with Topics
- Create a new group in Telegram
- Add your bot to the group
- Group Settings -> Enable Topics
3. Make Bot an Admin
- Group Settings -> Administrators -> Add your bot
- Enable: Manage Topics, Post Messages
4. Get Chat ID
- Send any message in the group
- Visit
https://api.telegram.org/botYOUR_TOKEN/getUpdates - Copy the chat ID (supergroups start with
-100)
5. Disable Privacy Mode
- @BotFather ->
/mybots-> Select bot - Bot Settings -> Group Privacy -> Turn off
Configuration
Environment Variables
Create ~/.telegram-env:
export TELEGRAM_BOT_TOKEN="123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
export TELEGRAM_CHAT_ID="-1001234567890"
export TELEGRAM_MIRROR=true
# Optional:
# export TELEGRAM_MIRROR_VERBOSE=true
# export TELEGRAM_BRIDGE_SOCKET=~/.config/claude-telegram-mirror/bridge.sock
# export TELEGRAM_STALE_SESSION_TIMEOUT_HOURS=72 # Auto-cleanup dead sessions (default: 72)Source in your shell profile (~/.bashrc or ~/.zshrc):
[[ -f ~/.telegram-env ]] && source ~/.telegram-envConfig File (Alternative)
The ctm setup wizard creates ~/.config/claude-telegram-mirror/config.json:
{
"botToken": "your-token",
"chatId": -1001234567890,
"enabled": true,
"verbose": true
}Environment variables take precedence over config file values.
Test Connection
ctm doctor
# Checks: config, hooks, socket, tmux, systemd/launchd, Telegram APIProject-Level Hooks
If your project has .claude/settings.json with custom hooks, global hooks are ignored. Install hooks to the project:
cd /path/to/your/project
ctm install-hooks --projectHow Messages Flow
| Direction | Event | Display | |-----------|-------|---------| | CLI -> Telegram | User types | User (cli): ... | | CLI -> Telegram | Tool starts | Running tests (summarized) | | CLI -> Telegram | Claude responds | Claude: ... | | CLI -> Telegram | Session starts | New Forum Topic created | | CLI -> Telegram | Context compacting | Notification sent | | CLI -> Telegram | AskUserQuestion | Inline buttons rendered | | Telegram -> CLI | User sends message | Injected via tmux | | Telegram -> CLI | User sends photo | Downloaded, path injected | | Telegram -> CLI | User types "stop" | Sends Escape interrupt |
Technical Details
- Binary: Single native Rust executable (
ctm), ~10 MB - Session storage: SQLite at
~/.config/claude-telegram-mirror/sessions.db - Socket path:
~/.config/claude-telegram-mirror/bridge.sock - PID file:
~/.config/claude-telegram-mirror/bridge.pid(flock-guarded) - Downloads:
~/.config/claude-telegram-mirror/downloads/(0700 permissions) - Response extraction: Reads Claude's transcript
.jsonlon Stop event - Deduplication: Telegram-originated messages tracked to prevent echo
- Topic routing: Each daemon only processes topics it created (multi-bot safe)
- Rate limiting: Governor-based with exponential backoff retry queue
- Token scrubbing: All log output filtered through regex to strip bot tokens
- Test suite: 512 Rust tests (unit + 10 integration test files)
Troubleshooting
Run the diagnostic tool first:
ctm doctor
ctm doctor --fix # Auto-fix common issuesCommon Issues
Hooks not firing?
- Check if project has local
.claude/settings.jsonoverriding globals - Run
ctm install-hooks -pfrom project directory - Restart Claude Code after installing hooks
409 Conflict error?
- Only one polling connection per bot token is allowed
- If running multiple systems, each needs its own bot (see Multi-System Architecture)
- Kill duplicate daemons:
ctm stop --force
Bridge not receiving events?
- Check socket:
ls -la ~/.config/claude-telegram-mirror/bridge.sock - Check daemon logs for errors
- Run
ctm statusto verify daemon is running
tmux injection not working?
- Verify tmux session:
tmux list-sessions - Check daemon logs for "Session tmux target stored"
Messages going to wrong topic?
- Clear session DB:
rm ~/.config/claude-telegram-mirror/sessions.db
Service not starting (Linux)?
- Check status:
systemctl --user status claude-telegram-mirror - View logs:
journalctl --user -u claude-telegram-mirror -f - Enable linger:
loginctl enable-linger $USER
Service not starting (macOS)?
- Check status:
launchctl list | grep claude - View logs:
cat ~/Library/Logs/claude-telegram-mirror.*.log
Build from Source
For developers who want to build from source or contribute:
# 1. Clone and build
git clone https://github.com/robertelee78/claude-telegram-mirror.git
cd claude-telegram-mirror/rust-crates
cargo build --release
# Binary at: rust-crates/target/release/ctm
# 2. Run tests
cargo test
# 3. Use the binary directly
./target/release/ctm setup
./target/release/ctm startProject Structure (30 source files)
rust-crates/ctm/src/
main.rs # CLI entry point (clap)
lib.rs # Library re-exports
hook.rs # Hook event processing
config.rs # Configuration loading (env > file > defaults)
error.rs # Centralized error types (thiserror)
types.rs # Shared types, validation, security constants
session.rs # SQLite session management
socket.rs # Unix socket server/client (flock, NDJSON)
injector.rs # tmux input injection
formatting.rs # Message formatting, chunking, ANSI stripping
summarize.rs # Tool action summarizer (30+ patterns)
colors.rs # ANSI color helpers for terminal output
doctor.rs # Diagnostic checks with --fix
installer.rs # Hook installer
setup.rs # Interactive setup wizard
bot/ # Telegram API client (client.rs, queue.rs, types.rs)
daemon/ # Bridge daemon (mod.rs, event_loop.rs, socket_handlers.rs,
# telegram_handlers.rs, callback_handlers.rs, cleanup.rs, files.rs)
service/ # OS service management (mod.rs, systemd.rs, launchd.rs, env.rs)
rust-crates/ctm/tests/ # 10 integration test filesLicense
MIT
Credits
Built for remote Claude Code interaction from mobile devices.
