Codex 钩子技巧:在命令执行前后自动跑检查脚本

发布于 2026-10-31 · 5 分钟读完 · Codex / 使用技巧 / Hooks

Codex 的钩子(Hooks)能在工具调用前后、发出提示词时、每轮结束时自动运行脚本。本文讲清楚钩子写在哪、有哪些时间点,以及拦截危险命令、自动复查、拦住误贴密钥三个实用写法。

想在 Codex 执行命令前自动检查一遍、在每轮对话结束时自动跑校验,或者防止把 API 密钥误贴进对话,可以用 Codex 的「钩子」(Hooks)。钩子会在 Codex 工作的固定时间点运行你写的脚本或 MCP 工具。本文按官方文档讲清楚钩子写在哪、有哪些时间点、怎么拦截命令,以及几个实用写法。

钩子能做什么

官方文档列出的典型用法有:

  • 把对话记录发到自己的日志或统计系统;
  • 扫描团队的提示词,拦住误贴的 API 密钥;
  • 自动总结对话,生成长期记忆;
  • 每轮对话结束时跑一遍自定义检查,确保符合团队规范;
  • 在特定目录下自动补充提示内容。

钩子默认开启。不想用时,在 config.toml 里写:

[features]
hooks = false

钩子写在哪里

Codex 会在配置所在的位置查找钩子,可以写成单独的 hooks.json,也可以写在 config.toml 的 [hooks] 表里。最常用的四个位置:

  • ~/.codex/hooks.json
  • ~/.codex/config.toml
  • <项目>/.codex/hooks.json
  • <项目>/.codex/config.toml

几处都有钩子时,Codex 会全部加载,高优先级的配置不会覆盖低优先级的钩子。同一层里既有 hooks.json 又有 [hooks] 时会合并并在启动时警告,建议每层只用一种写法。项目里的钩子只有在项目的 .codex/ 被信任后才会加载。

有哪些时间点

  • 一轮对话进行中:PreToolUse(工具调用前)、PermissionRequest(申请权限时)、PostToolUse(工具调用后)、PreCompact / PostCompact(压缩对话前后)、UserPromptSubmit(你发出提示词时)、SubagentStop、Stop(一轮结束时)。
  • 你打断正在进行的一轮时:Interrupt。
  • 会话或子代理开始时:SessionStart、SubagentStart。
  • 主会话结束时:SessionEnd。

配置长什么样

钩子分三层:事件 → 匹配规则(matcher)→ 要运行的处理程序。下面这个例子在 Codex 每次执行 Bash 命令前运行一个检查脚本:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py\"",
            "statusMessage": "Checking Bash command",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

几个要点:

  • matcher 是正则表达式,写 "*"、留空或不写就匹配全部。工具类事件按工具名匹配,例如 Bash、Edit|Write、mcp__filesystem__.*。
  • timeout 单位是秒,不写时大多数钩子默认 600 秒;SessionEnd 和 Interrupt 默认 1 秒,最多 3 秒。
  • 脚本在会话的工作目录下运行。项目里的钩子建议像上例那样从 git 根目录找脚本,避免从子目录启动 Codex 时找不到。
  • Windows 上可以用 commandWindows 单独指定命令。
  • 处理程序支持 command(运行脚本)和 mcp_tool(调用已连接的 MCP 服务器上的工具)两种。

技巧一:在命令执行前拦截危险操作

PreToolUse 钩子会从标准输入收到一个 JSON,里面有 tool_name、tool_input 等字段,Bash 命令的内容在 tool_input.command 里。脚本判断要拦截时,输出:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Destructive command blocked by hook."
  }
}

更简单的做法是以退出码 2 结束,并把原因写到标准错误输出。不想拦截、只想提醒模型时,返回 additionalContext 字段,这段文字会作为补充信息交给模型。还可以返回 permissionDecision: "allow" 加 updatedInput,直接改写要执行的命令。

技巧二:一轮结束时自动再检查一遍

Stop 钩子在每轮结束时运行,必须输出 JSON。如果检查没通过,返回:

{
  "decision": "block",
  "reason": "Run one more pass over the failing tests."
}

这里的 block 不是拒绝,而是让 Codex 继续干活:Codex 会把 reason 当作一条新的提示词自动接着做。输入里的 stop_hook_active 字段告诉你这一轮是不是已经被 Stop 钩子续过,脚本里判断一下,避免无限循环。

技巧三:拦住误贴的密钥

UserPromptSubmit 钩子会收到你即将发送的提示词(prompt 字段)。脚本发现里面有密钥格式的内容时,返回 {"decision": "block", "reason": "..."} 或以退出码 2 结束,这条提示词就不会发出去。

安全机制:先审查再运行

非托管的钩子必须先经过你审查、信任,才会运行。Codex 按钩子定义的哈希值记录信任,钩子一改就要重新审查。在命令行里输入 /hooks 可以查看钩子来源、审查新钩子、信任或停用某个钩子。插件自带的钩子也一样,装了插件不等于自动信任。

官方也提醒:钩子是有用的防护,但不是完整的强制边界,像网页搜索这类托管工具不走钩子。

上手建议

先从一个只记录日志的 PostToolUse 钩子开始,确认能收到 JSON、能正常运行,再加拦截规则。钩子输出要简短,多个钩子的内容会叠加进上下文,太长会影响模型表现。

钩子在本地 Codex 里使用,用 ChatGPT 账号登录后,用量跟着会员套餐走。还没有会员的,可以在 BuyBuy代充(buybuytopup.cn) 开通 ChatGPT Plus,开通后就能照本文配置钩子。

参考资料

  1. Hooks(OpenAI 官方文档)

需要 AI 会员?

BuyBuy代充提供 ChatGPT(含 Codex)等会员套餐,支付宝、微信付款,付款后自动发货。

查看全部套餐
AI 会员 自动发货

ChatGPT Plus

适合当前为免费版的账号。付款后自动发卡密,按说明自助兑换。

¥149.00 10月21日更新 · 以下单时价格为准 平台支付手续费另计
AI 会员 自动发货

ChatGPT Pro 100

适合当前为免费版的账号。付款后自动发卡密,按说明自助兑换。

¥838.50 10月21日更新 · 以下单时价格为准 平台支付手续费另计

更多文章

全部文章