Claude Code 改完几个文件,代码逻辑没问题,格式却乱了。你补了一句:“按项目的 Prettier 配置格式化一下。”,Claude Code开始格式化代码。

再比如,你的项目里有 .envpackage-lock.json,还有 .git/ 目录下的文件。这些文件通常不应被 AI 在一次普通需求里顺手改掉。

为避免反复补充,格式化、敏感文件保护等项目约定,可以写进 CLAUDE.md、Rules 或 Skill。但这些只是说明,不是强制执行。Claude 通常会遵守,却不能保证每次修改后都格式化,也不能保证在修改敏感文件前都拦截。

有些场景要求某件事必须在指定时点执行,或者某个操作必须在执行前拦住。

Hooks 用来处理这类要求。

1 · Hooks 是什么

Hooks 是由用户定义的处理程序,会在 Claude Code 生命周期的特定节点自动执行。最常见的处理方式是 Shell 命令。它们能够以确定性的方式控制 Claude Code 的行为,确保某些操作总会发生,而不是依赖大模型自行选择是否运行。

可以把 Hook 理解为:把一个命令绑定到某个事件上;事件一发生,这个命令就执行。

Hooks 可用于强制执行项目规则、自动化重复任务,或把 Claude Code 接入已有工具链。

它和 Git Hook、CI 检查的思路相似:把靠人记住的动作放进固定流程。不同的是,Claude Code 的 Hook 挂在 Agent 生命周期里,可以在工具调用前后介入。

2 · 配置 Hook 及其如何被命中

Hook 配置放在哪里

配置位置决定 Hook 影响谁。

位置适合放什么管理与分发方式
~/.claude/settings.json跨项目的个人保护规则,如拦截 rm -rf 等危险命令不提交
.claude/settings.json团队共享的项目规则,如代码格式化、密钥保护或敏感信息检查提交
.claude/settings.local.json只在当前项目使用的个人偏好,如本地开发环境检查不提交
Managed policy settings组织统一的安全或合规策略由管理员管理
Plugin 的 hooks/hooks.json可复用的插件能力随插件分发
Skill 或 Agent 的 frontmatter只在某个 Skill 或 Agent 运行时生效的行为随组件维护

选好配置位置后,在对应的 JSON 文件中添加 hooks 字段;文件不存在就创建它。

最小配置与执行顺序

一个最小配置如下:

{  "hooks": {    "PostToolUse": [      {        "matcher": "Edit|Write",        "hooks": [          {            "type": "command",            "command": "./.claude/hooks/after-edit.sh"          }        ]      }    ]}}

最外层的 hooks 是配置入口。下面三层分别对应 JSON 中的不同位置:

JSON 中的位置名称作用
"PostToolUse"Event(事件)决定何时触发
包含 matcher 和内层 hooks 的对象Matcher Group(匹配组)决定哪些工具调用会进入处理
内层 hooks 数组中的对象Handler(处理程序)决定实际运行什么

这份配置的执行顺序是:PostToolUse 发生 → matcher: "Edit|Write" 筛选出编辑或新建文件 → 运行 command 指定的脚本。这里的脚本路径只是结构示例,后面的实战会给出可直接使用的配置。

matcherif 筛选

if 是 Handler 中可选的进一步筛选条件,和 typecommand 写在同一层:

{  "type": "command",  "if": "Bash(rm *)",  "command": "./.claude/hooks/block-rm.sh"}

它只在工具调用相关事件中有效。上例表示:只有 Bash 命令以 rm 开头时,才运行这个脚本。

下图展示了这些层级的关系:

matcher 先筛选工具,if 再筛选工具的参数。这样不必为每条 Bash 命令都启动检查脚本。

这套筛选并不适用于所有事件。StopUserPromptSubmit 这类事件不支持 matcher,写了也会被忽略;if 只用于工具调用相关事件,放在其他事件的 Handler 中,该 Handler 不会执行。

matcher 有几种常见写法:

  • Edit:精确匹配 Edit 工具。
  • Edit|Write:精确匹配 EditWrite 工具。
  • Bash:只匹配 Bash 工具。
  • *、空字符串或省略:匹配该事件的全部触发。
  • mcp__github__.*:用正则匹配某个 MCP Server 暴露的全部工具。

工具名区分大小写,edit 不会匹配 Edit

多个 Handler 如何执行

同一个事件中,所有命中的 Handler 都会并行执行。同一匹配组内的 hooks 数组可以放多个处理程序:

