mcpField
P
py-git-hooks

py-git-hooks

github.com/l-mb测试与质量5643 次安装34 周前更新
代码仓库

关于 py-git-hooks

py-git-hooks 是用于配置 Python pre-commit 检查和 Claude Code lint 门禁的技能,帮助项目维护者迁移手动钩子、检查变更文件,并在 lint 或类型错误未解决时阻止结束。

主要功能

  1. 01配置 pre-commit 钩子
  2. 02迁移现有手动钩子
  3. 03检查变更的 Python 文件
  4. 04自动修复格式与 lint 问题
  5. 05阻止未解决的 lint 或类型错误
  6. 06添加 Claude Code Stop lint 门禁

适用场景

  1. 01为 Git 提交添加质量检查
  2. 02替换手动 pre-commit 脚本
  3. 03在 Claude Code 结束前检查 Python 修改

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/l-mb/python-refactoring-skills --skill py-git-hooks

安装后在 Claude Code 中输入/py-git-hooks确认已加载。

附带文件lint-gate.py

详细介绍

Python Git Hooks 设置

使用 pre-commit 框架配置 git pre-commit 钩子,在提交前确保代码质量。

目标

  1. 安装包含 Python 质量检查钩子的 pre-commit 框架
  2. 将任何现有的手动钩子迁移到 pre-commit 框架
  3. 配置 Claude Code Stop 钩子检查门(在向用户返回前运行完整 lint 套件)
  4. 确保钩子仅对已更改的文件增量运行
  5. 尽可能自动修复问题,并在出现严重错误时阻止提交

所需工具

添加到 [dependency-groups] dev:"pre-commit"、"ruff"、"mypy"、"basedpyright"

  • pre-commit:钩子管理框架(必需)
  • ruff:支持自动修复的快速 linter
  • mypy:标准 Python 类型检查器
  • basedpyright:增强型类型分析工具

权限:先运行 py-quality-setup,以使用所有所需工具权限配置 .claude/settings.local.json。

设置工作流

步骤 1:检查现有钩子
# Check if manual hooks exist
ls -la .git/hooks/pre-commit 2>/dev/null

# If exists and not a pre-commit managed hook, migrate it (see Migration section)
步骤 2:创建 Pre-commit 配置

创建 .pre-commit-config.yaml:

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.8.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.13.0
    hooks:
      - id: mypy
        additional_dependencies: []  # Add type stubs as needed

  - repo: local
    hooks:
      - id: basedpyright
        name: basedpyright
        entry: basedpyright
        language: system
        types: [python]
        pass_filenames: true
步骤 3:安装钩子
# Install pre-commit to project venv
uv pip install pre-commit

# Install git hooks
pre-commit install

# Verify installation
ls -la .git/hooks/pre-commit
步骤 4:测试钩子
# Run on all files (initial validation)
pre-commit run --all-files

# Or test on staged files only
git add some_file.py
pre-commit run
步骤 5:配置 Claude Code Stop 钩子检查门

强烈建议:配置 Claude Code Stop 钩子,在 Claude 将控制权交还给用户前,对已修改的 Python 文件运行完整 lint 套件(ruff、mypy、basedpyright)。如果任何 linter 报告错误,Claude 将无法停止,必须先修复错误。

这取代了较早的 PostToolUse 方案(该方案在每次单独编辑后运行 ruff,会在中间状态产生噪声)。

安装 lint 检查门脚本(使用符号链接,以便更新自动生效):

mkdir -p ~/.claude/hooks
ln -sf ~/.claude/skills/py-git-hooks/lint-gate.py ~/.claude/hooks/lint-gate.py

在 ~/.claude/settings.json 中配置 Stop 钩子:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/hooks/lint-gate.py"
          }
        ]
      }
    ]
  }
}

工作原理:

  • 在 Claude 完成回复时触发一次,并在用户看到结果前运行
  • 通过 git diff 查找已修改的 .py 文件(已暂存、未暂存和未跟踪的文件)
  • 自动修复阶段:运行 ruff check --fix 和 ruff format,静默修复简单问题(导入排序、空白字符、代码风格)
  • 检查阶段:运行 ruff check、mypy 和 basedpyright,查找其余无法自动修复的错误
  • 如果仍有错误:返回 {"decision": "block", "reason": "..."} —— Claude 会看到 lint 输出,并继续处理以修复问题
  • 如果检查通过(自动修复后):返回 {"decision": "stop"} —— Claude 将控制权交还给用户
  • 防止循环:如果输入中的 stop_hook_active 为 true(表示 Claude 正在上一次被阻止后重试),钩子将允许停止,以防止无限循环
  • 如果项目中未安装相关工具,则会优雅地跳过

相较于 PostToolUse 钩子的优势:

  • 每轮运行一次,而不是每次编辑后都运行——避免中间状态产生噪声
  • 自动修复简单问题,让 Claude 只会因实际错误而被阻止
  • 运行完整套件(ruff + mypy + basedpyright),而不只是 ruff
  • Claude 返回时,用户看到的始终是整洁的代码库
  • Claude 会从反馈中学习,避免重复犯同样的错误

从手动钩子迁移

如果项目已有手动 .git/hooks/pre-commit 脚本:

步骤 1:备份现有钩子
cp .git/hooks/pre-commit .git/hooks/pre-commit.backup
步骤 2:分析现有钩子

阅读现有钩子,了解其运行的检查:

  • Lint 检查(ruff、flake8、pylint)?
  • 类型检查(mypy、pyright)?
  • 格式化(black、isort)?
  • 自定义检查?
步骤 3:映射到 Pre-commit 配置

对于手动钩子中的每项检查,在 .pre-commit-config.yaml 中添加对应配置:

手动钩子检查Pre-commit 对应项
ruff checkruff-pre-commit 仓库
blackruff-format(ruff 可替代 black)
isort使用 isort 规则(I)的 ruff
flake8ruff(可替代 flake8)
mypymirrors-mypy 仓库
basedpyright本地钩子
自定义脚本使用 entry: ./script.sh 的本地钩子
步骤 4:安装 Pre-commit 并移除手动钩子
pre-commit install  # This overwrites .git/hooks/pre-commit
pre-commit run --all-files  # Verify all checks pass
步骤 5:验证并清理
# Test that hooks work
git add .
git commit -m "test" --dry-run

# If successful, remove backup
rm .git/hooks/pre-commit.backup

Hook 行为

可自动修复的问题(由 pre-commit 和 Stop hook lint gate 共同处理):

  • 导入排序
  • 行尾空格
  • 简单的风格违规
  • 许多代码质量问题

阻塞问题(需要 Claude 或人工干预):

  • 类型错误(mypy/basedpyright)
  • 语法错误
  • 无法自动修复的复杂 lint 违规

绕过(谨慎使用):

git commit --no-verify

性能优化

对于大型代码库:

  • Pre-commit 默认只对已暂存的文件运行
  • 使用 mypy 增量模式(缓存位于 .mypy_cache)
  • 为提升速度,可考虑只在 CI 中运行 mypy/basedpyright

对于单体仓库:

  • 在 hook 配置中使用 files: 模式限制范围
  • 为每个包配置单独的 hook
- id: mypy
  files: ^src/mypackage/

故障排除

Hook 未运行:

pre-commit install --force  # Reinstall hooks

未找到工具:

# Ensure tools installed in venv
uv pip install ruff mypy basedpyright

Hook 运行过慢:

  • 分析性能:pre-commit run --verbose
  • 考虑从 pre-commit 中移除 mypy/basedpyright,改为在 CI 中运行
  • 对运行缓慢的 hook 使用 stages: [manual],并显式运行

更新 hook 版本:

pre-commit autoupdate

从 PostToolUse Hooks 迁移

如果项目之前为 ruff 配置了 PostToolUse hooks(较早的做法),请迁移到 Stop hook lint gate:

步骤 1:检查现有的 PostToolUse Hooks
grep -A 10 '"PostToolUse"' ~/.claude/settings.json
步骤 2:移除 PostToolUse Ruff Hooks

编辑 ~/.claude/settings.json,移除所有匹配 Edit|Write|MultiEdit 且运行 ruff check 的 PostToolUse 条目。保留所有非 ruff 的 PostToolUse hooks。

步骤 3:安装 Stop Hook

按照上文设置工作流中的步骤 5,安装 lint-gate.py 并配置 Stop hook。

步骤 4:验证

进行一次会引入 ruff 错误的 Python 编辑。确认:

  • 编辑完成后不会立即出现反馈(已移除 PostToolUse hook)
  • Claude 完成响应后,Stop hook 会触发并因错误而阻止流程
  • Claude 会修复错误并返回无错误的输出

Lint 学习

Claude 应从 lint gate 的反馈中学习,避免重复犯同样的错误。

被 lint gate 阻止后:记录错误模式。如果同一条 linter 规则在多次编辑中反复触发,请将其记录到 auto-memory 的 lint-patterns 主题下。格式:

- **[rule-code]** (tool): What triggers it and how to avoid it.

编辑 Python 文件前:查阅 auto-memory,了解此项目中已知的 lint 陷阱。主动运用这些经验教训,让 lint gate 一次通过。

这会形成跨会话反馈循环:每次 lint gate 阻止流程,都会帮助 Claude 下次写出更干净的代码。

验证清单

  • .pre-commit-config.yaml 已配置 ruff、mypy、basedpyright hooks
  • 已运行 pre-commit install
  • pre-commit run --all-files 通过
  • 已迁移所有现有的手动 hooks
  • 已安装 ~/.claude/hooks/lint-gate.py,且该文件可执行
  • 已在 ~/.claude/settings.json 中配置 Claude Code Stop hook
  • 已从设置中移除所有旧的 PostToolUse ruff hooks
  • 紧急情况下可通过 --no-verify 绕过(仅适用于 git pre-commit)

示例

示例:新项目设置

1. Create venv: uv venv && source .venv/bin/activate
2. Install tools: uv pip install pre-commit ruff mypy basedpyright
3. Create .pre-commit-config.yaml with ruff, mypy, basedpyright
4. Install hooks: pre-commit install
5. Test: pre-commit run --all-files
6. Install lint-gate.py and configure Stop hook in settings.json

示例:从 PostToolUse 迁移到 Stop hook

1. Remove PostToolUse ruff hooks from ~/.claude/settings.json
2. Symlink lint-gate.py to ~/.claude/hooks/
3. Add Stop hook to ~/.claude/settings.json
4. Verify: make an edit with a ruff error, confirm block-on-stop behavior

示例:迁移现有的手动 hook

1. Backup: cp .git/hooks/pre-commit .git/hooks/pre-commit.backup
2. Read backup to identify checks (ruff, mypy, custom scripts)
3. Create .pre-commit-config.yaml mapping each check
4. Install: pre-commit install (overwrites manual hook)
5. Verify: pre-commit run --all-files
6. Clean up: rm .git/hooks/pre-commit.backup

示例:添加到现有的 pre-commit 配置

1. Edit .pre-commit-config.yaml
2. Add basedpyright local hook
3. Run: pre-commit run --all-files
4. Commit updated config

相关技能

  • 前置条件:py-quality-setup(添加 hooks 前必须先配置工具)
  • 互补技能:py-security(将 bandit 添加到 pre-commit 以进行安全扫描)
  • 另请参阅:所有技能都能从通过 hooks 实施的自动化检查中受益

评论

支持 Markdown