Skip to content
hooks-configuration logo

Claude Code Hooks Configuration

hooks-configuration

Claude Code hooks configuration and development. Covers hook lifecycle events, configuration patterns, input/output schemas, and common automation use cases. Use when user mentions hooks, automation, PreToolUse, PostToolUse, SessionStart, SubagentStart, or needs to enforce consistent behavior in ...

SKILL.md

Full skill instructions

Claude Code Hooks Configuration

Expert knowledge for configuring and developing Claude Code hooks to automate workflows and enforce best practices.

Core Concepts

What Are Hooks? Hooks are user-defined shell commands that execute at specific points in Claude Code's lifecycle. Unlike relying on Claude to "decide" to run something, hooks provide deterministic, guaranteed execution.

Why Use Hooks?

  • Enforce code formatting automatically
  • Block dangerous commands before execution
  • Inject context at session start
  • Log commands for audit trails
  • Send notifications when tasks complete

Hook Lifecycle Events

EventWhen It FiresKey Use Cases
SessionStartSession begins/​resumesEnvironment setup, context loading
UserPromptSubmitUser submits promptInput validation, context injection
PreToolUseBefore tool executionPermission control, blocking dangerous ops
PostToolUseAfter tool completesAuto-formatting, logging, validation
StopAgent finishesNotifications, git reminders
SubagentStartSubagent is about to startInput modification, context injection
SubagentStopSubagent finishesTask completion evaluation
PreCompactBefore context compactionTranscript backup
NotificationClaude sends notificationCustom alerts
SessionEndSession terminatesCleanup, state persistence

Configuration

File Locations

Hooks are configured in settings files:

  • ~/​.claude/​settings.json - User-level (applies everywhere)
  • .claude/​settings.json - Project-level (committed to repo)
  • .claude/​settings.local.json - Local project (not committed)

Claude Code merges all matching hooks from all files.

Frontmatter Hooks (Skills and Commands)

Hooks can also be defined directly in skill and command frontmatter using the hooks field:

---
name: my-skill
description: A skill with hooks
allowed-tools: Bash, Read
hooks:
  PreToolUse:
    - matcher: "Bash"
      hooks:
        - type: command
          command: "echo 'Pre-tool hook from skill'"
          timeout: 10
---

This allows skills and commands to define their own hooks that are active only when that skill/​command is in use.

Basic Structure

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

Matcher Patterns

  • Exact match: "Bash" - matches exactly "Bash" tool
  • Regex patterns: "Edit|Write" - matches either tool
  • Wildcards: "Notebook.*" - matches tools starting with "Notebook"
  • All tools: "*" - matches everything
  • MCP tools: "mcp__server__tool" - targets MCP server tools

Input Schema

Hooks receive JSON via stdin with these common fields:

{
  "session_id": "unique-session-id",
  "transcript_path": "/​path/​to/​conversation.json",
  "cwd": "/​current/​working/​directory",
  "permission_mode": "mode",
  "hook_event_name": "PreToolUse"
}

PreToolUse additional fields:

{
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  }
}

PostToolUse additional fields:

{
  "tool_name": "Bash",
  "tool_input": { ... },
  "tool_response": { ... }
}

SubagentStart additional fields:

{
  "subagent_type": "Explore",
  "subagent_prompt": "original prompt text",
  "subagent_model": "claude-sonnet-4-20250514"
}

Output Schema

Exit Codes

  • 0: Success (command allowed)
  • 2: Blocking error (stderr shown to Claude, operation blocked)
  • Other: Non-blocking error (logged in verbose mode)

JSON Response (optional)

PreToolUse:

{
  "permissionDecision": "allow|deny|ask",
  "permissionDecisionReason": "explanation",
  "updatedInput": { "modified": "input" }
}

Stop/​SubagentStop:

{
  "decision": "block",
  "reason": "required explanation for continuing"
}

SubagentStart (input modification):

{
  "updatedPrompt": "modified prompt text to inject context or modify behavior"
}

SessionStart:

{
  "additionalContext": "Information to inject into session"
}

Common Hook Patterns

Block Dangerous Commands (PreToolUse)

#!/​bin/​bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

# Block rm -rf /
if echo "$COMMAND" | grep -Eq 'rm\s+(-rf|-fr)\s+/'; then
    echo "BLOCKED: Refusing to run destructive command on root" >&2
    exit 2
fi

exit 0

Auto-Format After Edits (PostToolUse)

#!/​bin/​bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

if [[ "$FILE" == *.py ]]; then
    ruff format "$FILE" 2>/​dev/​null
    ruff check --fix "$FILE" 2>/​dev/​null
elif [[ "$FILE" == *.ts ]] || [[ "$FILE" == *.tsx ]]; then
    prettier --write "$FILE" 2>/​dev/​null
fi

exit 0

Remind About Built-in Tools (PreToolUse)

#!/​bin/​bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if echo "$COMMAND" | grep -Eq '^\s*cat\s+[^|><]'; then
    echo "REMINDER: Use the Read tool instead of 'cat'" >&2
    exit 2
fi

exit 0

Load Context at Session Start (SessionStart)

#!/​bin/​bash
GIT_STATUS=$(git status --short 2>/​dev/​null | head -5)
BRANCH=$(git branch --show-current 2>/​dev/​null)

cat << EOF
{
  "additionalContext": "Current branch: $BRANCH\nPending changes:\n$GIT_STATUS"
}
EOF

Inject Context for Subagents (SubagentStart)

