Block Destructive Git & Shell Commands
A short, deliberately narrow deny-list for commands that are almost never what you meant to run unattended: git push --force, git reset --hard, git clean -f, a DROP DATABASE, or rm -rf outside /tmp. Pairs well with the production-command hook above — this one is infrastructure-agnostic and works the same in every repo.
1. Save this as the hook script
#!/usr/bin/env python3
"""PreToolUse hook — blocks a short list of commands that are almost never
what you meant to run unattended. Wire this to the Bash matcher."""
import json, re, sys
data = json.load(sys.stdin)
command = (data.get("tool_input") or {}).get("command", "")
DESTRUCTIVE = [
r"rm\s+-rf\s+(?!/tmp|\./tmp|/var/tmp)",
r"git\s+push\s+.*--force",
r"git\s+reset\s+--hard",
r"git\s+clean\s+-f",
r"DROP\s+DATABASE",
]
for pattern in DESTRUCTIVE:
if re.search(pattern, command, re.IGNORECASE):
print(f"BLOCKED: command matches destructive pattern `{pattern}`.", file=sys.stderr)
print("Re-run manually outside the agent if this is genuinely intentional.", file=sys.stderr)
sys.exit(2)
sys.exit(0)
Save to a path inside your project, e.g. .claude/hooks/block-destructive-commands.sh, then chmod +x it.
2. Wire it into .claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{"type": "command", "command": "python3 .claude/hooks/block-destructive-commands.py"}
]
}
]
}
}
Before you use this
A hook runs with your local shell's permissions — review the script above before adding it, the same way you'd review any script you didn't write yourself. See our guide on hook security risks for the specific CVEs this category of feature has already produced.
Related hooks