Claude Code: 钩子系统

最后更新:2026-08-31

钩子让你在 Claude Code 的关键节点插入自定义逻辑——修改前自动备份、提交前自动测试、出错时自动回滚。

💡 提示:钩子是 Claude Code 生命周期中的"拦截器"——你在特定事件发生时执行自定义脚本,实现自动化工作流。

📋 前置知识:第十七章 输出样式

1. 你将学到


2. 钩子生命周期

(1) 事件类型

100%
graph LR
    A[用户输入] --> B[before:prompt]
    B --> C[意图解析]
    C --> D[before:tool:read]
    D --> E[读取文件]
    E --> F[after:tool:read]
    F --> G[before:tool:write]
    G --> H[写入文件]
    H --> I[after:tool:write]
    I --> J[before:tool:bash]
    J --> K[执行命令]
    K --> L[after:tool:bash]
    L --> M[生成回复]
    M --> N[after:response]
事件 触发时机 常见用途
before:prompt 处理用户输入前 输入预处理
before:tool:read 读取文件前 记录访问日志
after:tool:read 读取文件后 敏感内容过滤
before:tool:write 写入文件前 自动备份
after:tool:write 写入文件后 自动格式化
before:tool:bash 执行命令前 安全检查
after:tool:bash 执行命令后 结果后处理
after:response 回复生成后 发送通知

(2) 钩子上下文

每个钩子接收上下文对象:

TYPESCRIPT
interface HookContext {
  event: string;
  timestamp: string;
  tool?: string;
  filePath?: string;
  command?: string;
  content?: string;
  result?: string;
  sessionId: string;
}

▶ 示例 1: 钩子触发流程

TEXT 📖 仅展示
> 修改 src/auth/jwt.ts

触发钩子序列:
1. [before:tool:write] → 自动备份 jwt.ts
2. [写入文件]
3. [after:tool:write] → 运行 ESLint --fix
4. [before:tool:bash] → 检查命令安全性
5. [执行: npm test -- auth.test.ts]
6. [after:tool:bash] → 解析测试结果
7. [after:response] → 发送 Slack 通知

3. 钩子配置

(1) 全局钩子配置

JSON
// ~/.claude/hooks.json
{
  "hooks": {
    "before:tool:write": [
      {
        "name": "auto-backup",
        "command": "cp ${filePath} ${filePath}.bak",
        "enabled": true
      }
    ],
    "after:tool:write": [
      {
        "name": "auto-format",
        "command": "npx prettier --write ${filePath}",
        "enabled": true
      }
    ],
    "after:tool:bash": [
      {
        "name": "log-commands",
        "command": "echo '${command}' >> ~/.claude/command-log.txt",
        "enabled": true
      }
    ]
  }
}

(2) 项目级钩子配置

JSON
// .claude/hooks.json
{
  "hooks": {
    "before:tool:write": [
      {
        "name": "protect-config",
        "condition": "filePath.endsWith('.env') || filePath.includes('config/prod')",
        "command": "echo '拒绝修改配置文件' && exit 1",
        "enabled": true
      }
    ],
    "after:tool:write": [
      {
        "name": "lint-fix",
        "command": "npx eslint --fix ${filePath} 2>/dev/null || true",
        "enabled": true,
        "files": ["src/**/*.ts"]
      }
    ]
  }
}

4. 实战场景

▶ 示例 2: 自动备份钩子

JSON
{
  "hooks": {
    "before:tool:write": [
      {
        "name": "git-backup",
        "command": "git stash push -m 'auto-backup-before-claude' -- ${filePath} 2>/dev/null || true",
        "enabled": true
      }
    ]
  }
}

▶ 示例 3: 安全审查钩子

JSON
{
  "hooks": {
    "before:tool:bash": [
      {
        "name": "block-dangerous-commands",
        "condition": "command.includes('rm -rf') || command.includes('DROP TABLE') || command.includes('npm publish')",
        "command": "echo '⚠️ 危险命令被拦截' && exit 1",
        "enabled": true
      }
    ]
  }
}

▶ 示例 4: 自动测试钩子

JSON
{
  "hooks": {
    "after:tool:write": [
      {
        "name": "auto-test",
        "condition": "filePath.includes('src/') && filePath.endsWith('.ts')",
        "command": "npm test -- ${filePath.replace('src/', 'tests/').replace('.ts', '.test.ts')} 2>&1 | tail -5",
        "enabled": true
      }
    ]
  }
}

