大家好,我是子昕,一个干了10年的后端开发,现在在AI编程这条路上边冲边摸索,每天都被新技术追着跑。
最近在用Claude Code开发项目时,遇到了一个小痛点:
经常需要在多个项目间切换,有时候让AI跑一个任务后就去忙别的事情,结果经常忘记回来查看进度,或者需要不断切换窗口确认任务状态。
作为程序员,我当然知道Hook这个概念的强大之处,只是之前一直没抽时间深入研究Claude Code的Hooks功能
。这次为了解决这个效率问题,我决定好好钻研一下,结果发现这玩意儿的威力远超想象。
今天就把我的研究成果分享给大家,从Hook机制的底层原理到实际应用,让你彻底掌握这个AI编程自动化的核心工具。
什么是Hook?用智能家居场景深度理解
最近我家新房装修,正在研究智能家居系统。在配置智能设备时,我突然意识到Hook机制和智能家居的工作原理几乎一模一样。
传统编程流程就像老式家居:
- 开灯要手动按开关
- 空调要手动调温度
- 安防要手动布撤防
Hook机制就像智能家居系统:
- 设置规则:"当我回家时,自动开灯、调节空调、解除安防"
- 系统监听:"检测到手机连接WiFi(触发条件)"
- 自动执行:"依次执行预设的所有动作"
在Claude Code中,Hook就是这样的「智能家居管家」:
- 监听事件:Claude Code在特定时刻(如任务开始、文件写入、任务完成)发出「信号」
- 触发条件:你预设的规则被激活
- 自动执行:运行你编写的自定义脚本
Hook的技术原理:深入理解触发机制
事件驱动架构
Claude Code采用事件驱动架构,整个工作流程被分解为多个关键节点:
vbnet
用户输入 → SessionStart → UserPromptSubmit → PreToolUse →
工具执行 → PostToolUse → PreCompact → Stop → SessionEnd
每个节点都是一个事件
,Hook就是在这些事件上挂载的监听器
。
核心事件详解
事件名称 | 触发时机 | 典型应用场景 |
---|---|---|
SessionStart |
会话开始 | 加载项目配置、初始化环境 |
UserPromptSubmit |
用户提交请求后 | 请求预处理、内容过滤 |
PreToolUse |
工具使用前 | 安全检查、权限验证 |
PostToolUse |
工具使用后 | 代码格式化、质量检查 |
Stop |
任务完成 | 结果通知、统计记录 |
SessionEnd |
会话结束 | 清理工作、数据归档 |
数据流转机制
Hook的强大之处在于它能够获取和处理Claude Code的内部数据。
重要提醒:不同的事件和工具会传递不同结构的JSON数据。
例如PostToolUse事件的数据格式:
json
{
"session_id": "abc123",
"cwd": "/path/to/project",
"hook_event_name": "PostToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "/path/to/file.js",
"content": "console.log('Hello World');"
},
"tool_response": {
"filePath": "/path/to/file.js",
"success": true
}
}
而Notification事件的数据格式则完全不同:
json
{
"session_id": "abc123",
"cwd": "/path/to/project",
"hook_event_name": "Notification",
"message": "Task completed successfully"
}
这个JSON对象通过标准输入(stdin)传递给你的脚本。
由于每种事件和工具的数据结构都不相同,建议查阅官方文档了解具体格式:
Hook脚本核心:JSON数据处理
Hook脚本的核心是处理Claude Code传来的JSON数据,例如下面这个示例,我从JSON数据中获取相关信息,输出到日志文件:
bash
#!/bin/bash
# 设置日志文件
LOG_FILE="/tmp/claude_hook.log"
echo"=== Hook执行开始 $(date) ===" >> "$LOG_FILE"
# 读取标准输入的JSON数据
input=$(cat)
echo"接收到的数据: $input" >> "$LOG_FILE"
# 使用jq工具解析JSON(推荐)
ifcommand -v jq >/dev/null 2>&1; then
project_dir=$(echo"$input" | jq -r '.cwd')
tool_name=$(echo"$input" | jq -r '.tool_name // "unknown"')
file_path=$(echo"$input" | jq -r '.tool_input.file_path // "empty"')
echo"解析结果 - 项目: $project_dir, 工具: $tool_name" >> "$LOG_FILE"
else
# 备用方案:简单的文本处理
project_dir=$(echo"$input" | grep -o '"cwd":"[^"]*' | cut -d'"' -f4)
echo"备用解析 - 项目: $project_dir" >> "$LOG_FILE"
fi
# 根据解析结果执行不同逻辑
case$tool_namein
"Write"|"Edit")
echo"处理文件操作: $file_path" >> "$LOG_FILE"
# 这里可以调用代码格式化工具
;;
"Bash")
echo"处理命令执行" >> "$LOG_FILE"
# 这里可以记录命令执行日志
;;
*)
echo"处理其他工具: $tool_name" >> "$LOG_FILE"
;;
esac
echo"=== Hook执行结束 ===" >> "$LOG_FILE"
下面我来通过命令的方式配置Hook演示一下。
执行/hooks
命令,可以看到已经配置过的hook以及新建hook。这里我选择的是在工具调用之前(PreToolUse)
执行:

