你有没有想过:能不能在Claude Code执行某些操作前,自动跑一些检查?或者在会话结束时,自动提交代码?

Hooks系统就是干这个的。它让你在AI Agent的生命周期关键节点"插一脚",执行自定义逻辑。

什么是Hooks?自定义拦截点

Hooks就像机场的安检关卡:在特定位置设置检查点,符合条件的旅客(操作)要经过检查才能通过。

Claude Code支持26个Hook事件,覆盖整个生命周期:

会话生命周期

  • SessionStart:会话开始
  • Setup:仓库初始化
  • SessionEnd:会话结束

工具执行生命周期

  • PreToolUse:工具执行前
  • PostToolUse:工具执行成功
  • PostToolUseFailure:工具执行失败
  • PermissionRequest:权限请求时
  • PermissionDenied:权限被拒绝

响应生命周期

  • UserPromptSubmit:用户提交提示词
  • Stop:AI即将结束响应
  • StopFailure:API错误导致回合结束

多Agent生命周期

  • SubagentStart:子Agent启动
  • SubagentStop:子Agent结束
  • TeammateIdle:队友进入空闲
  • TaskCreated/Completed:任务创建/完成

文件与配置变更

  • FileChanged:监听文件变更
  • CwdChanged:工作目录变更
  • ConfigChange:配置变更
  • InstructionsLoaded:CLAUDE.md加载

其他

  • PreCompact/PostCompact:压缩前后
  • Elicitation/ElicitationResult:MCP交互
  • WorktreeCreate/Remove:工作树操作

四种Hook类型

Hooks支持四种执行方式:

1. command类型:Shell命令

最基础的方式,执行Shell脚本:

{
  "type": "command",
  "command": "echo 'Hello from hook'",
  "shell": "bash",
  "timeout": 60,
  "if": "Bash(git *)"
}

特点:

  • 支持bashpowershell
  • 可以用if条件过滤(权限规则语法)
  • 超时默认10分钟,SessionEnd默认1.5秒

2. prompt类型:LLM评估

把Hook输入发给轻量级LLM评估:

{
  "type": "prompt",
  "prompt": "检查这个操作是否安全: $ARGUMENTS",
  "model": "claude-haiku-4-5"
}

$ARGUMENTS会被替换为Hook输入的JSON。

3. agent类型:Agent验证器

启动完整Agent循环来验证条件:

{
  "type": "agent",
  "prompt": "检查单元测试是否通过",
  "timeout": 120,
  "model": "claude-sonnet-4-6"
}

这是最强大的类型,可以执行复杂验证。

4. http类型:Webhook

POST到指定URL:

{
  "type": "http",
  "url": "https://example.com/hook",
  "headers": {"Authorization": "Bearer $TOKEN"},
  "allowedEnvVars": ["TOKEN"]
}

注意:HTTP Hook不支持SessionStartSetup事件。

退出码语义:Hook如何与Claude Code通信

Hook通过退出码传递决策:

退出码含义行为
0成功/允许stdout/stderr不显示(或仅在transcript模式显示)
2阻塞错误stderr发送给模型,阻塞当前操作
其他非阻塞错误stderr仅显示给用户,操作继续

不同事件的退出码2有特殊行为:

  • PreToolUse:阻止工具调用,stderr给模型
  • Stop:stderr给模型,但继续对话(实现"继续编码"模式)
  • UserPromptSubmit:阻塞处理,擦除原始提示词,仅显示stderr
  • SessionStart/Setup:阻塞错误被忽略(不允许阻塞启动)

JSON输出协议

除了退出码,Hook可以通过stdout输出JSON传递结构化信息:

{
  "continue": false,
  "decision": "block",
  "reason": "代码格式不符合prettier",
  "systemMessage": "请格式化代码后再提交"
}

对于PreToolUse事件,还可以修改工具输入:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "updatedInput": {
      "file_path": "/new/path.ts"
    }
  }
}

实战配置示例

示例1:PreToolUse格式检查

在写入TypeScript文件前自动检查格式:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(echo $ARGUMENTS | jq -r '.file_path') && prettier --check \"$CLAUDE_PROJECT_DIR/$FILE\" || echo '{\"decision\":\"block\",\"reason\":\"格式检查失败\"}'",
            "if": "Write(*.ts)",
            "statusMessage": "检查格式..."
          }
        ]
      }
    ]
  }
}

示例2:自动提交

会话结束时自动提交未保存的更改:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "检查是否有未提交的更改,如果有,创建合适的commit并提交",
            "timeout": 120
          }
        ]
      }
    ]
  }
}

示例3:环境初始化

会话开始时设置开发环境:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'export NODE_ENV=development' >> $CLAUDE_ENV_FILE",
            "statusMessage": "设置开发环境..."
          }
        ]
      }
    ]
  }
}

异步与后台执行

Hook可以通过两种方式后台执行:

配置声明

{
  "type": "command",
  "command": "long-running-task",
  "async": true
}

或:

{
  "asyncRewake": true
}

asyncRewake特殊:后台Hook退出码为2时,会唤醒模型继续处理。

运行时声明

Hook在第一行输出{"async": true},立即进入后台。

信任门控

Hooks执行需要信任确认:

  • 非交互模式(SDK):信任隐含,直接执行
  • 交互模式:需要信任对话框确认

这是纵深防御:即使有人恶意配置了危险Hook,用户不点"信任"就不会执行。

配置来源与合并

Hooks可以来自多个来源:

  1. 配置快照(settings.json)
  2. 注册式Hook(SDK callback、插件原生Hook)
  3. 会话Hook(Agent frontmatter注册)
  4. 会话函数Hook(结构化输出强制器)

来源按优先级合并,支持allowManagedHooksOnly策略限制。

模式提炼

模式1:退出码即协议

Shell命令与宿主进程之间需要轻量级语义通信。定义明确的退出码契约:

  • 0 = 成功/允许
  • 2 = 阻塞错误
  • 其他 = 非阻塞错误

模式2:配置快照隔离

配置文件可能在运行时修改。在启动时捕获快照,运行时使用快照而非实时读取。用户显式修改时更新快照。

模式3:命名空间化去重

同一Hook可能出现在多个配置源。去重键包含来源上下文,同一命令在不同插件保持独立,在同一来源层级合并。

总结

Hooks系统是Claude Code的可扩展性核心:

  • 26个事件点:覆盖完整生命周期
  • 四种类型:command、prompt、agent、http
  • 退出码语义:简单有效的通信协议
  • 信任门控:安全的默认行为
  • 配置合并:多来源支持

这就像:

  • 机场安检(拦截检查)
  • 自动驾驶的接管机制(人工介入)
  • CI/CD的流水线(自动化流程)

理解Hooks,你就能:

  • 自定义Claude Code的行为
  • 实现项目特定的自动化
  • 在自己的AI Agent中设计扩展点

下篇咱们聊聊Agent集群——当AI开始"组队打怪"。