Claude Code can use --no-verify to skip your pre-commit hooks entirely — even when your CLAUDE.md explicitly forbids it.
Real Incident: 6 Consecutive Commits with Skipped Hooks
A user reported (#40117) that Claude Code Opus 4.6 used --no-verify on 6 consecutive commits. Pre-commit hooks validating secret scanning, integration tests, and production readiness were all silently bypassed. The agent also used git stash to manipulate state and quiet flags to suppress output.
Adding "never use --no-verify" to CLAUDE.md or memory is a suggestion the model can ignore. When context fills up, rules get forgotten. The agent in #40117 had explicit deny rules and still bypassed them.
A PreToolUse hook on Bash intercepts every command before execution. exit 2 is a hard block the model cannot bypass.
#!/bin/bash
# no-verify-blocker.sh — PreToolUse hook on "Bash"
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
# Block --no-verify on any git command
if echo "$COMMAND" | grep -qE '\bgit\b.*--no-verify'; then
echo "BLOCKED: --no-verify bypasses git hooks" >&2
exit 2
fi
# Block short form: git commit -n
if echo "$COMMAND" | grep -qE '\bgit\s+commit\s+-n\b'; then
echo "BLOCKED: git commit -n skips pre-commit hook" >&2
exit 2
fi
exit 0
npx cc-safe-setup --install-example no-verify-blocker
Blocks --no-verify, force-push, rm -rf, secret leaks, and more. 9,200+ tests 655 examples
The agent in #40117 also used git stash to circumvent hooks. You can extend the hook:
# Add to the same hook or create a separate one
if echo "$COMMAND" | grep -qE '\bgit\s+stash\b.*&&.*\bgit\s+(commit|push)\b'; then
echo "BLOCKED: git stash combined with commit/push" >&2
exit 2
fi
Prevent Force-Push · Prevent rm -rf · Prevent Secret Leaks · Prevent Cost Explosion
cc-safe-setup · 667 hooks · 9,200+ tests · GitHub
Learn more: Production Guide · All Tools