Research Gate: Runtime enforcement hooks for Claude Code — blocks infrastructure commands without prior research A developer created runtime enforcement hooks for Claude Code that block infrastructure commands unless the model has performed at least two research actions in the current session. The hooks move enforcement from the model's context window to the harness layer, preventing the model from ignoring CLAUDE.md instructions to research before executing commands. The solution includes a research gate, a research logger, and a session reset script, all configurable via environment variables. Claude Code models Opus 4.5, 4.6, 4.7 systematically ignore CLAUDE.md instructions to research before executing infrastructure commands. This has been documented across multiple issues: 72651 https://github.com/anthropics/claude-code/issues/72651 — Model ignores CLAUDE.md behavioral instructions 59515 https://github.com/anthropics/claude-code/issues/59515 — Model skips research before infrastructure actions 28469 https://github.com/anthropics/claude-code/issues/28469 — Regression from Opus 4.5 to 4.6 41217 https://github.com/anthropics/claude-code/issues/41217 — Systematic failure to follow explicit behavioral constraints Prompt-level enforcement CLAUDE.md rules, memory files, repeated instructions fails because enforcement lives in the model's context window, where the model can override it. The model acknowledges the rule, then ignores it. Three hooks that move enforcement to the harness layer, where the model cannot override it: - research-gate.sh PreToolUse on Bash — Blocks infrastructure commands gcloud deploy, aws ec2, kubectl apply, terraform, etc. unless the model has performed at least 2 research actions in the current session. - research-logger.sh PostToolUse on WebSearch|WebFetch|Read — Logs each research tool call to a session ledger file. - research-session-reset.sh SessionStart — Clears the research ledger so each session starts at zero. The model must earn the right to run infrastructure commands by researching first. Infrastructure commands that modify state: gcloud run deploy , gcloud compute instances create , gcloud container clusters create aws ec2 run-instances , aws ecs create-service , aws lambda create-function kubectl apply , kubectl create , kubectl delete terraform apply , terraform destroy docker push , docker build bash deploy .sh , python deploy .py , python launch .py Read-only and safe commands: gcloud storage ls , gcloud auth , gcloud config aws s3 ls , aws s3 cp , aws sts gh issue , gh pr docker ps , docker images , docker logs nvidia-smi - Any non-infrastructure bash command ls , grep , cat , etc. mkdir -p ~/.claude/hooks ~/.claude/receipts Copy research-gate.sh, research-logger.sh, research-session-reset.sh to ~/.claude/hooks/ and make executable chmod +x ~/.claude/hooks/research-gate.sh chmod +x ~/.claude/hooks/research-logger.sh chmod +x ~/.claude/hooks/research-session-reset.sh Add these entries to the hooks object: { "hooks": { "PreToolUse": { "matcher": "Bash", "hooks": { "type": "command", "command": "~/.claude/hooks/research-gate.sh" } } , "PostToolUse": { "matcher": "WebSearch|WebFetch|Read", "hooks": { "type": "command", "command": "~/.claude/hooks/research-logger.sh" } } , "SessionStart": { "hooks": { "type": "command", "command": "~/.claude/hooks/research-session-reset.sh" } } } } Set CC RESEARCH BYPASS=1 as an environment variable to allow a single infrastructure command without research. The bypass is logged to ~/.claude/receipts/research-gate-YYYY-MM-DD.jsonl for audit. python3 for regex pattern matching jq optional, used in some patterns Edit research-gate.sh to customize: MIN RESEARCH=2 — minimum research actions required default: 2 infra patterns — list of regex patterns that trigger the gate safe patterns — list of regex patterns that always pass "Prose rules cannot be the load-bearing element of architectural guarantees. The load-bearing element has to live in the harness at the point of action." This is the same principle behind seatbelt interlocks, type systems, and database constraints. If the model can choose to ignore a rule, it will. The enforcement must be external to the model. If you have infrastructure patterns to add, false positives to report, or improvements to the matching logic, please comment. The goal is a community-maintained hook package that compensates for the model's inability to follow its own instructions. MIT. Use it, fork it, improve it.