数月来,Claude Code一直在生产环境中运行,处理并行代理和自主子任务。然而,其设置文件中一个极其强大的功能——“hooks”——却常常被忽视。这些未被详细记录的shell命令,能在工具调用前后、会话开始或结束时自动执行。许多构建AI自动化管道的开发者对它们的存在及其潜力一无所知。
Hook类型详解
Claude Code的~/.claude/settings.json文件定义了四个特定的hook触发点:
- PreToolUse: 在任何工具调用之前执行。它能够检查工具名称和输入,最重要的是,它可以阻止工具调用继续执行。
- PostToolUse: 在任何工具调用完成之后运行。除了工具名称和输入外,它还能获取工具调用的输出结果。
- SessionStart: 当Claude Code会话启动时触发一次。
- SessionEnd: 当Claude Code会话关闭时执行。
这些hooks在settings.json文件中的配置结构如下所示:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 /path/to/your/hook.py"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "bash /path/to/post-edit.sh"
}
]
}
],
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "bash /path/to/session-start.sh"
}
]
}
]
}
}matcher字段是一个字符串,用于指定该hook适用于哪个工具。例如,“Bash”匹配Bash工具,“Edit”匹配Edit工具。您也可以使用通配符“.*”来匹配所有工具。
Hooks如何接收上下文
文档中常常忽略的一个关键细节是Claude Code如何将上下文传递给您的hooks。它通过stdin以JSON对象的形式将相关的工具上下文传递给您的hook脚本。对于PreToolUse hook,传入的负载结构将是:
{
"tool_name": "Bash",
"tool_input": {
"command": "rm -rf /tmp/old-builds",
"description": "Clean old build artifacts"
}
}当PostToolUse hook被触发时,JSON负载会扩展,包含工具的响应:
{
"tool_name": "Edit",
"tool_input": {
"file_path": "/src/app/api/route.ts",
"old_string": "...",
"new_string": "..."
},
"tool_response": "The file has been updated successfully."
}您的hook脚本需要从stdin读取这个JSON,执行其指定的操作,然后退出。退出码决定结果:退出码0表示允许(对于PreToolUse hook,允许工具调用继续),而任何非零退出码将阻止PreToolUse hook的工具调用。对于PostToolUse hook,退出码不会阻止后续执行,只会记录hook脚本的结果。
实际案例1:阻止破坏性命令
一个实际应用是防止自主代理执行潜在危险的命令,如git reset --hard或rm -rf some-dir。通过实现一个PreToolUse hook,可以在执行此类破坏性操作之前强制进行人工检查,从而在自动化工作流中确保更高的控制力和安全性。