|
|
Claude Code 从入门到脱发 · Day 5
昨天聊了权限管理,那是"不让它做什么"。今天聊 Hooks,这是"让它做完之后自动做点什么"。
你有没有这样的经历:Claude Code 帮你改了一个文件,你看了一眼——缩进乱了。于是你手动跑一下 Prettier。然后它又改了一个文件,缩进又乱了。你又跑 Prettier。如此反复,你开始怀疑人生。
Hooks 就是解决这类问题的。它让你在 Claude Code 的操作前后,自动执行自定义的脚本。编辑文件后自动格式化、执行命令前自动检查、每次提交前自动跑 lint——全自动,你不用动手。
本文你将学到:
Hooks 的三种类型:PreToolUse、PostToolUse、Stop
如何配置实用的 Hooks
常见 Hooks 示例(格式化、类型检查、安全扫描)
Hooks 的调试技巧
阅读时间:8 分钟 | 实操时间:20 分钟 | 难度:中级
━━━━━━━━━━━━━━━━━━━━
Hooks 是什么
Hooks 是 Claude Code 在执行操作前后自动触发的脚本。你定义好规则,它自动执行,不需要你每次手动干预。
三种 Hook 类型:
| 类型 | 触发时机 | 典型用途 |
|------|---------|---------|
| PreToolUse | 工具执行前 | 拦截危险操作、修改参数 |
| PostToolUse | 工具执行后 | 自动格式化、检查结果 |
| Stop | 会话结束时 | 最终审计、清理 |
━━━━━━━━━━━━━━━━━━━━
配置文件
Hooks 配置在(全局)或(项目级)的字段里。
基本结构:
- {
- "hooks": {
- "PreToolUse": [
- {
- "matcher": "工具匹配规则",
- "hooks": [
- {
- "type": "command",
- "command": "要执行的命令"
- }
- ]
- }
- ],
- "PostToolUse": [...],
- "Stop": [...]
- }
- }
复制代码 决定什么时候触发,可以匹配工具名(如、、)。
━━━━━━━━━━━━━━━━━━━━
实用 Hooks 示例
示例一:编辑文件后自动格式化
这是最常用的 Hook。每次 Claude Code 编辑 JS/TS 文件后,自动跑 Prettier。
- {
- "hooks": {
- "PostToolUse": [
- {
- "matcher": "Edit|Write",
- "hooks": [
- {
- "type": "command",
- "command": "filepath="$CLAUDE_FILE_PATH"; if echo "$filepath" | grep -qE '\\.(js|ts|jsx|tsx)$'; then npx prettier --write "$filepath" 2>/dev/null; fi"
- }
- ]
- }
- ]
- }
- }
复制代码
效果:Claude Code 改完文件,Prettier 自动格式化。你再也不用手动跑了。
示例二:编辑 TypeScript 后自动类型检查
- {
- "hooks": {
- "PostToolUse": [
- {
- "matcher": "Edit|Write",
- "hooks": [
- {
- "type": "command",
- "command": "filepath="$CLAUDE_FILE_PATH"; if echo "$filepath" | grep -qE '\\.tsx?$'; then npx tsc --noEmit 2>&1 | head -20; fi"
- }
- ]
- }
- ]
- }
- }
复制代码
效果:每次改完 .ts/.tsx 文件,自动跑类型检查。如果有类型错误,Claude Code 会看到错误信息并尝试修复。
示例三:拦截 console.log
你不想让代码里留下调试用的 console.log,配一个检查 Hook:
- {
- "hooks": {
- "PostToolUse": [
- {
- "matcher": "Edit|Write",
- "hooks": [
- {
- "type": "command",
- "command": "filepath="$CLAUDE_FILE_PATH"; if echo "$filepath" | grep -qE '\\.(js|ts|jsx|tsx)$' && grep -n 'console\\.log' "$filepath" 2>/dev/null; then echo 'WARNING: console.log detected in '$filepath; fi"
- }
- ]
- }
- ]
- }
- }
复制代码
效果:编辑后如果检测到 console.log,会输出警告。Claude Code 看到警告后通常会主动移除。
示例四:长时间命令提醒
有些命令(、)可能跑很久,用 PreToolUse Hook 提醒使用 tmux:
- {
- "hooks": {
- "PreToolUse": [
- {
- "matcher": "Bash",
- "hooks": [
- {
- "type": "command",
- "command": "cmd="$CLAUDE_BASH_COMMAND"; if echo "$cmd" | grep -qE '^(npm|pnpm|yarn|cargo|docker) (install|build|run)'; then echo 'TIP: Consider running long commands in tmux or background'; fi"
- }
- ]
- }
- ]
- }
- }
复制代码
示例五:Session 结束时审计
- {
- "hooks": {
- "Stop": [
- {
- "hooks": [
- {
- "type": "command",
- "command": "git diff --name-only | xargs grep -l 'console.log' 2>/dev/null && echo 'Audit: Found console.log in modified files' || echo 'Audit: Clean'"
- }
- ]
- }
- ]
- }
- }
复制代码
效果:每次对话结束时,检查被修改的文件里有没有遗留的 console.log。
━━━━━━━━━━━━━━━━━━━━
Hook 的环境变量
Hook 脚本可以使用 Claude Code 提供的环境变量:
| 变量 | 说明 |
|------|------|
|| 被操作的文件路径 |
|| Bash 工具要执行的命令 |
|| 当前工具名称 |
这些变量让你的 Hook 脚本能够根据具体操作做出不同反应。
━━━━━━━━━━━━━━━━━━━━
Hook 的返回值
Hook 脚本的退出码和输出有特殊含义:
退出码 0:操作继续
退出码非 0(PreToolUse):阻止操作执行
stdout 输出:会显示给 Claude Code 看,它会据此调整行为
这意味着 PreToolUse Hook 可以真正"拦截"操作。比如阻止向超过 500 行的文件继续添加代码:
- {
- "hooks": {
- "PreToolUse": [
- {
- "matcher": "Edit|Write",
- "hooks": [
- {
- "type": "command",
- "command": "filepath="$CLAUDE_FILE_PATH"; if [ -f "$filepath" ] && [ $(wc -l < "$filepath") -gt 500 ]; then echo "BLOCKED: File exceeds 500 lines. Split first."; exit 1; fi"
- }
- ]
- }
- ]
- }
- }
复制代码
这比在 CLAUDE.md 里写"不要超过 500 行"强硬多了。CLAUDE.md 是建议,Hook 是铁门。
━━━━━━━━━━━━━━━━━━━━
调试 Hooks
Hook 不生效?几个排查步骤:
检查 JSON 语法:配置文件一个逗号错了整个都不工作。用- cat ~/.claude/settings.json | python3 -m json.tool
复制代码 验证语法。
手动测试命令:把 Hook 里的命令单独在终端跑一下,看有没有报错。
检查 matcher:matcher 是正则表达式。匹配 Edit 或 Write 工具。确保工具名拼写正确。
查看输出:Hook 的 stdout 会显示在 Claude Code 的输出中,看看有没有意外的输出。
━━━━━━━━━━━━━━━━━━━━
常见问题 Q&A
Q1:Hooks 会拖慢 Claude Code 吗?
轻量级的 Hook(格式化、grep 检查)基本没感觉。但如果你的 Hook 跑一个完整的测试套件,那确实会卡住。建议 Hook 脚本控制在几秒内完成。
Q2:Hook 报错了会怎样?
PreToolUse Hook 报错(非 0 退出码)会阻止操作。PostToolUse Hook 报错不会回滚操作,只会显示错误信息。
Q3:能不能用 Python 或 Node.js 写 Hook?
可以。字段可以执行任何 shell 命令,包括或。对于复杂逻辑,建议写成独立脚本文件,Hook 里只调用脚本。
━━━━━━━━━━━━━━━━━━━━
小结
今天学了 Hooks 系统:
三种类型:PreToolUse(执行前)、PostToolUse(执行后)、Stop(结束时)
实用场景:自动格式化、类型检查、console.log 拦截、文件行数限制
PreToolUse 返回非 0 可以阻止操作,是真正的"硬约束"
CLAUDE.md 是建议,Hooks 是规则——两者配合使用效果最好
到目前为止,Claude Code 已经能在你的终端里读代码、改代码、遵守你的规范、自动执行检查。但它还是个"单机游戏"——只能操作本地文件和命令。
如果它能连数据库查数据呢?能操作浏览器测试页面呢?能调用 Slack 发通知呢?
明天 Day 6,我们聊 MCP——Model Context Protocol,让 Claude Code 拥有连接外部世界的能力。
━━━━━━━━━━━━━━━━━━━━
系列进度:5/10 |
|