第 15 章 Hooks——事件驱动的自动化
❓ 引导问题:如何在 Claude 执行操作前后自动运行自定义脚本?10 种钩子事件分别做什么?如何用退出代码和 JSON 输出精细控制行为?
📖 15.1 Hooks 是什么
Hooks(钩子)是用户自定义的 Shell 命令,在 Claude Code 生命周期的特定节点自动执行。它们是应用级的硬规则——只要触发对应事件就强制执行,稳定性和可靠性高于提示词约束。
典型场景:桌面通知提醒、代码自动格式化、操作日志审计、阻止修改敏感文件、代码规范校验。
⚠️ 钩子运行时直接使用当前系统凭证,使用前必须逐行审查命令逻辑和权限,避免在钩子中执行来源不明的脚本。
📖 15.2 十种钩子事件
工具类事件(支持匹配器筛选特定工具)
| 事件 | 触发时机 | 核心作用 |
|---|---|---|
PreToolUse | 工具调用前 | 拦截工具执行、修改入参、自动批准/拒绝权限 |
PermissionRequest | 弹出权限请求对话框时 | 自动处理权限申请 |
PostToolUse | 工具调用成功后 | 执行后置操作(格式化代码、记录日志) |
Notification | Claude 发送通知时 | 自定义通知方式(桌面弹窗、邮件) |
PreCompact | 执行上下文压缩前 | 自定义压缩规则、备份重要上下文 |
会话/任务类事件(无匹配器)
| 事件 | 触发时机 | 核心作用 |
|---|---|---|
UserPromptSubmit | 用户提交提示后、Claude 处理前 | 验证提示合法性、补充上下文 |
Stop | 主 Agent 完成响应时 | 智能判断是否需继续执行任务 |
SubagentStop | 子 Agent 任务完成时 | 评估子任务结果,决定是否终止 |
SessionStart | 启动/恢复会话时 | 初始化环境、加载项目配置 |
SessionEnd | 会话结束时 | 清理临时文件、记录会话日志 |
📖 15.3 两种钩子类型
| 特性 | command 类型(命令钩子) | prompt 类型(提示词钩子) |
|---|---|---|
| 执行方式 | 运行 Shell 命令/脚本 | 调用 LLM(默认 Haiku)做智能决策 |
| 决策逻辑 | 基于代码逻辑的确定性判断 | 基于上下文的灵活语义判断 |
| 响应速度 | 快(本地执行) | 较慢(需 API 调用) |
| 适用场景 | 代码格式化、日志记录、权限拦截 | 任务完成度评估、复杂意图判断 |
📖 15.4 快速入门:命令日志记录
步骤 1:输入 /hooks,选择 PreToolUse 事件
步骤 2:添加匹配器,输入 Bash(仅 Bash 工具触发)
步骤 3:添加钩子命令:
jq -r '"\(.tool_input.command) - \(.tool_input.description // "无描述")"' >> ~/.claude/bash-command-log.txt
步骤 4:选择存储位置——User settings(全局)或 Project settings(当前项目)
验证:让 Claude 执行 ls,然后 cat ~/.claude/bash-command-log.txt 查看日志。
📖 15.5 退出代码与 JSON 输出
退出代码控制
| 退出代码 | 含义 | 行为 |
|---|---|---|
0 | 执行成功 | stdout 可返回 JSON 做高级控制 |
2 | 阻止操作 | stderr 反馈给 Claude,阻止当前事件继续 |
| 其他非零值 | 非阻塞错误 | stderr 仅在详细模式显示,不影响事件执行 |
JSON 高级控制(退出代码为 0 时)
| 通用字段 | 作用 |
|---|---|
continue: true/false | 是否允许事件继续(false 优先于其他规则) |
stopReason | continue=false 时展示给用户的原因 |
systemMessage | 向用户显示的警告信息 |
PreToolUse 特有:permissionDecision(allow/deny/ask)、updatedInput(修改工具入参)
PostToolUse 特有:additionalContext(向 Claude 注入附加上下文)
📖 15.6 实用配置示例
自动格式化 TypeScript 文件
{
"hooks": {
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read fp; if echo \"$fp\" | grep -q '\\.ts$'; then npx prettier --write \"$fp\"; fi; }"
}]
}]
}
}
禁止修改敏感文件
{
"hooks": {
"PreToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "python3 -c \"import json, sys; d=json.load(sys.stdin); p=d.get('tool_input',{}).get('file_path',''); sys.exit(2 if any(x in p for x in ['.env','package-lock.json','.git/']) else 0)\""
}]
}]
}
}
退出代码 2 阻止工具调用,从而禁止修改这些文件。
Claude 等待输入时发送桌面通知
{
"hooks": {
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "notify-send 'Claude Code' '请确认权限或输入指令'"
}]
}]
}
}
📖 15.7 扩展配置(Skill/Agent 内嵌 Hooks)
在 Skill 或 Agent 的 YAML frontmatter 中内嵌 Hooks,仅在该组件生命周期内生效:
---
name: secure-operations
description: 执行 Shell 命令前做安全校验
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: "command"
command: "./scripts/security-check.sh"
once: true # 会话内仅运行一次
timeout: 15
---
📖 15.8 匹配器规则
| 匹配规则 | 示例 | 说明 |
|---|---|---|
| 精确匹配 | Write | 仅匹配 Write 工具 |
| 多工具匹配 | Edit|Write | 匹配 Edit 或 Write |
| 前缀匹配 | Notebook.* | 匹配所有 Notebook 开头的工具 |
| 全匹配 | * 或空字符串 | 匹配所有工具 |
| MCP 工具 | mcp__memory__.* | 匹配 memory 服务器的所有工具 |
📖 15.9 配置文件路径
| 配置级别 | 文件路径 | 生效范围 |
|---|---|---|
| 用户级 | ~/.claude/settings.json | 所有项目 |
| 项目级 | .claude/settings.json | 当前项目 |
| 本地项目级 | .claude/settings.local.json | 当前项目,不提交 Git |
| 托管策略级 | 管理员指定路径 | 企业统一管控 |
📖 15.10 安全与调试
安全最佳实践:严格校验 tool_input 中的文件路径和命令参数,防止路径遍历(../);Shell 中使用 "$VAR" 而非 $VAR 避免参数注入;钩子脚本仅赋予必要权限,避免 sudo。
调试:钩子不生效 → 执行 /hooks 检查注册状态,验证 JSON 语法,检查匹配器与工具名是否一致。查看详细日志 → 启动时加 --debug 参数。
📖 15.XX 要点总结
- 钩子是硬规则——事件触发必定执行,比提示词约束更可靠
- 10 种事件分两类:工具类(支持匹配器,精确控制哪些工具触发)+ 会话/任务类(无匹配器,全局生效)
- 退出代码 2 = 阻止操作;退出代码 0 + JSON = 精细控制(修改入参、注入上下文、动态权限决策)
- command vs prompt 类型:固定规则用 command(快),灵活判断用 prompt(智能)
- 扩展配置允许在 Skill/Agent frontmatter 中内嵌 Hooks,作用域仅限组件生命周期