"hooks": [  {    "type": "command",    "command": "./.claude/hooks/format.sh"  },  {    "type": "command",    "command": "./.claude/hooks/check.sh"  }]

上面的格式化和检查脚本会同时运行。如果两步有先后依赖,例如必须先格式化再检查,应把它们放进同一个脚本,按顺序执行。

PreToolUse 而言,即使其中一个 Handler 拒绝本次操作,同组中用于记录日志的 Handler 仍会照常运行。

3 · Claude Code 的 Hook 生命周期

Hook 会在会话、对话和工具调用的不同节点触发。

从触发频率看,SessionStartSessionEnd 是每个会话一次;UserPromptSubmitStop 是每轮对话一次;PreToolUsePostToolUse 则跟随每次工具调用触发。

一次普通任务通常经过这些节点:

本文后面的两个实战分别使用 PreToolUsePostToolUse

主线图回答“何时触发”。接下来按 Hook 对当前流程的影响来归类:

介入方式关键事件能做什么
操作前拦截UserPromptSubmitPreToolUseStop阻止提示词处理、工具调用或任务结束
权限决策PermissionRequest对权限请求作出允许、拒绝或进一步询问的决定
后续处理与通知PostToolUsePostToolUseFailureNotification格式化、记录、检查、补充后续上下文
会话与环境SessionStartSessionEndConfigChange初始化、清理、响应环境变化

工具已经执行完成后,Hook 不能撤销这次操作,但可以影响 Claude 接下来的处理。

MCP 交互、子 Agent、任务协作、上下文压缩和 worktree 也有对应事件;遇到这些场景时,再按事件名查配置即可。

4 · Hook 的五种处理程序

Hook 的处理程序共有五种:

能由规则明确处理,就用 command;需要模型判断,用 prompt;还要检查项目实际状态,再用 agent。调用远程服务用 http,已有 MCP 工具用 mcp_tool

command:运行本地命令或脚本

格式化、敏感文件保护、代码检查和记录日志通常用 command。它从 stdin 接收事件 JSON,通过退出码和 stdout 返回结果;第 5 章会展开说明。

http:把 Hook 接到服务

HTTP Hook 会把事件 JSON 以 POST 发送给服务,适合调用内部审计、通知或策略服务。服务返回非 2xx、连接失败或超时,只会记为非阻塞错误,本次流程仍会继续。要在支持拦截的事件中阻止操作,服务必须返回 2xx 响应,并在 JSON 中给出相应的拒绝决定。

mcp_tool:调用已连接的 MCP 工具

mcp_tool 会调用已经连接的 MCP Server 中的工具。它适合把 Hook 接到 GitHub、工单或内部系统。

prompt:把事件交给模型判断

prompt 不直接执行命令。Claude Code 会把你写的规则和本次事件信息交给模型;模型返回允许,或阻止并说明原因。

它不会自行读取文件或运行命令;如果判断依赖项目里的实际代码、测试结果或文件状态,应使用 agent

下面以“Claude 准备修改 .env”为例:

图中的 $ARGUMENTS 是 Claude Code 自动传入的本次工具调用信息。模型返回 ok: false 后,Claude Code 会取消这次 Edit,并把 reason 交给主 Claude。

不同事件对“阻止”的处理不同。PreToolUse 会拒绝本次工具调用;Stop 则会把原因交给 Claude,让它继续处理而不是结束任务。

agent:先调查,再判断

agent 返回的也是允许或阻止,但它会先启动子 Agent 去读取文件、搜索代码或运行检查。

例如,Claude 准备结束任务时,Agent 可以检查单元测试是否通过;失败时返回:

{  "ok": false,  "reason": "单元测试失败:UserServiceTest 有 2 个用例未通过。"}

agent 仍是实验性能力。能用脚本完成的规则,优先使用 command

5 · 命令型 Hook 的输入、输出与异步执行

命令型(command) Hook 从 stdin 读取事件 JSON。处理完成后,它可以通过退出码、stderrstdout 把结果交回 Claude Code。

本章说的“输出”,不是 Hook 修改后的文件,也不是 Claude 的回答,而是 Hook 脚本结束时交回 Claude Code 的结果。

例如,Claude 决定调用 Bash 工具执行 npm test 后,在真正执行前会触发 PreToolUse。Claude Code 同时构造一份描述本次工具调用的 JSON,并传给 Hook:

