Skip to content

mideco-tech/codex-tg

codex-tg: Codex Telegram remote UI

Codex Telegram bot and remote UI for local OpenAI Codex App Server, built in Go.

codex-tg turns a Telegram bot into a mobile control surface for local Codex threads: it watches Codex GUI/CLI activity, keeps thread identity visible, routes replies back to the right thread, and exposes high-signal controls such as Plan Mode prompts, Stop, Steer, Details, Tools file, and Get full log.

Why codex-tg?

  • Codex Telegram remote UI for local OpenAI Codex App Server.
  • Control and observe Codex threads from Telegram without exposing App Server to the internet.
  • Reuse your existing Codex setup: skills, MCP servers, plugins, repo instructions, and local workflows.
  • Thread-first routing keeps replies, tools, Plan Mode, Details, and Final cards attached to the right run.
  • Built for long-running local coding-agent work from a phone.

Current release: v0.4.0.

codex-tg Telegram Plan Mode demo

The demo flow is documented in docs/demo/telegram-plan-mode-demo.md.

Why It Matters

  • Keep local Codex work observable from a phone without exposing Codex App Server to the internet.
  • Continue supervising long-running coding tasks while away from the workstation.
  • Use Telegram as a low-friction fallback surface on unreliable or constrained networks.
  • Preserve local-first ownership: Codex sessions, workspaces, SQLite state, and tokens stay on your machine.

Demo Screenshots

1. User request and Plan Mode

User request and Plan Mode

2. Tool execution and output

Tool execution and output

3. Final answer and Details

Final answer and Details

