Skip to content

Hooks 实操指南

用 shell 命令在 Claude Code 生命周期节点自动执行,确定性地控制其行为。

是什么

Hooks 是用户自定义的 shell 命令,在 Claude Code 生命周期的特定节点执行。相比依赖 LLM 自行选择,它提供确定性控制,确保某些动作一定发生,可用于强制项目规则、自动化重复任务、把 Claude Code 接入现有工具链。

除确定性规则外,对需要判断的决策还可用 prompt-based hooks(type: "prompt",由 Claude 模型做单轮判断)和实验性的 agent-based hooks(type: "agent",子代理可读文件、跑命令做多轮校验)。本指南覆盖常见用例与上手;完整事件 schema、JSON 输入输出、async/MCP tool hooks 见 Hooks reference。

怎么工作

  • 在 settings 文件里加 hooks 块;每个事件名是单个 hooks 对象里的一个 key,多个事件名互为同级,不要整体替换
  • 事件触发时,所有匹配的 hooks 并行运行,相同命令会自动去重;全部跑完后 Claude Code 合并结果
  • hook 通过 stdin/stdout/stderr 和 exit code 与 Claude Code 通信:事件数据以 JSON 传入 stdin(含 session_id、cwd、hook_event_name、tool_name、tool_input 等)
  • exit 0 = 无异议正常继续(PreToolUse 不等于批准,仍走正常 permission 流程);exit 2 = 阻断并把 stderr 作为反馈给 Claude;其他 exit code = 动作继续但显示 hook error
  • 需更精细控制时 exit 0 并向 stdout 打印 JSON(如 PreToolUse 的 permissionDecision: allow/deny/ask);不要把 exit 2 与 JSON 混用
  • matcher 用于按事件字段过滤(如 PostToolUse 的 Edit|Write 按工具名);为空则该事件每次都触发
  • type 决定运行方式:command(默认 shell)、http、mcp_tool、prompt、agent

怎么配置 / 用法

上手(macOS 桌面通知,编辑 ~/.claude/settings.json):

json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          { "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'" }
        ]
      }
    ]
  }
}

步骤:1) 把 hooks 块加入 settings 文件(也可让 Claude 帮你写);2) 输入 /hooks 打开浏览器确认 hook 已注册(菜单只读,增删改要直接编辑 JSON 或让 Claude 改);3) 触发一个需要权限的动作来测试。

编辑后自动格式化(项目根 .claude/settings.json):

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }]
      }
    ]
  }
}

什么时候用

  • 强制项目规则(如 PreToolUse + exit 2 阻断对 .env、package-lock.json、.git/ 等受保护文件的修改)
  • 自动化重复任务(编辑后自动跑 Prettier、记录每条 Bash 命令到日志)
  • Claude 需要输入时发桌面通知,便于切去做别的事
  • 会话开始或 compaction 后用 SessionStart 重新注入上下文/项目约定
  • 审计配置变更(ConfigChange)、按目录/文件变化重载环境变量(CwdChanged/FileChanged 配 CLAUDE_ENV_FILE)

限制 / 坑

  • command hooks 只能通过 stdout/stderr/exit code 通信,不能触发 / 命令或工具调用
  • PostToolUse hooks 无法撤销已执行的动作
  • PermissionRequest hooks 在非交互模式(-p)下不触发,应改用 PreToolUse
  • Stop hooks 在 Claude 每次结束响应时都触发(非仅任务完成),用户中断时不触发;连续阻断 8 次后会被覆盖
  • 多个 PreToolUse hook 用 updatedInput 改写同一工具参数时,因并行执行顺序不确定,最后完成者生效

硬事实速查(12 条)

  • 合并规则:PreToolUse 权限决策取最严结果,deny 覆盖 ask 覆盖 allow;一个 hook 返回 deny 不会阻止同级其他 hook 继续执行
  • hook 返回 allow 只跳过交互式提示,不能绕过 settings 里的 deny 规则;managed settings 的 deny 始终优先
  • PreToolUse hook 在权限模式检查之前触发:返回 deny 可在 bypassPermissions 或 --dangerously-skip-permissions 下仍阻断,可强制用户无法绕过的策略
  • 作用域由位置决定:~/.claude/settings.json 全部项目、.claude/settings.json 单项目可提交、.claude/settings.local.json 单项目且 gitignore、managed policy 组织级、plugin 与 skill/agent frontmatter 各有作用域
  • matcher 大小写敏感;MCP 工具命名为 mcp__<server><tool>,可用正则如 mcp__github.* 匹配
  • if 字段(需 v2.1.85+)用 permission rule 语法按工具名+参数过滤,仅对 PreToolUse/PostToolUse/PostToolUseFailure/PermissionRequest/PermissionDenied 生效
  • 超时按类型:command/http/mcp_tool 为 10 分钟(UserPromptSubmit 降到 30 秒),prompt 30 秒,agent 60 秒;可用 timeout 字段(秒)覆盖
  • Stop hook 应解析 stop_hook_active,为 true 时提早 exit 0 避免触顶 8 次阻断上限;可用 CLAUDE_CODE_STOP_HOOK_BLOCK_CAP 提高上限
  • 设为 "disableAllHooks": true 可禁用 hooks;直接编辑 settings 时文件监听通常自动生效,未生效可重启会话
  • 调试:Ctrl+O 看 transcript 每个 hook 的单行摘要;用 claude --debug-file /tmp/claude.log 或会话中 /debug 看完整执行细节
  • JSON 校验失败常因 shell profile 里无条件的 echo 把输出混入;用 if [[ $- == i ]] 仅在交互式 shell 执行 echo
  • 可手动测试:echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh 并检查 echo $?;脚本需 chmod +x,路径用绝对路径或 $CLAUDE_PROJECT_DIR

官方出处:https://code.claude.com/docs/en/hooks-guide