Claude-cod-top-2026 / hooks
CLAUDE.md9 starsChanged 6 months agoMITView on GitHub
hooks/utils.py still exists as a backward-compatible facade re-exporting every symbol, so old from utils import X call sites keep working — but it is a facade, not the source. New code should import directly from hooks/lib/{runtime,state, discovery,security}.py, not from utils. Never duplicate these symbols elsewhere. Missing this = infinite loop when Claude Code invokes subagents. Claude Code SDK uses a different signal per hook type (full detail: hooks/lib/runtime.py's module docstring): - PreToolUse — call emit_permission_decision() from hooks/lib/runtime.py (JSON hookSpecificOutput to…
In this repository164 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .codex/AGENTS.mdAGENTS.md
- agents/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- claude-md/CLAUDE.mdCLAUDE.md
- insight-architectSkill
- agent-teamsSkill
- brainstormingSkill
- claim-decomposerSkill
- context-engineeringSkill
- dispatcherSkill
- git-worktreesSkill
- hd-mavp-routerSkill
- mentor-modeSkill
- reference-registrySkill
- routing-policySkill
- skill-self-updateSkill
- tdd-workflowSkill
- ab-testSkill
- academic-researchSkill
- advanced-methodology-extensionsSkill
- agent-governanceSkill
- ai-hyp-gateSkill
- algorithm-designSkill
- analystSkill
- archcode-genomicsSkill
- arm-cortex-microcontrollersSkill
- atomizeSkill
- backward-traceabilitySkill
- boyko-constraint-engineSkill
- boyko-epistemic-auditSkill
- boyko-goal-expansion-100Skill
- boyko-knowledge-architectureSkill
- boyko-leverage-mapSkill
- boyko-methodSkill
- boyko-preflightSkill
- boyko-project-radarSkill
- boyko-rippleSkill
- boyko-scientific-consortiumSkill
- boyko-specialistSkill
- boyko-toolcheckSkill
- boyko-triangle-auditSkill
- boyko-why-ladderSkill
- browser-actSkill
- build-autoSkill
- c4-architectureSkill
- career-prepSkill
- changelog-genSkill
- citation-managementSkill
- code-debuggingSkill
- code-materialitySkill
- codex-skepticSkill
- codex-solverSkill
- codex-tracySkill
- combinatorial-creativitySkill
- common-groundSkill
- conductorSkill
- consilienceSkill
- construct-measurement-gateSkill
- convertSkill
- The first 60 shown.
The file
We split this CLAUDE.md into the rules it gives an agent
5 rules. About 0 are common, 4 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 18
If a hook runs via async_wrapper.py, stdout goes to DEVNULL → emit_hook_result silently fails.
- Distinctive: line 22
Every hook that calls Claude or reads memory must check:
- Distinctive: line 55
Never raise unhandled exceptions — hook dies silently
- Distinctive: line 59
Add recursion guard if hook reads memory or calls Claude
- Distinctive: line 61
Add entry to README hook table
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Hooks — Local Rules
Architecture
Shared code lives in hooks/lib/{runtime,state,discovery,security}.py, grouped by
responsibility (hook I/O protocol, state files/locking, project discovery,
sanitization/secrets) — split out 2026-08-22 from a single utils.py that had grown
to 36 symbols and fan-in 74 (HS-01, artifacts/architecture-coupling/hotspots.json).
hooks/utils.py still exists as a backward-compatible facade re-exporting every
symbol, so old from utils import X call sites keep working — but it is a facade,
not the source. New code should import directly from hooks/lib/{runtime,state,
discovery,security}.py, not from utils. Never duplicate these symbols elsewhere.
Critical Patterns
stdout is the hook protocol
emit_hook_result() writes JSON to stdout → Claude Code reads it.
If a hook runs via async_wrapper.py, stdout goes to DEVNULL → emit_hook_result silently fails.
Never wrap a hook in async_wrapper if it needs to inject context.
Recursion guard
Every hook that calls Claude or reads memory must check:
if os.environ.get("CLAUDE_INVOKED_BY"):
sys.exit(0)Missing this = infinite loop when Claude Code invokes subagents.
Blocking protocol — two different mechanisms, do not mix
Claude Code SDK uses a different signal per hook type (full detail:
hooks/lib/runtime.py's module docstring):
- PreToolUse — call
emit_permission_decision()fromhooks/lib/runtime.py(JSONhookSpecificOutputto stdout). A baresys.exit(N)does NOT block a PreToolUse call the way this repo does it — only exit code 2 blocks per Claude Code's own protocol, and this repo standardizes on the JSON path instead. Correct examples:pre_commit_guard.py,security_verify.py,input_guard.py,scripts/redact.py. - PostToolUse — the tool has already run; no exit code blocks it.
sys.exit(2)is the strongest available signal (surfaces stderr to Claude prominently) — current convention, seeskeptic_auto_trigger.py,goal_stub_detector.py,validation_theater_guard.py(migrated 2026-08-29).sys.exit(1)is a legacy pattern with no special surfacing semantics — avoid it for new PostToolUse hooks.
Exit codes
sys.exit(0)— success or skip (no action needed)sys.exit(2)— PreToolUse: blocks, per Claude Code protocol (this repo prefersemit_permission_decision()instead of a bare exit code). PostToolUse: strongest available signal shown to Claude — NOT a true block, the tool already ran.sys.exit(1)— non-blocking everywhere. Legacy PostToolUse pattern with no special surfacing semantics, being replaced bysys.exit(2).- Never raise unhandled exceptions — hook dies silently
Adding a New Hook
- Import
from lib.runtime import emit_hook_result, hook_main, parse_stdin - Add recursion guard if hook reads memory or calls Claude
- Register in
settings.jsonwith__PYTHON_CMD__ __CLAUDE_HOME__/hooks/<name>.py - Add entry to README hook table
Known Anti-Patterns
async_wrapper+emit_hook_result= silent failure (learned 2026-04-19)- Missing
CLAUDE_INVOKED_BYguard = Agent SDK infinite loop datetime.utcnow()mixed with timezone-aware datetimes = TypeError at runtime
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

