这一篇开始真正创建 Hook。
但我们不会一上来做危险自动化。 第一个 Hook 只做一件事:
``
当 Codex 准备执行命令时,先提醒你检查命令风险。
`
它不修改文件、不删除文件、不联网、不提交代码、不替你批准权限。 它只是一个“执行命令前的提醒器”。
> 前置教程:第一次查看和审查 Hooks
> 如果你还没有用 /hooks 看过来源、事件、命令和信任状态,先完成前置教程。
依据来源:OpenAI Codex 官方手册中 Hooks、/hooks 审查、hooks.json、PreToolUse、matcher、trust review、project .codex/ 受信任后加载等章节。
适合已经做到下面这些事的人:
- 已经能正常打开 Codex CLI。
- 已经知道 AGENTS.md
和config.toml分别负责什么。 - 已经知道 Hook 是生命周期自动化,不是普通提示词。
- 已经用 /hooks
看过当前会话里的 Hook 状态。 - 想让 Codex 用得更专业,但不想一上来引入危险自动化。
如果你只是想让 Codex 记住项目规则,优先用 AGENTS.md。 如果你只是想复用一段写作流程,优先用 Skill。 只有当你希望某个检查“在特定生命周期自动发生”时,才考虑 Hook。
完成后你应该得到:
- 一个项目级 .codex/hooks.json
。 - 一个项目级 .codex/ecosystem/hooks/pre_tool_use_notice.cmd
。 - 一个只匹配 Bash
的PreToolUseHook。 - 一次结果确认,证明它只提醒、不修改文件。
为什么第一个 Hook 要这么保守
Section titled “为什么第一个 Hook 要这么保守”
Hook 的特点是“自动触发”。
普通提示词需要你手动发给 Codex。 AGENTS.md 是 Codex 做事时会参考的项目规则。 Skill 是 Codex 在合适任务中加载的可复用流程。 Hook 则会插入 Codex 的执行生命周期。
也就是说,如果 Hook 写坏了,它可能在你没完全注意时反复运行。 所以第一篇实操必须保守。
本篇 Hook 的设计原则是:
| 设计点 | 本篇选择 | 原因 |
| ------- | --------------------- | ----------------- |
| 位置 | 项目级 .codex/hooks.json | 只影响当前练习项目 |
| 事件 | PreToolUse | 在工具执行前提醒 |
| matcher | ^Bash$ | 只匹配命令执行,不影响所有工具 |
| 命令 | .cmd 脚本 | Windows 用户更容易照着输入 |
| 行为 | 输出官方支持的 Hook JSON | 显示提醒但不修改文件 |
| 超时 | 5 秒 | 防止脚本卡住 |
第 1 步:先让 Codex 检查当前项目
Section titled “第 1 步:先让 Codex 检查当前项目”
不要直接创建 Hook。 先让 Codex 只读检查项目状态。
复制这段给 Codex:
`
请先只读检查当前项目是否适合创建第一个低风险 Hook。
要求:
- 不要创建、修改、删除任何文件。
- Codex 会先读项目结构。
- 如果没有 .codex/
,它会告诉你可以创建。 - 如果已有 Hook,它会提醒你先审查。
- 它不会直接动文件。
- 只创建项目级 Hook。
- 文件只有 .codex/hooks.json
和.codex/ecosystem/hooks/pre_tool_use_notice.cmd。 - 没有出现 Remove-Item
、git commit、git push、联网命令。 - 没有让脚本读取 .env
、API Key、SSH Key。 - 没有把 matcher 写成匹配所有工具。
- 有明确回滚方式。
- 只创建或修改这两个路径:
- .codex/hooks.json
- .codex/ecosystem/hooks/pre_tool_use_notice.cmd
- 展示本次新增或修改的文件列表。
- Codex 会告诉你事件是 PreToolUse
。 - matcher 是 ^Bash$
。 - command 是执行 .cmd
脚本。 - 脚本只输出一行合法 JSON。
- JSON 同时包含 systemMessage
和hookSpecificOutput.additionalContext。 - 没有修改、删除、联网、读取密钥行为。
- 来源是不是当前项目的 .codex/hooks.json
。 - 事件是不是 PreToolUse
。 - matcher 是不是 ^Bash$
或等价的 Bash 匹配。 - command 是否指向 .codex/ecosystem/hooks/pre_tool_use_notice.cmd
。 - 状态是否提示需要审查或信任。
- 检查 .codex/hooks.json 是否存在。
- 不要运行 Hook。
- 来源是你当前练习项目。
- 配置内容你刚刚创建并审查过。
- matcher 只匹配 Bash
。 - 脚本只输出提醒 JSON。
- timeout 很短。
- 回滚方式清楚。
- Codex 准备执行命令前,会显示 systemMessage
提醒。 - 模型会收到 additionalContext
中的风险检查要求。 - Codex 随后才继续做 Git 状态检查。
- 最终不会修改文件。
- 这次任务是否真的触发了 Bash 工具。
- 本次新增文件只有 .codex/hooks.json 和 .codex/ecosystem/hooks/pre_tool_use_notice.cmd。
- Hook 已创建在项目级 .codex/hooks.json。
- 事件为 PreToolUse,matcher 为 Bash。
- 脚本只输出提醒 JSON。
- 未发现修改、删除、联网、读取密钥行为。
- 已通过 /hooks 审查并触发一次。
- 如果 .codex/hooks.json 里只有这个 Hook,可以删除整个 .codex/hooks.json。
- 在任务提示词里写清验收标准。
- 在 AGENTS.md
里写清项目常用检查命令。 - 让 Codex 根据任务和项目规则主动选择检查。
- 等流程稳定后,再考虑用 Hook 做必要提醒或强约束。
- .codex/hooks.json
的关键内容。 - .codex/ecosystem/hooks/pre_tool_use_notice.cmd
的关键内容。 - /hooks` 中看到的来源、事件、matcher 和 command。
- Hook 触发时的提醒内容。
- Codex 对 Hook 风险的中文总结。
- 一段回滚方案。
2. 检查当前目录是不是一个 Git 项目。
3. 检查是否已经存在 .codex/hooks.json。
4. 检查是否已经存在 .codex/ecosystem/hooks/ 目录。
5. 检查是否已经存在项目级 .codex/config.toml。
6. 如果发现已有 Hook,只总结来源、事件、matcher 和 command,不要信任、不要执行。
7. 最后告诉我:是否建议继续创建一个只输出官方 Hook JSON、不修改文件的 PreToolUse Hook。
`
预期结果:
如果 Codex 发现项目里已经有陌生 Hook,不要继续本篇。 先回到前置教程,审查已有 Hook。
第 2 步:让 Codex 生成创建方案
Section titled “第 2 步:让 Codex 生成创建方案”
确认项目适合后,先让 Codex 给方案,不要立刻写文件。
复制这段:
`
请给我一个“第一个低风险 Hook”的创建方案,先不要写文件。
目标:
当 Codex 准备执行 Bash 工具时,运行一个 Windows .cmd 脚本,输出包含 systemMessage 和 additionalContext 的合法 JSON,提醒我检查命令风险。
限制:
2. Hook 配置放在 .codex/hooks.json。
3. 脚本放在 .codex/ecosystem/hooks/pre_tool_use_notice.cmd。
4. 事件使用 PreToolUse。
5. matcher 只匹配 Bash。
6. 脚本只输出合法 Hook JSON,不读取敏感信息,不联网,不修改文件,不删除文件。
7. timeout 设置为 5 秒。
8. 方案里要列出将创建的文件、每个文件的内容摘要、风险点 and 回滚方式。
`
你要检查方案里有没有这些内容:
如果方案看起来不对,直接让 Codex 重写:
`
这个方案风险太高,请改成只输出合法提醒 JSON、不读取任何项目文件、不修改任何文件的版本。
`
第 3 步:让 Codex 创建文件
Section titled “第 3 步:让 Codex 创建文件”
确认方案后,再让 Codex 创建文件。
复制这段:
`
按刚才的方案创建第一个低风险 Hook。
要求:
2. 如果 .codex/hooks.json 已经存在,不要覆盖,先读取并把新增内容合并进去。
3. .cmd 脚本只能输出一行合法 JSON,通过 systemMessage 和 additionalContext 提醒风险。
4. 不要读取 .env、不要读取任何密钥文件、不要联网、不要删除文件、不要提交 Git。
5. 完成后告诉我实际修改了哪些文件,并展示每个文件的关键内容。
`
推荐的 hooks.json 结构应该接近这样:
`
{
"hooks": {
"PreToolUse": [
{
"matcher": "^Bash$",
"hooks": [
{
"type": "command",
"command": "cmd /c .codex\\hooks\\pre_tool_use_notice.cmd",
"timeout": 5,
"statusMessage": "检查命令风险"
}
]
}
]
}
}
`
推荐的 pre_tool_use_notice.cmd 应该接近这样:
`
@echo off
echo {"systemMessage":"即将执行命令,请检查删除、覆盖、密钥、联网和发布风险。","hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"执行命令前先检查:是否删除或覆盖文件、读取密钥、联网、提交或发布。"}}
`
注意:这里直接用 cmd /c 调用 .cmd 文件,和整站的 Windows 命令口径保持一致。PreToolUse 会忽略普通文本 stdout,所以不能只写多行 echo 文案;必须返回官方支持的 JSON 结构。
第 4 步:先看 diff,先不要信任
Section titled “第 4 步:先看 diff,先不要信任”
创建完成后,继续让 Codex 检查改动。
复制这段:
`
请检查刚才创建的 Hook 文件。
要求:
2. 总结 .codex/hooks.json 的事件、matcher、command、timeout。
3. 总结 .codex/ecosystem/hooks/pre_tool_use_notice.cmd 是否只输出合法提醒 JSON。
4. 明确判断它是否会修改文件、删除文件、联网、读取密钥。
5. 如果存在风险,先不要继续,让我确认。
`
预期结果:
如果 Codex 说不清楚,就不要信任。
第 5 步:打开 /hooks 审查
Section titled “第 5 步:打开 /hooks 审查”
在 Codex CLI 中输入:
`
/hooks
`
你应该看到新 Hook 出现在列表里。
重点检查:
官方手册里说明,非托管命令 Hook 需要审查并信任后才会运行。 所以这里看到“需要信任”是正常现象。
如果 /hooks 看不到它,先不要乱改。 让 Codex 只读排查:
`
我在 /hooks 里看不到刚才创建的 Hook。
请只读排查原因:
2. 检查 JSON 语法是否正确。
3. 检查 hooks 顶层结构是否正确。
4. 检查当前 Codex 会话是否在项目根目录或子目录。
5. 检查项目级 .codex 是否可能尚未被信任。
6. 不要修改任何文件。
`
信任 Hook 前,再问 Codex 一次:
`
请根据 /hooks 中看到的信息,帮我做一次信任前审查。
要求:
2. 解释这个 Hook 什么时候触发。
3. 解释它会执行什么命令。
4. 解释脚本内容是否只输出合法提醒 JSON。
5. 判断是否会修改、删除、联网、读取密钥。
6. 给出是否建议信任的结论。
`
只有当结论明确为低风险,才继续。
你可以信任它的理由应该是:
在 /hooks 中按界面提示信任这个 Hook。
然后发一个会触发命令工具、但本身低风险的任务:
`
请检查当前项目的 Git 状态,并用中文总结。
不要修改任何文件。
`
预期结果:
如果提醒没有出现,不要马上扩大 Hook 范围。 先排查:
`
刚才的任务没有看到 Hook 提醒。
请只读排查:
2. matcher 是否写得过窄。
3. Hook 是否已经被信任。
4. 当前会话是否加载了项目级 Hook。
5. .cmd 脚本路径是否正确。
6. 不要修改任何文件。
`
让 Codex 做最后验收:
`
请验收这个第一个低风险 Hook。
验收标准:
2. Hook 事件是 PreToolUse。
3. matcher 只匹配 Bash。
4. 脚本只输出包含中文提醒的合法 Hook JSON。
5. 没有修改文件、删除文件、联网、读取密钥、提交代码。
6. 我已经能在 /hooks 里看到它。
7. 我已经看到它在命令执行前触发。
请按“通过 / 不通过 / 需要补充”的格式输出。
`
你最终应该得到类似结论:
`
通过:
`
如果你不想继续使用这个 Hook,让 Codex 回滚:
`
请移除刚才创建的第一个低风险 Hook。
要求:
2. 如果 .codex/hooks.json 里还有其他 Hook,只删除本篇教程新增的 PreToolUse Bash 提醒 Hook。
3. 删除 .codex/ecosystem/hooks/pre_tool_use_notice.cmd。
4. 如果 .codex/ecosystem/hooks/ 目录为空,可以删除空目录。
5. 不要删除其他 .codex 配置。
6. 完成后总结删除了哪些文件,保留了哪些文件。
`
如果你只是临时不用,也可以先在 /hooks 中禁用它。 但长期不用的 Hook,不建议留在项目里占位置。
为什么不用 UserPromptSubmit
Section titled “为什么不用 UserPromptSubmit”
因为第一篇实操不要覆盖太宽。
UserPromptSubmit 会在用户提交提示时触发,而且 matcher 不适合像工具事件那样筛选具体工具。 新手第一篇先从 PreToolUse + Bash 开始,更容易理解“什么时候触发”。
因为本篇目标是学会低风险 Hook 的完整流程,不是立刻写安全策略引擎。
真正拦截危险命令需要解析命令内容、处理误判、处理跨平台差异,还要明确哪些命令允许、哪些命令拒绝。 这属于后续进阶内容。
Codex 本身在很多任务中会根据上下文主动做构建、测试或检查。 Hook 不应该一开始就替你强行加测试流程。
更专业的做法是:
能,但第一篇不建议。
用户级 ~/.codex/hooks.json 会影响你的多个项目。 如果写错,影响范围更大。 先在练习项目里完成一次,确认自己理解事件、matcher、信任 and 回滚,再考虑用户级。
完成本篇后,你应该能拿出:
只要这些都具备,你就完成了第一个低风险 Hook。
下一步才适合继续学习 Subagents,或者把 Hook 从“提醒”升级成“检查”,但那已经不是第一篇 Hook 实操该做的事。