关于 py-git-hooks
py-git-hooks 是用于配置 Python pre-commit 检查和 Claude Code lint 门禁的技能,帮助项目维护者迁移手动钩子、检查变更文件,并在 lint 或类型错误未解决时阻止结束。
主要功能
- 01配置 pre-commit 钩子
- 02迁移现有手动钩子
- 03检查变更的 Python 文件
- 04自动修复格式与 lint 问题
- 05阻止未解决的 lint 或类型错误
- 06添加 Claude Code Stop lint 门禁
适用场景
- 01为 Git 提交添加质量检查
- 02替换手动 pre-commit 脚本
- 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 钩子,在提交前确保代码质量。
目标
- 安装包含 Python 质量检查钩子的 pre-commit 框架
- 将任何现有的手动钩子迁移到 pre-commit 框架
- 配置 Claude Code Stop 钩子检查门(在向用户返回前运行完整 lint 套件)
- 确保钩子仅对已更改的文件增量运行
- 尽可能自动修复问题,并在出现严重错误时阻止提交
所需工具
添加到 [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 check | ruff-pre-commit 仓库 |
black | ruff-format(ruff 可替代 black) |
isort | 使用 isort 规则(I)的 ruff |
flake8 | ruff(可替代 flake8) |
mypy | mirrors-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 实施的自动化检查中受益