Skip to main content
Hooks are event-driven automations that fire before or after tool executions. They enforce code quality, catch mistakes early, and automate repetitive checks without manual intervention.

How Hooks Work

1

User Request

You make a request: “Add authentication middleware”
2

Claude Picks Tool

Claude decides to use the Edit tool to modify a file
3

PreToolUse Hook Fires

Before the edit executes, PreToolUse hooks run:
  • Doc file warning checks if it’s a non-standard .md file
  • Strategic compact suggests manual compaction if needed
4

Tool Executes

The Edit tool modifies the file
5

PostToolUse Hook Fires

After the edit completes, PostToolUse hooks run:
  • Prettier auto-formats the file
  • TypeScript check runs tsc --noEmit
  • Console.log warning scans for debug statements

Hook Types

ECC uses five hook event types:

PreToolUse

When: Before a tool executesCan: Block execution (exit code 2) or warn (stderr)Use cases:
  • Block dev servers outside tmux
  • Warn about non-standard file creation
  • Secret detection in prompts
  • Rate limiting validation

PostToolUse

When: After a tool completesCan: Analyze output, trigger followup actionsCannot: Block execution (already completed)Use cases:
  • Auto-format code after edits
  • Run type checks
  • Log PR URLs after creation
  • Background build analysis

Stop

When: After each Claude responseUse cases:
  • Audit all modified files
  • Extract session patterns
  • Update metrics

SessionStart

When: Session beginsUse cases:
  • Load previous context
  • Detect package manager
  • Initialize session state

SessionEnd

When: Session endsUse cases:
  • Persist session state
  • Extract patterns for continuous learning
  • Save checkpoints

PreCompact

When: Before context compactionUse cases:
  • Save state before compaction
  • Log compaction event
  • Archive context

Hooks in ECC

PreToolUse Hooks

Matcher: BashBehavior: Blocks npm run dev, pnpm dev, yarn dev, bun run dev outside tmuxExit code: 2 (blocks execution)Why: Ensures you can access server logs later via tmux attachExample:
Matcher: BashBehavior: Warns about long-running commands (tests, builds, docker)Exit code: 0 (warns only)Commands matched:
  • npm install, npm test
  • cargo build, make
  • docker, pytest, vitest, playwright
Example:
Matcher: BashBehavior: Reminds to review changes before git pushExit code: 0 (warns only)Example:
Matcher: WriteBehavior: Warns about non-standard .md/.txt filesExit code: 0 (warns only)Allowed files:
  • README.md, CLAUDE.md, CONTRIBUTING.md
  • CHANGELOG.md, LICENSE, SKILL.md
  • Files in docs/ or skills/ directories
Example:
Matcher: Edit|WriteBehavior: Suggests manual /compact every ~50 tool callsExit code: 0 (warns only)Example:

PostToolUse Hooks

Matcher: BashBehavior: Logs PR URL after gh pr createExample:
Matcher: BashBehavior: Async analysis after build commandsAsync: Yes (doesn’t block)Timeout: 30 secondsCommands matched: npm run build, yarn build, tsc, webpack
Matcher: EditBehavior: Runs Prettier on JS/TS files after editsFiles matched: .js, .jsx, .ts, .tsxExample:
Matcher: EditBehavior: Runs tsc --noEmit after editing .ts/.tsx filesExample:
Matcher: EditBehavior: Warns about console.log statements in edited filesExample:

Lifecycle Hooks

Event: SessionStartActions:
  • Loads previous session context from .claude/session-state.json
  • Detects package manager (npm, pnpm, yarn, bun)
  • Initializes continuous learning observer
Example:
Event: PreCompactActions:
  • Saves current state to .claude/pre-compact-state.json
  • Archives context for potential recovery
Example:
Event: Stop (after each response)Actions:
  • Scans all modified files for console.log
  • Reports findings with file paths and line numbers
Example:
Event: SessionEndActions:
  • Persists session state to .claude/session-state.json
  • Evaluates session for extractable patterns
  • Updates continuous learning instincts
Example:

Hook Input Schema

Hooks receive JSON on stdin:

Exit Codes

Hooks communicate via exit codes:

Writing Custom Hooks

Hooks are Node.js scripts that read JSON from stdin:

Add to hooks.json

Common Hook Recipes

Warn About TODO Comments

Block Large File Creation

Auto-Format Python with Ruff

Require Test Files for New Source

Cross-Platform Compatibility

All ECC hooks use Node.js for maximum compatibility across Windows, macOS, and Linux. Avoid bash-specific syntax.
Windows Users: Hooks using bash or shell-specific features may not work. ECC hooks use node -e for portability.

Hook Best Practices

Blocking hooks (exit 2) should only be used for critical issues like security violations or dev server misconfigurations. Most hooks should warn (stderr) instead.
Hooks run synchronously (except async hooks). Slow hooks delay tool execution. Keep hook logic under 100ms.
Hooks must console.log(data) to pass the original input through. Forgetting this breaks the tool chain.
Build analysis, background jobs, or slow checks should use "async": true to avoid blocking.
Verify that blocking hooks (exit 2) actually block tool execution, and warning hooks (exit 0) don’t.

Disabling Hooks

To disable a hook, override it in ~/.claude/settings.json:

Next Steps

Explore Rules

Learn about always-follow guidelines

Hook Reference

Full catalog of all hooks

Memory Persistence

Session lifecycle hooks for context management

Custom Hooks

Step-by-step guide to building your own hooks