第九章:钩子与自动化工作流
钩子系统架构
钩子(Hooks)是 Claude Code 的自动化扩展机制,它允许你在特定事件发生时自动执行自定义脚本。如果把 Claude Code 比作一个操作系统,那么钩子就是它的 "自动化脚本引擎"——你可以编写脚本在特定时机自动触发,从而实现工作流的自动化。
钩子系统采用事件驱动的架构,整体分为三个层次:
- 事件源:Claude Code 运行过程中的各类事件(工具调用、消息收发等)
- 钩子注册表:定义在 settings.json 中的钩子配置,指定事件与脚本的映射关系
- 执行引擎:负责在事件发生时调用对应的钩子脚本,并处理返回值
钩子脚本可以是任意的可执行脚本(Shell、Node.js、Python 等),Claude Code 不限制脚本语言。脚本通过标准输入接收事件数据,通过标准输出返回处理结果。
支持的事件类型
钩子系统支持两大类事件:前置钩子(Pre-hooks)和后置钩子(Post-hooks)。每种事件在触发时机和执行语义上有所不同:
Tool-use 事件(工具调用前)
在 Claude Code 调用任何工具之前触发。前置钩子可以拦截、修改或拒绝工具调用。例如,你可以用这个钩子实现权限控制,阻止危险命令的执行。
Tool-result 事件(工具调用后)
在工具执行完毕并返回结果后触发。后置钩子可以检查、过滤或增强工具的执行结果。例如,自动格式化命令的输出,或者记录工具调用日志。
Message 事件(消息收发)
在发送或接收消息时触发。你可以利用这个钩子实现消息内容的预处理,比如自动翻译、敏感信息脱敏等。
Session 事件(会话生命周期)
在会话开始或结束时触发。适合用于初始化工作环境、清理临时资源、记录会话统计信息等。
| 事件类型 | 触发时机 | 用途示例 |
|---|---|---|
| tool-use | 工具调用前 | 命令白名单校验、参数修正 |
| tool-result | 工具返回后 | 结果格式化、日志记录 |
| message | 消息收发时 | 内容翻译、敏感信息过滤 |
| session | 会话开始/结束 | 环境初始化、清理工作 |
编写钩子脚本
钩子脚本本质上是一个从标准输入(stdin)读取事件数据、通过标准输出(stdout)返回结果的可执行程序。事件数据以 JSON 格式传递。
以下是一个前置钩子脚本示例,用于阻止在生产环境中执行危险命令:
#!/bin/bash
# pre-tool-check.sh - 命令安全校验钩子
read input
event=$(echo "$input" | jq -r '.event')
tool=$(echo "$input" | jq -r '.toolName')
if [ "$event" = "tool-use" ] && [ "$tool" = "Bash" ]; then
command=$(echo "$input" | jq -r '.args.command')
# 检查是否包含危险命令
if echo "$command" | grep -qE "rm -rf|drop table|shutdown"; then
echo '{"status": "rejected", "reason": "检测到危险命令,已阻止执行"}'
exit 0
fi
fi
# 允许执行
echo '{"status": "allowed"}'
以下是一个后置钩子脚本示例,用于记录所有工具调用日志:
#!/usr/bin/env node
// post-tool-logger.js - 工具调用日志记录
const chunks = [];
process.stdin.on("data", (chunk) => chunks.push(chunk));
process.stdin.on("end", () => {
const event = JSON.parse(chunks.join(""));
const log = {
timestamp: new Date().toISOString(),
tool: event.toolName,
status: event.result?.status || "unknown",
duration: event.duration,
};
// 写入日志文件
const fs = require("fs");
fs.appendFileSync(
".claude/tool-audit.log",
JSON.stringify(log) + "\n"
);
// 原样传递结果
process.stdout.write(JSON.stringify({ status: "pass_through" }));
});
自动化工作流设计模式
结合不同类型的事件钩子,你可以设计出复杂的自动化工作流。以下是几种常见的设计模式:
审计模式:在 tool-result 事件上注册日志记录钩子,记录所有操作行为。适合合规性要求高的项目。
防护模式:在 tool-use 事件上注册安全检查钩子,拦截危险操作。适合生产环境或共享开发环境。
增强模式:在 tool-result 事件上注册结果增强钩子,自动格式化或补充工具输出。适合提升日常开发效率。
初始化模式:在 session 事件上注册初始化钩子,自动配置开发环境。适合有特定环境要求的团队项目。
钩子配置(settings.json 中注册)
在 .claude/settings.json 中注册钩子,指定事件类型和对应的脚本路径:
{
"hooks": {
"pre": {
"tool-use": {
"security-check": {
"command": "bash .claude/hooks/pre-tool-check.sh"
}
}
},
"post": {
"tool-result": {
"audit-log": {
"command": "node .claude/hooks/post-tool-logger.js"
}
},
"session": {
"session-cleanup": {
"command": "bash .claude/hooks/session-end.sh"
}
}
}
}
}
配置中的 key(如 security-check、audit-log)是钩子的标识名,方便管理和调试。同一事件类型下可以注册多个钩子,它们会按照配置顺序依次执行。
实战:git commit 前自动运行 lint
一个非常实用的自动化场景是:在 Claude Code 执行 git commit 之前自动运行代码检查,确保提交的代码符合规范。
步骤 1:创建 pre-commit 钩子脚本
#!/bin/bash
# .claude/hooks/pre-commit-lint.sh
read input
# 检查是否为 git commit 操作
event=$(echo "$input" | jq -r '.event')
tool=$(echo "$input" | jq -r '.toolName')
command=$(echo "$input" | jq -r '.args.command // ""')
if [ "$event" = "tool-use" ] && [ "$tool" = "Bash" ] && echo "$command" | grep -q "git commit"; then
echo "检测到 git commit 操作,正在运行代码检查..." >&2
# 运行 lint
if npm run lint 2>&1; then
echo "代码检查通过,允许提交" >&2
echo '{"status": "allowed"}'
else
echo "代码检查未通过,提交已阻止" >&2
echo '{"status": "rejected", "reason": "Lint 检查未通过,请先修复代码风格问题"}'
fi
else
echo '{"status": "allowed"}'
fi
步骤 2:注册钩子
{
"hooks": {
"pre": {
"tool-use": {
"pre-commit-lint": {
"command": "bash .claude/hooks/pre-commit-lint.sh"
}
}
}
}
}
步骤 3:验证效果
现在当你在 Claude Code 中说 "提交代码" 时,Claude Code 在执�� git commit 之前会自动触发钩子脚本运行 npm run lint:
- 如果 lint 通过:git commit 正常执行
- 如果 lint 失败:git commit 被阻止,你会收到提示信息
钩子系统是 Claude Code 实现自动化工作流的关键基础设施。通过合理设计钩子,你可以将重复性的人工检查转变为自动化的质量门禁,让 Claude Code 在提升开发效率的同时,也成为代码质量的守护者。