A Telegram bot that gives you remote access to @openai/codex through a PTY-backed Node.js runtime.
It is strictly inspired by RichardAtCT/claude-code-telegram, but this project is implemented for Codex CLI + MCP + Subagent routing.
This bot connects Telegram to Codex CLI and routes tasks to the right execution surface:
- Coding tasks -> Codex CLI in
node-pty(real TTY, stable interactive behavior) - Explicit tool tasks -> Subagents (
/mcp,GitHub Skill) - Proactive automation -> Cron scheduler for daily summaries and push notifications
Key design goals:
- Keep Codex interactive sessions smooth and stream-safe on Telegram
- Enforce zero-trust access with whitelist-only users
- Avoid duplicate MCP calls by separating Codex MCP vs Bot MCP responsibilities
- Node.js 20+ -- https://nodejs.org/en/download/current
- Codex CLI -- https://github.com/openai/codex
- Telegram Bot Token -- from
@BotFather
git clone https://github.com/MackDing/codex-telegram-claws.git
cd codex-telegram-claws
npm installcp .env.example .envMinimum required:
BOT_TOKEN=123456789:telegram-token
ALLOWED_USER_IDS=123456789
CODEX_WORKDIR=.npm run startDevelopment mode:
npm run devSanity check:
npm run check
npm testTelegram Message
-> src/bot/handlers.js
-> src/orchestrator/router.js
-> src/runner/ptyManager.js (coding tasks -> Codex CLI)
-> src/orchestrator/skills/*.js (general tasks -> MCP/GitHub subagents)
-> src/bot/formatter.js
-> Telegram sendMessage/editMessageText
Core modules:
src/index.js: bootstrap and lifecyclesrc/config.js: env parsing and validationsrc/bot/: auth middleware, formatting, command handlerssrc/orchestrator/: routing + MCP client + skillssrc/runner/ptyManager.js: Codex PTY process + streamingsrc/cron/scheduler.js: proactive scheduled push
To avoid duplicated context fetch:
- Coding requests are sent directly to Codex CLI (Codex can use its own MCP stack)
- Bot-side MCP is only used by explicit
/mcp ...commands
This prevents:
- duplicate queries against the same MCP server
- extra latency/token/tool cost
- context drift from two independent MCP execution surfaces
General:
/start- bootstrap message/help- command summary/interrupt- sendCtrl+Cto current PTY session/stop- terminate current PTY session/cron_now- trigger daily summary immediately
MCP skill:
/mcp tools <server>/mcp call <server> <tool> {"query":"..."}
GitHub skill:
/gh commit "feat: message"->git add .+ commit + push/gh push-> push current branch/gh create repo my-new-repo-> create repo and bind origin/gh run tests-> launch test job/gh test status <jobId>-> read test status/output tail
PTY output is streamed with throttled editMessageText updates.
- Throttle: controlled by
STREAM_THROTTLE_MS(default1200) - Long output: auto-chunked to Telegram-safe message sizes
- MarkdownV2: escaped to avoid parse failures
- Reasoning tags:
<think>...</think>extracted and rendered as:- spoiler (
||...||, default) - quote block (if
REASONING_RENDER_MODE=quote)
- spoiler (
- If
node-ptycannot spawn on the current host, the runner falls back tocodex execfor per-request execution
node-cron is built in for proactive behavior:
- Daily summary schedule:
CRON_DAILY_SUMMARY(default0 9 * * *) - Target users:
PROACTIVE_USER_IDS - Summary includes commit count, changed files, insertions/deletions, and recent commits
Use /cron_now for manual trigger during debugging.
Required:
BOT_TOKEN=...
ALLOWED_USER_IDS=123456789,987654321
CODEX_WORKDIR=.Common options:
CODEX_COMMAND=codex
CODEX_ARGS=
STREAM_THROTTLE_MS=1200
STREAM_BUFFER_CHARS=120000
REASONING_RENDER_MODE=spoiler
CRON_DAILY_SUMMARY=0 9 * * *
CRON_TIMEZONE=Asia/Shanghai
PROACTIVE_USER_IDS=123456789MCP:
MCP_SERVERS=[]GitHub:
GITHUB_TOKEN=ghp_xxx
GITHUB_DEFAULT_WORKDIR=.
GITHUB_DEFAULT_BRANCH=main
E2E_TEST_COMMAND=npx playwright test --reporter=line- Whitelist-only access (
ALLOWED_USER_IDS) is mandatory - Do not commit
.env, tokens, or session artifacts - Run bot under a restricted OS user in production
- Keep
CODEX_WORKDIRscoped to a safe workspace root - Prefer least-privilege GitHub PAT
- Bot not responding: verify
BOT_TOKENandALLOWED_USER_IDS - Codex not producing output: verify
CODEX_COMMANDandCODEX_WORKDIR - Markdown parse errors: reduce output size/context; check special characters in tool output
- MCP failures: run
/mcp tools <server>first to validate server availability - GitHub API failures: verify
GITHUB_TOKENscope (repo) and account permissions - Duplicate MCP suspicion: ensure coding tasks are routed directly to Codex, and bot MCP is used only for
/mcp posix_spawnp failed: this means PTY spawn is blocked on the host; the runner will fall back tocodex exec
- Inspired by: https://github.com/RichardAtCT/claude-code-telegram
- This implementation: Codex-first Node.js stack (
telegraf,node-pty,node-cron, MCP SDK)