Skip to content
hooks-mastery logo

Claude Code Hooks Mastery

hooks-mastery

This skill should be used when the user asks to "create a hook", "configure hooks", "validate hook configuration", "add a PreToolUse hook", "add a PostToolUse hook", "add a SessionStart hook", mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, UserPromptSubmit, Permi...

SKILL.md

Full skill instructions

Claude Code Hooks Mastery

Overview

Claude Code hooks are event-driven extensions that execute commands or LLM evaluations at specific lifecycle points. This skill provides guidance for creating production-ready hooks following the official protocol specification.

Core Concepts

Hook Types

Command Hooks: Execute bash scripts with JSON input via stdin

{
  "type": "command",
  "command": "python3 /​path/​to/​script.py",
  "timeout": 60
}

Prompt-Based Hooks: Use LLM (Haiku) for intelligent evaluation

{
  "type": "prompt",
  "prompt": "Evaluate if Claude should stop: $ARGUMENTS",
  "timeout": 30
}

Hook Events

EventMatcherPurposeCommon Use Cases
PreToolUseYesBefore tool executionValidation, modification, blocking
PermissionRequestYesPermission dialogAuto-approve/​deny
PostToolUseYesAfter tool executionFormatting, validation
UserPromptSubmitNoBefore prompt processingContext injection, validation
Stop/​SubagentStopNoAgent finishingDetermine if work complete
SessionStartYesSession start/​resumeEnvironment setup, context loading
SessionEndNoSession endCleanup, logging
NotificationYesNotifications sentExternal alerting
PreCompactYesBefore compactValidation, logging

Configuration Structure

Hooks are configured in settings files (user, project, or local scope):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash|Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/​.claude/​hooks/​validator.py",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

Creating Hooks

Step 1: Choose Hook Event

Identify which lifecycle point to hook into:

  • Validation before action: PreToolUse, PermissionRequest
  • Processing after action: PostToolUse
  • Context enhancement: UserPromptSubmit, SessionStart
  • Flow control: Stop, SubagentStop

Step 2: Write Hook Script

Input Protocol: Hooks receive JSON via stdin with these common fields:

{
  "session_id": "string",
  "transcript_path": "string",
  "cwd": "string",
  "permission_mode": "default|plan|acceptEdits|bypassPermissions",
  "hook_event_name": "EventName",
  // Event-specific fields...
}

Output Protocol: Respond via exit codes and stdout:

Exit Code 0 (Success):

  • stdout: Plain text or JSON for structured control
  • JSON enables advanced decisions

Exit Code 2 (Blocking):

  • stderr: Error message fed to Claude
  • Blocks the action (behavior varies by event)

Exit Code 1+ (Non-blocking):

  • stderr: Logged to verbose mode
  • Execution continues

Step 3: Configure Hook

Add to appropriate settings file:

  • ~/​.claude/​settings.json - User-level
  • .claude/​settings.json - Project-level (team-shared)
  • .claude/​settings.local.json - Local (git-ignored)

Step 4: Test Hook

Enable debug mode to see hook execution:

claude --debug

Use verbose mode (Ctrl+O) during session to see hook output.

Common Patterns

Pattern 1: Validation Hook (PreToolUse)

Validate and potentially block tool calls:

#!/​usr/​bin/​env python3
import json
import sys

# Read input
input_data = json.load(sys.stdin)

# Validate
if should_block(input_data):
    print("Validation failed: reason", file=sys.stderr)
    sys.exit(2)  # Block execution

# Allow with optional modification
output = {
    "hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "allow",
        "updatedInput": {
            "modified_field": "new_value"
        }
    }
}
print(json.dumps(output))
sys.exit(0)

Pattern 2: Context Enrichment (UserPromptSubmit)

Add context before Claude processes prompt:

#!/​usr/​bin/​env python3
import json
import sys
import datetime

input_data = json.load(sys.stdin)

# Add context (plain text stdout with exit 0)
context = f"Current time: {datetime.datetime.now()}\n"
context += f"Current directory: {input_data['cwd']}"
print(context)

sys.exit(0)

Pattern 3: Environment Setup (SessionStart)

