block-no-verify-hook

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Block No-Verify Hook

拦截No-Verify钩子

PreToolUse hook configuration that intercepts and blocks bypass-flag usage before execution, ensuring AI agents cannot skip pre-commit hooks, GPG signing, or other git safety mechanisms.
PreToolUse钩子配置可在命令执行前拦截并阻止绕过标志的使用,确保AI代理无法跳过pre-commit钩子、GPG签名或其他git安全机制。

Overview

概述

AI coding agents (Claude Code, Codex, etc.) can run shell commands with flags like
--no-verify
that bypass pre-commit hooks. This defeats the purpose of linting, formatting, testing, and security checks configured in pre-commit hooks. The block-no-verify hook adds a PreToolUse guard that rejects any tool call containing bypass flags before execution.
AI编码代理(Claude Code、Codex等)可能会运行带有
--no-verify
这类标志的shell命令来绕过pre-commit钩子,这会让pre-commit钩子中配置的代码检查、格式化、测试和安全检查完全失效。本拦截no-verify的钩子新增了PreToolUse防护,可在执行前拒绝任何包含绕过标志的工具调用。

Problem

存在的问题

When AI agents commit code, they may use bypass flags to avoid hook failures:
bash
undefined
AI代理提交代码时,可能会使用绕过标志来避免钩子执行失败:
bash
undefined

These commands skip pre-commit hooks entirely

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

This allows:
- Unformatted code to enter the repository
- Linting errors to bypass checks
- Security scanning to be skipped
- Unsigned commits to bypass signing policies
- Test suites to be circumvented
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

这会导致:
- 未格式化的代码进入代码仓库
- 代码检查错误绕过校验
- 安全扫描被跳过
- 未签名提交绕过签名策略
- 测试套件被规避

Solution

解决方案

Add a
PreToolUse
hook to
.claude/settings.json
that inspects every Bash tool call and blocks commands containing bypass flags.
.claude/settings.json
中添加
PreToolUse
钩子,检查每一次Bash工具调用,阻止包含绕过标志的命令执行。

Configuration

配置方法

Add the following to your project's
.claude/settings.json
:
json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; 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"
        }
      }
    ]
  }
}
将以下配置添加到项目的
.claude/settings.json
中:
json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; 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"
        }
      }
    ]
  }
}

How It Works

工作原理

  1. Matcher: The hook targets only
    Bash
    tool calls, so it does not interfere with other tools (Read, Edit, Grep, etc.).
  2. Inspection: The
    $TOOL_INPUT
    environment variable contains the full command the agent is about to execute. The hook uses
    printf
    to safely pass input (avoiding
    echo
    pitfalls with special characters) and checks for
    --no-verify
    or
    --no-gpg-sign
    flags only when preceded by a
    git
    command.
  3. Blocking: If a bypass flag is found in a git command, the hook exits with code 2 and prints an error message. Exit code 2 signals Claude Code to reject the tool call entirely.
  4. Pass-through: If no bypass flag is found, the hook exits with code 0 and the command executes normally.
  1. 匹配规则:该钩子仅针对
    Bash
    工具调用,因此不会影响其他工具(Read、Edit、Grep等)的运行。
  2. 命令检查
    $TOOL_INPUT
    环境变量包含代理即将执行的完整命令。钩子使用
    printf
    安全传递输入(避免
    echo
    处理特殊字符的坑),仅在
    git
    命令后检查是否存在
    --no-verify
    --no-gpg-sign
    标志。
  3. 拦截逻辑:如果git命令中发现绕过标志,钩子会以状态码2退出并打印错误信息。状态码2会告知Claude Code完全拒绝该工具调用。
  4. 放行逻辑:如果未发现绕过标志,钩子以状态码0退出,命令正常执行。

Exit Codes

退出码说明

CodeMeaning
0Allow the tool call to proceed
1Error (tool call still proceeds, warning shown)
2Block the tool call entirely
状态码含义
0允许工具调用继续执行
1发生错误(工具调用仍会执行,展示警告)
2完全阻止工具调用执行

Blocked Flags

被拦截的标志

FlagPurposeWhy Blocked
--no-verify
Skips pre-commit and commit-msg hooksBypasses linting, formatting, testing, security checks
--no-gpg-sign
Skips GPG commit signingBypasses commit signing policy
标志用途拦截原因
--no-verify
跳过pre-commit和commit-msg钩子绕过代码检查、格式化、测试、安全校验
--no-gpg-sign
跳过GPG提交签名绕过提交签名策略

Installation

安装方法

Per-Project Setup

单项目配置

Create or update
.claude/settings.json
in your project root:
bash
mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; 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
bash
mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; 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

Global Setup

全局配置

To enforce across all projects, add to
~/.claude/settings.json
:
bash
mkdir -p ~/.claude
cat > ~/.claude/settings.json << 'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; 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
bash
mkdir -p ~/.claude
cat > ~/.claude/settings.json << 'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; 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

Verification

效果验证

Test that the hook blocks bypass flags:
bash
undefined
测试钩子是否可以正常拦截绕过标志:
bash
undefined

This should be blocked by the hook:

该命令应该被钩子拦截:

git commit --no-verify -m "test"
git commit --no-verify -m "test"

This should succeed normally:

该命令应该正常执行成功:

git commit -m "test"
undefined
git commit -m "test"
undefined

Extending the Hook

钩子扩展

Adding More Blocked Flags

新增拦截标志

To block additional flags (e.g.,
--force
), extend the grep pattern:
json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign|force-with-lease|force)'; then echo 'BLOCKED: Bypass flags are not allowed.' >&2; exit 2; fi"
        }
      }
    ]
  }
}
如需拦截更多标志(例如
--force
),可扩展grep匹配规则:
json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign|force-with-lease|force)'; then echo 'BLOCKED: Bypass flags are not allowed.' >&2; exit 2; fi"
        }
      }
    ]
  }
}

Combining with Other Hooks

与其他钩子结合使用

The block-no-verify hook works alongside other PreToolUse hooks:
json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; then echo 'BLOCKED: Bypass flags not allowed.' >&2; exit 2; fi"
        }
      },
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE 'rm\\s+-rf\\s+/'; then echo 'BLOCKED: Dangerous rm command.' >&2; exit 2; fi"
        }
      }
    ]
  }
}
本拦截no-verify的钩子可与其他PreToolUse钩子同时运行:
json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; then echo 'BLOCKED: Bypass flags not allowed.' >&2; exit 2; fi"
        }
      },
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE 'rm\\s+-rf\\s+/'; then echo 'BLOCKED: Dangerous rm command.' >&2; exit 2; fi"
        }
      }
    ]
  }
}

Best Practices

最佳实践

  1. Commit the settings file -- Add
    .claude/settings.json
    to version control so all team members benefit from the hook.
  2. Document in onboarding -- Mention the hook in your project's contributing guide so developers understand why bypass flags are blocked.
  3. Pair with pre-commit hooks -- The block-no-verify hook ensures pre-commit hooks run; make sure you have meaningful pre-commit hooks configured.
  4. Test after setup -- Verify the hook works by intentionally triggering it in a test commit.
  1. 提交配置文件 -- 将
    .claude/settings.json
    加入版本控制,让所有团队成员都能使用该钩子。
  2. 写入入职文档 -- 在项目贡献指南中说明该钩子,让开发者理解为何要拦截绕过标志。
  3. 配合pre-commit钩子使用 -- 本拦截钩子仅确保pre-commit钩子能正常运行,请确保你已经配置了有效的pre-commit钩子规则。
  4. 配置后测试 -- 在测试提交中故意触发拦截,验证钩子是否正常工作。