Telegram bot bridge for Claude Code CLI (Rust)
Find a file
Alan 78dbf7b78a
Some checks are pending
CI / Lint & Test (push) Waiting to run
docs: closeout — fix stale session compat note, finalize SESSION_NOTES
2026-07-13 11:07:31 -04:00
.github/workflows ci: install Rust via shell (dtolnay/rust-toolchain not mirrored on Forgejo) 2026-05-05 20:13:44 -04:00
docs docs: closeout — fix stale session compat note, finalize SESSION_NOTES 2026-07-13 11:07:31 -04:00
scripts feat(m1): T10 — canary test + fixture capture script 2026-07-13 01:31:35 -04:00
skills fix: remove hardcoded local path from send.sh 2026-03-01 21:55:38 -05:00
src fix: dogfood bugfixes — absolute paths, allowedTools, outbox for text (0.2.2) 2026-07-13 10:54:11 -04:00
tests feat(m2): steps 9-11 — taskdir integration tests, fmt/clippy gate 2026-07-13 02:08:08 -04:00
.cgcignore chore: add agent charter files and CodeGraphContext ignore 2026-07-09 23:49:37 -04:00
.env.example Initial commit: Rust rewrite of claude-code-telegram bot 2026-02-27 19:06:52 -05:00
.gitignore Initial commit: Rust rewrite of claude-code-telegram bot 2026-02-27 19:06:52 -05:00
AGENTS.md chore: add agent charter files and CodeGraphContext ignore 2026-07-09 23:49:37 -04:00
Cargo.lock chore: bump 0.2.1, CHANGELOG, README for M3 2026-07-13 02:22:23 -04:00
Cargo.toml fix: dogfood bugfixes — absolute paths, allowedTools, outbox for text (0.2.2) 2026-07-13 10:54:11 -04:00
CHANGELOG.md fix: dogfood bugfixes — absolute paths, allowedTools, outbox for text (0.2.2) 2026-07-13 10:54:11 -04:00
CLAUDE.md chore: add agent charter files and CodeGraphContext ignore 2026-07-09 23:49:37 -04:00
CLAUDE.md.example Initial commit: Rust rewrite of claude-code-telegram bot 2026-02-27 19:06:52 -05:00
GEMINI.md chore: add agent charter files and CodeGraphContext ignore 2026-07-09 23:49:37 -04:00
LICENSE Initial commit: Rust rewrite of claude-code-telegram bot 2026-02-27 19:06:52 -05:00
README.md docs: closeout — fix stale session compat note, finalize SESSION_NOTES 2026-07-13 11:07:31 -04:00
TODOS.md docs: add v0.2 design doc, session handoff, and TODO backlog 2026-07-09 23:49:37 -04:00

🤖 claude-code-telegram

CI

A personal AI assistant you can message from anywhere via Telegram. Text your bot, it runs Claude Code, sends back the response.

Rewritten in Rust from the original Python version — single binary, no runtime dependencies, 78x faster startup, 3x less memory.

Features

  • 💬 Text messages — send prompts to Claude Code, get formatted responses
  • 📷 Photo messages — send screenshots or images with optional caption; Claude sees the file
  • 📎 Document messages — send any file (PDF, code, data); filename preserved
  • 📤 File output — Claude can write files to an outbox directory, delivered back as Telegram documents
  • 📁 Project switching/project to list or switch workspaces; per-project sessions persist across restarts
  • 🧠 Session persistence — conversations maintain context across messages, per-project
  • 🎤 Voice messages — transcribe and forward to Claude (optional, --features voice)
  • 📝 Markdown → Telegram HTML — headings, bold, italic, code blocks, links, lists, blockquotes
  • ✂️ Message splitting — long responses split at paragraph boundaries with HTML tag tracking
  • 📤 Send subcommand — send messages from scripts or other Claude sessions
  • ⚙️ Service management — install as systemd/launchd service with auto-restart

🔄 How It Works