对于工具执行
类事件,需要增加一个matcher
,意思是你需要匹配哪些工具。所以,对于其他的事件,没有这一步,你也别意外。

接下来就是设置matcher,可以看到,Claude Code也给我们提示了可以使用的工具列表,支持正则表达式,下面会讲解。
这里我用LS和Read两个工具来演示,LS是查询文件列表,Read是查询文件内容:

接下来就是设置hook
,也就是脚本:

这里我直接执行test.sh脚本文件($CLAUDE_PROJECT_DIR是内置的变量,代表获取当前项目路径)。这里不理解的先别着急,后面会继续讲解。

然后选择hook的层级,下面也有讲解:

接下来就大功告成了:

配置好hook之后,需要重启Claude Code。
演示LS和Read工具很简单,只需要让Claude解释一下项目即可:

然后看下日志文件的内容:

Hook配置深度解析
配置文件层级
Claude Code支持三个层级的配置,优先级递增:
- 全局配置 (
~/.claude/settings.json
):适用于所有项目 - 项目配置 (
.claude/settings.json
):团队共享配置 - 本地配置 (
.claude/settings.local.json
):个人配置,不提交到Git
高级配置选项
上面通过命令添加的hook,其实最终也是以下面这种格式存储到Claude Code的配置文件中。
因此,你也可以直接修改配置文件,而不通过命令的方式添加hook。
kotlin
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit", // 工具匹配模式
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/scripts/format.sh",
"timeout": 30// 超时设置(秒)
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 -c "import json, sys; data=json.load(sys.stdin); cmd=data.get('tool_input',{}).get('command',''); sys.exit(2 if 'rm -rf' in cmd else 0)""
}
]
}
]
}
}
Matcher模式详解
- 精确匹配 :
Write
只匹配Write工具 - 多选匹配 :
Write|Edit
匹配Write或Edit工具 - 正则匹配 :
.*Edit.*
匹配包含Edit的所有工具 - 全匹配 :
*
或空字符串匹配所有工具
Hook命令执行:灵活的自动化方式
现在我们了解了Hook的配置结构,来深入看看command
字段的强大之处。
Hook并不局限于Shell脚本,它可以执行任何命令行命令:
- Shell脚本 :
./scripts/notify.sh
- Python脚本 :
python3 scripts/analyze.py
- Node.js脚本 :
node scripts/webhook.js
- 直接命令 :
curl -X POST https://api.example.com/notify
- Claude Code无头模式 :
claude -p 「检查代码质量」
这种灵活性让你可以用任何编程语言编写Hook逻辑,甚至直接调用系统命令或API接口。
实战案例:飞书任务完成通知系统
现在我们用一个完整的案例来展示Hook的实际应用。
需求分析
我们要实现的功能:
- Claude Code完成任务后自动发送飞书通知
- 通知内容包括:项目名称、完成时间、任务耗时
- 支持不同类型任务的差异化通知
步骤1:飞书机器人配置
在飞书中搜索「飞书机器人助手」→创建新应用→选择「Webhook触发」→配置「发送飞书消息」操作→获取Webhook URL。

创建应用

新建消息发送流程

添加触发器

配置参数

配置消息内容

