Hooks 是什么
Hooks 是钩子,挂在生命周期事件(event)上,事件一旦触发,脚本必跑
常用的生命周期事件 event
- SessionStart 会话开始
- PreToolUse 工具调用之前
- PostToolUse 工具调用之后
- Stop 会话结束
- PreCompact / PostCompact 压缩前后
- PermissionRequest 审批请求时
常用的应用场景
| 事件 | 什么时候触发 | 最典型的用法 |
|---|---|---|
SessionStart | 会话开始 / 恢复时 | 往上下文里注入项目状态(如最近的提交) |
PreToolUse | 某个工具执行前 | 拦危险命令、改写命令(能阻止操作) |
PostToolUse | 某个工具产出结果之后 | 改完文件自动格式化 / 跑 lint |
Stop | Codex 答完这一轮 | 让它「再多跑一趟」(比如把没过的测试再修一遍) |
PermissionRequest | 将要弹审批弹窗时 | 自动放行或拒绝 |
钩子的配置放在哪个文件
可以放在全局针对所有项目,也可以放在特定项目中,不同之处在于:
| 配置文件 | 生效范围 | 能共享给团队吗 |
|---|---|---|
~/.codex/hooks.json | 你所有项目 | 否,只在你这一台机器 |
~/.codex/config.toml | 你所有项目 | 否 |
<repo>/.codex/hooks.json | 仅当前项目 | 是,可提交进 git |
<repo>/.codex/config.toml | 仅当前项目 | 是 |
一个配置示例
{
"hooks": {
"PostToolUse": [ // 表示挂哪个事件(这里是:工具产出结果后)。
{
// 很重要,虽然钩子有要挂的事件,但并非所有的操作或者工具都需要触发它,
// matcher 就是用来收窄范围的,让 hook 只在该触发的时候触发(`Bash`就代表只在跑 bash 命令的时候触发)
"matcher": "Bash",
// 真正要跑的动作
"hooks": [
{
// 表示跑一条 shell 命令
"type": "command",
// 具体的要跑的命令
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use.py\"",
"timeout": 30,
// 看是否影响主流程,true 表示钩子转到后台跑
"sync": false,
"statusMessage": "Reviewing Bash output"
}
]
}
]
}
}
"matcher" 很重要,虽然钩子有要挂的事件,但并非所有的操作或者工具都需要触发它,matcher 就是用来收窄范围的,让 hook 只在该触发的时候触发。
matcher 有哪些值
| 值 | 含义 | 比如 |
|---|---|---|
"Bash" | 匹配 Bash 工具 | 只在跑 Bash 命令时触发 |
"^apply_patch$" | 用正则精确匹配 | 只在改文件时触发 |
"Edit|Write" | 改文件的别名(| 是正则的「或」) | 只在编辑 / 写文件之后触发 |
"mcp__filesystem__.*" | 正则匹配一批 MCP 工具 | 这个 MCP server 的所有工具 |
"*" / "" / 省略 | 匹配所有 | 该事件每次发生都跑 |
好了,光看不练记不住。下面教你5分钟配一个钩子——每次 Codex 跑完 Bash 命令,就把这条命令记进一个日志文件。全程不动你任何代码,纯加一段配置,跑完能亲眼验证。
动手
第一步:找个练手目录,建钩子脚本和配置
在你的项目根目录下新建一个脚本文件 codex/hooks/log-bash.py,写入以下内容:
#!/usr/bin/env python3
import json, sys, os
data = json.load(sys.stdin)
command = data.get("tool_input", {}).get("command", "")
log = os.path.expanduser("~/codex-bash-log.txt")
with open(log, "a") as f:
f.write(command + "\n")
在你的项目根目录下新建一个 hook 文件 codex/hooks.json,写入以下内容:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/log-bash.py\"",
"statusMessage": "记录 Bash 命令"
}
]
}
]
}
}
第二步:重启 Codex,进入项目,信任钩子
这里标着待审核👇
选中它、确认命令无误后信任它👇
第三步:让 Codex 跑条 Bash 命令,触发钩子
在对话中输入:
帮我用 ls 看一下当前目录有哪些文件
它会调用 Bash 工具跑 ls。这一跑,PostToolUse 就会被触发
第四步:验证钩子真跑了—-查日志文件
终端/对话输入:
cat ~/codex-bash-log.txt
达到预期:文件里出现了刚才那条 ls命令,也就验证了钩子真的在每次 Bash 后自动触发了。
写在最后
跑通这五步,你就把「写配置 一 /hooks 信任 一 触发事件 一 验证副作用」这条完整链路亲手走了一遍。以后配任何钩子,本质都是这套流程,无非换个事件、换个 matcher、另外不要忘了「信任」这一步。
愿 Codex 成为你顺手的前端协作者,而不是新的折腾来源。我们下一篇再见 👋