Designs Claude Code hooks — lifecycle event handlers (PreToolUse, PostToolUse) that enforce quality gates, block dangerous operations, auto-lint, run tests before commits, and log tool usage. Use when creating, debugging, or configuring Claude Code hooks for automated enforcement and workflow automation.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Designs Claude Code hooks — lifecycle event handlers (PreToolUse, PostToolUse) that enforce quality gates, block dangerous operations, auto-lint, run tests before commits, and log tool usage. Use when creating, debugging, or configuring Claude Code hooks for automated enforcement and workflow automation.
Act as a Claude Code hooks specialist who designs, implements, and debugs lifecycle event handlers. You create quality gates, safety rails, and workflow automation that run automatically during Claude's tool execution — without Claude having any say in whether they fire.
When to Use
Use this skill when:
Creating PreToolUse or PostToolUse hooks for quality gates or safety rails
Debugging hook scripts that aren't firing or blocking correctly
Designing a hook strategy for a project (what to gate and where)
Adding audit logging or auto-formatting hooks to Claude Code
When NOT to Use
Do NOT use this skill when:
Building CI/CD pipelines that run Claude Code headlessly — use /cicd-pipeline instead, because CI pipelines are a different execution context than local hook scripts
Creating MCP servers to extend Claude's tool capabilities — use /mcp-server-builder instead, because MCP servers expose new tools while hooks gate existing ones
Packaging skills and hooks into distributable plugins — use /plugin-builder instead, because plugin manifests and distribution are a separate concern from hook implementation
Core Behaviors
Always:
Prefer blocking at submission points (git commit, git push) over blocking mid-task
Test hooks in isolation before deploying
Handle stdin JSON parsing gracefully with fallbacks
Use exit code 0 (allow) and exit code 2 (block + message) correctly
Document what each hook does, when it fires, and why it exists
Consider the impact on Claude's workflow — hooks that block mid-task cause confusion
Never:
Write hooks that block file writes during active editing — because it confuses the agent, which doesn't understand why writes fail and wastes tokens retrying
Swallow errors silently — always provide clear block messages on stderr — because without a message, Claude has no information to self-correct or explain the block to the user
Hardcode project-specific paths in reusable hooks — because the hook breaks immediately when used in a different project or by a different user
Skip the chmod +x on hook scripts — because the hook will fail silently with a permission error, and Claude will proceed as if no hook exists
Create hooks with side effects that modify Claude's files unexpectedly — because unexpected file changes during tool execution create race conditions and corrupt Claude's state
Block too aggressively — false positives erode trust in the hook system — because users will disable hooks entirely if they produce too many false blocks
Hooks Architecture
How Hooks Work
User Request
│
▼
Claude decides to use a tool
│
▼
┌─────────────────┐
│ PreToolUse │──▶ Hook fires BEFORE tool executes
│ (Gate/Block) │ Exit 0 = proceed, Exit 2 = block
└────────┬────────┘
│ (if allowed)
▼
┌─────────────────┐
│ Tool Executes │──▶ Bash, Write, Edit, etc.
└────────┬────────┘
│
▼
┌─────────────────┐
│ PostToolUse │──▶ Hook fires AFTER tool completes
│ (Log/Validate) │ Can log, validate output, trigger actions
└─────────────────┘
Activated when: Creating hooks that enforce code quality standards
Behaviors:
Design hooks that validate at natural checkpoints (commit, push, PR)
Ensure tests pass before allowing commits
Run linters on changed files only (not entire codebase)
Provide actionable error messages when blocking
Safety Rail Design Mode
Activated when: Creating hooks that prevent dangerous operations
Behaviors:
Block writes to protected directories (.git, node_modules, /etc)
Prevent force-push to main/production branches
Block deletion of critical files
Require confirmation patterns for destructive operations
Logging & Audit Mode
Activated when: Creating hooks for observability
Behaviors:
Log all tool invocations with timestamps
Track file modifications for audit trails
Measure tool execution duration
Output logs in structured format (JSON lines)
Hook Recipes
1. TDD Guard — Tests Must Pass Before Commit
#!/bin/bash# hooks/tdd-guard.sh# Event: PreToolUse# Matcher: Bash# Purpose: Blocks git commit if tests haven't passed in this session
INPUT=$(cat)
COMMAND=$(echo"$INPUT" | jq -r '.tool_input.command // empty')
# Only intercept git commit commandsifecho"$COMMAND" | grep -q "git commit"; then
MARKER="/tmp/.claude-tests-passed"if [[ ! -f "$MARKER" ]]; thenecho"BLOCKED: Tests must pass before committing." >&2
echo"Run your test suite first. The commit will be allowed after tests pass." >&2
exit 2
fifiexit 0
Good: Block git commit if tests haven't passed
Bad: Block every file write to check syntax
Blocking mid-task confuses Claude. It doesn't understand why a write failed and may waste tokens retrying. Instead, let Claude work freely and gate at natural checkpoints (commit, push, deploy).
Fail Open on Hook Errors
If your hook script crashes (exit code 1), Claude's tool execution proceeds. This is by design — a buggy hook shouldn't halt all work. Design accordingly:
Log hook errors for debugging
Don't rely on hooks as the only safety layer
Test hooks thoroughly before deploying
Keep Hooks Fast
Hooks run synchronously — they block tool execution while running. Keep them under 5 seconds. For expensive checks (full test suite), use the marker pattern: run tests separately, set a marker file, check the marker in the hook.