关于 block-no-verify-hook
block-no-verify-hook 是面向使用 AI 编码 Agent 团队的 Claude Code PreToolUse 钩子。它检查 Bash 调用,并在执行前拦截 Git 绕过标志,同时不影响其他工具调用。
主要功能
- 01拦截 Bash 工具调用
- 02阻止绕过 Git 钩子和签名的标志
- 03检查 JSON 输入中的命令文本
- 04通过退出码决定拦截或放行
- 05支持项目级或全局设置
适用场景
- 01防止提交时跳过 pre-commit 钩子
- 02对 Git 命令执行 GPG 签名要求
- 03阻止 Agent 使用短标志绕过检查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ wshobson/ agents --skill block-no-verify-hook安装后在 Claude Code 中输入/block-no-verify-hook确认已加载。
详细介绍
阻止 --no-verify 钩子
PreToolUse 钩子配置,可在执行前拦截并阻止绕过标志的使用,确保 AI Agent 无法跳过 pre-commit 钩子、GPG 签名或其他 git 安全机制。
概述
AI 编码 Agent(Claude Code、Codex 等)可以使用 --no-verify 等标志运行 shell 命令,从而绕过 pre-commit 钩子。这会使 pre-commit 钩子中配置的 linting、格式化、测试和安全检查失去意义。block-no-verify 钩子添加了一个 PreToolUse 防护,在执行前拒绝任何包含绕过标志的工具调用。
问题
当 AI Agent 提交代码时,它们可能会使用绕过标志来避免钩子失败:
# These commands skip pre-commit hooks entirely
git commit --no-verify -m "quick fix"
git push --no-verify
git commit --no-gpg-sign -m "unsigned commit"
git merge --no-verify feature-branch
这会导致:
- 未格式化的代码进入仓库
- Linting 错误绕过检查
- 安全扫描被跳过
- 未签名提交绕过签名策略
- 测试套件被规避
解决方案
在 .claude/settings.json 中添加一个 PreToolUse 钩子,用于检查每次 Bash 工具调用并阻止包含绕过标志的命令。
配置
将以下内容添加到项目的 .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
}
]
}
]
}
}
工作原理
- 匹配器:该钩子仅针对
Bash工具调用,因此不会干扰其他工具(Read、Edit、Grep 等)。 - 检查:Claude Code 通过 stdin 以 JSON 形式将工具调用发送给钩子,并且不会设置
$TOOL_INPUT变量。该钩子使用grep -E搜索该 JSON 中的command值,因此不需要jq或node,其他字段中的文本(例如cwd或工具调用的描述)也不会触发它。它会阻止--no-verify、--no-gpg-sign以及 git 接受的它们的任意较短前缀,例如--no-veri。它还会阻止同一条命令中跟在commit之后、包含n的短选项组,例如-n或-nm,因为-n是--no-verify的短形式。该钩子不会查找git这个词,因此它也能捕获if git ...、sudo git ...和g=git; $g commit --no-verify。误匹配(例如提交信息中提到了某个标志)会阻止该调用,这是一种安全的失败方式。 - 阻止:如果在 git 命令中发现绕过标志,钩子会以代码 2 退出并打印错误消息。退出代码 2 会通知 Claude Code 完全拒绝该工具调用。
- 放行:如果未发现绕过标志,钩子会以代码 0 退出,命令将正常执行。
- 限制:该钩子检查的是文本,因此它可以阻止出于习惯而使用绕过标志的 Agent。它无法阻止刻意规避它的 Agent,例如通过拼接各部分来构造标志,或运行
git -c core.hooksPath=/dev/null commit。
退出代码
| 代码 | 含义 |
|---|---|
| 0 | 允许工具调用继续 |
| 1 | 错误(工具调用仍会继续,并显示警告) |
| 2 | 完全阻止工具调用 |
被阻止的标志
| 标志 | 用途 | 为什么阻止 |
|---|---|---|
--no-verify | 跳过 pre-commit 和 commit-msg 钩子 | 绕过 linting、格式化、测试、安全检查 |
--no-gpg-sign | 跳过 GPG 提交签名 | 绕过提交签名策略 |
安装
按项目设置
在项目根目录创建或更新 .claude/settings.json:
mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
}
]
}
]
}
}
EOF
全局设置
要在所有项目中强制执行,请添加到 ~/.claude/settings.json:
mkdir -p ~/.claude
cat > ~/.claude/settings.json << 'EOF'
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
}
]
}
]
}
}
EOF
验证
测试该钩子会阻止绕过标志:
# This should be blocked by the hook:
git commit --no-verify -m "test"
# This should succeed normally:
git commit -m "test"
扩展钩子
添加更多被阻止的标志
要阻止其他标志(例如 --force),请扩展 grep 模式:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n|git([[:space:]]|\\\\t)([^\"\\\\]|\\\\.)*--force)'; then echo 'BLOCKED: Bypass flags are not allowed.' >&2; exit 2; fi"
}
]
}
]
}
}
与其他钩子组合使用
block-no-verify 钩子可与其他 PreToolUse 钩子一起使用:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n)'; then echo 'BLOCKED: Bypass flags not allowed.' >&2; exit 2; fi"
}
]
},
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if grep -qE 'rm[[:space:]]+-rf[[:space:]]+/'; then echo 'BLOCKED: Dangerous rm command.' >&2; exit 2; fi"
}
]
}
]
}
}
最佳实践
- 提交设置文件 -- 将
.claude/settings.json纳入版本控制,让所有团队成员都能受益于该 hook。 - 在入门文档中说明 -- 在项目的贡献指南中提及该 hook,让开发者理解为什么绕过标志会被阻止。
- 与 pre-commit hook 配合使用 -- block-no-verify hook 会确保 pre-commit hook 运行;请确保你配置了有实际作用的 pre-commit hook。
- 设置后进行测试 -- 在一次测试提交中有意触发该 hook,以验证其正常工作。