📱 Inbound (you → Claude):

Telegram → claude-code-telegram → claude -p "message" → response → Telegram

📢 Outbound (Claude → you):

Claude skill → send.sh / claude-code-telegram send → Telegram API → you

🚀 Quick Start

Prerequisites

Build & Run

# Clone and install
git clone https://codeberg.org/alan090/claude-code-telegram-rs.git
cd claude-code-telegram-rs
cargo install --path .

# Configure
cp .env.example .env
# Edit .env with your bot token and user ID (see Configuration below)

# Run
claude-code-telegram

Note: cargo install places the binary in ~/.cargo/bin/ — outside the source tree, so cargo clean can never accidentally remove it. Prefer this over running from target/release/ for any persistent deployment.

🔧 Configuration

Copy .env.example to .env and set:

Variable Required Description
TELEGRAM_BOT_TOKEN Bot token from @BotFather
TELEGRAM_CHAT_ID For send Your user ID from @userinfobot
ALLOWED_USERS ⚠️ Recommended Comma-separated user IDs (empty = allow all)
CLAUDE_WORKSPACE No Path to workspace with CLAUDE.md (default: $HOME)
CLAUDE_PATH No Path to claude binary (default: claude)
CLAUDE_TIMEOUT_SECS No Task timeout in seconds (default: 1800)
CLAUDE_MODEL No Override Claude model selection
PROJECTS No Comma-separated name=path pairs for project switching
CLAUDE_PROJECTS_ROOT No Directory to scan for git projects (immediate children)

🤖 Getting Your Bot Token

  1. Message @BotFather on Telegram
  2. Send /newbot and follow the prompts
  3. Copy the token into TELEGRAM_BOT_TOKEN

🆔 Getting Your User ID

  1. Message @userinfobot on Telegram
  2. Copy your numeric ID into ALLOWED_USERS and TELEGRAM_CHAT_ID

💬 Usage

Bot Commands

Command Description
/new 🔄 Clear active project's session
/cancel 🛑 Cancel running task (second /cancel abandons stuck tasks)
/status Show user ID, session status, running task, voice support
/project 📁 List registered projects with active one marked
/project <name> 📁 Switch to a project (exact or unique prefix match)
(any text) 🧠 Send to Claude with session context

CLI

# Run the bot (default)
claude-code-telegram
claude-code-telegram run

# Send a message
claude-code-telegram send "Build completed successfully ✅"
claude-code-telegram send --chat-id 12345 "Custom target"

# Install as system service
claude-code-telegram install

# Remove service
claude-code-telegram uninstall

🖥️ Service Management

Linux — the recommended setup uses a system service with EnvironmentFile= so the binary and config are decoupled:

# /etc/systemd/system/claude-telegram-bot.service
[Unit]
Description=Claude Code Telegram Bot
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=alan
ExecStart=/home/alan/.cargo/bin/claude-code-telegram
EnvironmentFile=/path/to/claude-code-telegram-rs/.env
Restart=on-failure
RestartSec=10
Environment=PATH=/home/alan/.local/bin:/usr/local/bin:/usr/bin:/bin

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now claude-telegram-bot
journalctl -u claude-telegram-bot -f

Alternatively, the built-in install subcommand creates a systemd user service:

claude-code-telegram install
systemctl --user status claude-code-telegram
journalctl --user -u claude-code-telegram -f

macOS — creates a launchd agent with auto-restart on failure and network dependency.

🎤 Voice Support

Build with the voice feature to enable voice message transcription via whisper.cpp:

cargo build --release --features voice

Requirements:

  • cmake and a C++ compiler at build time
  • The whisper model (~140MB) is downloaded and cached automatically on first voice message
  • Audio is decoded from OGG/Opus → 16kHz mono PCM → transcribed locally

🔌 Skills

The skills/ directory contains Claude Code skills for automation:

Skill Description
📤 telegram-sender Send messages from Claude Code sessions — notifications, alerts, reminders
🌅 daily-brief Automated morning briefing with weather, news, and quotes

