Codex Hooks 入门实战:生命周期事件、matcher 与5分钟跑通一个钩子

0 阅读3分钟

Hooks 是什么

Hooks 是钩子,挂在生命周期事件(event)上,事件一旦触发,脚本必跑

常用的生命周期事件 event

  • SessionStart 会话开始
  • PreToolUse 工具调用之前
  • PostToolUse 工具调用之后
  • Stop 会话结束
  • PreCompact / PostCompact 压缩前后
  • PermissionRequest 审批请求时

常用的应用场景

事件什么时候触发最典型的用法
SessionStart会话开始 / 恢复时往上下文里注入项目状态(如最近的提交)
PreToolUse某个工具执行前拦危险命令、改写命令(能阻止操作)
PostToolUse某个工具产出结果之后改完文件自动格式化 / 跑 lint
StopCodex 答完这一轮让它「再多跑一趟」(比如把没过的测试再修一遍)
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,进入项目,信任钩子

这里标着待审核👇 image.png

选中它、确认命令无误后信任它👇

image.png

第三步:让 Codex 跑条 Bash 命令,触发钩子

在对话中输入:

帮我用 ls 看一下当前目录有哪些文件

它会调用 Bash 工具跑 ls。这一跑,PostToolUse 就会被触发

image.png

第四步:验证钩子真跑了—-查日志文件

终端/对话输入:

cat ~/codex-bash-log.txt

image.png

达到预期:文件里出现了刚才那条 ls命令,也就验证了钩子真的在每次 Bash 后自动触发了。

写在最后

跑通这五步,你就把「写配置 一 /hooks 信任 一 触发事件 一 验证副作用」这条完整链路亲手走了一遍。以后配任何钩子,本质都是这套流程,无非换个事件、换个 matcher、另外不要忘了「信任」这一步。

愿 Codex 成为你顺手的前端协作者,而不是新的折腾来源。我们下一篇再见 👋