发布应用
步骤2:编写通知脚本
创建./feishu-notify.sh
:
bash
#!/bin/bash
# 读取输入数据
input=$(cat)
# 解析JSON数据
ifcommand -v jq >/dev/null 2>&1; then
session_id=$(echo"$input" | jq -r '.session_id // "unknown"')
project_dir=$(echo"$input" | jq -r '.cwd // "unknown"')
hook_event=$(echo"$input" | jq -r '.hook_event_name // "unknown"')
tool_name=$(echo"$input" | jq -r '.tool_name // ""')
else
session_id="unknown"
project_dir=$(pwd)
hook_event="Stop"
tool_name=""
fi
# 提取项目信息
project_name=$(basename "$project_dir")
completion_time=$(date '+%H:%M:%S')
session_short=${session_id:0:8}
# 根据不同事件构造消息
case$hook_eventin
"Stop")
message="🎉 Claude Code任务完成! 📁 项目:$project_name ⏰ 时间:$completion_time 🔗 会话:$session_short"
;;
"PostToolUse")
message="🛠️ 工具执行完成:$tool_name 📁 项目:$project_name ⏰ 时间:$completion_time"
;;
*)
message="📢 Claude Code事件通知:$hook_event 📁 项目:$project_name ⏰ 时间:$completion_time"
;;
esac
# 构造JSON并发送
webhook_url=""# 替换成实际地址
ifcommand -v jq >/dev/null 2>&1; then
json_data=$(jq -n \
--arg text "$message" \
'{content: {text: $text}}')
else
escaped_message=$(echo"$message" | sed 's/"/\"/g')
json_data="{"msg_type":"text","content":{"text":"$escaped_message"}}"
fi
# 发送通知
response=$(curl -s -X POST "$webhook_url" \
-H 'Content-Type: application/json' \
-d "$json_data")
# 可选:记录日志
# echo "$(date): Hook触发 - $hook_event, 项目: $project_name" >> ~/.claude/hook.log
步骤3:Hook配置
在项目根目录创建.claude/settings.local.json
:
bash
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/feishu-notify.sh",
"timeout": 10
}
]
}
]
}
}
步骤4:测试和调试
bash
# 给脚本添加执行权限
chmod +x ./feishu-notify.sh
重新启动Claude Code,随便执行一条命令,等结束后查看飞书消息:

进阶应用:Hook的实用场景
1. 自动代码格式化
每次修改代码文件后自动格式化:
bash
#!/bin/bash
# 文件:.claude/scripts/auto-format.sh
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
if [[ $file_path == *.js ]]; then
npx prettier --write "$file_path"
elif [[ $file_path == *.py ]]; then
black "$file_path"
fi
echo "代码格式化完成: $file_path"
配置:
bash
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/scripts/auto-format.sh"
}
]
}
]
}
}
2. 安全命令检查
防止执行危险的Bash命令:
kotlin
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 -c "import json, sys; data=json.load(sys.stdin); cmd=data.get('tool_input',{}).get('command',''); dangerous=['rm -rf', 'sudo rm', '> /dev/']; sys.exit(2 if any(d in cmd for d in dangerous) else 0)""
}
]
}
]
}
}
当检测到危险命令时,Hook返回退出代码2,Claude Code会拒绝执行该命令。
扩展资源
想要深入掌握Claude Code Hooks,推荐阅读官方文档:
- Hooks指南 :docs.claude.com/en/docs/cla...
- Hooks参考 :docs.claude.com/en/docs/cla...
- Claude Code文档 :docs.claude.com/en/docs/cla...
总结
Hook机制让Claude Code从单纯的AI助手升级为可编程的自动化平台。通过合理配置Hook,你可以:
- 提升效率:自动化重复性任务
- 增强安全:预防危险操作
- 数据洞察:收集和分析编程行为数据
- 工具集成:连接各种外部服务和工具
最佳实践提醒:
- 每个Hook脚本都要有日志记录功能
- 使用
$CLAUDE_PROJECT_DIR
等环境变量提高可移植性 - 设置合理的超时时间避免阻塞
- 项目级Hook配置记得提交到版本控制
Hook不仅仅是一个功能,它是重新定义人机协作方式的桥梁。当你开始用Hook思维设计工作流程时,会发现AI编程的边界被大大拓展了。