From rcc
Guides creation of Claude Code writing hooks for code quality gates, static analysis, and workflow automation using structured TDD tasks on events like PreToolUse.
npx claudepluginhub wayne930242/reflexive-claude-codeThis skill uses the workspace's default tool permissions.
**Writing hooks IS creating automated quality gates.**
Guides writing secure, reliable, performant Claude Code hooks. Validates design decisions, enforces best practices, prevents pitfalls when creating, reviewing, or debugging hooks.
Develops Claude Code hooks to run shell commands or LLM prompts on events like PreToolUse for automations, guardrails, quality checks, and pre-push tests.
Configures user-defined shell commands as hooks for Claude Code lifecycle events like session start, pre/post tool use. Ensures deterministic automation for enterprise workflows and code quality enforcement.
Share bugs, ideas, or general feedback.
Writing hooks IS creating automated quality gates.
Hooks run on Claude Code events (PreToolUse, PostToolUse, etc.) and can block actions with exit code 2.
Core principle: Hooks enforce what humans forget. Fast checks only—slow hooks kill productivity.
Violating the letter of the rules is violating the spirit of the rules.
Pattern: Skill Steps Handoff: none Next: none
Before ANY action, create task list using TaskCreate:
TaskCreate for EACH task below:
- Subject: "[writing-hooks] Task N: <action>"
- ActiveForm: "<doing action>"
Tasks:
Announce: "Created 7 tasks. Starting execution..."
Execution rules:
TaskUpdate status="in_progress" BEFORE starting each taskTaskUpdate status="completed" ONLY after verification passesTaskList to confirm all completed| TDD Phase | Hook Creation | What You Do |
|---|---|---|
| RED | Test without hook | Write code, observe quality issues slip through |
| Verify RED | Document violations | Note specific issues that should be caught |
| GREEN | Write hook | Create script that catches those issues |
| Verify GREEN | Test blocking | Verify exit code 2 blocks violating code |
| REFACTOR | Optimize speed | Reduce hook runtime, filter file types |
Goal: Understand what quality gate to create.
Questions to answer:
Event Selection:
| Event | When | Use For |
|---|---|---|
PreToolUse | Before tool runs | Block bad writes before they happen |
PostToolUse | After tool runs | Validate written code |
UserPromptSubmit | Before prompt processed | Add context to prompts |
Verification: Can describe the violation and the command to detect it.
Goal: Write code WITHOUT the hook. Observe violations that slip through.
Process:
Verification: Documented at least 1 violation that should have been caught.
Goal: Create Python script that catches the violations you documented.
.claude/hooks/
├── eslint_check.py
├── prettier_check.py
└── typecheck.py
| Code | Meaning | Effect |
|---|---|---|
| 0 | Pass | Continue, stdout shown in verbose |
| 2 | Block | Action blocked, stderr fed to Claude |
| Other | Warning | Continue, stderr shown in verbose |
See references/static-checks.md for complete hook templates. Key pattern: read JSON from stdin, filter by extension, run check, exit 2 to block.
Verification:
chmod +x)Goal: Register hook in .claude/settings.json.
CRITICAL: Use .claude/settings.json, NOT settings.local.json. Settings are team-shared.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/eslint_check.py",
"timeout": 30
}]
}
]
}
}
| Matcher | Matches |
|---|---|
Write|Edit | Write or Edit tools |
Bash | Bash tool only |
.* | All tools |
Verification:
$CLAUDE_PROJECT_DIRGoal: Verify hook script works correctly.
Test command:
echo '{"tool_input":{"file_path":"test.ts"}}' | .claude/hooks/your_hook.py
echo $? # Should be 0 (pass) or 2 (block)
Checklist:
Verification: Manual test passes for both valid and invalid inputs.
Goal: Verify hook actually blocks bad code in Claude Code.
Process:
Verification:
Goal: Have hook reviewed by hook-reviewer subagent.
Agent tool:
- subagent_type: "rcc:hook-reviewer"
- prompt: "Review hook at [path/to/hook] with settings at [path/to/.claude/settings.json]"
Outcomes:
This is the REFACTOR phase: Close loopholes identified by reviewer.
Verification: hook-reviewer returns "Pass" rating.
See references/static-checks.md for linting, type checking, and auto-fix examples.
These thoughts mean you're rationalizing. STOP and reconsider:
All of these mean: You're about to create a weak hook. Follow the process.
| Excuse | Reality |
|---|---|
| "I'll remember to lint" | You won't. Hooks enforce what humans forget. |
| "Slow hooks are thorough" | Slow hooks = disabled hooks. Keep it fast. |
| "Check everything" | Full project check = 30+ seconds. Check changed file only. |
| "settings.local.json" | Local = not shared. Team hooks go in settings.json. |
| "Simple logic doesn't need tests" | Hook failures are silent. Always test. |
digraph hook_creation {
rankdir=TB;
start [label="Need hook", shape=doublecircle];
analyze [label="Task 1: Analyze\nrequirements", shape=box];
baseline [label="Task 2: RED\nTest without hook", shape=box, style=filled, fillcolor="#ffcccc"];
write [label="Task 3: GREEN\nWrite hook script", shape=box, style=filled, fillcolor="#ccffcc"];
config [label="Task 4: Configure\nsettings.json", shape=box];
validate [label="Task 5: Validate\nbehavior", shape=box];
validate_pass [label="Tests\npassed?", shape=diamond];
test [label="Task 6: Test\nblocking", shape=box];
review [label="Task 7: REFACTOR\nQuality review", shape=box, style=filled, fillcolor="#ccccff"];
review_pass [label="Review\npassed?", shape=diamond];
done [label="Hook complete", shape=doublecircle];
start -> analyze;
analyze -> baseline;
baseline -> write;
write -> config;
config -> validate;
validate -> validate_pass;
validate_pass -> test [label="yes"];
validate_pass -> write [label="no"];
test -> review;
review -> review_pass;
review_pass -> done [label="pass"];
review_pass -> write [label="fail\nfix issues"];
}