- Message @BotFather on Telegram
- Send
/newbotand follow prompts - Copy the bot token (looks like
123456789:ABCdef...)
- Message @userinfobot on Telegram
- It will reply with your user ID (a number like
123456789)
Create a docker-compose.yml:
services:
telegram-code:
image: node:20volumes:
# Your project directory
- ./my-project:/workspace:rw# Persist npm global installs (claude, opencode)
- telegram-code-npm:/home/agent/.npm-global# Host configs for git
- ~/.gitconfig:/home/agent/.gitconfig:ro
- ~/.ssh:/home/agent/.ssh:roenvironment:
- HOME=/home/agent
- TELEGRAM_BOT_TOKEN=your-bot-token-here
- ALLOWED_USERS=your-telegram-id
- WORK_DIR=/workspace# Optional: voice transcription
- GROQ_API_KEY=your-groq-key# Optional: for Claude (or set in container)
- ANTHROPIC_API_KEY=your-anthropic-keyworking_dir: /workspacecommand: npx -y telegram-code-botrestart: unless-stoppedvolumes:
telegram-code-npm:docker compose up -dDocker is recommended for environment isolation, but you can run directly:
# Prerequisites: Node.js 20+, tmux (for Claude CLI)# Clone and install
git clone https://github.com/anthropics/telegram-code-bot
cd telegram-code-bot
yarn install
# Set environment variablesexport TELEGRAM_BOT_TOKEN=your-bot-token
export ALLOWED_USERS=your-telegram-id
export WORK_DIR=/path/to/your/project
export ANTHROPIC_API_KEY=your-key # for Claude# Run
yarn startNote: When running without Docker, ensure claude and/or opencode CLI tools are installed and available in PATH.
- Open your bot in Telegram
- Send
/claudeor/opencodeto start a session - Send your coding request
- Use
/stopwhen done
| Agent | Command | Description |
|---|---|---|
| Claude Code | /claude | Anthropic's Claude Code CLI (tmux-based) |
| OpenCode | /opencode or /oc | OpenCode AI agent (HTTP API) |
Switch agents anytime with /agent command.
| Command | Description |
|---|---|
/claude | Start Claude Code session |
/opencode | Start OpenCode session |
/agent | Choose agent (shows buttons) |
/model | Switch model (shows numbered list) |
/sessions | Show previous sessions to resume |
/stop | Stop current session |
/status | Show current status |
/output | Show last 500 lines of output |
/c | Send Ctrl+C (interrupt) |
/y | Send "y" (yes) |
/n | Send "n" (no) |
/enter | Press Enter |
/up / /down | Arrow keys |
/tab | Tab (autocomplete) |
/clear | Delete chat messages |
Start agents by typing phrases like:
- "claude", "claude fix the bug"
- "opencode", "opencode add tests"
| Variable | Required | Description |
|---|---|---|
TELEGRAM_BOT_TOKEN | Yes | From @BotFather |
ALLOWED_USERS | Yes | Comma-separated Telegram user IDs |
WORK_DIR | No | Working directory (default: /workspace) |
DEFAULT_AGENT | No | Default agent: claude or opencode |
GROQ_API_KEY | No | Voice transcription (free, preferred) |
OPENAI_API_KEY | No | Voice transcription (fallback) |
ANTHROPIC_API_KEY | No | For Claude Code |
OPENCODE_URL | No | OpenCode server URL (default: http://localhost:4096) |
OPENCODE_BIN | No | Custom opencode binary path |
Telegram <-> Bot (Node.js) <-> Adapter <-> AI Agent
|
+-> Claude CLI (via tmux)
+-> OpenCode (via HTTP API)
Each AI backend implements the AgentAdapter interface:
startSession()/stopSession()- lifecyclesendInput()/sendSignal()- communicationsetModel()/getAvailableModels()- model selection- Events:
output,closed,error
src/bot.ts- Telegram bot, commands, message handlingsrc/adapters/- Agent adapters (Claude CLI, OpenCode)src/types.ts- AgentAdapter interfacesrc/rateLimiter.ts- Telegram API rate limit handlingsrc/installManager.ts- Auto-install tools
yarn install
yarn dev # Uses tsx watch for hot reload# Restart to apply changes
docker compose restart telegram-code
# Full recreate
docker compose down telegram-code && docker compose up -d telegram-codeyarn dev- Development with hot reloadyarn build- Compile TypeScriptyarn start- Run compiled versionyarn typecheck- Type check
The bot edits messages in place instead of spamming:
- User sends input -> new message created for response
- AI produces output -> same message is updated
- Rapid updates are debounced (1s batching)
Telegram API rate limits (429) are handled automatically:
- Waits for
retry_after+ jitter - Retries once, then marks user as rate-limited
- Skips sends during cooldown period
Claude CLI TUI elements are stripped from output:
- Status lines, borders, spinners
- Tool calls are preserved with status icons (
⏳running,✓done)
Bot not responding:
- Check
TELEGRAM_BOT_TOKENis correct - Verify your user ID is in
ALLOWED_USERS - Check container logs:
docker compose logs telegram-code
Voice messages not working:
- Set
GROQ_API_KEY(free) orOPENAI_API_KEY
Claude not starting:
- Check
ANTHROPIC_API_KEYis set - Verify tmux is installed in container
OpenCode not starting:
- Check if server is running:
/status - OpenCode auto-starts on first use
MIT