{  "session_id": "abc123",  "cwd": "/Users/sarah/myproject",  "hook_event_name": "PreToolUse",  "tool_name": "Bash",  "tool_input": {    "command": "npm test"  }}

脚本可以用 jq 取出 tool_input.commandtool_input.file_path,再按自己的规则处理。

最简单的返回方式是退出码:

  • exit 0:Hook 正常结束。如果没有输出 JSON,Claude Code 按默认流程继续;对 PreToolUse 而言,这不等于自动批准,后续仍按权限流程处理;
  • exit 2:在可阻止的事件中中止相应流程,并把 stderr 的内容反馈给 Claude;
  • 其他非零值:通常表示 Hook 自己出错,Claude Code 会继续默认流程。

保护敏感文件的脚本会把拦截原因写到 stderr,然后 exit 2

需要更细的控制时,脚本向 stdout 打印结构化 JSON,并以 exit 0 结束。Claude Code 只会在 exit 0 时解析 JSON;stderr 用于错误信息,不放 JSON,JSON 不能与 exit 2 混用。

如果要停止 Claude Code 的整个后续流程,返回顶层字段:

printf '%s\n' '{"continue": false, "stopReason": "Build failed"}'exit 0

continue: false 会停止后续处理,stopReason 则把原因显示给用户。

如果只想控制本次事件,返回 hookSpecificOutput。例如,PreToolUse 可以拒绝一次工具调用:

printf '%s\n' '{  "hookSpecificOutput": {    "hookEventName": "PreToolUse",    "permissionDecision": "deny",    "permissionDecisionReason": "Destructive command blocked by hook"  }}'exit 0

hookEventName 指明这是一份 PreToolUse 的结果;permissionDecision: "deny" 拒绝本次工具调用,permissionDecisionReason 是 Claude 收到的原因。

除了作出决定,JSON 也能通过 additionalContext 向 Claude 补充运行时信息。例如,PostToolUse 发现刚被修改的是生成文件时,同样把下面这段 JSON 打印到 stdout 并以 exit 0 结束:

{  "hookSpecificOutput": {    "hookEventName": "PostToolUse",    "additionalContext": "这个文件由代码生成。请修改 src/schema.ts,然后运行 bun generate。"  }}

Claude 会在下一次模型调用时看到这条信息,并据此决定后续操作。

异步 Hook:让 Claude Code 不必等待

默认情况下,Claude Code 会等 Hook 执行完再继续。设置 "async": true 后,命令型 Hook 会在后台运行,Claude Code 不必等待。它适合日志、通知和后台测试这类不需要立即决定结果的任务。

例如,文件修改后在后台运行测试:

{  "type": "command",  "command": "npm test",  "async": true,  "timeout": 300}

Claude Code 会继续工作;脚本可通过 additionalContext 在后续对话把结果交给 Claude。

如果后台任务失败后需要 Claude 立刻处理,设置 asyncRewake: true;脚本以 exit 2 结束时,Claude 会收到错误信息。

异步只支持 command,并且不能阻止当前工具调用。

无论同步还是异步,都应设置合适的 timeout。格式化通常只需几十秒;全量测试或网络请求才需要更长时间。不要把一个可能卡住的任务放在工具调用前。

6 · Hook 的安全、性能与调试

不同处理程序的风险点不同。配置时,至少检查下面五点。

  1. 安全。添加前先审查并手动测试 Hook 脚本;项目级的配置和脚本同样应进入代码审查。
  2. 输入与路径。不要信任输入 JSON 里的路径和字符串:引用 Shell 变量时用双引号;拒绝包含 .. 的路径,避免脚本访问项目目录外的文件;用 "${CLAUDE_PROJECT_DIR}" 指向项目内的脚本。
  3. 权限控制。if 用于减少无关 Hook 的执行,不是硬性安全边界。强制允许或拒绝某类操作,应使用 Claude Code 的权限规则。
  4. 性能。同步 Hook 会阻塞 Claude Code 后续执行。缩小事件、matcherif 的范围;不要在每次编辑前跑全仓库测试或慢网络请求。耗时但不影响当前操作的任务,使用异步 Hook。
  5. 调试。/hooks 可查看 Hook 是否注册、来自哪个配置文件和具体配置。claude --debug 会把 Hook 的匹配、退出码以及 stdoutstderr 写入调试日志;它不会直接打印到终端。也可用 claude --debug-file <路径> 指定日志位置。

Hook 不触发或报错,怎么查

