Hooks
Event-based automation that encodes your judgment into executable code. Your expertise runs before Claude even responds.
What Are Hooks?
Most developers configure Claude session-by-session: "This is a client project, watch for scope creep", "Remember to run lint before commits". Every session starts from zero.
Hooks are scripts that run automatically based on Claude Code events. Instead of repeating instructions, your past decisions apply themselves.
The Core Insight
Hooks let you encode your judgment once and have it apply automatically forever. You're building a context-aware operating system where your expertise runs as executable code.
Without Hooks
- • You: "This is a client project..."
- • You: "Watch for scope creep..."
- • You: "Run lint before commits..."
- Every. Single. Session.
With Hooks
- • Hook detects: client project
- • Hook flags: "can we also..."
- • Hook blocks: commit without lint
- Automatically. Every time.
Hook Types
Claude Code supports four hook types, each triggered at different points in the workflow:
SessionStart
Runs when Claude Code starts in a directory. Perfect for detecting project type and injecting context.
UserPromptSubmit
Runs before Claude processes your message. Ideal for scope creep detection and warning injection.
PreToolUse
Runs before Claude uses a specific tool. Quality gates before commits, dangerous operation checks.
Stop
Runs when Claude finishes a task. Completion checks, summaries, cleanup tasks.
Example: Scope Creep Detection
Here's a practical example: a UserPromptSubmit hook that flags scope creep phrases before Claude processes your message.
#!/usr/bin/env python3
import json, sys, re
input_data = json.load(sys.stdin)
prompt = input_data.get("prompt", "")
# Scope creep triggers
triggers = ["can we also", "while you're at it", "quick change"]
pattern = "|".join(triggers)
result = {"continue": True}
if re.search(pattern, prompt, re.IGNORECASE):
result["systemMessage"] = "⚠️ SCOPE ALERT: Is this in scope?"
print(json.dumps(result))Input
Reads user prompt from stdin as JSON
Output
Returns JSON with continue flag and optional systemMessage
Configuration
Hooks are configured in ~/.claude/settings.json:
{
"hooks": {
"SessionStart": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/hooks/session-start.py",
"timeout": 5
}]
}],
"UserPromptSubmit": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/hooks/prompt-submit.py",
"timeout": 3
}]
}]
}
}Key fields: matcher controls which directories trigger the hook.timeout prevents slow hooks from blocking Claude.
Getting Started
- 1.Create the hooks directorymkdir -p ~/.claude/hooks
- 2.Create a hook script
Python or Bash script that reads stdin (JSON) and prints JSON to stdout.
- 3.Configure settings.json
Add your hook to the appropriate event type in ~/.claude/settings.json
- 4.Test it
Start a new Claude Code session and trigger the hook to verify it works.
Best Practices
✓ Do's
- •Keep hooks fast (<5 seconds)
- •Always return valid JSON
- •Test scripts standalone first
- •Start simple, add complexity gradually
✗ Don'ts
- •Don't make hooks that take >10 seconds
- •Don't store secrets in hook scripts
- •Don't block everything - be selective
- •Don't over-engineer - solve real problems
⚠️ Security Note
Hooks run with your user permissions. Review hook scripts before using them, just like you would review any executable code you add to your system.
Hooks in Context
Hooks are powerful on their own, but they're part of a bigger system:
CLAUDE.md provides passive context. Skills encode reusable workflows. Hooks automate when those workflows activate. Archetypes bundle everything into coherent work modes.