codex-desktop-channel
v0.1.0
Published
Node CLI for sending notifications and waking Codex Desktop threads from Hermes or local automation.
Maintainers
Readme
codex-desktop-channel
codex-desktop-channel 是一个 Node CLI 和 skills 套件,用 Hermes 作为桥接层,让 Codex Desktop 支持 channel。
它做两件事:
- 外部 channel 可以通过 Hermes 唤醒 Codex Desktop 指定 thread。
- Codex Desktop 可以通过钉钉或 Hermes webhook 支持的 channel 向外发消息,例如微信、飞书/Lark、Slack、Discord 或自定义 route。
为什么一定是 Codex Desktop?因为 Codex Desktop 有我很喜欢、也很依赖的 Chrome 插件工作流,特别适合做浏览器验收。这个项目的目标不是替代 Codex Desktop,而是在保留 Desktop 工作流的前提下,给它补上 channel 式的唤醒和通知能力。
前提条件
- 已安装并配置好 Hermes。
- 已安装并启动 Codex Desktop。
- 已开启 Codex Desktop 调试能力,让 Electron DevTools 端点可访问,通常是
http://127.0.0.1:9229。 - 可以使用 BigPizzaV3/CodexPlusPlus 辅助开启或管理 Codex Desktop 的调试能力。
所有 channel id、webhook route、thread 默认值都存放在全局配置文件里:
~/.codex-desktop-channel/config.json安装
npm install -g codex-desktop-channel从源码安装:
git clone https://github.com/zwmmm/codex-desktop-channel
cd codex-desktop-channel
npm link
codex-desktop-channel --help给 Agent 的安装提示词
把下面这段提示词复制给 Codex、Hermes、Claude Code 或其他本地 coding agent。把占位符替换成你自己的值即可。
请帮我安装并配置 codex-desktop-channel。
仓库地址:
https://github.com/zwmmm/codex-desktop-channel
目标:
1. 先检查我已经安装并配置好了 Hermes。
2. 确认 Codex Desktop 正在运行,并且调试端口可访问,默认是 `http://127.0.0.1:9229`。如果没有开启,请提示我可以使用 BigPizzaV3/CodexPlusPlus:https://github.com/BigPizzaV3/CodexPlusPlus
3. 克隆仓库并执行 npm link,让 `codex-desktop-channel` 和 `codex-channel` 命令可用。
4. 执行交互式初始化 `codex-desktop-channel init`,让我选择 channel,并把相关 id 写入 `~/.codex-desktop-channel/config.json`。
5. 安装 Codex 和 Hermes 两份 skills。
6. 配置通知通道:
- 钉钉:使用 dws,不要走 Hermes webhook。先提示我安装和初始化 dws,并确认授权 `chat.message:list`,然后让我输入 robotCode、users 和 conversation id。
- 飞书/微信/Slack/Discord/其他:自动创建或配置 Hermes webhook route。
7. 配置 Codex Desktop 默认 thread id:<你的 Codex Desktop thread id,可选>。
8. 验证:
- `codex-desktop-channel config show`
- 如果配置了钉钉,发送一条测试通知。
- 如果配置了 thread id 且 Codex Desktop 正在运行,执行 wake 测试。
注意:
- 所有 id、route、robotCode、users 都必须写进 `~/.codex-desktop-channel/config.json`,不要写进 skill 文档。
- 钉钉走 dws 的原因是 Hermes webhook 的钉钉 socket 通道需要用户侧先发消息激活,才能保证推送可靠。
- 如果 wake 时发现当前 turn 正在运行并返回 `turn_active_stop_button_visible`,不要点停止,说明脚本保护生效。配置
推荐直接使用交互式初始化:
codex-desktop-channel init初始化流程会:
- 用方向键选择 channel:钉钉、飞书、微信/企微、Lark 或自定义 Hermes webhook。
- 检查该 channel 需要的工具。
- 只询问缺失的必填项;已有配置和默认值不会反复确认。
- 非钉钉 channel 会自动生成 route/event,并在检测到 Hermes 时直接创建 webhook。
- 仅在缺少时询问 channel 的人类可读名字和别名,例如
小钉、钉钉。 - 交互式输入相关 id,并写入
~/.codex-desktop-channel/config.json。 - 钉钉 channel 会根据 conversation id 写入 Hermes 的
channel_skill_bindings和channel_prompts,让这条钉钉会话自动加载codex-desktop-channelskill。
钉钉比较特殊。钉钉 channel 使用 dws 直发,不走 Hermes webhook。初始化时会提示你先安装并初始化 dws,常用命令是:
dws auth login --format json
dws auth status --format json
dws doctor --json
dws config list --format json如果希望“钉钉回复 Codex”时不手动带 Thread ID,还需要给 dws 授权 chat.message:list。CLI 会用它读取当前钉钉会话最近消息,严格寻找 Codex 通知底部的 Thread ID: <uuid>。
脚本化配置也支持:
codex-desktop-channel init --channel dingtalk --type dingtalk --robot-code "<robot>" --users "<users>"
codex-desktop-channel init --channel dingtalk --type dingtalk --robot-code "<robot>" --users "<users>" --conversation-id "<ding conversation id>" --thread "<thread id>" --name "小钉" --aliases "小钉,钉钉"
codex-desktop-channel init --channel feishu --type hermes-webhook --route "<hermes webhook route>"
codex-desktop-channel config set codex.defaultThreadId "<thread id>"
codex-desktop-channel webhook create --route codex-desktop-channel --thread "<thread id>"Hermes 侧 skill 会读取每个 channel 的 name 和 aliases。例如配置里有:
{
"channels": {
"dingtalk": {
"name": "小钉",
"aliases": ["小钉", "钉钉"]
}
}
}那么在 Hermes 里说“给小钉发消息:构建完成了”,就应该触发:
codex-desktop-channel notify --channel dingtalk --text "构建完成了"钉钉默认走:
dws chat message send-by-bot这是有意设计。钉钉的 Hermes webhook socket 通道需要用户侧先发消息激活,才能保证推送可靠,所以钉钉默认走 dws 直发。其他 channel 默认调用:
hermes webhook test <route> --payload '<json>'发送通知
codex-desktop-channel notify --channel dingtalk --title "小钉消息" --text "Done" --thread "$CODEX_THREAD_ID"
codex-desktop-channel notify --channel feishu --title "Codex" --text "Done" --thread "$CODEX_THREAD_ID"主动发送通知时,CLI 默认会根据 codex.replyHint 在消息底部追加 footer。Codex 发消息时必须把当前会话的真实 Thread ID 显式传给 --thread,由 CLI 把它渲染进 footer。
在 Codex Desktop 里,当前会话 ID 通过环境变量 CODEX_THREAD_ID 暴露,所以 Codex skill 应该调用 --thread "$CODEX_THREAD_ID"。notify 不会猜当前 active thread,也不接受 --thread current、--thread active 或裸 --thread。缺少合法 Thread ID 时命令会直接失败,避免发出 Thread ID: true 这种假值。
外部 channel 回复 Codex 时,Hermes 不依赖本机状态文件。它应该先看用户回复里有没有明确的 Thread ID: <uuid>;如果是钉钉且消息里没有这个 footer,就让 CLI 通过 dws 读取当前钉钉会话最近消息,严格寻找最近一条 Codex 通知底部的 Thread ID: <uuid>,然后唤醒对应 thread。
codex-desktop-channel wake --channel dingtalk --message "继续干活"默认提示文案在配置里:
{
"codex": {
"replyHint": "Thread ID: {threadId}"
}
}如果某条消息不需要追加提示,可以使用:
codex-desktop-channel notify --channel dingtalk --text "Done" --no-reply-hint创建 Hermes Webhook
这个工具不会在每次通知时偷偷创建 webhook。需要接收用户回复时,请显式创建一次 Hermes webhook route:
codex-desktop-channel webhook create --route codex-desktop-channel --thread "<thread id>"也可以在初始化时顺手创建:
codex-desktop-channel init --thread "<thread id>" --create-webhook --webhook-route codex-desktop-channel创建后,Hermes 会使用 codex-desktop-channel skill,把外部 channel 的回复通过 codex-desktop-channel wake 转发给 Codex Desktop。
唤醒 Codex Desktop
Codex Desktop 必须正在运行,并且 Electron DevTools 端口可访问,通常是 http://127.0.0.1:9229。
codex-desktop-channel wake --thread "<thread id>" --message "Continue the task."wake 命令会查找:
[data-app-action-sidebar-thread-id="local:<thread id>"]然后激活对应 thread,在 composer 中输入消息并按 Enter。如果目标 thread 当前正在运行,它会返回 turn_active_stop_button_visible,不会点击停止,也不会打断正在执行的任务。
钉钉回复场景可以不手动传 thread:
codex-desktop-channel wake --channel dingtalk --message "继续干活"这个命令不会使用 codex.defaultThreadId 兜底,而是实时调用 dws chat message list 读取配置里 channels.dingtalk.conversationId 对应会话,从当前时间往前找到最近的 Thread ID: <uuid> footer 后再唤醒 Codex。
安装 Skills
codex-desktop-channel install-skills
codex-desktop-channel install-skills --codex
codex-desktop-channel install-skills --hermes