English | 简体中文
imtty is a personal Telegram bridge for controlling local Codex sessions from any Telegram client.
It keeps Codex running on your own machine, inside tmux, and sends prompts, approvals, media, and final answers through Telegram. It is built for a single owner who wants remote access to the normal Codex workflow without exposing a raw shell or turning the project into an autonomous agent platform.
- Telegram webhook bridge for a single owner
tmux-backed Codex sessions namedcodex-{project}- Codex
app-serverintegration with structured event output - final-answer-first Telegram replies with terminal noise suppressed
- explicit human approval flow with full Telegram text prompts and manual replies
- project whitelist with dynamic add/remove commands
- session reattach after bridge restart
- local desktop attach protection for writable
tmuxclients - Telegram Mini App companion UI for session and project control
- image input from Telegram
photoand imagedocument - text/code/PDF document analysis through temporary local files
- optional Telegram
voicetranscription through localffmpegandwhisper.cpp
imtty is intentionally not:
- a hosted service
- a multi-user system
- an agent orchestrator
- a generic remote shell
- a web admin dashboard
- a file sync or long-term media storage service
Telegram -> imtty bridge -> tmux session -> Codex app-server
|
+-> Telegram Mini App
Core rules:
- Telegram is the primary IM entrypoint.
tmuxis the only session backend.- Codex must run inside the
tmuxsession. - Telegram output comes from Codex structured events, not terminal screen scraping.
- One Telegram chat can bind to one active session at a time.
- Multiple project sessions can exist at the same time.
- Codex approvals are never auto-confirmed by the bridge.
Verified local baseline:
- macOS
- Go
1.26.1 tmux 3.6acodex-cli 0.125.0- Telegram bot token
- public HTTPS webhook URL, for example through Cloudflare Tunnel
Optional voice input:
ffmpegwhisper.cppwhisper-cli- local GGML whisper model
cp config.toml.example config.tomlEdit at least:
telegram_bot_token = "BOT_TOKEN"
telegram_webhook_secret = "SECRET"
telegram_owner_id = 123456789
mini_app_base_url = "https://imtty.example.com"
[projects]
demo = "/absolute/path/to/your/project"config.toml is ignored by git. Commit config.toml.example, not your local config.
go run ./cmd/imtty-bridgeFor a sandbox-friendly local build cache:
GOCACHE=/tmp/imtty-go-build go run ./cmd/imtty-bridgeHealth check:
curl -s http://127.0.0.1:8080/healthzA named Cloudflare Tunnel is the recommended long-running setup:
cloudflared tunnel login
cloudflared tunnel create imtty
cloudflared tunnel route dns imtty imtty.example.com
cloudflared tunnel run imttyExample ~/.cloudflared/config.yml:
tunnel: imtty
credentials-file: /Users/<you>/.cloudflared/<tunnel-id>.json
ingress:
- hostname: imtty.example.com
service: http://127.0.0.1:8080
- service: http_status:404Set the Telegram webhook:
curl -X POST "https://api.telegram.org/bot${IMTTY_TELEGRAM_BOT_TOKEN}/setWebhook" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://imtty.example.com/telegram/webhook",
"secret_token": "'"${IMTTY_TELEGRAM_WEBHOOK_SECRET}"'"
}'Verify:
curl -s "https://api.telegram.org/bot${IMTTY_TELEGRAM_BOT_TOKEN}/getWebhookInfo"
curl -s http://127.0.0.1:8080/healthz/projects
/open demo
hello
Voice input is disabled by default. Enable it only after configuring local transcription:
[voice]
enabled = true
ffmpeg_bin = "ffmpeg"
whisper_bin = "/opt/whisper.cpp/build/bin/whisper-cli"
model_path = "/opt/whisper.cpp/models/ggml-large-v3-turbo.bin"
language = "zh"Behavior:
- Telegram
voicefiles are downloaded to a local temp directory. ffmpegconverts the audio to 16 kHz mono WAV.whisper.cpptranscribes the audio locally.- The transcript is submitted to the current active Codex session as plain text.
- The bridge does not keep long-term voice files.
Voice input does not implement voice commands, voice approvals, speaker diarization, long-audio jobs, or multi-message merging.
/list
/projects
/project_add <name> <abs-path>
/project_remove <name>
/open <project> [thread-id]
/close
/kill
/clear
/status
/model [model-id]
/reasoning [effort]
/plan_mode [default|plan]
The Mini App is a lightweight companion UI inside Telegram. It supports:
- current active session view
- session list
- project list
- open / close / kill controls
- project add / remove
- host-side directory browser for selecting project roots
It does not replace the Telegram chat, live terminal output, prompt entry, or Codex approval flow.
The frontend lives in web/mini-app/. Built assets are checked in under web/mini-app/dist/ so the Go bridge can serve them directly.
Run all Go tests:
GOPATH=/tmp/imtty-go GOMODCACHE=/tmp/imtty-go/pkg/mod GOCACHE=/tmp/imtty-go-build go test ./...Build the Mini App:
cd web/mini-app
npm install
npm run build- Only whitelisted projects can be opened.
- Telegram webhook requests must include the configured secret token.
- Mini App requests must pass Telegram
initDatavalidation and owner checks. - Images, documents, and voice files are stored only as temporary local files.
- The bridge refuses Telegram writes and
/killwhen the sametmuxsession has a writable local desktop attach. - The bridge never auto-approves Codex permission prompts.