Claude Code Hooks 完全指南
Hooks 是 Claude Code 的强制性干预机制,允许在特定生命周期节点自动执行自定义脚本。与 Skills(通过场景描述触发)不同,Hooks 是固定条件、百分百触发的。
一、Hook 生命周期的执行逻辑图
下面这张图是hooks系统运行时的宏观执行逻辑图。

Claude Hooks
│
├─ Session(会话生命周期层)
│ ├─ SessionStart (会话开始或恢复时触发)
│ ├─ Setup (初始化模式启动时触发)
│ └─ SessionEnd (会话结束时触发)
│
├─ User(用户交互层)
│ ├─ UserPromptSubmit (用户提交 Prompt 后触发)
│ ├─ UserPromptExpansion(命令展开为 Prompt 时触发)
│ ├─ Notification (Claude 发送系统通知时触发)
│ └─ MessageDisplay (Claude 输出消息时持续触发)
│
├─ Tool(工具执行层)
│ ├─ PreToolUse (工具执行前触发,可阻断执行)
│ ├─ PermissionRequest (请求工具权限时触发)
│ ├─ PermissionDenied (工具权限被拒绝时触发)
│ ├─ PostToolUse (工具成功执行后触发)
│ ├─ PostToolUseFailure (工具执行失败后触发)
│ └─ PostToolBatch (一批工具全部执行完成后触发)
│
├─ Agent(智能体与任务层)
│ ├─ SubagentStart (子智能体启动时触发)
│ ├─ SubagentStop (子智能体结束时触发)
│ ├─ TeammateIdle (团队成员即将空闲时触发)
│ ├─ TaskCreated (创建新任务时触发)
│ └─ TaskCompleted (任务完成时触发)
│
├─ Runtime(运行时环境层)
│ ├─ Stop (Claude 完成当前响应时触发)
│ ├─ StopFailure (响应因错误中断时触发)
│ ├─ CwdChanged (工作目录变化时触发)
│ ├─ FileChanged (监听文件发生变化时触发)
│ ├─ WorktreeCreate (创建 Git Worktree 时触发)
│ └─ WorktreeRemove (删除 Git Worktree 时触发)
│
├─ Configuration(配置与规则层)
│ ├─ InstructionsLoaded(CLAUDE.md 或 Rules 加载时触发)
│ └─ ConfigChange (配置文件发生变化时触发)
│
└─ Context(上下文与 MCP 层)
├─ PreCompact (上下文压缩前触发)
├─ PostCompact (上下文压缩后触发)
├─ Elicitation (MCP 请求用户输入时触发)
└─ ElicitationResult (用户输入返回 MCP 前触发)
二、漏斗模型:事件 → 匹配器 → 处理器
Hooks 系统的执行逻辑是一个逐层过滤的漏斗流水线:
| 层级 | 官方术语 | 大白话含义 |
|---|---|---|
| 第一层 | Event(事件) | 什么时候? 选择监听的生命周期节点(如 PreToolUse) |
| 第二层 | Matcher(匹配器) | 什么情况下? 比如“只有在使用 Bash 工具且命令包含 rm 时”才触发 |
| 第三层 | Handler(处理器) | 干什么? 具体执行的自动化动作、脚本或通知 |
三、配置hooks
Hook 定义在 settings.json 文件中(支持全局 ~/.claude/settings.json 或项目 .claude/settings.json,作用域合并规则见后文)。
示例:
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}
可以同时定义多个 hooks(不同事件或同一事件的多个匹配器)。
四、Matcher 语法详解
| 匹配器写法 | 含义 | 适用事件 |
|---|---|---|
"" 或省略 |
匹配该事件下的所有情况 | Notification、Stop 等 |
"Bash" |
仅匹配名为 Bash 的工具 |
PreToolUse、PostToolUse |
"Edit|Write" |
正则匹配,匹配 Edit 或 Write 工具 |
PreToolUse、PostToolUse |
| 路径过滤 | 不支持 glob 路径(如 src/**),需要在 Hook 脚本内部通过 $CLAUDE_FILE_PATH 自行过滤 |
PreToolUse(配合 Edit/Write) |
⚠️ 常见错误:
matcher大小写敏感,必须与工具名完全一致(Bash而非bash,Edit而非edit)。
五、多个 Hook 的执行顺序与阻断规则
同一事件下可以配置多个匹配器/处理器,执行规则如下:
顺序执行:按照
settings.json中数组定义的顺序依次执行。阻断影响:如果某个
PreToolUsehook 返回{"continue": false},后续的同事件 hook 仍然会执行(官方行为),但最终该工具会被阻断。💡 若希望“一旦阻断就跳过后续 hook”,需在 hook 脚本中自行实现(如写临时标志文件,后面的脚本检查后提前退出)。
超时:每个 hook 脚本默认超时 60 秒,超时后 Claude Code 会视为失败并继续执行(对 PreToolUse 可能决定放行或阻断,取决于具体事件)。
六、全局与项目配置的合并规则
全局:
~/.claude/settings.json项目:
.claude/settings.json(项目根目录)
合并规则:
两个文件会合并,而不是覆盖。
同一 hook 事件(如
PreToolUse)的匹配器数组会 拼接:全局的在前,项目的在后。无法删除全局中定义的某个 hook。如果希望“屏蔽”全局 hook,只能自行修改全局文件或改用其他策略。
示例:
全局定义了 Notification hook,项目中也定义了 Notification → 两者都会执行,先全局后项目。
模块化hooks
.claude/
├── settings.json # 主配置(引用各模块脚本)
│
├── hooks/ # 所有 hook 脚本(团队共享)
│ ├── pre-tool-use/ # PreToolUse 事件专用脚本
│ │ ├── block-dangerous-commands.sh
│ │ └── log-bash-commands.py
│ ├── post-tool-use/ # PostToolUse 事件专用脚本
│ │ ├── auto-format.sh
│ │ └── notify-on-write.py
│ ├── notification/ # Notification 事件脚本
│ │ └── dingtalk-webhook.py
│ └── common/ # 公共函数库(被其他脚本引用)
│ ├── logging.sh
│ └── json-helper.py
如何使用这种多文件目录
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/pre-tool-use/block-dangerous-commands.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/post-tool-use/auto-format.sh"
}
]
}
],
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/notification/dingtalk-webhook.py"
}
]
}
]
}
}
可以在哪些场景使用hooks?
- 自动安全审查
- 自动格式化代码
- 自动运行测试
- 自动生成 Git Commit
- 自动更新 CLAUDE.md
- 自动保护关键文件
- 自动加载项目上下文
- 自动消息通知
更多参考,查看一下列表,根据项目情况选择适合自己的: