05-Hooks 自动化

使用 Claude Code 2.1.81+ 的 Hooks 机制自动化工作流程,实现代码检查、测试运行、Git 提交等任务的自动化。


一、Hooks 基础概念

1.1 什么是 Hooks

Hooks 是在特定事件发生时自动执行的脚本或命令,用于自动化重复性工作。

工作流程:

用户执行操作
    ↓
触发 Hook
    ↓
自动执行预设任务
    ↓
任务完成,继续主流程

1.2 Claude Code 中的 Hooks 类型

Claude Code 2.1.81+ 支持以下 Hook 类型:

时机 触发条件 应用场景
pre-file-edit AI 准备修改文件 代码规范检查、备份
post-file-edit AI 完成修改文件 自动格式化、测试运行
pre-command 运行终端命令前 环境检查、命令验证
post-command 运行终端命令后 结果分析、日志记录
pre-commit 执行 git commit 测试检查、lint 检查
post-commit 完成 git commit 消息通知、推送
pre-exit 退出 Claude Code 前 未保存检查、状态备份
session-start 会话启动时 环境初始化、欢迎消息

二、Hooks 配置方法

2.1 配置文件位置

Hooks 配置存储在 Claude Code 的配置目录中:

平台 路径
Windows %APPDATA%\claude\hooks.json
macOS ~/.config/claude/hooks.json
Linux ~/.config/claude/hooks.json

项目级配置(覆盖全局):

  • 项目根目录下的 .claude/hooks.json

2.2 配置文件格式

{
  "hooks": {
    "pre-file-edit": [
      {
        "name": "syntax-check",
        "command": "python -m py_compile {file}",
        "priority": 1,
        "condition": "{file} ends_with '.py'",
        "on_error": "abort"
      }
    ],
    "post-file-edit": [
      {
        "name": "black-format",
        "command": "black {file}",
        "priority": 10,
        "condition": "{file} ends_with '.py'"
      },
      {
        "name": "run-tests",
        "command": "pytest {file} -v",
        "priority": 20,
        "on_error": "warn"
      }
    ],
    "pre-commit": [
      {
        "name": "test-suite",
        "command": "pytest tests/",
        "priority": 1,
        "on_error": "abort"
      }
    ]
  }
}

2.3 配置字段说明

字段 必填 说明 示例
name Hook 名称标识 "black-check"
command 要执行的命令 "black {file}"
priority 执行顺序(数字小优先) 10
condition 触发条件 "{file} ends_with '.py'"
on_error 错误处理策略 "abort", "warn", "ignore"
timeout 超时时间(秒) 30

2.4 变量占位符

Hooks 支持以下变量占位符:

占位符 说明 示例值
{file} 当前操作的文件路径 src/main.py
{project} 项目根目录 E:\myproject
{command} 当前执行的命令 pytest
{model} 当前使用的模型 claude-sonnet-4-20250514
{timestamp} 当前时间戳 2025-04-06T10:30:00Z

三、自然语言自动化

3.1 自然语言描述自动化流程

Claude Code 的独特优势是可以用自然语言描述自动化流程:

# 示例:自动化测试流程
> 创建自动化流程:
  每当我修改 Python 文件后,自动运行 pytest 检查
  如果测试失败,显示错误详情
  如果测试通过,自动格式化代码

3.2 自动化执行代码生成

# 示例:生成带自动化的代码
> 创建一个 Python 脚本并配置自动化:
  1. 创建 src/processor.py 数据处理脚本
  2. 添加代码:读取 CSV、处理数据、输出结果
  3. 配置:每次修改后自动运行脚本验证

四、实战自动化场景

4.1 自动化代码检查

> 配置自动化工作流程:

  在修改任何 Python 文件后,自动执行:
  1. 运行 black 检查代码格式
  2. 运行 flake8 检查代码规范
  3. 运行 mypy 检查类型
  4. 如果有错误,显示详细报告
  5. 如果全部通过,显示 "✓ 代码检查通过"

配置为 hooks.json:

{
  "hooks": {
    "post-file-edit": [
      {
        "name": "black-format",
        "command": "black {file}",
        "priority": 10,
        "condition": "{file} ends_with '.py'"
      },
      {
        "name": "flake8-lint",
        "command": "flake8 {file}",
        "priority": 15,
        "condition": "{file} ends_with '.py'",
        "on_error": "warn"
      },
      {
        "name": "mypy-type-check",
        "command": "mypy {file} --ignore-missing-imports",
        "priority": 20,
        "condition": "{file} ends_with '.py'",
        "on_error": "warn"
      }
    ]
  }
}

4.2 自动化测试流程

> 配置测试自动化:

  每当我创建或修改测试文件时:
  1. 自动运行相关测试
  2. 生成测试覆盖率报告
  3. 如果覆盖率低于 80%,提醒补充测试
  4. 显示测试结果的摘要

4.3 自动化 Git 工作流

> 配置 Git 自动化:

  当我要求提交代码时:
  1. 先运行所有测试
  2. 如果测试通过,自动添加所有修改
  3. 根据修改内容生成提交消息
  4. 执行提交
  5. 显示提交结果

五、高级配置

5.1 条件表达式

Hooks 支持灵活的条件表达式:

{
  "condition": "{file} ends_with '.py' and {file} not_contains 'test_'"
}

支持的运算符

运算符 说明 示例
equals 等于 {model} equals 'claude-opus-4-20250514'
contains 包含 {command} contains 'pytest'
not_contains 不包含 {file} not_contains '.git'
starts_with 以…开头 {file} starts_with 'src/'
ends_with 以…结尾 {file} ends_with '.py'
matches 正则匹配 `{file} matches '.(js
and 逻辑与 cond1 and cond2
or 逻辑或 cond1 or cond2

5.2 错误处理策略

策略 说明 适用场景
abort 错误时停止后续操作 关键检查(如语法错误)
warn 错误时仅警告,继续执行 非关键检查(如格式警告)
ignore 忽略错误 可选检查

5.3 优先级管理

{
  "hooks": {
    "post-file-edit": [
      {
        "name": "backup",
        "priority": 1,
        "command": "copy {file} {file}.bak"
      },
      {
        "name": "format",
        "priority": 10,
        "command": "black {file}"
      },
      {
        "name": "test",
        "priority": 100,
        "command": "pytest {file}"
      }
    ]
  }
}

执行顺序:backup → format → test(按 priority 值从小到大)


六、实战配置示例

6.1 Python 项目完整配置

hooks.json:

{
  "hooks": {
    "session-start": [
      {
        "name": "welcome",
        "command": "echo Python API 项目已加载 && python --version",
        "priority": 1
      }
    ],
    "pre-file-edit": [
      {
        "name": "syntax-check",
        "command": "python -m py_compile {file}",
        "priority": 1,
        "condition": "{file} ends_with '.py'",
        "on_error": "abort"
      }
    ],
    "post-file-edit": [
      {
        "name": "black",
        "command": "black {file}",
        "priority": 10,
        "condition": "{file} ends_with '.py'"
      },
      {
        "name": "isort",
        "command": "isort {file}",
        "priority": 15,
        "condition": "{file} ends_with '.py'"
      },
      {
        "name": "flake8",
        "command": "flake8 {file} --max-line-length=100",
        "priority": 20,
        "condition": "{file} ends_with '.py'",
        "on_error": "warn"
      }
    ],
    "pre-commit": [
      {
        "name": "full-test-suite",
        "command": "pytest tests/ -x -v --tb=short",
        "priority": 10,
        "on_error": "abort",
        "timeout": 120
      }
    ]
  }
}

6.2 Node.js 项目配置

{
  "hooks": {
    "post-file-edit": [
      {
        "name": "prettier-format",
        "command": "npx prettier --write {file}",
        "priority": 10,
        "condition": "{file} matches '\.(js|jsx|ts|tsx|json|css|md)$'"
      },
      {
        "name": "eslint-check",
        "command": "npx eslint {file} --fix",
        "priority": 20,
        "condition": "{file} matches '\.(js|jsx|ts|tsx)$'",
        "on_error": "warn"
      }
    ]
  }
}

七、自动化脚本编写

7.1 代码检查脚本

使用 Claude Code 生成检查脚本:

> 创建一个自动化脚本 check_code.py:
  功能:
  1. 检查指定的 Python 文件
  2. 运行 black、flake8、mypy
  3. 收集所有检查结果
  4. 输出报告(通过/失败)
  5. 如果有失败,返回非零退出码

生成的脚本示例:

#!/usr/bin/env python3
"""代码检查自动化脚本"""

import subprocess
import sys
from pathlib import Path

def run_command(cmd: list[str], description: str) -> tuple[bool, str]:
    """运行命令并返回结果"""
    print(f"\n {description}...")
    result = subprocess.run(cmd, capture_output=True, text=True)
    
    if result.returncode == 0:
        print(f"  通过")
        return True, ""
    else:
        print(f"  失败")
        return False, result.stdout + result.stderr

def check_file(file_path: str) -> bool:
    """检查单个文件"""
    path = Path(file_path)
    if not path.exists():
        print(f" 文件不存在: {file_path}")
        return False
    
    all_passed = True
    errors = []
    
    # Black 格式检查
    passed, error = run_command(
        ["black", "--check", str(path)], 
        "检查代码格式 (black)"
    )
    if not passed:
        all_passed = False
        errors.append(f"Black:\n{error}")
    
    # Flake8 规范检查
    passed, error = run_command(
        ["flake8", str(path)],
        "检查代码规范 (flake8)"
    )
    if not passed:
        all_passed = False
        errors.append(f"Flake8:\n{error}")
    
    # 输出结果
    print("\n" + "="*50)
    if all_passed:
        print(" 所有检查通过!")
        return True
    else:
        print(" 检查失败:")
        for error in errors:
            print(f"\n{error}")
        return False

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("用法: python check_code.py <file_path>")
        sys.exit(1)
    
    file_path = sys.argv[1]
    passed = check_file(file_path)
    sys.exit(0 if passed else 1)

7.2 集成到工作流

> 在修改 src/*.py 文件后,自动运行 check_code.py 检查

使用方式:
修改文件 → Claude 自动调用 check_code.py → 显示结果

八、与 CI/CD 集成

8.1 GitHub Actions 集成

创建 .github/workflows/claude-hooks.yml

name: Claude Code Hooks Validation

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.11'
    
    - name: Install dependencies
      run: |
        pip install black flake8 mypy pytest
    
    - name: Run pre-commit hooks
      run: |
        black --check src/
        flake8 src/
        mypy src/
        pytest tests/ -x

8.2 pre-commit 框架集成

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: claude-black
        name: Claude Code Black Format
        entry: black
        language: system
        files: '\.py$'
        stages: [commit]
      
      - id: claude-pytest
        name: Claude Code Test Runner
        entry: pytest
        language: system
        pass_filenames: false
        always_run: true
        stages: [push]

九、项目级 Hooks 配置

9.1 创建项目级配置

在项目根目录创建 .claude/hooks.json

{
  "project": "MyAPI",
  "extends": "%APPDATA%\\claude\\hooks.json",
  "hooks": {
    "post-file-edit": [
      {
        "name": "project-specific-test",
        "command": "python manage.py test {file}",
        "priority": 50
      }
    ]
  }
}

加载顺序

  1. 全局配置 %APPDATA%\claude\hooks.json
  2. 项目配置 .claude\hooks.json(覆盖全局)

9.2 团队协作

共享 Hooks 配置

# 将 hooks.json 加入版本控制
git add .claude/hooks.json

# 添加安装脚本
scripts/setup-hooks.py  # 自动安装 hooks 配置

setup-hooks.py(Windows 版):

#!/usr/bin/env python3
"""安装项目级 hooks 配置"""

import shutil
import os
from pathlib import Path

def install_hooks():
    project_hooks = Path(".claude/hooks.json")
    global_dir = Path(os.environ.get("APPDATA", Path.home() / "AppData" / "Roaming")) / "claude"
    global_dir.mkdir(parents=True, exist_ok=True)
    
    if project_hooks.exists():
        # 创建备份
        target = global_dir / "hooks.json"
        if target.exists():
            backup = global_dir / "hooks.json.backup"
            shutil.copy(target, backup)
            print(f" 已备份原配置到 {backup}")
        
        shutil.copy(project_hooks, target)
        print(f" 已安装 hooks 配置到 {target}")
    else:
        print(" 项目级 hooks.json 不存在")

if __name__ == "__main__":
    install_hooks()

十、调试与故障排查

10.1 启用调试模式

# 在 Claude Code 中启用 hooks 调试
> /config hooks.debug true

# 或使用环境变量
set CLAUDE_HOOKS_DEBUG=1

10.2 查看执行日志

调试模式下,Claude Code 会显示详细日志:

[Hook] 触发 pre-file-edit
[Hook] 执行: black --check src/main.py
[Hook] 结果: 通过 (0.2s)
[Hook] 执行: copy src/main.py src/main.py.bak
[Hook] 结果: 通过 (0.01s)
[Hook] 全部通过,继续文件编辑

10.3 常见问题

Q1: Hook 命令未执行

排查步骤:

  1. 检查 hooks.json 路径是否正确:%APPDATA%\claude\hooks.json
  2. 验证 JSON 语法:python -m json.tool %APPDATA%\claude\hooks.json
  3. 检查条件表达式是否匹配
  4. 确认命令是否存在:where black

Q2: Hook 执行太慢

优化方法:

{
  "name": "quick-test",
  "command": "pytest {file} -x --tb=short",
  "timeout": 30,
  "priority": 50
}
  • 使用 -x 参数让测试在第一个失败时停止
  • 设置合理的 timeout
  • 使用 condition 限制触发范围

Q3: 临时跳过 Hooks

# 临时禁用所有 hooks
> /config hooks.enabled false

# 单次跳过
> 这次编辑跳过 hooks,直接保存 src/main.py

# 重新启用
> /config hooks.enabled true

Q4: 查看已配置的 Hooks

> /hooks list

已配置的 Hooks:
pre-file-edit:
  - black-check (priority: 10)
  - backup (priority: 5)
post-file-edit:
  - auto-format (priority: 10)

十一、最佳实践

11.1 设计原则

原则 说明 示例
快速优先 耗时短的 hooks 优先级调高 语法检查(priority=1)
快速失败 关键检查使用 abort 策略 语法错误立即阻止
非阻塞 可选检查使用 warn 策略 格式警告不阻塞
条件精确 使用 condition 限制触发范围 只检查 .py 文件

11.2 渐进式配置建议

  1. 第一阶段:只配置 post-file-edit 的自动格式化
  2. 第二阶段:添加 pre-file-edit 的语法检查
  3. 第三阶段:配置 pre-commit 的测试检查
  4. 第四阶段:添加 CI/CD 集成和团队协作配置

十二、下一步学习

完成本指南后,建议继续学习:

  1. 06-Skills复用.md - 复用自动化配置
  2. 09-实战:PythonWebAPI开发.md - 自动化实战应用

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