5. 自定义钩子脚本

▶ 示例 5: 复杂钩子脚本

BASH
#!/bin/bash
# .claude/hooks/notify.sh
# 文件修改后发送通知

FILE_PATH=$1
CHANGE_TYPE=$2

# 只通知关键文件变更
if [[ "$FILE_PATH" == *"/auth/"* ]] || [[ "$FILE_PATH" == *"/payment/"* ]]; then
  curl -X POST "https://hooks.slack.com/services/xxx" \
    -H "Content-Type: application/json" \
    -d "{
      \"text\": \"Claude Code 修改了关键文件: $FILE_PATH ($CHANGE_TYPE)\",
      \"channel\": \"#code-changes\"
    }" 2>/dev/null
fi
JSON
{
  "hooks": {
    "after:tool:write": [
      {
        "name": "notify-critical-changes",
        "command": "bash .claude/hooks/notify.sh ${filePath} write",
        "enabled": true
      }
    ]
  }
}

6. 钩子调试与排错

(1) 调试技巧

BASH
# 启用钩子日志
export CLAUDE_HOOK_DEBUG=1

# 查看钩子执行日志
cat ~/.claude/hooks.log

# 临时禁用所有钩子
claude --no-hooks

(2) 常见问题排查

问题 原因 解决方案
钩子不触发 enabled: false 检查配置
钩子报错 命令路径问题 使用绝对路径
钩子慢 脚本执行时间长 异步执行或精简逻辑
循环触发 钩子触发另一个钩子 加条件避免循环
权限不足 脚本无执行权限 chmod +x script.sh

7. 综合示例:完整钩子方案

JSON
{
  "hooks": {
    "before:tool:write": [
      {
        "name": "auto-backup",
        "command": "cp ${filePath} /tmp/claude-backup/$(basename ${filePath}).$(date +%s)",
        "enabled": true
      },
      {
        "name": "protect-env",
        "condition": "filePath.endsWith('.env') || filePath.endsWith('.env.local')",
        "command": "echo '❌ 禁止修改环境变量文件' && exit 1",
        "enabled": true
      }
    ],
    "after:tool:write": [
      {
        "name": "format",
        "command": "npx prettier --write ${filePath} 2>/dev/null; npx eslint --fix ${filePath} 2>/dev/null; true",
        "enabled": true,
        "files": ["src/**/*.ts", "src/**/*.tsx"]
      }
    ],
    "before:tool:bash": [
      {
        "name": "block-dangerous",
        "condition": "command.match(/rm -rf|DROP|npm publish|git push --force/)",
        "command": "echo '⛔ 危险命令已拦截' && exit 1",
        "enabled": true
      }
    ],
    "after:response": [
      {
        "name": "log-session",
        "command": "echo '$(date): ${sessionId}' >> ~/.claude/sessions.log",
        "enabled": true
      }
    ]
  }
}

❓ 常见问题

Q 钩子会拖慢 Claude Code 吗?
A 会。每个钩子需要执行命令,慢钩子会明显影响体验。建议钩子脚本控制在 1 秒内完成。
Q 钩子失败会阻止操作吗?
A before 钩子失败(exit 1)会阻止操作;after 钩子失败不影响已完成操作。
Q 钩子能修改 Claude Code 的输出吗?
A 不能直接修改。钩子只能执行副作用操作(备份、格式化、通知),不改变返回内容。
Q 钩子和插件有什么区别?
A 钩子是轻量级的事件响应(执行命令),插件是完整的功能扩展(注册工具、修改行为)。简单需求用钩子,复杂需求用插件。
Q 钩子配置能提交到 git 吗?
A .claude/hooks.json 可以提交,团队共享。个人钩子放在全局配置中。
Q 如何查看所有已配置的钩子?
A 运行 claude /hooks 查看当前所有钩子配置和状态。

📖 小节


📝 作业

  1. 基础题(难度⭐):配置一个 after:tool:write 钩子,在文件修改后自动运行 Prettier 格式化。
  2. 进阶题(难度⭐⭐):配置安全钩子,拦截 rm -rfnpm publish 等危险命令。
  3. 挑战题(难度⭐⭐⭐):设计一套完整的钩子方案,覆盖备份、格式化、安全检查、通知四个维度。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