
作为前端开发者,我们对"钩子"这个词再熟悉不过:Vue 的生命周期钩子让我们在组件不同阶段插入逻辑、Webpack 的 Tapable 钩子让我们在编译流程中扩展功能、Husky 的 Git 钩子在 commit 前自动跑 lint。Claude Code 的 Hooks 也是同样的思路------给 AI 的工作流加上"插槽",让它按你的规矩干活。
前言:为什么前端开发者一看就懂 Hooks
我们写 Vue 组件时,会在 onMounted 里发请求、在 onBeforeUnmount 里清定时器。同样的事件驱动思想,Claude Code 把整个 AI 协作过程拆成了 25 个生命周期事件:用户输入、调用工具前、调用工具后、会话开始、会话结束......每个节点都能挂钩子。
这意味着什么?意味着你可以:
- 强制 Claude 写完代码自动跑 Prettier------再也不用提醒它"记得格式化"
- 拦截危险命令 ------比如不小心执行了
rm -rf直接被钩子干掉 - 追踪上下文消耗------知道每次请求烧了多少 token
- 统一团队规范 ------把规则写进
.claude/settings.json,提交到 Git,所有人共享
下面我们从配置层级讲起,一步步搞懂这套机制。
一、配置层级:和前端工具链异曲同工
熟悉前端的朋友应该见过 .eslintrc 的层级覆盖:项目级覆盖用户级、当前目录覆盖父目录。Claude Code 的 hooks 也走同一套逻辑:
| 配置位置 | 作用范围 | 类比前端 |
|---|---|---|
~/.claude/settings.json |
用户全局 | 全局 .npmrc |
.claude/settings.json |
项目共享(提交 Git) | 项目根 .eslintrc |
.claude/settings.local.json |
本地私有(不提交) | .env.local |
Plugin hooks/hooks.json |
插件内部 | 包内置规则 |
| Skill / Agent frontmatter | 组件级 | 组件 scoped 样式 |
最佳实践:团队共享规则放 .claude/settings.json,个人偏好放 settings.local.json。
基础配置结构
json
{
"hooks": {
"EventName": [
{
"matcher": "ToolPattern",
"hooks": [
{
"type": "command",
"command": "your-command-here",
"timeout": 60
}
]
}
]
}
}
字段说明:
matcher:工具名匹配模式,支持精确匹配"Write"、正则"Edit|Write"、通配符"*",甚至 MCP 工具"mcp__memory__.*"type:四种类型------command(执行 shell)、http(调远程 webhook)、prompt(让 LLM 评估)、agent(派子 agent 验证)timeout:超时时间,默认 60 秒once:是否只运行一次(每个会话)
二、四种钩子类型:从命令到 AI 评估
1. Command Hook:最常用的 Shell 命令
跟 Husky 的 pre-commit 一模一样,执行一段脚本:
json
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/validate.py\"",
"timeout": 60
}
脚本通过 stdin 接收 JSON、通过 exit code 反馈结果:
- exit 0:通过,继续执行
- exit 2:阻断,stderr 作为错误消息
- 其他:非阻断错误,仅在 verbose 模式可见
2. HTTP Hook:调用远程 Webhook
v2.1.63 新增,适合接入团队的 CI/CD 系统、企业内部审计平台:
json
{
"type": "http",
"url": "https://my-webhook.example.com/hook",
"matcher": "Write"
}
⚠️ 安全提示:URL 中插值环境变量必须显式声明
allowedEnvVars,防止敏感信息泄漏到外部接口。
3. Prompt Hook:让 LLM 当裁判
主要用在 Stop / SubagentStop 事件,让 AI 自己评估"任务是否完成":
json
{
"type": "prompt",
"prompt": "Evaluate if Claude completed all requested tasks.",
"timeout": 30
}
LLM 会返回结构化决策:approve / block,并附理由。对于"需求是否真的实现"这种主观判断,比写正则靠谱多了。
4. Agent Hook:派子 Agent 多步验证
比 Prompt Hook 更强:派一个能用工具(Read/Grep/Bash)的子 agent 来做复杂检查,比如对照设计文档验证架构合规性:
json
{
"type": "agent",
"prompt": "Verify the code changes follow our architecture guidelines.",
"timeout": 120
}
三、25 个事件:前端开发者最关心的几个
完整事件表覆盖了从会话启动到工具调用的整个生命周期,对前端开发者最实用的是这几个:
| 事件 | 触发时机 | 能否阻断 | 前端典型用途 |
|---|---|---|---|
| PreToolUse | 工具执行前 | ✅ allow/deny/ask | 拦截危险命令、改写参数 |
| PostToolUse | 工具执行成功后 | ❌ | 自动 lint/格式化、Bundle 校验 |
| PostToolUseFailure | 工具执行失败 | ❌ | 错误埋点、Sentry 上报 |
| UserPromptSubmit | 用户提交输入 | ✅ | 校验、注入项目上下文 |
| Stop | Claude 回答结束 | ✅ | 任务完整性检查 |
| SessionStart | 会话启动 | ❌ | 加载环境变量、激活 nvm |
| FileChanged | 监听文件变化 | ❌ | 触发 HMR、重启 dev server |
PreToolUse:你的"防火墙"
跟 Vue Router 的 beforeEach 一样:可以拦截、放行、改写。
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/validate-bash.py"
}
]
}
]
}
}
输出可以控制:
permissionDecision:"allow"/"deny"/"ask"updatedInput:改写工具入参(比如自动修正路径)
PostToolUse:你的"自动美容师"
代码写完立刻格式化,再也不用提 Prettier。
四、前端开发者实战:5 个高价值钩子场景
场景 1:写完代码自动 Prettier + ESLint
.claude/hooks/format-code.sh:
bash
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | python3 -c "import sys, json; print(json.load(sys.stdin).get('tool_name', ''))")
FILE_PATH=$(echo "$INPUT" | python3 -c "import sys, json; print(json.load(sys.stdin).get('tool_input', {}).get('file_path', ''))")
if [ "$TOOL_NAME" != "Write" ] && [ "$TOOL_NAME" != "Edit" ]; then
exit 0
fi
case "$FILE_PATH" in
*.js|*.jsx|*.ts|*.tsx|*.vue|*.json)
command -v prettier &>/dev/null && prettier --write "$FILE_PATH" 2>/dev/null
command -v eslint &>/dev/null && eslint --fix "$FILE_PATH" 2>/dev/null
;;
*.css|*.scss|*.less)
command -v stylelint &>/dev/null && stylelint --fix "$FILE_PATH" 2>/dev/null
;;
esac
exit 0
挂到 PostToolUse,从此 AI 写完一个 .vue 文件,下一秒就符合团队规范。
场景 2:阻断危险 Bash 命令
validate-bash.py:
python
#!/usr/bin/env python3
import json, sys, re
BLOCKED_PATTERNS = [
(r"\brm\s+-rf\s+/", "禁止 rm -rf 根目录"),
(r"\bsudo\s+rm", "禁止 sudo rm"),
(r"\bnpm\s+publish", "publish 必须人工确认"),
(r"\bgit\s+push\s+.*--force", "禁止 force push"),
]
def main():
data = json.load(sys.stdin)
if data.get("tool_name") != "Bash":
sys.exit(0)
cmd = data.get("tool_input", {}).get("command", "")
for pattern, msg in BLOCKED_PATTERNS:
if re.search(pattern, cmd):
print(msg, file=sys.stderr)
sys.exit(2)
sys.exit(0)
if __name__ == "__main__":
main()
exit 2 = 阻断 + 在终端显示原因,比写一堆 docstring 提醒 Claude "别这么干" 有效得多。
场景 3:写文件时扫描敏感信息
security-scan.py 检测代码里是否硬编码了 API Key、密码:
python
SECRET_PATTERNS = [
(r"password\s*=\s*['\"][^'\"]+['\"]", "可能硬编码密码"),
(r"api[_-]?key\s*=\s*['\"][^'\"]+['\"]", "可能硬编码 API Key"),
(r"sk-[a-zA-Z0-9]{32,}", "可能泄漏 OpenAI Key"),
]
发现后通过 additionalContext 把警告塞回 Claude 的上下文里,让它自己修。这比 Code Review 靠人眼盯快得多。
场景 4:Session 启动时加载 nvm 环境
前端项目经常有 .nvmrc。在 SessionStart 钩子里:
bash
#!/bin/bash
if [ -n "$CLAUDE_ENV_FILE" ] && [ -f ".nvmrc" ]; then
NODE_VERSION=$(cat .nvmrc)
echo "export NVM_NODE_VERSION=$NODE_VERSION" >> "$CLAUDE_ENV_FILE"
fi
exit 0
CLAUDE_ENV_FILE 是个特殊环境变量,写进去的 export 语句会持久化到整个会话------这点比普通 shell 命令强多了。
场景 5:上下文用量追踪(Hook Pair 玩法)
把 UserPromptSubmit 和 Stop 当作 "请求开始 / 请求结束" 来用,计算每次对话的 token 消耗:
python
# UserPromptSubmit 时记录当前 token 数
# Stop 时再计算一次,差值就是本轮消耗
delta_tokens = current_tokens - pre_tokens
print(f"本次请求约消耗 {delta_tokens:,} tokens", file=sys.stderr)
类比:跟你在 Vue 里用 performance.mark('start') / performance.measure() 测量函数耗时,是同一种思想。
五、组件级 Hooks:把规则嵌进 Skill / Agent
如果你写了一个 Skill,希望它每次执行时自动做某些校验,可以直接在 frontmatter 里挂钩子:
yaml
---
name: secure-operations
description: Perform operations with security checks
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/check.sh"
once: true # 整个会话只跑一次
---
支持事件:PreToolUse、PostToolUse、Stop。
特别说明 :当 Stop 钩子写在子 agent 的 frontmatter 里时,会自动转成 SubagentStop------只在该子 agent 完成时触发,不影响主会话。
六、JSON I/O 与环境变量
输入(stdin JSON)
json
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.jsonl",
"cwd": "/current/working/directory",
"hook_event_name": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "/path/to/file.js",
"content": "..."
},
"tool_use_id": "toolu_01ABC123...",
"agent_id": "agent-abc123",
"agent_type": "main"
}
输出(stdout JSON, exit 0)
json
{
"continue": true,
"suppressOutput": false,
"systemMessage": "可选的警告消息",
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "文件在允许目录内",
"updatedInput": {
"file_path": "/modified/path.js"
}
}
}
关键环境变量
| 变量 | 用途 |
|---|---|
CLAUDE_PROJECT_DIR |
项目根目录绝对路径(永远用这个,别硬编码!) |
CLAUDE_ENV_FILE |
持久化环境变量的文件路径(仅 SessionStart/CwdChanged/FileChanged) |
CLAUDE_CODE_REMOTE |
是否在远程环境(值为 "true") |
${CLAUDE_PLUGIN_ROOT} |
插件目录(仅插件内 hooks) |
七、安全最佳实践:别给自己挖坑
Hooks 执行的是任意 shell 命令,跟 Husky 一样有风险。一份对照表:
| ✅ 应该做 | ❌ 不要做 |
|---|---|
| 校验、清洗所有输入 | 盲信输入数据 |
引号包裹变量 "$VAR" |
裸用 $VAR(命令注入) |
禁止路径穿越 .. |
接受任意路径 |
用 $CLAUDE_PROJECT_DIR |
硬编码绝对路径 |
跳过 .env、.git/、密钥文件 |
处理所有文件 |
| 在隔离环境中先测试 | 直接上线 |
HTTP hook 显式声明 allowedEnvVars |
把所有环境变量塞给外部接口 |
特别提醒:statusLine 和 fileSuggestion 类钩子需要工作区信任授权才生效------这是新版加的安全闸。
八、调试技巧
bash
# 启动 debug 模式查看完整钩子日志
claude --debug
# 独立测试钩子(绕过 Claude)
echo '{"tool_name": "Bash", "tool_input": {"command": "ls -la"}}' | python3 .claude/hooks/validate-bash.py
echo $? # 看 exit code
会话内 Ctrl+O 切换 verbose 模式,能看到每个钩子的实时执行情况。
常见坑
- 钩子不执行 :检查 JSON 语法、matcher 拼写、脚本权限(
chmod +x) - 意外阻断:先用样例 JSON 跑一遍,确认 exit code
- JSON 解析报错:永远从 stdin 读,别从命令行参数读
九、Claude Hooks vs 前端工具链对比
把所有概念串起来,给前端老司机一张速查表:
| 前端世界 | Claude Hooks | 共同点 |
|---|---|---|
Husky pre-commit |
PreToolUse (Bash) |
阻断危险操作 |
Husky post-commit |
PostToolUse |
操作后处理 |
lint-staged |
PostToolUse (Write/Edit) |
改完即格式化 |
Webpack compiler.hooks.done |
Stop |
任务结束钩子 |
Vue onMounted |
SessionStart |
启动初始化 |
Vue onBeforeUnmount |
SessionEnd |
退出清理 |
Vue Router beforeEach |
PreToolUse (allow/deny) |
导航守卫 |
Vite handleHotUpdate |
FileChanged |
文件变更响应 |
十、写在最后:Hooks 是 AI 协作的"工程化护栏"
我们做前端的,最在意的不是写得多炫,而是协作可控、规范统一。Hooks 给了我们把 AI 也纳入工程化体系的能力:
- 写代码自动符合规范 → 不需要 Code Review 反复挑格式
- 危险命令直接阻断 → AI 失误也烧不了项目
- 关键节点自动审计 → 满足合规、安全要求
- 团队规则共享 → 提交
.claude/settings.json即统一
下次再有同事说 "AI 写的代码我看着不放心",把这篇丢给他------让 AI 和你的工程化体系打通,AI 才真正变成可信赖的工程师,而不是只会写代码的助手。
十一、完整配置示例
以下是一个生产级别的完整配置,涵盖前文提到的所有核心场景:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/validate-bash.py\"",
"timeout": 10
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/format-code.sh\"",
"timeout": 30
},
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/security-scan.py\"",
"timeout": 10
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/validate-prompt.py\""
}
]
}
],
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/session-init.sh\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Evaluate if Claude completed all requested tasks. Check: 1) Were all files created/modified? 2) Were there unresolved errors? If incomplete, explain what's missing.",
"timeout": 30
}
]
}
]
}
}
配置说明:
| 事件 | 匹配器 | 钩子类型 | 用途 |
|---|---|---|---|
PreToolUse |
Bash |
command | 拦截危险命令(rm -rf、force push 等) |
PostToolUse |
`Write | Edit` | command × 2 |
UserPromptSubmit |
- | command | 验证用户输入,阻断危险操作 |
SessionStart |
startup |
command | 加载 nvm 环境、初始化工作区 |
Stop |
- | prompt | AI 回答结束后评估任务完成度 |
配套脚本清单:
| 脚本 | 触发时机 | 功能 |
|---|---|---|
validate-bash.py |
PreToolUse/Bash | 阻断危险 Shell 命令 |
format-code.sh |
PostToolUse | 根据扩展名自动 Prettier/ESLint/StyleLint |
security-scan.py |
PostToolUse | 扫描硬编码密码、API Key 等敏感信息 |
validate-prompt.py |
UserPromptSubmit | 验证用户输入是否包含危险操作 |
session-init.sh |
SessionStart | 加载 .nvmrc、初始化环境变量 |
部署步骤:
bash
# 1. 创建钩子目录
mkdir -p .claude/hooks
# 2. 复制所有脚本(需自行实现上述脚本)
cp /path/to/your/hooks/* .claude/hooks/
chmod +x .claude/hooks/*.sh
chmod +x .claude/hooks/*.py
# 3. 将配置加入项目设置
# 将上述 JSON 配置添加到 .claude/settings.json 的 hooks 字段中
# 4. 提交到 Git(团队共享)
git add .claude/
git commit -m "feat: 添加 Claude Code Hooks 配置"
# 5. 验证钩子是否生效
claude --debug
推荐使用场景对照表:
| 团队规模 | 推荐配置 | 说明 |
|---|---|---|
| 个人开发者 | PreToolUse + PostToolUse | 聚焦安全与格式化 |
| 小团队 (3-10人) | + SessionStart + UserPromptSubmit | 统一环境 + 输入规范 |
| 中大型团队 | 全部开启 + HTTP Hook | 接入 CI/CD、审计平台 |
| 高安全要求 | 全部开启 + Agent Hook | 多步验证、合规审计 |