#!/​bin/​bash
INPUT=$(cat)
SUBAGENT_TYPE=$(echo "$INPUT" | jq -r '.subagent_type // empty')
ORIGINAL_PROMPT=$(echo "$INPUT" | jq -r '.subagent_prompt // empty')

# Add project context to Explore agents
if [ "$SUBAGENT_TYPE" = "Explore" ]; then
    PROJECT_INFO="Project uses TypeScript with Bun. Main source in src/​."
    cat << EOF
{
  "updatedPrompt": "$PROJECT_INFO\n\n$ORIGINAL_PROMPT"
}
EOF
fi

exit 0

Desktop Notification on Stop (Stop)

#!/​bin/​bash
# Linux
notify-send "Claude Code" "Task completed" 2>/​dev/​null

# macOS
osascript -e 'display notification "Task completed" with title "Claude Code"' 2>/​dev/​null

exit 0

Audit Logging (PostToolUse)

#!/​bin/​bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // "N/​A"')

echo "$(date -Iseconds) | $TOOL | $COMMAND" >> ~/​.claude/​audit.log
exit 0

Configuration Examples

Anti-Pattern Detection

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash $CLAUDE_PROJECT_DIR/​hooks-plugin/​hooks/​bash-antipatterns.sh",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

Auto-Format Python Files

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'FILE=$(cat | jq -r \".tool_input.file_path\"); [[ \"$FILE\" == *.py ]] && ruff format \"$FILE\"'"
          }
        ]
      }
    ]
  }
}

Git Reminder on Stop

{
  "hooks": {
    "Stop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'changes=$(git status --porcelain | wc -l); [ $changes -gt 0 ] && echo \"Reminder: $changes uncommitted changes\"'"
          }
        ]
      }
    ]
  }
}

Best Practices

Script Development:

  1. Always read input from stdin with cat
  2. Use jq for JSON parsing
  3. Quote all variables to prevent injection
  4. Exit with code 2 to block, 0 to allow
  5. Write blocking messages to stderr
  6. Keep hooks fast (< 5 seconds)

Configuration:

  1. Use $CLAUDE_PROJECT_DIR for portable paths
  2. Set appropriate timeouts (default: 60s)
  3. Use specific matchers over wildcards
  4. Test hooks manually before enabling

Security:

  1. Validate all inputs
  2. Use absolute paths
  3. Avoid touching .env or .git/ directly
  4. Review hook code before deployment

Debugging

Verify hook registration:

/​hooks

Enable debug logging:

claude --debug

Test hooks manually:

echo '{"tool_input": {"command": "cat file.txt"}}' | bash your-hook.sh
echo $?  # Check exit code

Available Hooks in This Plugin

  • bash-antipatterns.sh: Detects when Claude uses shell commands instead of built-in tools (cat, grep, sed, timeout, etc.)

See hooks/​README.md for full documentation.

More Productivity & Planning skills

brainstorming logo
Productivity & Planning

brainstorming

Structured design dialogue that validates ideas before implementation begins.

295.4K 385.7K
View
ui-ux-pro-max logo
Productivity & Planning

ui-ux-pro-max

Comprehensive design intelligence for web and mobile UI/UX across 10 technology stacks.

133.1K 383.9K
View
writing-plans logo
Productivity & Planning

writing-plans

Comprehensive implementation plans for multi-step tasks, breaking down specs into bite-sized, testable steps.

295.4K 268K
View
using-superpowers logo
Productivity & Planning

using-superpowers

Introduction to the obra skills system with mandatory skill invocation rules and best practices.

295.4K 259.8K
View
executing-plans logo
Productivity & Planning

executing-plans

Execute a written implementation plan with critical review and task checkpoints.

295.4K 229.1K
View
dispatching-parallel-agents logo
Productivity & Planning

dispatching-parallel-agents

Delegate independent tasks to specialized agents working concurrently with isolated context.

295.4K 206.3K
View
using-git-worktrees logo
Productivity & Planning

using-git-worktrees

Isolated git worktrees with smart directory selection and safety verification.

295.4K 205.2K
View
webapp-testing logo
Productivity & Planning

webapp-testing

Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.

179.7K 170.6K
View
content-strategy logo
Productivity & Planning

content-strategy

Plan searchable and shareable content that drives traffic, builds authority, and generates leads.

53.3K 150.9K
View
repo-intake-and-plan logo
Productivity & Planning

repo-intake-and-plan

README-first repository scanner that extracts commands and classifies reproduction candidates without executing them.

497 139.6K
View
marketing-ideas logo
Productivity & Planning

marketing-ideas

Brainstorm and prioritize marketing strategies tailored to your SaaS stage, budget, and goals.

53.3K 137.2K
View
site-architecture logo
Productivity & Planning

site-architecture

Plan and optimize your website's page hierarchy, navigation, URL structure, and internal linking.

53.3K 112.8K
View

Productivity AI tools

Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View
SaveDay logo
Productivity

SaveDay

Capture, organize, and utilize your knowledge effortlessly.

Free
View
A
Productivity

Any Summary

Instant Summaries of Audio & Video Interviews with AnySummary

Freemium
View
M
Productivity

Map This

Transform PDFs into engaging mind maps.

Freemium
View
ChatPDF logo
Productivity

ChatPDF

Chat with any PDF instantly

Free
View
I
Productivity

intellisay

Create an optimal daily plan using your voice

Paid
View
A
Productivity

Aurora AI

A productivity platform to centralize organizational knowledge and workflows with contextual AI assistance.

Paid
View
AskYourPDF logo
Productivity

AskYourPDF

AskYourPDF Pricing Plans: Tailored to Your Needs

Free
View