Claude Code 高阶用户自定义:如何配置 hooks
学习如何配置 Claude Code hooks,用它们自动处理重复任务、执行项目规则,并把动态上下文注入你的编码 session。
即使 Claude Code 工作流已经很顺畅,时间久了也会积累摩擦点。每次 Claude 写文件后,都要手动运行 Prettier。每次它运行 npm test,都出现同样的权限提示。每个 session 开始时,你都要把同一段项目背景样板粘到第一条消息里。
好消息是,hooks 可以消除这些摩擦点。它们是你可以配置的触发器,会在某些动作之前或之后触发,让你把自定义逻辑、脚本和命令直接接入 Claude 的操作流程。
本文面向已经熟悉 Claude Code 基础的开发者,介绍高级配置。读完后,你会理解八种 hook 类型、各自适用场景、如何配置,以及出问题时如何调试。
我们开始吧。
什么是 hook?
Hook 是你创建的自定义 shell 命令,当 Claude Code session 中发生目标事件时会自动执行,例如 Claude 即将写文件,或你提交 prompt 时。你可以把 hooks 用在很多事情上:在动作执行前拦截、注入 Agent 上下文、自动批准操作,或在操作发生前阻止它。
Hooks 在设置文件中通过 JSON 结构配置,包含事件名、matchers(用于过滤哪些工具会触发 hook)以及要运行的命令。它们以你的用户权限在本地环境执行,通过 stdin 接收触发事件的信息,并通过 exit codes 和 stdout 回传结果。这让你无需修改 Claude Code 本身,就能精确控制它的行为。
为什么在 Claude Code 中使用 hooks?
Hooks 解决三类问题。
第一,它们消除重复的手动步骤。无需在每次文件变更后手动运行格式化工具,PostToolUse hook 会自动处理。无需第无数次批准 npm test,PermissionRequest hook 可以自动批准它。
第二,hooks 会自动执行项目特定规则。你可以在危险命令执行前阻止它们,在写入前验证文件路径,或确保命名约定被遵守。这些护栏每次都会运行,而不是只在你想起来检查时运行。
第三,hooks 无需人工操作就能注入动态上下文。SessionStart hook 可以把当前 git 状态和 TODO list 提供给 Claude。UserPromptSubmit hook 可以把你的 sprint 优先级追加到每次请求中。Claude 会保持了解情况,而你不必反复说明。
Claude Code hook 类型以及何时使用
Claude Code 提供八种 hook events,覆盖 session 的完整生命周期:从启动,到工具执行,再到完成。每种 hook 都在特定时刻触发,让你精确控制自动化何时运行。选择哪个 hook 取决于你想完成什么。
Hooks 概览
PreToolUse
这是最常用的 hook,在 Claude 选择要使用的工具之后、工具真正执行之前触发。你的脚本可以检查计划中的动作,并批准、阻止、请求用户确认或修改参数,同时用 matcher 过滤哪些工具会触发这个 hook。
这个 PreToolUse hook 示例会在文件写入执行前评估它。Claude 会根据指定标准审查计划动作,并可依据 prompt 逻辑批准、阻止或标记疑虑。
{ "hooks" : { "PreToolUse" : [ { "matcher" : "Write" , "hooks" : [ { "type" : "command" , "command" : "/path/to/validate-file-path.sh" } ] } ] } }
何时使用 PreToolUse:
• 阻止 rm -rf 或 force pushes 等危险 Bash 命令
• 自动批准安全、重复的操作,减少提示疲劳
• 写入前验证文件路径,防止意外覆盖
• 修改工具输入,注入项目特定默认值
PermissionRequest
当 Claude 通常会显示权限对话框时,这个 hook 会触发。它会拦截你看到确认提示之前的那一刻,让你的脚本决定允许、拒绝,还是仍然询问用户。
{ "hooks" : { "PermissionRequest" : [ { "matcher" : "Bash(npm test*)" , "hooks" : [ { "type" : "command" , "command" : "/path/to/validate-test-command.sh" } ] } ] } }
这个示例会自动批准任何以 npm test 开头的 Bash 命令。matcher pattern 可以包含参数,实现更细粒度的控制。
何时使用 PermissionRequest:
• 自动批准每个 session 中会运行几十次的测试命令
• 阻止写入生产配置文件
• 允许对特定目录执行读取操作而不弹出提示
• 拒绝任何匹配危险模式的命令
PostToolUse
工具成功完成后立即触发。你的脚本会收到发生了什么的信息,包括工具输出,并可以用 matchers 过滤哪些工具会触发它。
这个 PostToolUse 示例会在 Claude 写入或编辑任何文件后运行 Prettier。matcher 中的管道语法表示 Write 和 Edit 工具都会触发它。
{ "hooks" : { "PostToolUse" : [ { "matcher" : "Write|Edit" , "hooks" : [ { "type" : "command" , "command" : "prettier --write \"$CLAUDE_TOOL_INPUT_FILE_PATH\"" } ] } ] } }
何时使用 PostToolUse:
• 每次写文件后运行 Prettier、Black 或 gofmt,强制格式化
• 把所有文件修改记录到审计日志
• 代码变更后触发 linters 并显示 warning
• 某些操作完成后发送通知
PreCompact
Claude 为释放空间而压缩对话上下文之前触发。压缩会总结对话的较早部分,这意味着一些细节会丢失。这个 hook 给你一次在压缩前保存信息的机会。
这个 PreCompact 示例会在自动压缩前备份 transcript。matcher 可以是 "auto" 或 "manual",因此你可以区分自动压缩和用户触发的压缩事件。
{ "hooks" : { "PreCompact" : [ { "matcher" : "auto" , "hooks" : [ { "type" : "command" , "command" : "/path/to/backup-transcript.sh" } ] } ] } }
何时使用 PreCompact:
• 在总结前把完整 transcript 备份到文件
• 提取并保存重要决策或代码片段
• 记录 session 里程碑,方便之后复盘
SessionStart
当 Claude Code 启动新 session 或恢复现有 session 时触发。你的脚本输出的任何内容都会被加入对话上下文,因此 Claude 一开始就已经加载这些信息。
{ "hooks" : { "SessionStart" : [ { "hooks" : [ { "type" : "command" , "command" : "git status --short && echo '---' && cat TODO.md" } ] } ] } }
每个 session 开始时,Claude 都会知道你当前的 git 状态和 TODO list。stdout 会自动变成上下文。
何时使用 SessionStart:
• 把当前 git branch 和最近 commits 提供给 Claude
• 加载 TODO list 或 sprint backlog 的内容
• 注入环境特定的配置细节
Stop
当 Claude 完成响应、通常会等待你下一次输入时触发。你的脚本可以检查 Claude 生成的内容,并决定任务是否真正完成。
脚本可以返回包含 "continue": true 的 JSON,让 Claude 继续工作,这对多步骤工作流很有用:
{ "hooks" : { "Stop" : [ { "hooks" : [ { "type" : "prompt" , "prompt" : "Review whether the task is complete. If all requirements are met, respond with 'complete'. If work remains, respond with 'continue' and specify what still needs to be done." } ] } ] } }
何时使用 Stop:
• 强制 Claude 继续,直到 checklist 中所有事项完成
• 在认为任务完成前验证测试通过
• 在 session 结束时触发摘要生成
• 停止前检查生成的代码能否编译
SubagentStop
当通过 Task 工具创建的 subagent 完成时,这个 hook 会触发。它的工作方式和 Stop 相同,但专门在 subagent 完成动作时触发,而不是主 Agent。SubagentStop 的配置结构与 Stop hook 一致:
{ "hooks" : { "SubagentStop" : [ { "hooks" : [ { "type" : "prompt" , "prompt" : "Evaluate the subagent's output. Verify the task was completed correctly and the results meet quality standards. If the output is satisfactory, respond with 'accept'. If issues exist, respond with 'reject' and explain what needs to be fixed." } ] } ] } }
何时使用 SubagentStop:
• 验证 subagent 输出是否满足质量标准
• 根据 subagent 结果触发后续动作
• 记录 subagent 活动,用于调试或审计
UserPromptSubmit
当你提交 prompt 后、Claude 处理它之前触发。你的脚本通过 stdout 输出的任何内容都会和你的 prompt 一起加入 Claude 的上下文,因此 UserPromptSubmit 很适合动态注入 Claude 应该考虑的信息。
在这个示例中,每次你提交 prompt,Claude 都会收到 sprint 上下文文件的内容。这让 Claude 了解当前优先级,而你无需重复说明。
{ "hooks" : { "UserPromptSubmit" : [ { "hooks" : [ { "type" : "command" , "command" : "cat ./current-sprint-context.md" } ] } ] } }
何时使用 UserPromptSubmit:
• 每次 prompt 都注入当前 sprint 上下文或项目优先级
• 在 prompt 到达 Claude 前验证它
• 基于内容阻止某些类型的请求
• 添加近期错误日志或测试结果等动态上下文
配置与文件位置
Hooks 位于三个层级的 JSON 设置文件中。项目级 hooks 放在仓库内的 .claude/settings.json,方便与团队共享。用户级 hooks 放在 ~/.claude/settings.json,适用于你的所有项目。本地项目 hooks 放在 .claude/settings.local.json,用于你不想提交的个人配置。
项目级设置优先于用户级设置。也可以使用企业托管的策略设置来进行组织级控制。完整细节请参阅 Claude Code settings 信息。
专业提示:这也是你可以为 Claude actions 设置细粒度权限的同一个文件,支持项目级、用户级或本地级。例如,你可以明确允许 Claude 读取某个目录中的所有文件,这样就不用每次都批准;也可以阻止对敏感文件的任何修改。
Matcher 语法
Matchers 用来过滤哪些工具可以触发你的 hook。它们只适用于 PreToolUse、PostToolUse 和 PermissionRequest hooks。
简单字符串匹配的行为和你预期的一样:"Write" 只匹配 Write 工具。
例如:
{ "hooks" : { "PreToolUse" : [ { "matcher" : "Write" , "hooks" : [ { "type" : "command" , "command" : "your-command-here" } ] } ] } }
管道语法允许匹配多个工具:"Write|Edit" 会触发其中任意一个,而通配符会匹配所有工具:"*" 或空字符串匹配全部工具。
注意:Matchers 区分大小写,所以 "bash" 不会匹配 Bash 工具。
如果需要更细粒度控制,像 "Bash(npm test*)" 这样的参数模式可以匹配特定命令参数。MCP 工具模式遵循 "mcp__memory__.*" 这样的格式,用于 Model Context Protocol 工具。
输入、输出与结构化响应
Hooks 会收到什么
所有 hooks 都会通过 stdin 收到 JSON,其中包含 session 信息和事件特定数据。常见字段包括:session_id、transcript_path、cwd、permission_mode 和 hook_event_name。
此外,与工具相关的 hooks 还会收到 tool_name 和 tool_input。这些数据让你的脚本可以更有依据地决定如何响应。
Hooks 如何响应
Exit codes 决定基本结果。Exit code 0 表示成功,stdout 会被处理为 JSON 或加入上下文。Exit code 2 表示阻塞错误:stderr 会成为错误消息,动作会被阻止。
其他 exit codes 表示非阻塞错误,stderr 会在 verbose mode 中显示。
除了 exit codes,hooks 还可以返回结构化 JSON 以获得更多控制。字段包括:decision(approve、block、allow 或 deny)、reason(显示给 Claude 的解释)、continue(用于 Stop hooks 强制继续)以及 updatedInput(在执行前修改工具参数)。
环境与执行
Hooks 可以访问环境变量,包括:CLAUDE_PROJECT_DIR 表示项目根路径,CLAUDE_CODE_REMOTE 在 Web 环境中为 true,CLAUDE_ENV_FILE 供 SessionStart hooks 持久化变量。你的 shell 中的标准环境变量也可以访问。
还要注意:hooks 默认超时时间为 60 秒,可按 hook 配置。当多个 hooks 匹配同一事件时,它们会并行运行。相同命令会自动去重。
安全注意事项
Hooks 会以你的用户权限执行任意 shell 命令。Claude Code 包含一项保护:直接编辑 hook 配置文件后,必须在 /hooks 菜单中审查后才会生效。这可以防止恶意代码悄悄向你的配置添加 hooks。
不过,如果你配置并批准了 hooks,它们就会以你的权限级别执行。
专业提示:在任何环境中运行命令之前,都要考虑风险。如果你打算用 hooks 运行命令,请考虑这些良好实践:验证并清理来自 stdin 的输入,引用 shell 变量以防注入,使用脚本的绝对路径,并避免处理 .env 或 credentials 等敏感文件。
调试与测试
Claude Code 会把所有内容记录到 transcript files 中,这让你无需额外设置就能看到工具调用和响应。每个 hook 都会收到 transcript_path 字段,指向包含完整 session 历史的 JSONL 文件。你可以用 SessionStart hook 记录每个 transcript 的位置:
{ "hooks" : { "SessionStart" : [ { "hooks" : [ { "type" : "command" , "command" : "jq -r '\"Session: \" + .transcript_path' >> ~/.claude/sessions.log" } ] } ] } }
然后 tail 这个 transcript,实时观察 Claude 工作:tail -f /path/to/transcript.jsonl | jq .
Hook 专属调试
对于 hook 专属调试,可以在 hook 脚本中添加日志。transcript files 会显示 Claude 做了什么,但不会显示你的 hook 为什么选择批准或阻止某个动作。
多花一点精力,你可以添加一个小 bash 脚本来包裹你的工具,并记录额外信息。例如 log-wrapper.sh:
#!/bin/bash LOG=~/.claude/hooks.log INPUT=$(cat) TOOL=$( echo " $INPUT " | jq -r '.tool_name // "n/a"' ) EVENT=$( echo " $INPUT " | jq -r '.hook_event_name // "n/a"' ) echo "=== $(date) | $EVENT | $TOOL ===" >> " $LOG " echo " $INPUT " | " $1 " CODE=$? echo "Exit: $CODE " >> " $LOG " exit $CODE
这个小 wrapper script 会把 stdin 捕获到变量中,记录时间戳和工具名,然后把输入通过 pipe 传给真正的工具。
写好 log-wrapper.sh 后,你可以把它加在 hook 中工具调用的前面:
{ "hooks" : { "PreToolUse" : [ { "matcher" : "Bash" , "hooks" : [ { "type" : "command" , "command" : "log-wrapper.sh your-tool-command.py" } ] } ] } }
专业提示:更多调试技巧请查看 Claude Code debugging documentation。
构建你自己的 hooks
从一个简单 hook 开始,解决你工作流中的真实摩擦点。PostToolUse formatter hook 是很好的第一个选择,因为反馈是即时且可见的。等它正常工作后,再根据你学到的东西扩展。
完整参考文档,包括所有可用字段和高级模式,请参阅官方 hooks documentation。
Hooks 让你可以把 Claude Code 塑造成匹配你工作流的样子,而不是让你的工作流去适应工具。投入时间配置 hooks,会在每个 session 中持续回报你。
从今天开始使用 hooks 自定义你的 Claude Code 工作流。