前言
Codex 的任务越来越复杂以后,有些任务一次会执行几十分钟甚至更久。
执行时间一长,中间做了很多事情,任务结束后再逐个核对文件和执行过程,审核成本会很高。
所以我希望任务结束后,能快速知道:
跑了多久、做了什么、改了什么。
这也是我开始使用 Hook 的原因。
先看看它能带来什么
先不急着讲 Hook 是什么,直接看一个实际效果。
下面这个 Codex 任务执行了 1 小时 11 分钟。
任务结束以后,我可以直接看到这一轮的大致执行情况:

从这段信息里,可以快速看到:
- 任务执行了多久
- 使用了哪些 Skill
- 启动了哪些子 Agent
- 新增、修改了多少文件
- 执行了多少 Git 指令
- 调用了多少 Shell 和本地工具
不用再把一个小时的执行过程重新翻一遍,就能先知道:
这一轮 Codex 大概干了什么。
Hook 在哪里?
Hook 并不是一个需要单独打开的软件。
它就在 Codex 的任务执行过程中。

比如图里的:
UserPromptSubmit
代表用户提交了任务。
而:
Stop
则表示当前这一轮任务结束。
除了任务开始和结束,在工具调用、子 Agent 启动等事件发生时,也可以触发对应的 Hook。
有 Hook 和没有 Hook,到底有什么区别?
这是我觉得最容易理解 Hook 的方式。
先明确一点:
有没有 Hook,并不会改变 Codex 原本的任务执行流程。
Codex 该分析代码还是分析代码,该调用工具还是调用工具,该运行测试还是运行测试。
区别只是:
某些事件发生以后,会额外触发 Hook。

可以看到:
没有 Hook
Codex 正常执行:
提交任务 → 执行任务 → 调用工具 / 修改文件 / 运行测试 → 任务结束 → 最终结果
有 Hook
Codex 还是执行完全相同的流程。
只是当某些事件发生以后,会额外触发:
- 记录任务开始
- 记录工具调用
- 记录文件变化
- 记录子 Agent
- 汇总任务信息
所以 Hook 并不会替代 Codex 原本的工作流程。
它只是额外多了一层:
观察、记录和处理。
我为什么开始关注 Hook?
原因其实不是为了研究一个新功能,而是日常使用 Codex 时确实遇到了几个问题。
1. Codex 的任务越来越长
现在有些任务会执行几十分钟,甚至一个小时。
一轮复杂任务可能会经历:

等它跑完以后,我不可能再把这一个小时的完整执行过程从头翻一遍。
我更希望最后直接知道:
跑了多久、调用了什么、修改了什么、大概做了多少事情。
2. 最终结果看不出中间到底发生了什么
Codex 最后通常会告诉我:
任务完成了。
但很多时候,我还会关心:
- 用了哪些 MCP?
- 命中了哪些 Skill?
- 启动了哪些子 Agent?
- 执行了多少工具调用?
这些信息能帮助我判断:
Codex 的执行过程是不是符合我的预期。
3. 我不会再逐个核对所有修改文件
现在 Codex 一次可能修改十几个,甚至几十个文件。
我的习惯更多是:

而不是每次都把所有文件逐个完整检查一遍。
所以我至少希望先知道:
- 新增了多少文件
- 修改了多少文件
- 删除了多少文件
这当然不能代替 Review,但可以快速判断这次改动的规模,把时间放到真正需要检查的地方。
4. 我想知道 MCP、Skill 有没有自动命中
还有一个我比较关心的问题。
有时候我并没有明确告诉 Codex:
使用某个 MCP。
或者:
使用某个 Skill。
但 Codex 可能会根据我的提示词和当前任务自动判断并使用。
所以我会想知道:
我的提示词,到底有没有成功让 Codex 命中我希望它使用的 MCP 或 Skill?
这对后面调整提示词也很有帮助。
这些问题最后其实都指向同一个需求:
我想知道 Codex 在执行任务的过程中,到底发生了什么。
而 Hook,刚好提供了这样一个入口。
Hook 到底是什么?
Hook 这个名字听起来比较技术化,但其实很好理解。
一句话概括:
当 Codex 中某个事件发生以后,自动触发我们提前准备好的程序。
关键在于:
先发生事件,再触发 Hook。

这里最重要的是理解:
Hook 是从 Codex 原本执行流程旁边额外分出来的一条支线。
并不是:
Codex → Hook → Codex
而是:
text
→ Hook → 自定义逻辑
/
Codex → 事件发生
\
→ Codex 继续执行
所以可以把 Hook 理解成:
在 Codex 的执行过程中,对某些事件进行监听。
事件发生以后,自己的程序就可以出来做点事情。
几个比较容易理解的 Hook
Codex 里的 Hook 不少,不过刚开始不用全部记住。
理解几个比较常见的事件就够了。

可以简单理解成:
UserPromptSubmit
用户提交任务。
事件发生以后,可以触发 Hook,记录:
这一轮任务开始了。
PreToolUse / PostToolUse
Codex 准备调用工具,或者工具调用完成。
这里就可以记录:
- MCP
- Shell
- 文件工具
- 其他工具调用
SubagentStart / SubagentStop
子 Agent 启动或结束。
于是可以知道:
- 有没有启动子 Agent
- 启动了几个
- 分别是什么
Stop
当前任务结束。
这时候可以把前面收集到的信息统一整理。
一个任务统计是怎么产生的?
如果以我前面的任务统计为例,本质上就是下面这个过程:

也就是说:
事件负责告诉我们发生了什么,Hook 负责处理这些事件。
最后再把需要的信息汇总起来。
这样才有了文章开头看到的那一段任务摘要。
Hook 不只是用来做统计
任务统计只是 Hook 的一种使用方式。
Hook 真正有意思的地方在于:
事件发生以后,你可以决定自己的程序做什么。
例如:

所以从更通俗的角度来说:
Hook 就是 Codex 留给我们的一些事件入口。
Codex 正常完成自己的任务。
而当某些事情发生以后,我们也可以让自己的程序参与进来。
为什么 Hook 现在越来越有用?
以前使用 AI 时,交互通常比较简单:
我问一个问题 → AI 回答
但现在 Codex 一次任务可能会:
分析项目、搜索代码、调用 MCP、启动子 Agent、修改代码、运行测试、继续修改、执行 Git......
当 AI 开始真正替我们完成越来越长、越来越复杂的任务以后,只看最后的答案其实已经不太够了。
以前我可能只关心:
"任务完成了吗?"
现在我还会开始关心:
"它是怎么完成的?"
而 Hook,正好给了我们一个观察这些过程的入口。
最后
如果第一次接触 Codex Hook,其实不用先研究各种配置,也不用记住所有事件名称。
只需要先理解一件事:
Codex 中某个事件发生以后,可以触发 Hook,再由 Hook 运行我们自己的程序。
也就是:

我最开始关注 Hook,也不是因为单纯想研究这个功能。
只是因为 Codex 的任务越来越复杂以后,我想解决一个很具体的问题:
这一轮 Codex,到底干了什么?
而 Hook,正好给了我一个观察这些过程的入口。
结语
以上就是我对 Hook 的理解和应用了,最后我把文中的实现示例的项目地址也放在这。
如果有和我一样需要这样的统计功能,可以直接拿去用,省的自己重新开发。