Agents block-no-verify-hook
Configure a PreToolUse hook to prevent AI agents from skipping git pre-commit hooks with --no-verify and other bypass flags. Use when setting up Claude Code projects that enforce commit quality gates.
git clone https://github.com/wshobson/agents
T=$(mktemp -d) && git clone --depth=1 https://github.com/wshobson/agents "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/block-no-verify/skills/block-no-verify-hook" ~/.claude/skills/wshobson-agents-block-no-verify-hook && rm -rf "$T"
plugins/block-no-verify/skills/block-no-verify-hook/SKILL.mdBlock No-Verify Hook
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.
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.
Problem
When AI agents commit code, they may use bypass flags to avoid hook failures:
# 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
Solution
Add a
PreToolUse hook to .claude/settings.json that inspects every Bash tool call and blocks commands containing bypass flags.
Configuration
Add the following to your project's
.claude/settings.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
- Matcher: The hook targets only
tool calls, so it does not interfere with other tools (Read, Edit, Grep, etc.).Bash - Inspection: The
environment variable contains the full command the agent is about to execute. The hook uses$TOOL_INPUT
to safely pass input (avoidingprintf
pitfalls with special characters) and checks forecho
or--no-verify
flags only when preceded by a--no-gpg-sign
command.git - 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.
- Pass-through: If no bypass flag is found, the hook exits with code 0 and the command executes normally.
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Allow the tool call to proceed |
| 1 | Error (tool call still proceeds, warning shown) |
| 2 | Block the tool call entirely |
Blocked Flags
| Flag | Purpose | Why Blocked |
|---|---|---|
| Skips pre-commit and commit-msg hooks | Bypasses linting, formatting, testing, security checks |
| Skips GPG commit signing | Bypasses commit signing policy |
Installation
Per-Project Setup
Create or update
.claude/settings.json in your project root:
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:
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:
# This should be blocked by the hook: git commit --no-verify -m "test" # This should succeed normally: git commit -m "test"
Extending the Hook
Adding More Blocked Flags
To block additional flags (e.g.,
--force), extend the grep pattern:
{ "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:
{ "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
- Commit the settings file -- Add
to version control so all team members benefit from the hook..claude/settings.json - Document in onboarding -- Mention the hook in your project's contributing guide so developers understand why bypass flags are blocked.
- Pair with pre-commit hooks -- The block-no-verify hook ensures pre-commit hooks run; make sure you have meaningful pre-commit hooks configured.
- Test after setup -- Verify the hook works by intentionally triggering it in a test commit.