按这个顺序排查:

  1. 运行 /hooks,确认 Hook 已注册,并查看它实际来自哪个配置文件。
  2. 检查事件名、matcherif 是否匹配。工具名区分大小写,edit 不会匹配 Edit
  3. 在终端单独运行脚本,确认脚本路径、执行权限、jq 等依赖和退出码都正常。
  4. 仍找不到原因时,用 claude --debug 启动 Claude Code,再查看 ~/.claude/debug/<session-id>.txt;或用 claude --debug-file /tmp/claude-debug.txt 把日志写到指定位置。

7 · 两个实战:自动格式化与敏感文件保护

实战一:编辑后自动格式化

Claude 修改或新建文件后,自动用 Prettier 格式化这个文件。

这里使用 PostToolUse,因为它会在编辑工具执行成功后触发。Edit|Write 表示只关注修改文件和新建文件,不会在 Claude 运行其他工具时触发。

把下面配置加到项目根目录的 .claude/settings.json

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

如果 .claude/settings.json 已有 hooks,只添加 PostToolUse 这一项,不要覆盖原来的其他 Hook。

这条命令做了两件事:

  1. jq -r '.tool_input.file_path' 从 Hook 输入里取出刚被修改的文件路径;
  2. xargs -I {} npx prettier --write "{}" 把完整路径交给 Prettier,让它按项目里的 Prettier 规则格式化。

这条配置依赖 jq 和项目中的 Prettier。

验证:触发 Hook

/hooks 确认配置已注册,再让 Claude 修改一个受 Prettier 支持的文件,检查格式是否变化。

实战二:敏感文件保护

格式化在文件写入后执行;文件保护必须在写入前判断。

把规则写入单独的脚本。先创建目录:

mkdir -p .claude/hooks

再创建 .claude/hooks/protect-files.sh

#!/bin/bashFILE_PATH=$(jq -r '.tool_input.file_path // empty' < /dev/stdin)if [[ -z "$FILE_PATH" ]]; thenecho "Blocked: unable to determine target file" >&2exit 2fiPROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")for pattern in "${PROTECTED_PATTERNS[@]}"; doif [[ "$FILE_PATH" == *"$pattern"* ]]; then    echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2    exit 2fidoneexit 0

在 macOS 或 Linux 上,再给脚本执行权限:

chmod +x .claude/hooks/protect-files.sh

再在 .claude/settings.json 注册它:

{  "hooks": {    "PreToolUse": [      {        "matcher": "Edit|Write",        "hooks": [          {            "type": "command",            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/protect-files.sh",            "args": []          }        ]      }    ]}}

如果 .claude/settings.json 已有 hooks,只添加 PreToolUse 这一项,不要覆盖原来的其他 Hook。

PreToolUseEditWrite 执行前触发。脚本读取目标路径;命中 .envpackage-lock.json.git/ 后,把原因写入 stderr 并以 exit 2 结束。Claude Code 会取消这次工具调用。

${CLAUDE_PROJECT_DIR} 指向项目根目录,避免 Claude 在项目子目录工作时找不到脚本。

args: [] 表示直接启动这个脚本。需要使用管道等 Shell 语法的命令,不应写 args

模式应保持狭窄。configsrc 会匹配大量正常文件,容易误拦截;先保护少量高风险文件。

验证:触发 Hook

/hooks 确认配置已注册,再尝试修改一个受保护文件,检查是否收到拦截原因。

8 · Claude Code 的常用机制怎么选

机制解决什么问题典型场景
Prompt当前一次任务的临时要求“这次只改登录页,不动接口”
CLAUDE.md每个会话加载的核心项目说明项目结构、构建命令、代码风格
Rules按主题或路径拆分项目规则测试、安全、API 设计等独立规则;或只对特定目录生效的规则
Skills按需渐进式加载专项知识和工作流发布、审查、迁移等重复任务
Subagent上下文隔离代码库探索、专项审查
MCP以统一方式连接外部工具和数据源GitHub、数据库、飞书、Figma
Hooks在生命周期事件触发时自动执行或拦截格式化、敏感文件保护、审计

9 · 结语

Hooks 的价值,是把需要确定执行的项目规则绑定到固定事件上。

格式化、敏感文件保护这类需求,不必依赖 Claude 临场记住。

先从一个规则开始:编辑后自动格式化,或保护 .env

学AI大模型的正确顺序,千万不要搞错了

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

在这里插入图片描述

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