Initialize environment variables and context:

#!/​bin/​bash

# Setup environment
source ~/​.nvm/​nvm.sh
nvm use 20

# Persist variables
if [ -n "$CLAUDE_ENV_FILE" ]; then
  echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
  echo 'export PATH="$PATH:./​node_modules/​.bin"' >> "$CLAUDE_ENV_FILE"
fi

# Add context
echo "Environment initialized: Node $(node --version)"

exit 0

Pattern 4: Intelligent Decision (Stop Hook)

Use LLM for context-aware decisions:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Context: $ARGUMENTS\n\nDetermine if all tasks are complete. Check for:\n1. All user requests fulfilled\n2. No errors requiring fixes\n3. Tests passing\n\nRespond: {\"decision\": \"approve\" or \"block\", \"reason\": \"explanation\"}"
          }
        ]
      }
    ]
  }
}

Matcher Patterns

Matchers determine when hooks execute (PreToolUse, PostToolUse, PermissionRequest, Notification, PreCompact, SessionStart):

Exact match: "matcher": "Write" - Only Write tool Regex: "matcher": "Edit|Write" - Multiple tools All tools: "matcher": "*" or "matcher": "" MCP tools: "matcher": "mcp__github__.*" - All GitHub server tools

Environment Variables

Available in all hooks:

  • CLAUDE_PROJECT_DIR - Project root directory
  • CLAUDE_CODE_REMOTE - "true" if web environment

SessionStart hooks only:

  • CLAUDE_ENV_FILE - File path for persisting environment variables

Plugin hooks only:

  • CLAUDE_PLUGIN_ROOT - Plugin directory

Security Considerations

Input Validation: Always validate and sanitize inputs

if '..' in file_path or file_path.startswith('/'):
    print("Path traversal detected", file=sys.stderr)
    sys.exit(2)

Shell Safety: Quote all variables

command="$CLAUDE_PROJECT_DIR/​script.sh"

Sensitive Files: Skip .env, .git/, keys, etc.

sensitive = ['.env', '.git/', 'id_rsa', '*.pem']
if any(p in file_path for p in sensitive):
    sys.exit(2)

Troubleshooting

Hook not executing:

  • Check configuration with /​hooks command
  • Verify matcher pattern matches tool name
  • Enable debug mode: claude --debug

Hook timing out:

  • Increase timeout in configuration
  • Default: 60s for command, 30s for prompt
  • Individual timeout doesn't affect other hooks

JSON parsing errors:

  • Validate JSON output with jq
  • Check exit code is 0 for JSON processing
  • Exit code 2 ignores stdout JSON

Permission denied:

  • Make scripts executable: chmod +x script.sh
  • Check file paths are absolute or use $CLAUDE_PROJECT_DIR

Quick Reference

Decision Control by Event

EventAllow ActionBlock ActionModify Input
PreToolUsepermissionDecision: "allow"permissionDecision: "deny"updatedInput: {}
PermissionRequestbehavior: "allow"behavior: "deny"updatedInput: {}
PostToolUse-decision: "block"-
UserPromptSubmit-decision: "block"-
Stop/​SubagentStop-decision: "block"-

Exit Code Behavior

CodestdoutstderrContinues
0Parsed as JSON/​textIgnoredYes
2IgnoredFed to Claude/​UserDepends
OtherIgnoredLoggedYes

Additional Resources

For detailed protocol specifications:

  • references/​protocol-specification.md - Complete protocol documentation
  • references/​event-reference.md - Detailed event specifications

For working examples:

  • examples/​pretooluse-validator/ - Bash command validation
  • examples/​userprompt-enricher/ - Context injection
  • examples/​sessionstart-setup/ - Environment initialization
  • examples/​stop-evaluator/ - Prompt-based decision making

For validation and testing:

  • scripts/​validate-hook-config.py - Validate hooks.json against schema
  • scripts/​test-hook-io.py - Test hook input/​output locally
  • scripts/​generate-hook-template.sh - Generate hook boilerplate

For schema validation:

  • assets/​hooks-schema.json - JSON schema for hooks configuration

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View