OMOTG β Telegram β OpenCode Bridge
OMOTG is a Go-based bidirectional bridge that connects Telegram to OpenCode via an MCP SSE server and Telegram webhook. It allows you to interact with OpenCode directly from Telegram.
Features
- π€ Telegram Bot β Send messages to OpenCode and get responses via Telegram
- π MCP SSE Server β Exposes Telegram tools (
send_message,send_notification) to any MCP client (including OpenCode itself) - π¦ Zero Dependencies β Pure Go standard library, no external packages
- π€ Multi-Bot Multi-Agent β Run N Telegram bots in one binary, each routing to a different OMO agent (Sisyphus, Prometheus, Atlas, Hephaestus)
- π Secure β Secret token verification, chat ID whitelist, TLS cert for webhook (or plain HTTP behind a reverse proxy)
- π§΅ Session Management β Thread-safe multi-session store with per-chat and per-topic routing; sessions persist until explicitly deleted. Session bindings survive server restarts via JSON persistence.
- π¬ Group & Forum Topics β Supports Telegram supergroup forum topics;
/topic newcreates a dedicated topic + OpenCode session - π€ Bot Persona β Reads bot name & description from Telegram for personalized welcome messages
- π Systemd Integration β Ships with systemd user service files for auto-start
Prerequisites
| Requirement | Version | Notes |
|---|---|---|
| Go | 1.26+ | For building from source |
| OpenCode CLI | latest | For opencode serve backend |
| systemd | any | User-mode services (logind) |
| OpenSSL | any | Required only for standalone TLS (or use a reverse proxy) |
| Linux | any | Tested on Ubuntu |
| Homebrew | latest | Optional β for installing via brew install omotg |
Installation
Option 1: Homebrew (recommended)
brew tap itokun99/omotg
brew install omotg
This installs the binary to $(brew --prefix)/bin/omotg and the env template to $(brew --prefix)/etc/omotg/env.template.
Option 2: Go Install (global binary)
go install github.com/itokun99/omotg@latest
This installs the omotg binary to $(go env GOPATH)/bin/omotg. Make sure
$(go env GOPATH)/bin is in your PATH.
Option 3: Build from Source
git clone [email protected]:itokun99/omotg.git
cd omotg
go build -o omotg .
sudo cp omotg /usr/local/bin/ # optional, for system-wide install
Or install directly to your local bin:
go build -o ~/.local/bin/omotg/omotg .
2. TLS Certificate (optional)
Telegram webhook requires HTTPS. You have two options:
Option A: Reverse proxy (recommended for production)
Place OMOTG behind a reverse proxy (Traefik, Caddy, Nginx) with Let's Encrypt. Set
both OMOTG_TLS_CERT_FILE= and OMOTG_TLS_KEY_FILE= to empty in your env file to
start the webhook server in plain HTTP mode. The proxy handles HTTPS termination.
Option B: Self-signed certificate (standalone)
mkdir -p ~/.config/omotg
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ~/.config/omotg/webhook.key \
-out ~/.config/omotg/webhook.crt \
-subj "/CN=your-domain.com" \
-addext "subjectAltName=DNS:your-domain.com"
Replace your-domain.com with your actual domain pointing to your server.
3. Create Environment Config
cp env.template ~/.config/omotg/env
# Then edit with your values:
# TELEGRAM_BOT_TOKEN β from @BotFather
# TELEGRAM_WEBHOOK_URL β https://your-domain.com/webhook (or :8443/webhook for standalone)
# TELEGRAM_SECRET_TOKEN β any random string
# OPENCODE_SERVER_PASSWORD β any string (opencode serve on localhost ignores auth)
#
# For reverse proxy mode, also set:
# OMOTG_TLS_CERT_FILE=
# OMOTG_TLS_KEY_FILE=
See Configuration for all options.
4. Set Up systemd Services
Copy the systemd service files:
mkdir -p ~/.config/systemd/user
opencode-serve.service β starts OpenCode headless server:
[Unit]
Description=OpenCode Headless Server (Serve)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/path/to/opencode serve --port 4096
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=default.target
omotg.service β starts the OMOTG bridge:
[Unit]
Description=OMOTG β Telegram β OpenCode bridge
After=network-online.target opencode-serve.service
Wants=network-online.target
BindsTo=opencode-serve.service
[Service]
Type=simple
ExecStart=/path/to/omotg
Restart=on-failure
RestartSec=5
EnvironmentFile=%h/.config/omotg/env
NoNewPrivileges=true
ProtectHome=read-only
ProtectSystem=full
PrivateTmp=true
[Install]
WantedBy=default.target
Then enable and start:
systemctl --user daemon-reload
systemctl --user enable opencode-serve omotg
systemctl --user start opencode-serve omotg
Configuration
Configuration is via environment variables in ~/.config/omotg/env:
Required
| Variable | Description |
|---|---|
TELEGRAM_BOT_TOKEN |
Bot token from @BotFather |
TELEGRAM_WEBHOOK_URL |
Public HTTPS URL for Telegram webhook (e.g. https://your.domain/webhook or https://your.domain:8443/webhook) |
TELEGRAM_SECRET_TOKEN |
Custom secret string to verify webhook requests |
OPENCODE_SERVER_PASSWORD |
Password for OpenCode API (opencode serve on localhost ignores auth, but field is required) |
Optional
| Variable | Default | Description |
|---|---|---|
OPENCODE_SERVER_URL |
http://127.0.0.1:4096 |
OpenCode serve URL |
OMOTG_WEBHOOK_PORT |
8443 |
Webhook listen port |
OMOTG_MCP_PORT |
9090 |
MCP SSE server port |
OMOTG_ALLOWED_CHAT_IDS |
(empty = all allowed) | Comma-separated Telegram chat IDs |
OMOTG_SESSION_TIMEOUT |
300 |
Session timeout in seconds |
OMOTG_TLS_CERT_FILE |
~/.config/omotg/webhook.crt |
TLS certificate path (empty = plain HTTP, for reverse proxy mode) |
OMOTG_TLS_KEY_FILE |
~/.config/omotg/webhook.key |
TLS key path (empty = plain HTTP, for reverse proxy mode) |
OMO_PROMETHEUS_BOT_TOKEN |
(none) | Auxiliary bot token β routes to Prometheus agent (/webhook/prometheus) |
OMO_ATLAS_BOT_TOKEN |
(none) | Auxiliary bot token β routes to Atlas agent (/webhook/atlas) |
OMO_HEPHAESTUS_BOT_TOKEN |
(none) | Auxiliary bot token β routes to Hephaestus agent (/webhook/hephaestus) |
Multi-Bot Routing
OMOTG can run multiple Telegram bots simultaneously, each bound to a different OMO agent:
| Bot Key | Env Var | Routes To | Webhook Path |
|---|---|---|---|
| Primary | TELEGRAM_BOT_TOKEN |
Sisyphus β ultraworker | /webhook |
| Prometheus | OMO_PROMETHEUS_BOT_TOKEN |
Prometheus β Plan Builder | /webhook/prometheus |
| Atlas | OMO_ATLAS_BOT_TOKEN |
Atlas β Plan Executor | /webhook/atlas |
| Hephaestus | OMO_HEPHAESTUS_BOT_TOKEN |
Hephaestus β Deep Agent | /webhook/hephaestus |
- The primary bot (
TELEGRAM_BOT_TOKEN) is required β it maps to Sisyphus for backward compatibility. - Auxiliary bots are optional β set only the
OMO_*_BOT_TOKENvars for the agents you want. - Each auxiliary bot gets its own webhook path (
/webhook/<key>) with its own Telegram webhook registration. - Bot sessions are isolated β each bot has its own
SessionMap.
To add an auxiliary bot, set its token and register the webhook via @BotFather:
https://your.domain.com/webhook/prometheus
Note: Hephaestus is configured but requires an upstream OpenCode server fix (server-side
UnknownErroras of 2026-06-22). Enable once resolved.
Usage
Telegram Commands
| Command | Description |
|---|---|
/start |
Welcome message |
/help |
Show available commands |
/status |
Check server status via OpenCode |
/deploy <env> |
Deploy application to environment |
/logs [N] |
Show last N lines of server logs (default: 50) |
/session |
Show current session info |
/session new [text] |
Create a new session (optionally with first prompt) |
/session list |
List all sessions |
/session switch <id> |
Switch to a different session |
/session delete <id> |
Delete a session |
/topic new <nama> |
Create a new forum topic with bound session (group only) |
/topic close |
Close the current forum topic (group only) |
/topic delete |
Permanently delete the current forum topic (group only) |
Any non-command message is forwarded to OpenCode using the current session.
Group & Forum Topics
OMOTG supports Telegram supergroup forum topics. Conversations are routed as follows:
- Message in a topic β OMOTG replies in the same topic thread, using the session bound to that topic
- Message in General β OMOTG replies in General using the group's default session
- Private chat β works as before, with persistent session
To create a dedicated workspace, use /topic new <nama> β this creates a new forum topic and binds a fresh OpenCode session to it. Use /topic close or /topic delete to clean up the topic and its session.
Each OpenCode session maps to one topic, keeping conversations organized in busy groups.
MCP Tools
Available via the MCP SSE server at http://127.0.0.1:9090/mcp/sse:
| Tool | Description |
|---|---|
send_message |
Send a text message to a Telegram chat |
send_notification |
Send a notification to a Telegram chat |
OpenCode MCP Integration
Add to your OpenCode config (~/.config/opencode/opencode.json):
{
"mcp": {
"omotg": {
"type": "remote",
"url": "http://127.0.0.1:9090/mcp/sse"
}
}
}
Architecture
Standalone TLS
Telegram App Server (VPS) OpenCode CLI
β β β
β POST /webhook β β
β βββββββββββββββββββββ omotg (port 8443, TLS) β
β β β β
β β β POST /session β
β β β POST /session/{id}/msg β
β β β DELETE /session/{id} β
β β βββββββββββββββββββββββββ opencode serve
β β β (port 4096)
β β β
β sendMessage β β
β βββββββββββββββββββββ omotg (sync response) β
β β β β
β β β MCP SSE endpoint β
β β β http://127.0.0.1:9090 β
β β β β
β β β βββ MCP tools ββββββ OpenCode
Behind Reverse Proxy (recommended)
Telegram App Server (VPS) OpenCode CLI
β β β
β POST /webhook β β
β βββββββββββββββββββββ Traefik (port 443, Let's Encrypt) β
β β β β
β β β http://172.17.0.1:8443 β
β β β β
β β omotg (plain HTTP) β
β β β β
β β β POST /session β
β β β POST /session/{id}/msg β
β β β DELETE /session/{id} β
β β βββββββββββββββββββββββββββββββββ opencode serve
β β β (port 4096)
β β β
β sendMessage β β
β βββββββββββββββββββββ omotg (sync response) β
β β β β
β β β MCP SSE endpoint β
β β β http://127.0.0.1:9090 β
β β β β
β β β βββ MCP tools ββββββββββββββ OpenCode
Ports
| Port | Service | Bind | Protocol |
|---|---|---|---|
| 8443 | OMOTG Webhook | 0.0.0.0 |
HTTPS (TLS) or plain HTTP behind proxy |
| 9090 | OMOTG MCP SSE | 127.0.0.1 |
HTTP/SSE |
| 4096 | OpenCode Serve | 127.0.0.1 |
HTTP/REST |
Uninstall
Via Homebrew
brew uninstall omotg
brew untap itokun99/omotg
Then proceed to steps 1β3 below to clean up services & config.
Manual
1. Stop & Disable Services
systemctl --user stop omotg opencode-serve
systemctl --user disable omotg opencode-serve
2. Remove Service Files
rm ~/.config/systemd/user/omotg.service
rm ~/.config/systemd/user/opencode-serve.service
systemctl --user daemon-reload
3. Unregister Telegram Webhook
curl -X POST "https://api.telegram.org/bot<YOUR_TOKEN>/deleteWebhook"
4. Remove Binary & Config
# If installed via Homebrew:
rm -rf ~/.config/omotg
# If installed from source:
rm -rf ~/.local/bin/omotg
rm -rf ~/.config/omotg
5. Remove OpenCode MCP Config (optional)
Edit ~/.config/opencode/opencode.json and remove the omotg entry from the mcp section.
Troubleshooting
Webhook: "Connection refused" in getWebhookInfo
This is normal if OMOTG was stopped. Start the service:
systemctl --user start omotg
"OpenCode server is not available"
OpenCode serve is not running:
systemctl --user status opencode-serve
systemctl --user start opencode-serve
Checking Logs
# OMOTG logs
journalctl --user -u omotg -f
# OpenCode serve logs
journalctl --user -u opencode-serve -f
Security Notes
- For standalone mode, the webhook server uses a self-signed certificate. For production, use a reverse proxy (Traefik/Caddy/Nginx) with Let's Encrypt and set
OMOTG_TLS_CERT_FILE=andOMOTG_TLS_KEY_FILE=to empty to disable internal TLS. - In reverse proxy mode, OMOTG binds to
0.0.0.0with plain HTTP. Ensure your proxy is the only publicly reachable endpoint and that the proxy port is firewalled. - The MCP server binds to
127.0.0.1only β not accessible from the network. - Chat ID whitelist is highly recommended. Without it, anyone who finds your bot can interact with OpenCode.
- The secret token verifies that webhook requests are genuinely from Telegram.
- OpenCode serve on localhost does not enforce authentication; keep it bound to 127.0.0.1.
License
CC BY-NC 4.0 β Attribution-NonCommercial 4.0 International
Copyright (c) 2026 Indrawan Lisanto
You are free to share and adapt this software for non-commercial purposes only, provided you give appropriate credit. Commercial use is strictly prohibited without explicit permission.
See LICENSE for full terms.
No comments yet
Be the first to share your take.