---
title: "用 Hooks 接入自动检查"
description: "基于官方 Codex Hooks 教程，讲清 hooks 能做什么、不能做什么，以及如何从低风险检查开始。"
verifiedAt: "2026-05-06"
---

import { Cards, Card } from 'fumadocs-ui/components/card';

Hooks 是 Codex 的扩展机制：在会话、提示词提交、工具调用、权限请求、工具调用结束、turn 停止等节点运行脚本。它适合做自动检查、日志记录、策略提醒和团队规范执行。

> [!CAUTION]
> Hook 不是让 Codex 更聪明的魔法。它是在工作流旁边插入脚本；脚本写错了，会打断体验、泄露信息，甚至放大权限风险。

<Cards>
  <Card title="Hooks" href="https://developers.openai.com/codex/hooks">
    官方 Hooks 配置、事件、matcher 和输出格式。
  </Card>
  <Card title="Build plugins" href="/docs/codex/official/03-extensions/69-build-plugins">
    需要分发生命周期配置时，再把 hook 放进 plugin。
  </Card>
  <Card title="Approvals" href="/docs/codex/official/02-config-security/07-approval-security">
    Hooks 不能替代 sandbox、approval 和代码审查。
  </Card>
</Cards>

## 它解决什么

```mermaid
flowchart LR
    Prompt["UserPromptSubmit"] --> Check["敏感信息 / 范围检查"]
    Tool["PreToolUse"] --> Policy["命令 / 路径策略"]
    Result["PostToolUse"] --> Review["输出审查"]
    Stop["Stop"] --> Continue["遗漏验证时继续"]
```

Hooks 适合做边界清楚的检查：

- 用户提交 prompt 前，检查是否误粘贴 API key。
- 工具运行前，检查危险命令或禁止路径。
- 权限请求时，把团队策略加到审批环节。
- 工具运行后，审查输出或补充上下文。
- turn 停止时，要求再跑一次验证。

Hooks 不适合做复杂业务逻辑，也不适合替代测试框架。它应该只做“是否允许继续”“是否补充上下文”“是否提示用户注意”的轻量决策。

## 启用和加载位置

Hooks 需要在 `config.toml` 打开 feature：

```toml
[features]
codex_hooks = true
```

Codex 会在 active config layers 旁边发现：

- `hooks.json`
- `config.toml` 里的 inline `[hooks]`

常见位置：

- `~/.codex/hooks.json`
- `~/.codex/config.toml`
- `<repo>/.codex/hooks.json`
- `<repo>/.codex/config.toml`

项目本地 hooks 只会在项目 `.codex/` layer 受信任时加载。一个层级里不要同时维护 `hooks.json` 和 inline hooks；官方会合并并给 warning，但新手排障会更难。

## 事件怎么选

- `UserPromptSubmit`：用户输入发给模型前。适合检查敏感信息、任务范围、是否需要补充上下文。
- `PreToolUse`：工具执行前。适合拦截危险 shell、禁止路径、提醒确认。
- `PermissionRequest`：权限请求时。适合把团队审批策略放进请求前后。
- `PostToolUse`：工具执行后。适合审查命令输出或把额外上下文反馈给 Codex。
- `Stop`：turn 结束时。适合发现测试没跑、文档没同步时让 Codex 继续。
- `SessionStart`：session 启动、恢复或清空时加载上下文。

注意两个细节：

- `UserPromptSubmit` 和 `Stop` 当前不使用 matcher。
- `PreToolUse`、`PermissionRequest`、`PostToolUse` 的 matcher 过滤 tool name，例如 `Bash`、`apply_patch` 或 MCP tool name。

## 第一版怎么做

第一版只做一个只读 hook，例如在 `UserPromptSubmit` 上检查 prompt 是否包含疑似 key。不修改文件，不运行复杂命令。

第二版再做 `PreToolUse`，只针对 `Bash` 或 `apply_patch`。matcher 要窄，不要全局匹配所有工具。

第三版再做 `PostToolUse` 或 `Stop`。这时你已经知道 hook 输入输出长什么样，也知道它对体验的影响。

不要一开始就把所有事件都挂上脚本。官方说明，同一个 event 上多个匹配 command hooks 会并发启动，一个 hook 不能阻止另一个匹配 hook 启动。

## 输出语义要写对

所有 command hook 都会从 `stdin` 收到一个 JSON 对象，常见字段包括 session id、当前 cwd、hook event name、模型、turn id 等。

`UserPromptSubmit` 可以输出额外 developer context，也可以 block prompt。

`PostToolUse` 发生在工具完成后，所以它不能撤销已经执行的 Bash 命令。它能把反馈传回 Codex，让后续处理从 hook 反馈继续。

`Stop` 的 block 不是拒绝本轮，而是让 Codex 继续，并把 reason 作为 continuation prompt。`Stop` 退出 0 时需要输出 JSON，plain text 对这个事件无效。

## 常见坑

- Hook 里做太多事：它应该短、小、可预测。
- matcher 太宽：每次操作都触发脚本，体验会变慢，也更容易误拦截。
- 忘记并发：多个匹配 hooks 会并发启动。
- 把 prompt、cwd、tool input、token 写进日志。
- 以为 `PostToolUse` 能撤销命令。
- 忽略 `Stop` 的 continuation 语义。
- 在不受信任项目里期待 project hook 生效。

## 验收清单

- 启动后没有 hooks 配置 warning。
- 目标事件确实触发。
- hook 能收到必要字段，但日志不保存敏感内容。
- 允许时不打断流程，拦截时给出人能理解的原因。
- 脚本异常、超时或输出非法 JSON 时，Codex 行为符合预期。
- 关闭 hook 后，相同任务能恢复正常，说明没有留下额外副作用。

## 官方资料

- [Hooks](https://developers.openai.com/codex/hooks)
- [Build plugins: bundled lifecycle config](https://developers.openai.com/codex/plugins/build#bundled-mcp-servers-and-lifecycle-config)
- [Agent approvals and security](https://developers.openai.com/codex/agent-approvals-security)
