Appearance
Hooks 钩子
模块编号: 6 · 难度: 进阶 · 预计时间: 1 小时
Hooks 是 Claude Code 的自动化神器。你可以把它想象成给 Claude 运行过程安装的“感应器”和“过滤器”。通过配置钩子,你能在 Claude 打算执行某个工具之前拦截它,或者在它写完代码后立刻自动运行格式化脚本。
钩子架构
所有的钩子都在 settings.json 文件中配置。它的结构非常清晰:一个事件对应一组钩子。
每个钩子通常包含三个核心部分:
- matcher: 用正则表达式匹配工具名称(例如
Write或Edit)。 - if: 一个可选的条件语句,用来进一步过滤触发场景。
- 脚本: 实际运行的 bash 命令或脚本路径。
在 settings.json 中的样子如下:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"if": "command.startsWith('rm -rf')",
"run": "echo '阻止危险操作'; exit 2"
}
]
}
}关键事件
了解 Claude 的生命周期是玩转钩子的前提。以下是几个最有用的事件:
1. PreToolUse
这是最常用的拦截点。在 Claude 真正调用工具之前触发。
- 用途: 权限检查、危险命令拦截、输入验证。
- 特权: 只有在这个阶段,你可以通过退出码
2来彻底阻止工具运行。
2. PostToolUse
工具运行结束后触发。
- 用途: 后处理。比如 Claude 刚写完一个文件,你立刻运行
prettier修复格式。 - 注入: 你可以将脚本的输出注入回对话上下文,告诉 Claude 刚才的操作结果如何。
3. UserPromptSubmit
当你在终端按下回车发送消息时触发。
- 用途: 自动添加背景信息,或者根据当前分支自动调整你的提问前缀。
4. Stop
当 Claude 完成了所有的思考和工具调用,准备把控制权交还给你时触发。
- 用途: 运行最后的质量检查或自动化测试。
钩子脚本编写
Claude 会通过标准输入(stdin)把当前操作的详细信息以 JSON 格式传给你的脚本。
脚本退出码的含义
- 0: 成功执行。
- 2: (仅限 PreToolUse)阻止当前工具运行。
- 其他: 报错或发出警告。
Python 示例:安全扫描器
这是一个简单的 Python 脚本,用来检查 Claude 是否尝试在 .env 文件中写入内容:
python
import sys
import json
# 读取来自 Claude 的上下文
data = json.load(sys.stdin)
# 检查操作路径
if ".env" in data.get("filePath", ""):
print("错误:严禁修改环境变量文件!")
sys.exit(2) # 阻止操作
sys.exit(0)常见模式
自动格式化
最经典的应用是在 PostToolUse 事件中针对 Write 和 Edit 工具运行格式化命令。这样 Claude 写出的代码永远符合你的项目规范。
安全沙箱
如果 Claude 尝试运行类似 rm -rf / 这种自杀式命令,你可以用 PreToolUse 钩子在毫秒级时间内将其拦截。
高级功能
prompt 类型钩子
这种钩子允许你调用 LLM 来做判断。比如在 Stop 事件中,你可以配置一个 prompt 类型的钩子,让另一个模型实例检查 Claude 刚才写的代码是否包含逻辑漏洞。
agent 类型钩子
这类钩子更强大,它们可以开启一个多步任务。如果某个验证没通过,它可以自动启动一个新的 Agent 去修复问题。
once: true
如果你不希望某个钩子在一次对话中反复触发,可以设置 "once": true。它常用于在对话开始时执行一次环境检查。
模板区
你可以直接将以下配置复制到你的 settings.json 中使用。
1. 危险命令防护墙 (PreToolUse)
拦截所有尝试删除非工作目录文件的危险操作。
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"if": "command.includes('rm ') && !command.includes('./')",
"run": "echo '为了安全,请手动确认该删除操作'; exit 2"
}
]
}
}2. 代码自动纠偏 (PostToolUse)
每当 Claude 修改 .ts 或 .js 文件后,自动运行 Lint 修复。
json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"if": "filePath.endsWith('.ts') || filePath.endsWith('.js')",
"run": "npx eslint --fix $filePath"
}
]
}
}测验
测验时间
第 1/3 题
在 PreToolUse 钩子中,退出码 2 代表什么?