Features

  • Thread-first routing over local codex app-server stdio.
  • Global observer for foreign GUI/CLI runs, with polling fallback through thread/read.
  • Telegram-origin live current tool rendering from App Server item/* events, while foreign GUI/CLI panels stay completed-tool only.
  • Stable visual identity per thread: emoji marker plus project/thread/run chips.
  • Explicit New run -> [User] -> [commentary] -> [Tool] -> [Output] -> [Final] chronology with status on the live commentary/final card.
  • Low-noise Telegram notifications: only New run (configurable), [Plan], and [Final] are audible; live progress and exports are sent silently.
  • Plan Mode starts from Telegram via /plan or /reply --plan; if a thread remains in Plan Mode, the Plan Final Card offers Turn off Plan and /stop also arms the next normal turn to leave Plan Mode. [Plan] prompt-cards keep reply-first routing and structured buttons when Codex provides choices.
  • Final Card with Details pagination and on-demand Tools file export.
  • On-demand full log archive from Codex session JSONL.
  • SQLite-backed durable state for bindings, routes, callbacks, observer target, panels, and delivery metadata.
  • macOS service installer with friendly first-run setup, user LaunchAgent management, and menu bar tray control.
  • Cross-platform Go daemon foundation for Windows, macOS, and Linux.

Platform Status

  • Windows: actively tested with the local Codex App Server, Telegram Bot API, observer flows, and live E2E demo.
  • macOS: v0.4.0 is verified stable on macOS 26.3.1 arm64 with Go 1.26.2, user LaunchAgent service setup, local build, package dry-run, Details binding validation, Telegram command-menu readback, real Chat folder creation, low-noise notification validation, Plan Mode reset validation, and live Telegram readback E2E.
  • Linux: CI runs tests/builds on Ubuntu; full local daemon/runtime validation is still pending.

Quickstart

Prerequisites:

  • OpenAI Codex CLI with codex app-server.
  • A Telegram bot token from BotFather.
  • Your Telegram numeric user id.

On macOS, download the latest .pkg from GitHub Releases, install it, then run:

ctr-go service install --start --start-at-login
ctr-go doctor

ctr-go service install starts a friendly first-run setup wizard when required. The same values can be passed with flags for scripted installs. It writes a private local config file at ~/.codex-tg/config.env by default, creates a user LaunchAgent, and starts the daemon when --start is present. If your shell uses proxy variables such as HTTPS_PROXY or NO_PROXY, the installer preserves them in the private config so the LaunchAgent can reach the same network without putting secrets or user ids into the plist.

For Linux, Windows, or manual macOS setup, download the latest ctr-go archive, unpack it, then run:

ctr-go init
ctr-go doctor
ctr-go daemon run

Use CTR_GO_CONFIG to point at another config file. Explicit environment variables still override config file values.

Build from source:

git clone https://github.com/mideco-tech/codex-tg.git
cd codex-tg
go run ./cmd/ctr-go init
go run ./cmd/ctr-go doctor
go run ./cmd/ctr-go daemon run

Environment-only setup remains supported:

$env:CTR_GO_TELEGRAM_BOT_TOKEN = "<telegram-bot-token>"
$env:CTR_GO_ALLOWED_USER_IDS = "<telegram-user-id>"
$env:CTR_GO_DEFAULT_CWD = "C:\Users\you\Projects\Codex"

In Telegram:

/start
/observe all
/threads
/context

Start or continue a Codex thread from Codex GUI/CLI. codex-tg should create a New run card, a [User] card, live progress cards, and then send a final answer card with Details while cleaning up transient live cards.

Set CTR_GO_NOTIFY_NEW_RUN=off to keep New run visible but silent. [Plan] prompts and [Final] cards still use normal Telegram notifications.

Runtime Commands

ctr-go init
ctr-go service install
ctr-go service start
ctr-go service stop
ctr-go service restart
ctr-go service status
ctr-go doctor
ctr-go status
ctr-go repair
ctr-go daemon run

Source-build equivalents:

go run ./cmd/ctr-go init
go run ./cmd/ctr-go service install
go run ./cmd/ctr-go doctor
go run ./cmd/ctr-go status
go run ./cmd/ctr-go repair
go run ./cmd/ctr-go daemon run

Telegram commands:

  • /start, /help
  • /threads, /projects, /new, /newchat, /newthread, /show, /bind, /reply, /plan
  • /settings, /model, /effort
  • /context, /whereami
  • /observe all, /observe off
  • /status, /repair, /stop, /approve, /deny

/projects opens cached project/workspace navigation sorted by the latest thread activity. Codex UI Chats from Documents/Codex are grouped under Chats: the main projects view shows recent Chat previews, Open Chats opens the full paginated Chat list, and choosing a Chat opens and binds its thread. Use New thread in a normal project menu to create a new thread in that project cwd. Use /newchat <prompt> to create a Codex UI Chat under Documents/Codex/<date>/<prompt-slug>. Use /newthread <prompt> when you need a thread without choosing a project or creating a Chat folder; App Server may still attach the daemon default cwd.

Configuration

Primary environment variables:

  • CTR_GO_HOME
  • CTR_GO_CONFIG (~/.codex-tg/config.env by default)
  • CTR_GO_CODEX_BIN
  • CTR_GO_APP_SERVER_LISTEN
  • CTR_GO_TELEGRAM_BOT_TOKEN
  • CTR_GO_ALLOWED_USER_IDS
  • CTR_GO_ALLOWED_CHAT_IDS
  • CTR_GO_DEFAULT_CWD
  • CTR_GO_CODEX_CHATS_ROOT (~/Documents/Codex by default)
  • CTR_GO_NOTIFY_NEW_RUN (true by default; set false/off/0 to send New run silently)
  • CTR_GO_LOG_ENABLED (true by default; set false/off/0 to discard daemon stdout logs)
  • CTR_GO_DIAGNOSTIC_LOGS (true by default; set false/off/0 to keep normal bot logs but suppress structured daemon_event diagnostics)
  • CTR_GO_OBSERVER_POLL_SECONDS
  • CTR_GO_REQUEST_TIMEOUT_SECONDS
  • CTR_GO_PROJECTS_PROJECT_PREVIEW_LIMIT (7 by default)
  • CTR_GO_PROJECTS_CHAT_PREVIEW_LIMIT (3 by default)
  • CTR_GO_CHATS_PAGE_SIZE (8 by default)
  • CTR_GO_INDEX_REFRESH_SECONDS
  • CTR_GO_ATTACH_REFRESH_SECONDS
  • CTR_GO_DELIVERY_RETRY_SECONDS
  • CTR_GO_DELIVERY_MAX_ATTEMPTS

Compatibility fallbacks:

  • CTR_TELEGRAM_BOT_TOKEN
  • CTR_ALLOWED_USER_IDS
  • CTR_ALLOWED_CHAT_IDS

Verification

go test ./...
go build -buildvcs=false ./...

Live Telegram readback E2E is documented in tests/live_e2e/README.md. It is intentionally gated by local env and is not part of go test ./....

Live demo for a screenshot:

$env:CTR_DEMO_TELEGRAM_E2E = "1"
$env:CTR_DEMO_TELEGRAM_CHAT_ID = "<telegram-chat-id>"
$env:CTR_GO_TELEGRAM_BOT_TOKEN = "<telegram-bot-token>"
$env:CTR_DEMO_KEEP_MESSAGES = "true"
go test -tags demo_e2e ./tests -run TestTelegramPlanModeScreenshotDemo -count=1 -v

See docs/demo/telegram-plan-mode-demo.md for the screenshot checklist.

GitHub Metadata

Suggested repository description:

Codex Telegram bot and remote UI for local OpenAI Codex App Server. Observe, approve, and steer Codex from Telegram.

Suggested topics:

codex telegram telegram-bot telegram-ui openai-codex codex-cli
codex-app-server ai-agents coding-agent remote-control developer-tools
local-first go golang macos windows linux plan-mode agent-observer json-rpc

Documentation

License

Apache License 2.0. This keeps the project permissive for the community while also providing an explicit patent grant that large companies usually expect from infrastructure and developer-tooling projects.

Operational Notes

  • Telegram long polling returns 409 Conflict when another process consumes the same bot token.
  • Do not expose Codex App Server on a public interface. codex-tg is designed around local stdio.
  • Keep bot tokens, Telegram sessions, SQLite databases, logs, and .env files out of git.