Require Explicit Scope on a High-Blast-Radius Prompt
In a project where every change needs to map to something reviewable, an unscoped prompt produces an unscoped diff. This blocks a small set of obviously unbounded phrasings and asks for a named file, directory, or ticket instead — a cheap nudge toward reviewable change sizes.
1. Save this as the hook script
#!/usr/bin/env python3
"""UserPromptSubmit hook — blocks an unscoped, high-blast-radius prompt
phrasing in a regulated project."""
import json, re, sys
data = json.load(sys.stdin)
prompt = data.get("user_prompt", "")
UNSCOPED_PATTERNS = [r"(?i)fix everything", r"(?i)clean up the whole (repo|project|codebase)"]
if any(re.search(p, prompt) for p in UNSCOPED_PATTERNS) and not re.search(r"(?i)\b(file|directory|ticket|module)\b", prompt):
print("BLOCKED: this prompt has no named scope (file, directory, ticket, "
"or module). Name one so the resulting change stays reviewable.", file=sys.stderr)
sys.exit(2)
sys.exit(0)
Save to a path inside your project, e.g. .claude/hooks/require-scope-high-blast-radius-prompt.sh, then chmod +x it.
2. Wire it into .claude/settings.json
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{"type": "command", "command": "python3 .claude/hooks/require-scope-high-blast-radius-prompt.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