Installing Skills Globally

cp -r skills/telegram-sender ~/.claude/skills/

Once installed, Claude can proactively send you messages:

"Send me a Telegram message when the build finishes"
"Remind me at 3pm to take a break"

📊 Performance

Benchmarked against the Python version on the same machine:

Metric Python Rust Improvement
🚀 Startup time 233 ms 3 ms 78x faster
💾 Idle memory 55 MB 7 MB 8x less
📝 Markdown conversion 1.26 ms 0.05 ms 26x faster
✂️ Message splitting 0.78 ms 0.48 ms 1.6x faster
📦 Deployment size 26 MB (venv) 14 MB (binary) 1.9x smaller
Runtime dependencies Python 3.10+ None Zero deps

🔄 Session Compatibility

Uses ~/.telegram-claude-sessions.json. The v0.2.1 session schema (v2: per-project sessions) is not backwards-compatible with the Python version. On first run, v1 files are migrated automatically and backed up to .v1.bak.

🔒 Security

⚠️ ALLOWED_USERS is critical

Always set ALLOWED_USERS in your .env file. If left empty, anyone who discovers your bot's username can send it messages and run Claude with full tool access on your machine.

🛠️ Tool access

The bot runs Claude with these tools enabled:

Read · Write · Edit · Bash · Glob · Grep · WebFetch · WebSearch · Task · Skill

This is powerful and intentional for a personal assistant, but understand that messages you send can trigger real actions on your system.

🔑 Protect your tokens

  • 🚫 Never commit .env (already in .gitignore)
  • 🤖 Your bot token lets anyone impersonate your bot
  • 💬 Your chat ID lets anyone send you messages via the bot

📁 Session file

Sessions are stored in ~/.telegram-claude-sessions.json. On shared systems:

chmod 600 ~/.telegram-claude-sessions.json

📁 Project Structure

claude-code-telegram-rs/
├── src/
│   ├── main.rs          # CLI entry (clap): run, send, install, uninstall
│   ├── config.rs         # .env loading + Config struct
│   ├── error.rs          # thiserror Error enum
│   ├── bot.rs            # teloxide dispatcher + handler wiring
│   ├── handlers.rs       # /new, /cancel, /status, /project, text, voice, photo, document handlers
│   ├── project.rs        # Project registry (PROJECTS env, CLAUDE_PROJECTS_ROOT scan)
│   ├── claude.rs         # Claude CLI NDJSON streaming parser + subprocess
│   ├── task.rs           # Task registry, spawn/kill discipline, progress watch
│   ├── taskdir.rs        # Per-task inbox/outbox directory lifecycle
│   ├── lib.rs            # Library crate root (integration test access)
│   ├── session.rs        # Session file read/write (Python-compatible, quarantine)
│   ├── markdown.rs       # comrak AST → Telegram-safe HTML
│   ├── message.rs        # Message splitting with HTML tag tracking
│   ├── voice.rs          # whisper-rs transcription (feature-gated)
│   └── service.rs        # systemd/launchd install/uninstall
├── skills/
│   ├── telegram-sender/  # Send messages from Claude sessions
│   └── daily-brief/      # Morning briefing skill
├── tests/
│   ├── kill_path.rs      # Integration tests: kill discipline, retry
│   ├── taskdir_tests.rs  # Integration tests: task dir lifecycle, outbox
│   ├── add_dir_spike.rs  # Permission spike: --add-dir flag (#[ignore])
│   ├── canary.rs         # CLI canary test (#[ignore])
│   ├── bin/fake-claude.sh # Fake CLI for integration tests
│   └── fixtures/         # NDJSON test fixtures
├── scripts/
│   └── capture-fixture.sh # Regenerate NDJSON fixtures from CLI
├── .env.example
├── CLAUDE.md.example     # Template for your Claude workspace
└── LICENSE

📄 License

GPL-3.0-or-later — see LICENSE