telegram-codex-bridge is a Go service that turns Telegram private chats and forum topics into a conversational front end for local coding-agent threads. Codex remains the primary backend, and Gemini CLI is available as an alternate provider.
Release history: CHANGELOG.md
- Telegram long polling over the Bot API
- User/chat allowlists
chat_id + topic_id -> Codex session_idrouting in SQLite- Persistent Telegram update offsets across restarts
- Auto-create a Codex thread on the first normal message in a chat or topic
- Auto-create and bind a dedicated workspace subdirectory for each new chat/topic thread
- Auto-resume the same Codex thread on later messages
- Codex
app-serveras the primary adapter, with CLI fallback when needed - Optional Gemini CLI backend for manual provider switching when Codex is unavailable or quota-limited
- Automatic Codex -> Gemini fallback for fresh thread creation when Codex is quota-limited or temporarily unavailable
- Topic-aware control commands:
/help,/where,/version,/status,/limit,/lang,/provider,/model,/think,/speed,/permission,/threads,/new,/archive,/delete - Telegram forum topic lifecycle sync for create/edit/close/reopen messages
- Telegram native
typingstatus while Codex is working; only final Codex output is sent as message text - Per-topic timing stats for new-thread and resume-thread runs
- Localized zh/en Telegram responses, plus a per-topic
/lang auto|zh|enoverride - Official
turn/steerfollow-up steering when an app-server turn is active - Telegram attachment input for photos, documents, voice notes, and audio files
- Automatic download of incoming attachments into the bound topic workspace
- Image attachments forwarded to Codex as native image inputs
- Document, voice, and audio attachments forwarded to Codex with saved file paths and caption context
- Automatic return of generated images, audio files, and common document outputs back to Telegram
- macOS
launchdmanagement through the unifiedtelegram-codex-bridgebinary - Linux
systemd --usermanagement through the same unifiedtelegram-codex-bridgebinary - macOS menu bar app with first-run setup, configurable UI language, quota display, restart, logs, and auto-start toggle
- GitHub Actions workflow for tests, release archives, and macOS app artifacts
- One Telegram private chat maps to one Codex thread
- One Telegram forum topic maps to one Codex thread
- The first thread for a chat/topic gets its own workspace folder under
CODEX_WORKSPACE_ROOT - Later runs in the same chat/topic keep reusing that same workspace folder
- Codex runs inside the per-topic folder but is additionally allowed to access the parent project root for cross-thread collaboration when needed
- Routing is keyed by
chat_id + topic_id - Private chat
topic_id=0and grouptopic_id=0do not conflict becausechat_idis part of the key
telegram-codex-bridge/
├── bin/ # built binaries
├── cmd/bridge/ # unified bridge + management entrypoint
├── docs/ # architecture, macOS, and Linux operation notes
├── internal/app/ # orchestration and message queueing
├── internal/control/ # cross-platform management subcommands
├── internal/codex/ # Codex app-server adapter, CLI fallback, and stream parsing
├── internal/config/ # env/config parsing
├── internal/macos/ # launchd helpers
├── internal/service/ # launchd/systemd service adapters
├── internal/store/ # SQLite topic-thread mapping
├── internal/telegram/ # Telegram transport
├── macos/BridgeStatusBarApp/ # menu bar app source
└── scripts/ # build helpers
- Copy
.env.exampleto.env. - Fill in your Telegram bot token, allowed ids, and workspace path.
- Optional: set
BRIDGE_LANGUAGE=auto|zh|enfor the default UI/system-message language. - Optional: set
CODEX_PROVIDER=codex|geminito choose the backend CLI. - Optional: when
CODEX_PROVIDER=codex, setCODEX_ADAPTER=auto|app-server|clito choose the Codex adapter. - Optional: set
CODEX_PERMISSION_MODE=default|full-accessfor the default execution permission. - Optional: when
CODEX_PROVIDER=gemini, setGEMINI_DEFAULT_MODELandGEMINI_MODELSto control the/modelmenu. - Optional: set
BRIDGE_LOG_LEVEL=info|debug, plusBRIDGE_LOG_MAX_SIZE_MBandBRIDGE_LOG_MAX_BACKUPSfor rotating logs. - Optional: set
BRIDGE_PREVENT_SLEEP=true|falseto keep the computer awake while the active backend is processing a task. - Run the bridge:
go run ./cmd/bridgeBuild the binaries and menu bar app:
./scripts/build-macos-app.shThis produces:
bin/telegram-codex-bridgedist/Telegram Codex Bridge.app
Useful commands:
./bin/telegram-codex-bridge status
./bin/telegram-codex-bridge version
./bin/telegram-codex-bridge limits
./bin/telegram-codex-bridge start
./bin/telegram-codex-bridge stop
./bin/telegram-codex-bridge restart
./bin/telegram-codex-bridge set-autostart on
./bin/telegram-codex-bridge set-autostart offOpen the menu bar app:
open "./dist/Telegram Codex Bridge.app"Or build a drag-and-drop DMG:
./scripts/build-macos-dmg.shMore details: docs/macos.md
Build release archives for Linux and macOS binaries:
./scripts/build-release-archives.shThis produces .tar.gz archives for:
linux/amd64linux/arm64darwin/amd64darwin/arm64
When UPX_ENABLED=true, Linux release binaries are additionally packed with UPX before archiving. macOS app bundles and the .dmg are not UPX-packed; the .dmg is already a compressed disk image, and UPX on macOS app executables is more likely to hurt compatibility than help.
On Debian or other systemd-based Linux distributions, the unified binary can manage a user service:
./bin/telegram-codex-bridge status
./bin/telegram-codex-bridge start
./bin/telegram-codex-bridge stop
./bin/telegram-codex-bridge restart
./bin/telegram-codex-bridge set-autostart on
./bin/telegram-codex-bridge set-autostart offLinux service details: docs/linux.md
The menu bar app now uses ~/Library/Application Support/TelegramCodexBridge as its runtime root. On first launch, it will:
- copy the embedded bridge binaries into that runtime directory
- check whether configuration exists
- validate Codex availability and login
- ask for Telegram token, workspace, and allowlist values if config is missing
Avoid running two bridge instances at once. If you already started telegram-codex-bridge manually, stop that process before switching to the menu bar app or launchd. telegram-codex-bridge status will warn when it detects a bridge process running outside launchd.
Because this bridge runs locally beside Codex, a sleeping machine cannot answer Telegram messages. For 24/7 availability:
- keep the macOS host awake
- or run the bridge on a Linux machine that does not auto-sleep
- or use a dedicated Debian service user with
systemd --userand lingering enabled
When BRIDGE_PREVENT_SLEEP=true, the bridge will also try to prevent the machine from sleeping while a Codex task is actively running:
- macOS:
caffeinate - Linux:
systemd-inhibit
That helps during long-running tasks, but it cannot wake a machine that is already asleep before a Telegram message arrives.
The bridge now writes its main operational log through an internal rotating logger:
- default path:
data/logs/bridge.stdout.log - default size limit:
20 MB - default retained backups:
5 - default level:
info
Use BRIDGE_LOG_LEVEL=debug only when actively debugging. The default info mode avoids the noisy per-message development logs.
The repository now includes build.yml, which will:
- run
go test ./... - build cross-platform release archives
- build the macOS
.appand.dmg - upload all of them as workflow artifacts
- install UPX on the Linux build runner and pack Linux release binaries before archiving
- automatically create a GitHub Release when you push a
v*tag - attach the generated Linux/macOS archives and macOS installer assets to that Release
- generate release notes from GitHub's native release notes API using release.yml
- use pull_request_template.md to make changelogs and issue links more consistent
Binary and app versions are derived from the git tag at build time. GitHub Releases remains the source of truth for published versions, while release history also lives in CHANGELOG.md.
Release policy:
- Publish fixes under a new
v*tag instead of reusing or force-updating an existing release tag. - Treat an already-published GitHub Release as immutable for normal maintenance.
- If the release pipeline itself needs a fix, merge that fix first and cut the next patch version.
- Approval prompts bridged into Telegram action buttons
- Topic deletion and archive lifecycle hardening
- Telegram entrypoints for Codex automations
- Telegram entrypoints for Codex multi-agent workflows