Claude Code hooks are scripts that execute automatically when specific events occur - before or after tool calls, on notifications, or when the session starts. I've built 39 hooks that automate my entire development workflow.
Here are 10 of the most impactful patterns.
How Hooks Work
Hooks fire on three event types:
- PreToolUse - Before Claude executes a tool (edit, bash, write)
- PostToolUse - After a tool completes
- Notification - When Claude sends a notification
Configure in .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"command": "bash .claude/hooks/lint-check.sh"
}
]
}
}
Hook 1: Auto-Lint on Every Edit
#!/bin/bash
# .claude/hooks/lint-check.sh
# Runs ESLint on any file being edited
FILE=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.file_path // empty')
if [[ "$FILE" == *.ts || "$FILE" == *.tsx ]]; then
npx eslint "$FILE" --fix 2>/dev/null
fi
Hook 2: Secret Scanner
#!/bin/bash
# Blocks any edit that would introduce a secret
INPUT=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.new_string // empty')
if echo "$INPUT" | grep -qE '(sk-[a-zA-Z0-9]{20,}|AKIA[A-Z0-9]{16}|ghp_[a-zA-Z0-9]{36})'; then
echo "BLOCKED: Potential secret detected in edit"
exit 1
fi
Hook 3: Test Runner After Changes
#!/bin/bash
# PostToolUse hook - runs tests after any file edit
FILE=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.file_path // empty')
if [[ "$FILE" == *.ts ]]; then
# Find and run related test file
TEST_FILE="${FILE%.ts}.test.ts"
if [[ -f "$TEST_FILE" ]]; then
npx jest "$TEST_FILE" --silent 2>&1 | tail -5
fi
fi
Hook 4: Import Verifier
#!/bin/bash
# Checks that all imports in edited files actually exist
FILE=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.file_path // empty')
if [[ "$FILE" == *.ts || "$FILE" == *.tsx ]]; then
npx tsc --noEmit "$FILE" 2>&1 | grep "Cannot find module" | head -5
fi
Hook 5: Build Validator
#!/bin/bash
# PostToolUse: ensures build still passes after changes
if [[ -f "package.json" ]]; then
npm run build 2>&1 | tail -3
if [[ $? -ne 0 ]]; then
echo "WARNING: Build failed after last change"
fi
fi
Hook 6: Git Diff Size Limiter
#!/bin/bash
# PreToolUse on Bash: warns if uncommitted changes are getting large
LINES_CHANGED=$(git diff --stat | tail -1 | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+')
if [[ "$LINES_CHANGED" -gt 500 ]]; then
echo "WARNING: $LINES_CHANGED lines changed without commit. Consider committing."
fi
Hook 7: Dependency Checker
#!/bin/bash
# After package.json edits, verify no vulnerabilities
FILE=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.file_path // empty')
if [[ "$FILE" == *"package.json" ]]; then
npm audit --production 2>&1 | grep -E "vulnerabilities|found"
fi
Hook 8: Documentation Sync
#!/bin/bash
# When a function signature changes, flag docs for update
FILE=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.file_path // empty')
OLD=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.old_string // empty')
if echo "$OLD" | grep -q "export function\|export const.*=.*=>"; then
README_REF=$(grep -l "$(basename $FILE)" README.md docs/*.md 2>/dev/null)
if [[ -n "$README_REF" ]]; then
echo "NOTE: Function signature changed. Update docs: $README_REF"
fi
fi
Hook 9: Performance Guard
#!/bin/bash
# Warns about common performance anti-patterns
NEW=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.new_string // empty')
if echo "$NEW" | grep -qE 'useEffect.*\[\].*fetch|setTimeout.*0|JSON\.parse.*JSON\.stringify'; then
echo "PERF WARNING: Detected potential performance anti-pattern"
fi
Hook 10: Deployment Blocker
#!/bin/bash
# PreToolUse on Bash: blocks deploy commands if tests haven't passed
CMD=$(echo "$CLAUDE_TOOL_INPUT" | jq -r '.command // empty')
if echo "$CMD" | grep -qE 'vercel deploy|git push|npm publish'; then
LAST_TEST=$(cat .claude/last-test-result 2>/dev/null)
if [[ "$LAST_TEST" != "passed" ]]; then
echo "BLOCKED: Cannot deploy - tests haven't passed. Run tests first."
exit 1
fi
fi
The Power of Chaining
The real productivity gain comes from combining hooks:
- You edit a file → lint hook auto-fixes formatting
- Edit completes → test hook runs related tests
- Tests pass → build hook verifies compilation
- Build passes → deploy hook allows deployment
Zero manual intervention. Every change is validated automatically.
Getting Started
Start with just 2-3 hooks (secret scanner + lint + test runner). Add more as you identify patterns in your workflow.
The full collection of 39 hooks, plus 125 custom commands and 13 MCP server configs, is in my Claude Code Mastery Guide.
What repetitive dev workflow would you automate first? Drop a comment - I might have a hook pattern for it.
Top comments (0)