Hooks

Event-driven automation for Claude Code's entire lifecycle

What are Hooks?

Hooks are scripts or prompts that execute in response to specific events in Claude Code. They support four types: command (shell scripts), HTTP (webhook calls), prompt (LLM-powered decisions), and agent (subagent verification). Use them to enforce policies, automate workflows, and integrate external tools.

Event-Driven

Respond to 20+ lifecycle events automatically

Four Hook Types

Command, HTTP, Prompt, and Agent hooks for different needs

Policy Enforcement

Enforce team standards, security policies, and code quality rules

External Integrations

Call webhooks, run scripts, and connect to external services

Available Hook Events (20+)

PreToolUse

Fired before Claude uses any tool. Validate, modify, or block tool usage.

Use case: Security validation, file protection

PostToolUse

Fired after a tool completes successfully. Process results, trigger notifications.

Use case: Auto-formatting, logging, metrics

UserPromptSubmit

Fired when user submits a prompt. Modify, augment, or intercept prompts.

Use case: Context injection, prompt enhancement

Notification

Fired when Claude sends a notification. Customize notification behavior.

Use case: Custom alerts, team notifications

SessionStart

Fired when a Claude session starts. Initialize resources, check environment, load context.

Use case: Environment setup, dependency checks

SessionEnd

Fired when a session ends. Clean up resources, save state, generate reports.

Use case: Cleanup, analytics, session summaries
NEW

Setup

Triggered via --init, --init-only, or --maintenance flags. For repository setup and maintenance.

Use case: Environment setup, dependency checks, project initialization
NEW

SubagentStop

Fired when a subagent completes. Process results, chain tasks, notify.

Use case: Result processing, task chaining
NEW

SubagentStart

Fired when a subagent is about to start. Monitor, inject context, or block.

Use case: Subagent monitoring, context injection
NEW

PermissionRequest

Fired when a permission is requested. Auto-approve, deny, or log requests.

Use case: Auto-approval policies, audit logging
NEW

PreCompact

Fired before context compaction. Save important information before context is compressed.

Use case: Context preservation, important data backup
NEW FEATURE

Prompt-Based Hooks

Use LLM-powered decision making in hooks. Describe what you want in natural language instead of writing code. The LLM evaluates the condition and returns a structured decision.

.claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "type": "prompt",
        "matcher": { "tool": "Write" },
        "prompt": "Review this file write operation. Check if it follows 
                   our coding standards. Respond with 'allow' or 'deny' 
                   and explain why."
      }
    ]
  }
}

When to Use

  • +Complex decision logic that's hard to write in code
  • +Code review and quality checks
  • +Context-aware validation

Response Format

{
  "decision": "allow" | "deny" | "skip",
  "reason": "Optional explanation",
  "modifiedInput": { /* optional */ }
}

Practical Examples

Auto-Format Code After Edits

Automatically run Prettier on files after Claude edits them

hooks/post-tool-use.js
// Auto-format files after Edit tool
export async function postToolUse({ tool, result }) {
  if (tool.name === 'Edit' && result.success) {
    const { execSync } = require('child_process');
    try {
      execSync(`prettier --write "${tool.params.file_path}"`);
      console.log('βœ“ Formatted', tool.params.file_path);
    } catch (error) {
      console.error('Format failed:', error.message);
    }
  }
}

Protect Sensitive Files

Prevent Claude from editing critical configuration files

hooks/pre-tool-use.js
// Protect sensitive files
export async function preToolUse({ tool }) {
  const protectedFiles = [
    '.env',
    'credentials.json',
    'package-lock.json'
  ];

  if (['Edit', 'Write'].includes(tool.name)) {
    const filePath = tool.params.file_path;
    if (protectedFiles.some(f => filePath.includes(f))) {
      return {
        allow: false,
        reason: `Cannot modify protected file: ${filePath}`
      };
    }
  }

  return { allow: true };
}

Send Slack Notifications via HTTP Hook

Call a webhook when deployment happens

hooks/post-tool-use.js
// Notify team on deployment
export async function postToolUse({ tool, result }) {
  if (tool.name === 'Bash' &&
      tool.params.command.includes('deploy')) {
    const webhook = process.env.SLACK_WEBHOOK;
    await fetch(webhook, {
      method: 'POST',
      body: JSON.stringify({
        text: `πŸš€ Deployment completed!
Success: ${result.success}
Command: ${tool.params.command}`
      })
    });
  }
}

Security Considerations

Hooks execute code on your system. Follow these security best practices:

⚠

Never store secrets in hook files β€” use environment variables

⚠

Validate all inputs before executing external commands

⚠

Review hooks from external sources before using them

⚠

Use try-catch blocks to handle errors gracefully

Best Practices

1

Keep Hooks Simple

Each hook should do one thing well. Complex logic can slow down Claude.

2

Handle Errors Gracefully

Always use try-catch blocks and provide meaningful error messages.

3

Use Async Hooks

Hooks support async execution for external API calls and long-running operations.

4

Test Your Hooks

Use /hooks command to browse and test hooks interactively.

Ready to Automate Your Workflow?

Start creating hooks to enforce standards, automate tasks, and integrate external tools.