Hooks 是用户定义的 Shell 命令,在 Claude Code 生命周期的特定节点自动执行——提供对 Claude 行为的确定性控制,确保某些操作一定发生,而非依赖 LLM 自行判断。
创建第一个 Hook(桌面通知示例)
最快捷的方式是通过 /hooks 交互菜单:
第一步:在 Claude Code 中输入 /hooks
第二步:选择事件类型(示例选 Notification,在 Claude 等待输入时触发)
第三步:设置 Matcher 为 *(匹配所有通知类型)
第四步:添加命令(按平台选择):
# macOS
osascript -e 'display notification "Claude Code needs your attention" with title "Claude Code"'
# Linux
notify-send 'Claude Code' 'Claude Code needs your attention'
# Windows PowerShell
powershell.exe -Command "[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')"第五步:选择存储位置(User settings → 全局,Project settings → 项目级)
第六步:按 Esc 返回,让 Claude 执行需要权限的操作,切换到其他窗口,验证收到桌面通知
5 大常用自动化场景
场景一:等待输入时桌面通知
// ~/.claude/settings.json
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude needs attention\" with title \"Claude Code\"'"
}
]
}
]
}
}场景二:编辑后自动格式化代码
Claude 每次编辑文件后自动运行 Prettier,保持代码格式一致:
// .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.path // empty' | xargs -I{} npx prettier --write {}"
}
]
}
]
}
}场景三:阻止修改受保护文件
通过非零退出码阻止 Claude 编辑特定文件(如 .env、config/secrets.yml):
#!/bin/bash
# ~/.claude/hooks/protect-secrets.sh
FILE=$(cat /dev/stdin | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('path',''))")
if [[ "$FILE" == *".env"* ]] || [[ "$FILE" == *"secrets"* ]]; then
echo "BLOCKED: Cannot edit protected file: $FILE" >&2
exit 2 # 非零退出码 → 阻止工具调用
fi{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "~/.claude/hooks/protect-secrets.sh" }]
}
]
}
}退出码含义:
0= 成功继续;2= 阻止当前工具调用;其他非零 = 警告但继续。
场景四:对话压缩后重新注入上下文
Claude 压缩对话历史后(PostCompact 事件),自动重新加载项目上下文:
{
"hooks": {
"PostCompact": [
{
"hooks": [
{
"type": "command",
"command": "cat .claude/project-context.md"
}
]
}
]
}
}Hook 的标准输出会被注入为新用户消息,Claude 自动读取上下文。
场景五:审计配置变更
使用 ConfigChange 事件记录所有配置修改:
{
"hooks": {
"ConfigChange": [
{
"hooks": [
{
"type": "command",
"command": "echo \"$(date): Config changed\" >> ~/.claude/config-audit.log"
}
]
}
]
}
}三种 Hook 类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
| command(Shell 命令) | 运行任意 shell 命令,通过 stdin 读取事件 JSON,stdout 输出控制行为 | 绝大多数场景 |
| prompt-based(LLM 评估) | 调用 Claude 模型评估条件 | 需要判断力而非确定性规则的场景 |
| agent-based(Agent 执行) | 调用 Agent 执行更复杂的任务 | 需要多步推理或工具使用的场景 |
| HTTP(外部服务) | 向指定 URL 发送 Webhook | 集成外部系统(CI/CD、Slack 通知等) |
Hook 的输入/输出机制
输入
Hook 命令通过 stdin 接收 JSON 格式的事件数据:
{
"hook_event_name": "PostToolUse",
"tool_name": "Edit",
"tool_input": { "path": "src/main.py", "diff": "..." },
"tool_response": { "success": true }
}输出
- stdout:内容作为用户消息注入 Claude 的上下文
- stderr:显示给用户(不影响 Claude 上下文)
- 退出码:
0→ Hook 成功,继续2→ 阻止当前工具调用(PreToolUse专用)- 其他非零 → 显示错误但继续
结构化 JSON 输出
如果 stdout 是有效 JSON,Claude Code 解析并处理结构化输出(高级场景)。
Matcher 过滤器
Matcher 控制 Hook 触发条件:
{
"matcher": "Edit|Write", // 仅对 Edit 或 Write 工具触发
"matcher": "Bash(git *)", // 仅对以 git 开头的 Bash 命令触发
"matcher": "*", // 匹配所有
"matcher": "" // 空字符串 = 匹配所有(等同 *)
}配置存储位置
| 范围 | 文件位置 |
|---|---|
| User(全局) | ~/.claude/settings.json |
| Project(项目) | .claude/settings.json |
| Local(本地,不提交) | .claude/settings.local.json |
| Managed(企业下发) | 系统级 settings.json |
故障排查
| 问题 | 解决方案 |
|---|---|
| Hook 未触发 | 检查 Matcher 语法;确认事件名称拼写正确 |
/hooks 显示无配置 | 检查 JSON 格式;确认文件路径正确 |
| Hook 出现在输出中的错误 | 查看 stderr 输出;用 set -e 调试脚本 |
| Stop Hook 无限运行 | 检查 PreToolUse Hook 是否意外阻止了所有工具 |
| JSON 验证失败 | 检查 Hook 的 stdout 输出是否为有效 JSON |
调试技巧:
# 在 Hook 脚本中添加调试日志
echo "Hook triggered: $0" >> /tmp/hook-debug.log
cat /dev/stdin | tee -a /tmp/hook-debug.log | process_input原文:Automate workflows with hooks - Claude Code Docs | 来源:Anthropic 官方文档