Control your OpenCode server from Telegram. This bot acts as a relay between Telegram and your local OpenCode server, allowing you to prompt OpenCode, manage sessions, approve permissions, and monitor task execution directly from your phone or desktop.
- Local-First: Everything runs on your machine - no cloud, no tunnels, no remote exposure
- Real-time Updates: SSE-based event streaming for instant notifications
- Session Management: Create, list, switch between OpenCode sessions
- Permission Handling: Approve/reject file access and tool execution requests
- Message Queueing: Automatically queues multiple prompts when OpenCode is busy
- Model/Mode Selection: Choose AI providers, models, and modes (build/plan/review)
- File Operations: List files, view content, search code
- Cost Tracking: Monitor token usage and costs per session
# Clone the repository
git clone https://github.com/vineetkishore01/Opencode-Telegram.git
cd Opencode-Telegram
# Install dependencies
npm install
# Build TypeScript
npm run build
# Install globally (may need sudo)
sudo npm install -g .Navigate to any project directory and run:
opencode-teleThe bot will guide you through setup:
-
Telegram Bot Token: Get from @BotFather
- Send
/newbotand follow instructions - Copy the token
- Send
-
Your User ID: Get from @userinfobot
- Message @userinfobot on Telegram
- Copy your numeric user ID
β³ Starting OpenCode server...
β
OpenCode server started on port 4097
π Starting Telegram bot...
π‘ Connecting to OpenCode at http://127.0.0.1:4097
β
Telegram bot started as @yourbot
π± You receive: "π OpenCode is Online π₯"
opencode-tele # Start OpenCode + bot (local-only, no tunnel)
opencode-tele -d /path/to/project # Start in specific directory
opencode-tele -p 5000 # Use different port
opencode-tele --tunnel # Enable Cloudflare tunnel for remote access
opencode-tele --no-server # Connect to existing OpenCode server
opencode-tele --uninstall # Remove project config| Option | Description |
|---|---|
-d, --directory <path> |
Project directory (default: current directory) |
-p, --port <port> |
OpenCode server port (default: 4097) |
--no-server |
Don't start OpenCode, connect to existing server |
--tunnel |
Enable Cloudflare tunnel (default: disabled, local-only) |
--uninstall |
Remove project configuration |
-h, --help |
Show help |
| Command | Description |
|---|---|
/session |
Create a new OpenCode session |
/session <id> |
Select existing session by ID |
/sessions |
List 10 most recent sessions |
/status |
Show current session, model, and mode |
/abort |
Stop the currently running task |
/delete |
Delete current session |
/reset |
Reset relay tracking state |
/clear |
Clear session, model, and mode settings |
| Command | Description |
|---|---|
/providers |
List available AI providers |
/models <provider> |
List models for a provider |
/model <provider> <model> |
Select a specific model |
| Command | Description |
|---|---|
/mode <name> |
Select mode (e.g., build or plan) |
| Command | Description |
|---|---|
/files [path] |
List files in directory |
/file <path> |
View file content |
/find <pattern> |
Search code |
| Command | Description |
|---|---|
/cost |
Show token usage and cost |
/todo |
Show task list |
/diff |
Show file changes |
/help |
Show all commands |
OpenCode provides the LLM with built-in tools that are automatically available during sessions. The bot relays tool events to Telegram in real-time.
| Tool | Icon | Description |
|---|---|---|
bash |
π₯οΈ | Execute shell commands |
edit |
βοΈ | Modify existing files |
write |
π | Create or overwrite files |
read |
π | Read file contents |
grep |
π | Search file contents (regex) |
glob |
π | Find files by pattern |
list |
π | List directory contents |
lsp |
π§ | LSP code intelligence (experimental) |
apply_patch |
π©Ή | Apply patches to files |
skill |
π | Load skill documentation |
todowrite |
π | Manage todo lists |
webfetch |
π | Fetch web content from URLs |
websearch |
π | Search the web (Exa AI) |
question |
β | Ask user questions (MCQs) |
OpenCode supports two web-related tools:
websearch: Performs web searches using Exa AI. Useful for finding current information, researching topics, or gathering information beyond training data. RequiresOPENCODE_ENABLE_EXA=1environment variable or using the OpenCode provider.webfetch: Fetches and reads content from specific URLs. Useful for looking up documentation or retrieving content from known sources.
To enable web search when starting the bot:
OPENCODE_ENABLE_EXA=1 opencode-teleWhen the LLM needs clarification or user input, it can ask questions via the question tool. The bot displays these as inline keyboards with:
- Option buttons for each choice
- A "Skip" button to dismiss the question
- Support for custom answers when no options are provided
Questions are displayed with a β header and the question text.
OpenCode provides the LLM with built-in tools that are automatically available during sessions. The bot relays tool events to Telegram in real-time.
| Tool | Icon | Description |
|---|---|---|
bash |
π₯οΈ | Execute shell commands |
edit |
βοΈ | Modify existing files |
write |
π | Create or overwrite files |
read |
π | Read file contents |
grep |
π | Search file contents (regex) |
glob |
π | Find files by pattern |
list |
π | List directory contents |
lsp |
π§ | LSP code intelligence (experimental) |
apply_patch |
π©Ή | Apply patches to files |
skill |
π | Load skill documentation |
todowrite |
π | Manage todo lists |
webfetch |
π | Fetch web content from URLs |
websearch |
π | Search the web (Exa AI) |
question |
β | Ask user questions (MCQs) |
OpenCode supports two web-related tools:
websearch: Performs web searches using Exa AI. Useful for finding current information, researching topics, or gathering information beyond training data. RequiresOPENCODE_ENABLE_EXA=1environment variable or using the OpenCode provider.webfetch: Fetches and reads content from specific URLs. Useful for looking up documentation or retrieving content from known sources.
To enable web search when starting the bot:
OPENCODE_ENABLE_EXA=1 opencode-teleWhen the LLM needs clarification or user input, it can ask questions via the question tool. The bot displays these as inline keyboards with:
- Option buttons for each choice
- A "Skip" button to dismiss the question
- Support for custom answers when no options are provided
Questions are displayed with a β header and the question text.
- Create session: Send
/session - Send prompt: Just type any message (e.g., "create a todo app")
- Watch progress: Receive real-time updates on thinking, tools, and completion
- Queue messages: If busy, messages auto-queue with position notification
graph TB
User["π€ User (Telegram)"]
Bot["π€ Telegram Bot (grammY)"]
Queue["π¬ Message Queue (Atomic)"]
Client["π OpenCode Client (HTTP/SSE)"]
Server["βοΈ OpenCode Server (localhost)"]
State["πΎ State Manager (JSON)"]
Events["π‘ Event Processor (SSE)"]
Perms["π Permission Handler"]
User -->|"Messages & Commands"| Bot
Bot -->|"Non-command text"| Queue
Queue -->|"Relay prompt"| Client
Client -->|"POST /prompt_async"| Server
Server -->|"SSE /event"| Events
Events -->|"Notifications"| User
Bot -->|"Permission replies"| Perms
Perms -->|"POST /permissions"| Server
Bot -->|"State queries"| State
Events -->|"State updates"| State
sequenceDiagram
participant U as User
participant T as Telegram Bot
participant Q as Message Queue
participant OC as OpenCode Client
participant S as OpenCode Server
participant E as Event Processor
U->>T: Send message
T->>Q: Check busy state
alt Session busy
Q->>T: Queue message (position N)
else Session idle
Q->>T: Send "Working..."
T->>OC: POST /prompt_async
OC->>S: Send prompt
S-->>E: SSE: message.started
E->>U: "OpenCode is working..."
S-->>E: SSE: tool.started (websearch, bash, etc.)
E->>U: Tool notification
S-->>E: SSE: question.asked
E->>U: Question with inline keyboard
U->>T: Select option
T->>OC: POST /question/{id}/reply
OC->>S: Submit answer
S-->>E: SSE: message.completed
E->>U: "β
Done!"
Q->>T: Process next queued message
end
graph LR
subgraph "Telegram Layer"
Cmd["Commands (23)"]
Hdl["Handlers"]
Q["Queue"]
end
subgraph "OpenCode Layer"
Clt["HTTP Client"]
Srv["Server Manager"]
Evts["Event Processor"]
Perm["Permission Handler"]
end
subgraph "State Layer"
State["StateManager"]
Config["Config"]
end
Cmd --> Hdl
Hdl --> Q
Hdl --> Clt
Hdl --> Perm
Evts --> Hdl
Clt --> Srv
State --> Cmd
State --> Hdl
Config --> Clt
| Component | Implementation |
|---|---|
| Event Stream | SSE (Server-Sent Events) - no polling |
| Server Management | Bot starts/stops OpenCode automatically |
| Network | Localhost only - no tunnels, no remote access |
| Message Queue | Atomic enqueue to prevent race conditions |
| Security | Single authorized user, no multi-tenant support |
| Question Handling | Inline keyboards with option buttons + skip |
| Permission Handling | Inline keyboards with Once/Always/Reject |
| Question Handling | Inline keyboards with option buttons + skip |
| Permission Handling | Inline keyboards with Once/Always/Reject |
Stored in .opencode-tele/ per project:
project/
βββ .opencode-tele/
β βββ config.json # Bot token, user ID
β βββ state.json # Sessions, models, modes
β βββ bot.log # Log file
Alternative to config files:
export TELEGRAM_BOT_TOKEN="your-bot-token"
export AUTHORIZED_USER_ID="your-user-id"
export OPENCODE_SERVER_URL="http://127.0.0.1:4097"
export LOG_LEVEL="info"By default, the bot starts OpenCode with --pure flag to disable:
- Push notifications via cloud tunnels
- External plugins
- Remote access features
This ensures everything stays local on 127.0.0.1.
If you need remote access, use the --tunnel flag:
opencode-tele --tunnelThis starts OpenCode without --pure, allowing it to create Cloudflare tunnels for remote access.
--tunnel if you:
- Understand the security implications
- Need remote access from outside your network
- Trust the OpenCode push notification system
Press Ctrl+C to stop:
π΄ Stopping services...
[OpenCode server stopped]
[Telegram bot stopped]
β
Goodbye!
π± You receive: "π΄ OpenCode is going down π₯"
# Use a different port
opencode-tele -p 5000
# Or stop existing server first
lsof -ti:4097 | xargs killnpm install -g opencode-ai
opencode --version # Verify- Check logs:
cat .opencode-tele/bot.log - Verify bot token with @BotFather
- Ensure your user ID matches config
If you see SSE connection failed in logs:
- This is normal if OpenCode doesn't support SSE
- Bot will still work via HTTP requests
- Events won't be real-time but will be processed
# In Telegram
/abort # Stop current task
/clear # Clear session state
/session # Create new sessionLogs written to .opencode-tele/bot.log:
# View logs
tail -f .opencode-tele/bot.log
# Set log level
export LOG_LEVEL=debugLevels: debug | info | warn | error
# Remove global command
sudo npm uninstall -g opencode-tele
# Clean project configs
opencode-tele --uninstall
# Or manually remove
rm -rf .opencode-tele/# Install dependencies
npm install
# Build
npm run build
# Run in development mode
npm run dev
# Type check
npm run typechecksrc/
βββ bot/
β βββ commands.ts # Telegram commands
β βββ handlers.ts # Message handlers
β βββ index.ts # TelegramBot class
β βββ queue.ts # Message queue (atomic operations)
βββ opencode/
β βββ client.ts # HTTP client with SSE
β βββ events.ts # Event processor
β βββ permission.ts # Permission handling
β βββ server.ts # OpenCode server management
βββ state/
β βββ manager.ts # State persistence
βββ utils/
β βββ config.ts # Configuration
β βββ formatter.ts # Telegram formatting
β βββ logger.ts # Logging
βββ types/
β βββ index.ts # TypeScript types
βββ index.ts # CLI entry point
Contributions welcome! Please:
- Open an issue to discuss the change
- Fork and create a PR
- Ensure tests pass
MIT License
- OpenCode - AI coding CLI
- grammy - Telegram Bot framework
- @BotFather - Telegram bot creation