A standalone bot that mirrors OpenCode sessions to Telegram topics, enabling collaborative AI-assisted coding conversations in Telegram.
| Feature | Description |
|---|---|
| 📱 Real-time Streaming | Live responses with typing indicators, markdown, code blocks, and inline diffs |
| 🎯 Interactive Controls | Buttons for questions, permissions, mode switching, and session control |
| 📋 Slash Commands | /interrupt, /plan, /build, /review, /rename for quick actions |
| 🔍 Diff Viewer | Automatic diff generation with syntax highlighting and shareable links |
| 📸 Media Support | Send images and voice messages (transcribed via Whisper) as prompts |
| 🧵 Thread Support | Telegram forum threads with automatic title sync from OpenCode sessions |
| 💾 Session Persistence | Resume sessions across devices and restarts |
| 🔄 Multi-instance | Run multiple mirrors for different sessions/channels |
npm install -g opencode-telegram-mirror-
Create a Telegram Bot:
- Message @BotFather on Telegram
- Send
/newbotand follow instructions - Copy your bot token
-
Get your Chat ID:
- Message @userinfobot
- Copy your chat ID
-
Configure environment variables:
export TELEGRAM_BOT_TOKEN="your-bot-token" export TELEGRAM_CHAT_ID="your-chat-id" # Optional: export TELEGRAM_THREAD_ID="your-thread-id"
-
Run the mirror in your project:
opencode-telegram-mirror .
That's it! Your OpenCode session will now be mirrored to Telegram.
The Telegram mirror streams OpenCode session interactions (questions, answers, tool usage, and file edits) to Telegram topics. This enables:
- Collaborative coding: Share your coding sessions with team members
- Remote pair programming: Get real-time feedback on your code
- Session persistence: Keep conversations going across devices
- Rich formatting: Code blocks, diffs, and interactive buttons
Each instance of the opencode-telegram-mirror binary mirrors one OpenCode session to one Telegram channel/thread. This 1:1 mapping ensures clean separation between different coding conversations.
OpenCode Server Connection:
- Without
OPENCODE_URL: The mirror spawns its own OpenCode server instance locally - With
OPENCODE_URL: The mirror connects to an existing OpenCode server at the specified URL
This flexibility allows you to either run self-contained mirrors (each with their own server) or connect to a shared/managed OpenCode server.
Telegram supports threaded conversations in forum-style channels:
- No thread ID: Messages go to the main channel
- With thread ID: Messages go to a specific topic thread within a forum channel
Each mirror instance should be configured with a unique TELEGRAM_THREAD_ID to prevent cross-contamination between different coding sessions.
While you can run a single mirror instance, production deployments typically require orchestration to support multiple concurrent sessions:
- Multiple sessions: Run separate mirror processes for different coding projects
- Thread isolation: Use unique thread IDs per session
- Server sharing: Point multiple mirrors to the same
OPENCODE_URLfor resource efficiency - Load balancing: Distribute mirrors across multiple servers
Example orchestration might involve:
- Docker containers for each mirror instance
- Kubernetes deployments with unique environment configs
- Process managers like PM2 for local deployment
Single Instance (Simple Case):
If you're running one opencode-telegram-mirror instance with one Telegram bot and one channel, you don't need TELEGRAM_UPDATES_URL. The mirror will poll Telegram's API directly using getUpdates.
Multi-Instance Deployments:
When running multiple mirror instances (e.g., one per coding session or per team), Telegram only allows one webhook or one getUpdates poller per bot. To support multiple mirrors:
- Central Updates Collector: Deploy a central service that polls
getUpdatesonce and distributes updates to multiple mirrors - Set
TELEGRAM_UPDATES_URL: Point each mirror to this central endpoint - Thread Isolation: Each mirror should have a unique
TELEGRAM_THREAD_ID
Updates URL API Contract: The central updates endpoint must accept GET requests with query parameters:
since: Last processedupdate_id(for pagination)chat_id: Filter updates to specific chatthread_id: Filter to specific thread (optional)
Response format (JSON):
{
"updates": [
{
"payload": {
"update_id": 123,
"message": {
"message_id": 456,
"message_thread_id": 789,
"date": 1640995200,
"text": "Hello world",
"from": { "id": 123456, "username": "user" },
"chat": { "id": -1001234567890 }
}
},
"update_id": 123
}
]
}The payload contains the standard Telegram Update object. Basic authentication is supported via URL credentials (https://user:[email protected]/updates).
opencode-telegram-mirror [directory] [session-id]directory: Working directory (defaults to current directory)session-id: Existing OpenCode session ID to resume
| Variable | Description | Required |
|---|---|---|
TELEGRAM_BOT_TOKEN |
Bot token from @BotFather | Yes |
TELEGRAM_CHAT_ID |
Chat ID from @userinfobot | Yes |
TELEGRAM_THREAD_ID |
Thread/topic ID for forum channels | No |
TELEGRAM_UPDATES_URL |
Central updates endpoint for multi-instance deployments | No |
TELEGRAM_SEND_URL |
Custom Telegram API endpoint (defaults to api.telegram.org) | No |
OPENCODE_URL |
External OpenCode server URL (if not set, spawns local server) | No |
OPENAI_API_KEY |
OpenAI API key for voice message transcription (Whisper) | No |
The bot loads configuration from (in order of priority):
- Environment variables (highest priority)
~/.config/opencode/telegram.json<repo>/.opencode/telegram.json
Example config file:
{
"botToken": "your-bot-token",
"chatId": "your-chat-id",
"threadId": 123,
"sendUrl": "https://api.telegram.org/bot",
"updatesUrl": "https://your-durable-object-endpoint"
}Send messages in Telegram to interact with OpenCode:
- Text messages: Sent as prompts to OpenCode
- Photos: Attached as image files to prompts
- Voice messages: Transcribed via OpenAI Whisper and sent as text prompts
- "x": Interrupt the current session
- /connect: Get the OpenCode server URL
- /interrupt: Stop the current operation
- /plan: Switch to plan mode
- /build: Switch to build mode
- /review: Review changes (accepts optional argument: commit, branch, or pr)
- /rename
<title>: Rename the session and sync to Telegram thread
Session titles are automatically synchronized between OpenCode and Telegram:
- On startup: If resuming an existing session, the thread title syncs from the session
- On auto-title: When OpenCode generates a title, it updates the Telegram thread
- On /rename: Manually set a title that updates both OpenCode and Telegram
Voice messages are transcribed using OpenAI's Whisper API. To enable:
- Get an API key from OpenAI Platform
- Set
OPENAI_API_KEYin your environment - Send voice messages to the bot - they'll be transcribed and sent to OpenCode
If OPENAI_API_KEY is not set, the bot will respond with setup instructions when a voice message is received.
The bot provides inline keyboard controls for:
- Interrupt: Stop the current session
- Mode switching: Toggle between "plan" and "build" modes
- Questions: Answer multiple-choice questions from OpenCode
- Permissions: Grant/deny file access permissions
When OpenCode makes file edits, the bot:
- Generates a visual diff
- Uploads it to a diff viewer
- Shares a link to view the changes
- Node.js 18+
- npm or bun
# Clone the repo
git clone <repository-url>
cd opencode-telegram-mirror
# Install dependencies
bun install
# Run in development
bun run start
# Run tests
bun run test:run# Type check
bun run typecheck
# Run mock server for testing
bun run test:mock-server- Cross-platform: Works on any device with Telegram
- Instant sync: Real-time message delivery
- Rich formatting: Markdown, code blocks, and media support
- Free: No rate limits or costs
- Persistent: Message history is always available
[Add your license here]