Codex CLI Hook 集成

不用自己动手运行命令,灯是怎么知道 Codex CLI 正在做什么的。

运行一次 andon-light install-hooks --agent codex 之后,灯就会自己更新。日常不需要你运行任何命令。这篇讲讲这个设置到底做了什么,为什么这么设计,方便你在遇到奇怪的情况时能有个参考。

Codex CLI 也支持和 Claude Code 一样的"hook"机制:在它自身生命周期里的一些节点,可以自动帮你运行一条命令。装好这个集成之后,每个这样的节点都会被接上,调用 andon-light 并传入对应的颜色。用的是同一个 andon-light 程序、同一条 USB 连接、同一套固件(参见Claude Code Hook 集成)。变的只是你电脑上运行的软件,设备那一端什么都没变。

什么时候触发哪种颜色

时机颜色原因
新会话开始时空闲(红)会话还没被交代要做什么。
你提交一条提示词时工作中(绿)你刚给了它一个任务。
每次使用工具之前工作中(绿)这个会在每一次工具调用前触发,所以在一长串密集调用工具的过程中,灯会一直保持绿色。
Codex 正要请求你的授权时等待中(黄)比如,正在等你批准执行某条命令。
内部整理("整理中")依次点亮模式内部维护:还在运行,只是在忙别的事。
一轮对话正常结束时空闲(红)回到空闲状态。
会话因为任何原因结束时空闲(红)覆盖那些"正常结束"节点可能漏掉的情况。

Claude Code 有一个 Codex 没有的东西:一个通用的"需要你关注"的通知。Codex 唯一的"等你处理"时刻就是上面的授权请求,所以黄色也只由这一个 hook 负责。详见下面的为什么没有通用通知 hook。

这些命令是一条接一条按顺序执行的,不是放在后台运行,和 Claude Code 一样的理由(参见为什么不放在后台运行)。Claude Code 的设置会合并进一个更大的设置文件,而 Codex 的 hook 放在自己专属的文件里,所以这个集成会直接写入(或合并进)那个文件,具体是全局的 ~/.codex/hooks.json,还是某一个项目自己的,取决于你安装时选的范围。如果你编辑了这个文件,需要重启 Codex CLI(或者开一个新会话)才会生效。

运行前先信任它

在你亲自在 CLI 里查看并批准之前,Codex 不会运行一个新增或改动过的 hook 文件。没有办法从外部授予这个信任。运行完 andon-light install-hooks --agent codex 之后,启动 Codex CLI,运行 /hooks,确认新的配置内容。

如果跳过这一步,灯没反应,先查这个:不受信任的 hook 不会报错,只会悄悄地不执行。

如果你用的是 ChatGPT 桌面应用,而不是终端

在 Windows 上,"Codex 应用"通常指的是 ChatGPT 桌面应用(Microsoft Store 上那个)里的 Codex 标签页,这是一个聊天窗口,不是你在终端里打的 codex 命令。这一点很重要,因为上面说的信任步骤只能在交互式的终端会话里完成,ChatGPT 应用本身没有 /hooks 界面。

不过信任设置本身和是从哪个应用授予的没有关系,终端和 ChatGPT 应用读的是同一份 ~/.codex 配置。所以就算你平时只用 ChatGPT 应用,也需要一次性打开终端里的 Codex CLI 会话,在那里运行 /hooks 并批准。之后 ChatGPT 应用就会自动使用同一份受信任的 hook 配置。

在完成这一步之前,ChatGPT 应用里的灯就是安安静静地没反应,也不会显示任何错误。和前面说的"不受信任的 hook"是同一种表现。

如果在终端里输入 codex 提示不是可识别的命令,那是因为 ChatGPT 应用内置了自己的一份 CLI,没有把它加进系统 PATH。在 PowerShell 里找到并运行它的方法:

  1. 先直接查看配置本身,这样你看到的是真实的值,而不是盲目相信某个脚本:

    Get-Content "$env:USERPROFILE\.codex\config.toml" | Select-String CODEX_CLI_PATH

    会打印出类似 CODEX_CLI_PATH = "C:\Users\you\AppData\...\codex.exe" 这样一行。

  2. 把这个路径原样加上引号,前面加 &(PowerShell 的"运行这个程序"运算符),把下面示例里的路径换成你刚才找到的那个:

    & "C:\Users\you\AppData\...\codex.exe"
  3. 这会打开一个真正的终端 Codex CLI 会话。在里面运行 /hooks,查看内容并批准。

  4. 关掉那个窗口就行。ChatGPT 应用的 Codex 标签页之后会自动使用这份受信任的 hook 配置。信任状态存在磁盘上,不依赖于是哪个窗口批准的。

几个设计上的考虑

为什么"每次使用工具之前"这么重要

和 Claude Code 一样的理由:上表里的大多数时机每轮只会发生一次,但 Codex 的一次回复里可能会连续调用几十次工具。把 hook 挂在"每次工具调用之前",意味着整个过程中灯会持续被刷新,而不会因为中途没人更新而变成"连接中断"的闪烁状态。一整轮完全没有调用任何工具、纯粹在思考的情况没被覆盖到,不过这种情况的时长通常远短于固件 30 分钟的看门狗超时,所以实际上不构成问题。参见固件概览。

为什么没有通用通知 hook

Claude Code 除了专门的授权请求 hook 之外,还有一个更宽泛的"需要你关注"hook。Codex 的生命周期 hook 里没有对应的东西。最接近的是一个叫 notify 的独立配置项,但它只在一轮结束时触发,而这已经被上面的"一轮结束"hook 覆盖了。这样一来,授权请求就是 Codex 以 hook 形式暴露出来的唯一"等你处理"时刻,黄色也就只由这一个 hook 负责。

为什么内部整理要有专属的显示效果

和 Claude Code 一样的理由:如果没有专属的图案,整理期间要么保持之前的颜色不变(如果之前是红色/空闲,容易让人误解),要么就得再加一个 hook,专门用来在整理结束后把颜色改回去。依次点亮模式一眼就能看出"还活着,在做后续整理",而且等下一个 hook 触发时会自然过渡到下一个状态。

为什么会话开始和结束都特意设成空闲

在会话开始时明确设成空闲,能保证新会话不会继承上一个可能中途崩溃的会话留下的颜色。在会话结束时(不管 Codex 报告的是什么原因)也同样设成空闲,能覆盖普通"一轮结束"hook 覆盖不到的情况,比如被中断或突然关闭的会话。

为什么不放在后台运行

和 Claude Code 一样的取舍:把每条 andon-light 调用放在后台运行,只能保证它按顺序"开始",不能保证按顺序"完成"。每条调用都是一个独立的短生命周期程序,虽然快(大约 40-50 毫秒),但也不是瞬间完成。所以在工具调用密集的时候,后开始的调用有时会比先开始的更早跑完,悄无声息地把正确的颜色又覆盖成过时的颜色。改成一条接一条按顺序执行,每次多花一点点等待时间,换来的是灯始终反映事件的真实顺序。完整的推理过程参见 Claude Code Hook 集成。

为什么每条命令都被设计成"静默失败"

和 Claude Code 一样的理由:如果板子被拔掉了,或者在一台根本没接设备的电脑上运行 Codex,没有这个设计的话,每一个 hook 都会在每次触发时弹出一条显眼的报错。这就违背了"安静地待在后台"这个状态灯本该有的定位。等到工具具备自动重连能力时,这个做法就值得重新考虑。详见 Claude Code Hook 集成。