|
1 | | -# codex-telegram-claws |
| 1 | +# Codex Telegram Claws |
2 | 2 |
|
3 | | -`codex-telegram-claws` 是一个 Node.js (ESM) Telegram 超级代理。它在宿主机使用 `node-pty` 安全托管 `@openai/codex` CLI,并提供智能路由、MCP/Subagent 技能、推理流可视化、GitHub 自动化和定时主动任务。 |
| 3 | +[](https://opensource.org/licenses/MIT) |
| 4 | +[](https://nodejs.org/en/download/current) |
4 | 5 |
|
5 | | -对标参考项目:`RichardAtCT/claude-code-telegram`,但本项目专注 Codex CLI + MCP + Subagent 组合。 |
| 6 | +A Telegram bot that gives you remote access to `@openai/codex` through a PTY-backed Node.js runtime. |
| 7 | +It is strictly inspired by `RichardAtCT/claude-code-telegram`, but this project is implemented for Codex CLI + MCP + Subagent routing. |
6 | 8 |
|
7 | | -## 核心特性 |
| 9 | +## What Is This? |
8 | 10 |
|
9 | | -- PTY 托管:强制 TTY 场景运行 CLI,避免无终端卡死。 |
10 | | -- Agentic Routing:将消息分流到 Codex 链路或 Skill 链路(MCP/GitHub)。 |
11 | | -- MCP Client:以 stdio 方式连接本机 MCP Server,供 Subagent/通用任务使用。 |
12 | | -- MCP 去重策略:编码任务不再由 Bot 侧预注入 MCP 上下文,避免与 Codex 自身 MCP 重复调用。 |
13 | | -- Reasoning Stream:解析 `<think>...</think>` 并用 Spoiler 或引用渲染。 |
14 | | -- 丝滑输出:节流 `editMessageText`,长文自动切片,MarkdownV2 防崩。 |
15 | | -- Zero Trust:白名单用户鉴权,非授权请求静默丢弃。 |
16 | | -- GitHub Skill:自然语言驱动 commit/push、创建 repo、触发和查看测试。 |
17 | | -- Cron 主动推送:每日发送“昨日代码变更摘要”。 |
| 11 | +This bot connects Telegram to Codex CLI and routes tasks to the right execution surface: |
18 | 12 |
|
19 | | -## 架构总览 |
| 13 | +- **Coding tasks** -> Codex CLI in `node-pty` (real TTY, stable interactive behavior) |
| 14 | +- **General/tooling tasks** -> Subagents (`MCP Skill`, `GitHub Skill`) |
| 15 | +- **Proactive automation** -> Cron scheduler for daily summaries and push notifications |
20 | 16 |
|
21 | | -```text |
22 | | -Telegram Message |
23 | | - -> bot/handlers.js |
24 | | - -> orchestrator/router.js |
25 | | - -> runner/ptyManager.js (编码任务 -> Codex CLI,使用 Codex 自身 MCP) |
26 | | - -> orchestrator/skills/*.js (通用任务 -> MCP/GitHub Subagent) |
27 | | - -> bot/formatter.js |
28 | | - -> Telegram editMessageText/sendMessage |
29 | | -``` |
| 17 | +Key design goals: |
30 | 18 |
|
31 | | -关键模块: |
| 19 | +- Keep Codex interactive sessions smooth and stream-safe on Telegram |
| 20 | +- Enforce zero-trust access with whitelist-only users |
| 21 | +- Avoid duplicate MCP calls by separating Codex MCP vs Bot MCP responsibilities |
32 | 22 |
|
33 | | -- `src/bot/`: 鉴权、中间件、格式化、Telegram 交互。 |
34 | | -- `src/orchestrator/`: 路由决策、MCP 客户端、技能调度。 |
35 | | -- `src/runner/`: PTY 生命周期、流式缓冲、节流刷新。 |
36 | | -- `src/cron/`: 定时任务注册与主动消息推送。 |
| 23 | +## Quick Start |
37 | 24 |
|
38 | | -## 目录结构 |
| 25 | +### Prerequisites |
39 | 26 |
|
40 | | -```text |
41 | | -codex-telegram-claws/ |
42 | | -├── package.json |
43 | | -├── .env.example |
44 | | -├── src/ |
45 | | -│ ├── index.js |
46 | | -│ ├── config.js |
47 | | -│ ├── bot/ |
48 | | -│ │ ├── middleware.js |
49 | | -│ │ ├── formatter.js |
50 | | -│ │ └── handlers.js |
51 | | -│ ├── orchestrator/ |
52 | | -│ │ ├── router.js |
53 | | -│ │ ├── mcpClient.js |
54 | | -│ │ └── skills/ |
55 | | -│ │ ├── githubSkill.js |
56 | | -│ │ └── mcpSkill.js |
57 | | -│ ├── runner/ |
58 | | -│ │ └── ptyManager.js |
59 | | -│ └── cron/ |
60 | | -│ └── scheduler.js |
61 | | -└── README.md |
62 | | -``` |
| 27 | +- Node.js 20+ -- https://nodejs.org/en/download/current |
| 28 | +- Codex CLI -- https://github.com/openai/codex |
| 29 | +- Telegram Bot Token -- from `@BotFather` |
63 | 30 |
|
64 | | -## 前置条件 |
| 31 | +### Install |
65 | 32 |
|
66 | | -- Node.js: https://nodejs.org/en/download/current |
67 | | -- Codex CLI: https://github.com/openai/codex |
68 | | -- Telegram Bot Token: 通过 `@BotFather` 获取 |
69 | | -- 可选:GitHub PAT(用于创建仓库与自动化操作) |
| 33 | +```bash |
| 34 | +git clone https://github.com/MackDing/codex-telegram-claws.git |
| 35 | +cd codex-telegram-claws |
| 36 | +npm install |
| 37 | +``` |
70 | 38 |
|
71 | | -## 快速开始 |
| 39 | +### Configure |
72 | 40 |
|
73 | 41 | ```bash |
74 | | -npm install |
75 | 42 | cp .env.example .env |
76 | | -# 至少配置 BOT_TOKEN, ALLOWED_USER_IDS, CODEX_WORKDIR |
77 | | -npm run start |
78 | 43 | ``` |
79 | 44 |
|
80 | | -开发与检查: |
| 45 | +Minimum required: |
81 | 46 |
|
82 | 47 | ```bash |
83 | | -npm run dev |
84 | | -npm run check |
| 48 | +BOT_TOKEN=123456789:telegram-token |
| 49 | +ALLOWED_USER_IDS=123456789 |
| 50 | +CODEX_WORKDIR=/absolute/path/to/your/workspace |
85 | 51 | ``` |
86 | 52 |
|
87 | | -## 环境变量说明 |
| 53 | +### Run |
88 | 54 |
|
89 | | -必填: |
| 55 | +```bash |
| 56 | +npm run start |
| 57 | +``` |
90 | 58 |
|
91 | | -- `BOT_TOKEN`: Telegram Bot Token。 |
92 | | -- `ALLOWED_USER_IDS`: 白名单用户 ID,逗号分隔。 |
93 | | -- `CODEX_WORKDIR`: Codex CLI 工作目录(建议受限目录)。 |
| 59 | +Development mode: |
94 | 60 |
|
95 | | -常用可选: |
| 61 | +```bash |
| 62 | +npm run dev |
| 63 | +``` |
96 | 64 |
|
97 | | -- `CODEX_COMMAND`, `CODEX_ARGS`: Codex 启动命令与参数。 |
98 | | -- `STREAM_THROTTLE_MS`: 1-1.5 秒最佳(建议 `1200`)。 |
99 | | -- `REASONING_RENDER_MODE`: `spoiler` 或 `quote`。 |
100 | | -- `CRON_DAILY_SUMMARY`, `CRON_TIMEZONE`: Cron 表达式与时区。 |
101 | | -- `MCP_SERVERS`: JSON 数组,定义 MCP stdio server。 |
102 | | -- `GITHUB_TOKEN`: GitHub API Token。 |
103 | | -- `GITHUB_DEFAULT_WORKDIR`: Git 技能本地目录。 |
104 | | -- `E2E_TEST_COMMAND`: 测试命令(默认 Playwright)。 |
| 65 | +Sanity check: |
105 | 66 |
|
106 | | -MCP 示例: |
| 67 | +```bash |
| 68 | +npm run check |
| 69 | +npm test |
| 70 | +``` |
107 | 71 |
|
108 | | -```env |
109 | | -MCP_SERVERS=[{"name":"filesystem","command":"npx","args":["-y","@modelcontextprotocol/server-filesystem","/abs/path/workspace"]}] |
| 72 | +## Architecture |
| 73 | + |
| 74 | +```text |
| 75 | +Telegram Message |
| 76 | + -> src/bot/handlers.js |
| 77 | + -> src/orchestrator/router.js |
| 78 | + -> src/runner/ptyManager.js (coding tasks -> Codex CLI) |
| 79 | + -> src/orchestrator/skills/*.js (general tasks -> MCP/GitHub subagents) |
| 80 | + -> src/bot/formatter.js |
| 81 | + -> Telegram sendMessage/editMessageText |
110 | 82 | ``` |
111 | 83 |
|
112 | | -## 路由与职责边界(避免冲突) |
| 84 | +Core modules: |
| 85 | + |
| 86 | +- `src/index.js`: bootstrap and lifecycle |
| 87 | +- `src/config.js`: env parsing and validation |
| 88 | +- `src/bot/`: auth middleware, formatting, command handlers |
| 89 | +- `src/orchestrator/`: routing + MCP client + skills |
| 90 | +- `src/runner/ptyManager.js`: Codex PTY process + streaming |
| 91 | +- `src/cron/scheduler.js`: proactive scheduled push |
113 | 92 |
|
114 | | -当前策略: |
| 93 | +## Routing and MCP Boundary |
115 | 94 |
|
116 | | -- 编码任务:直接路由到 Codex CLI,不做 Bot 侧 MCP 预取。 |
117 | | -- 通用任务:路由到 MCP Skill(或 GitHub Skill)。 |
118 | | -- 显式 MCP 指令:仅 `/mcp ...` 触发 Bot 侧 MCP 调用。 |
| 95 | +To avoid duplicated context fetch: |
119 | 96 |
|
120 | | -这样做的目的: |
| 97 | +- **Coding requests** are sent directly to Codex CLI (Codex can use its own MCP stack) |
| 98 | +- **Bot-side MCP** is only used by `/mcp ...` and general subagent requests |
121 | 99 |
|
122 | | -- 避免同一请求在 Bot MCP 与 Codex MCP 被重复查询。 |
123 | | -- 降低时延、配额消耗和上下文不一致风险。 |
124 | | -- 让“编码执行面”(Codex)与“控制面技能”(Subagent/Cron)解耦。 |
| 100 | +This prevents: |
125 | 101 |
|
126 | | -## Telegram 指令与技能 |
| 102 | +- duplicate queries against the same MCP server |
| 103 | +- extra latency/token/tool cost |
| 104 | +- context drift from two independent MCP execution surfaces |
127 | 105 |
|
128 | | -基础命令: |
| 106 | +## Commands |
129 | 107 |
|
130 | | -- `/help`: 查看帮助。 |
131 | | -- `/interrupt`: 向 PTY 发送 `Ctrl+C`。 |
132 | | -- `/stop`: 结束当前 chat 的 PTY 会话。 |
133 | | -- `/cron_now`: 手动触发一次日报推送。 |
| 108 | +General: |
134 | 109 |
|
135 | | -MCP Skill: |
| 110 | +- `/start` - bootstrap message |
| 111 | +- `/help` - command summary |
| 112 | +- `/interrupt` - send `Ctrl+C` to current PTY session |
| 113 | +- `/stop` - terminate current PTY session |
| 114 | +- `/cron_now` - trigger daily summary immediately |
| 115 | + |
| 116 | +MCP skill: |
136 | 117 |
|
137 | 118 | - `/mcp tools <server>` |
138 | 119 | - `/mcp call <server> <tool> {"query":"..."}` |
139 | 120 |
|
140 | | -GitHub Skill: |
| 121 | +GitHub skill: |
| 122 | + |
| 123 | +- `/gh commit "feat: message"` -> `git add .` + commit + push |
| 124 | +- `/gh push` -> push current branch |
| 125 | +- `/gh create repo my-new-repo` -> create repo and bind origin |
| 126 | +- `/gh run tests` -> launch test job |
| 127 | +- `/gh test status <jobId>` -> read test status/output tail |
| 128 | + |
| 129 | +## Streaming and Reasoning Visualization |
| 130 | + |
| 131 | +PTY output is streamed with throttled `editMessageText` updates. |
| 132 | + |
| 133 | +- Throttle: controlled by `STREAM_THROTTLE_MS` (default `1200`) |
| 134 | +- Long output: auto-chunked to Telegram-safe message sizes |
| 135 | +- MarkdownV2: escaped to avoid parse failures |
| 136 | +- Reasoning tags: `<think>...</think>` extracted and rendered as: |
| 137 | + - spoiler (`||...||`, default) |
| 138 | + - quote block (if `REASONING_RENDER_MODE=quote`) |
141 | 139 |
|
142 | | -- `/gh commit "feat: xxx"` 自动 `git add .` + commit + push。 |
143 | | -- `/gh push` 仅推送当前分支。 |
144 | | -- `/gh create repo my-new-repo` 在当前账号创建仓库并关联 origin。 |
145 | | -- `/gh run tests` 触发测试任务。 |
146 | | -- `/gh test status <jobId>` 查询测试状态与输出尾部。 |
| 140 | +## Event-Driven Automation |
147 | 141 |
|
148 | | -## 推理流可视化 |
| 142 | +`node-cron` is built in for proactive behavior: |
149 | 143 |
|
150 | | -当 Codex CLI 输出包含 `<think>...</think>` 时,`formatter.js` 会抽取并渲染: |
| 144 | +- Daily summary schedule: `CRON_DAILY_SUMMARY` (default `0 9 * * *`) |
| 145 | +- Target users: `PROACTIVE_USER_IDS` |
| 146 | +- Summary includes commit count, changed files, insertions/deletions, and recent commits |
151 | 147 |
|
152 | | -- `spoiler` 模式:`||...||`(默认,点击展开)。 |
153 | | -- `quote` 模式:引用块展示。 |
| 148 | +Use `/cron_now` for manual trigger during debugging. |
154 | 149 |
|
155 | | -普通输出与推理输出会分段显示,避免污染代码可读性。 |
| 150 | +## Configuration |
156 | 151 |
|
157 | | -## 定时任务设计 |
| 152 | +Required: |
158 | 153 |
|
159 | | -默认 Cron:每天 09:00(`CRON_DAILY_SUMMARY`)统计昨日提交数据并主动推送给 `PROACTIVE_USER_IDS`。 |
| 154 | +```bash |
| 155 | +BOT_TOKEN=... |
| 156 | +ALLOWED_USER_IDS=123456789,987654321 |
| 157 | +CODEX_WORKDIR=/abs/path/workspace |
| 158 | +``` |
| 159 | + |
| 160 | +Common options: |
160 | 161 |
|
161 | | -摘要包含: |
| 162 | +```bash |
| 163 | +CODEX_COMMAND=codex |
| 164 | +CODEX_ARGS= |
| 165 | +STREAM_THROTTLE_MS=1200 |
| 166 | +STREAM_BUFFER_CHARS=120000 |
| 167 | +REASONING_RENDER_MODE=spoiler |
| 168 | + |
| 169 | +CRON_DAILY_SUMMARY=0 9 * * * |
| 170 | +CRON_TIMEZONE=Asia/Shanghai |
| 171 | +PROACTIVE_USER_IDS=123456789 |
| 172 | +``` |
162 | 173 |
|
163 | | -- 提交数量 |
164 | | -- 改动文件数 / 插入 / 删除 |
165 | | -- 最近提交列表(最多 8 条) |
| 174 | +MCP: |
166 | 175 |
|
167 | | -## Subagent / Cron 与 Codex 的关系 |
| 176 | +```bash |
| 177 | +MCP_SERVERS=[{"name":"filesystem","command":"npx","args":["-y","@modelcontextprotocol/server-filesystem","/abs/path/workspace"]}] |
| 178 | +``` |
168 | 179 |
|
169 | | -默认不会产生逻辑冲突,前提是遵守职责边界: |
| 180 | +GitHub: |
170 | 181 |
|
171 | | -- Codex 负责“编码对话与执行”。 |
172 | | -- Subagent(MCP/GitHub)负责“外部工具调用和控制动作”。 |
173 | | -- Cron 负责“计划触发和状态通知”。 |
| 182 | +```bash |
| 183 | +GITHUB_TOKEN=ghp_xxx |
| 184 | +GITHUB_DEFAULT_WORKDIR=/abs/path/workspace |
| 185 | +GITHUB_DEFAULT_BRANCH=main |
| 186 | +E2E_TEST_COMMAND=npx playwright test --reporter=line |
| 187 | +``` |
174 | 188 |
|
175 | | -可能冲突点与建议: |
| 189 | +## Security Baseline |
176 | 190 |
|
177 | | -- 并发写仓库:Cron 与 Codex 同时操作同一目录时,建议将 Cron 任务限制为只读汇总。 |
178 | | -- 指令重入:对高风险指令(push/create repo)建议增加确认步骤或白名单命令。 |
179 | | -- 上下文漂移:尽量让同一任务只由一个执行面处理,不要在同一请求里混用双 MCP。 |
| 191 | +- Whitelist-only access (`ALLOWED_USER_IDS`) is mandatory |
| 192 | +- Do not commit `.env`, tokens, or session artifacts |
| 193 | +- Run bot under a restricted OS user in production |
| 194 | +- Keep `CODEX_WORKDIR` scoped to a safe workspace root |
| 195 | +- Prefer least-privilege GitHub PAT |
180 | 196 |
|
181 | | -## 安全基线 |
| 197 | +## Troubleshooting |
182 | 198 |
|
183 | | -- 白名单鉴权必须开启,拒绝公开 Bot。 |
184 | | -- 不提交 `.env`、Token、会话数据。 |
185 | | -- 建议使用最小权限 PAT,限制 repo scope。 |
186 | | -- 建议在生产使用独立系统用户运行并限制工作目录权限。 |
| 199 | +- **Bot not responding**: verify `BOT_TOKEN` and `ALLOWED_USER_IDS` |
| 200 | +- **Codex not producing output**: verify `CODEX_COMMAND` and `CODEX_WORKDIR` |
| 201 | +- **Markdown parse errors**: reduce output size/context; check special characters in tool output |
| 202 | +- **MCP failures**: run `/mcp tools <server>` first to validate server availability |
| 203 | +- **GitHub API failures**: verify `GITHUB_TOKEN` scope (`repo`) and account permissions |
| 204 | +- **Duplicate MCP suspicion**: ensure coding tasks are routed directly to Codex, and bot MCP is used only for `/mcp` or general tasks |
187 | 205 |
|
188 | | -## 常见问题排查 |
| 206 | +## Reference |
189 | 207 |
|
190 | | -- Bot 不响应:检查 `BOT_TOKEN` 与 `ALLOWED_USER_IDS` 是否正确。 |
191 | | -- Codex 无输出:检查 `CODEX_COMMAND` 是否可执行,`CODEX_WORKDIR` 是否存在。 |
192 | | -- Markdown 报错:确认输出是否超长,已内置切片与转义,但极端字符流仍建议缩短上下文。 |
193 | | -- GitHub 创建仓库失败:检查 `GITHUB_TOKEN` scope 与账号配额。 |
194 | | -- MCP 调用失败:先 `/mcp tools <server>` 验证服务连通与工具列表。 |
195 | | -- 觉得 MCP 重复调用:确认编码请求是否直接走 Codex;Bot 侧 MCP 仅在 `/mcp` 或通用任务触发。 |
| 208 | +- Inspired by: https://github.com/RichardAtCT/claude-code-telegram |
| 209 | +- This implementation: Codex-first Node.js stack (`telegraf`, `node-pty`, `node-cron`, MCP SDK) |
0 commit comments