Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    laurigates

    claude-code-hooks-configuration

    laurigates/claude-code-hooks-configuration
    DevOps
    5

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Configure Claude Code lifecycle hooks with proper timeout settings to prevent hook cancellation errors.

    SKILL.md

    Claude Code Hooks Configuration

    When to Use This Skill

    Use this skill when... Use plugin-settings instead when...
    Wiring a SessionStart, PreToolUse, PostToolUse, or Stop hook into .claude/settings.json Storing per-project plugin state in .claude/plugin-name.local.md
    Setting explicit hook timeouts to prevent "Hook cancelled" errors Configuring user-tunable plugin behaviour exposed by skill authors
    Choosing between command, http, prompt, and agent hook types Persisting agent state between sessions outside the hook lifecycle
    Debugging a hook that fires inconsistently or is silently skipped Configuring per-project rather than per-session behaviour

    Core Expertise

    Configure Claude Code lifecycle hooks (all 17 events including SessionStart, Stop, PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, WorktreeCreate, TeammateIdle, TaskCompleted, ConfigChange, and more) with proper timeout settings to prevent "Hook cancelled" errors during session management.

    Hook Events

    Hook Trigger Default Timeout
    SessionStart When Claude Code session begins 600s (command)
    SessionEnd When session ends or /clear runs 600s (command)
    Stop When main agent stops responding 600s (command)
    SubagentStop When a subagent (Task tool) finishes 600s (command)
    PreToolUse Before a tool executes 600s (command)
    PostToolUse After a tool completes 600s (command)
    PostToolUseFailure After a tool execution fails 600s (command)
    PermissionRequest When Claude requests permission for a tool 600s (command)
    WorktreeCreate New git worktree created via EnterWorktree 600s (command)
    WorktreeRemove Worktree removed after session exits 600s (command)
    TeammateIdle Teammate in agent team goes idle 600s (command)
    TaskCompleted Task in shared task list marked complete 600s (command)
    ConfigChange Claude Code settings change at runtime 600s (command)

    Default timeouts: command = 600s, prompt = 30s, agent = 60s. Always set explicit timeouts — it documents intent.

    Hook Types

    Type How It Works Default Timeout Use When
    command Runs a shell command, reads stdin, returns exit code/JSON 600s Deterministic rules
    http Sends hook data to an HTTPS endpoint 30s Remote/centralized policy
    prompt Single-turn LLM call, returns {ok: true/false} 30s Judgment on hook input data
    agent Multi-turn subagent with tool access, returns {ok: true/false} 60s Verification needing file/tool access

    Async and Once

    • async: true on command hooks: fire-and-forget, does not block the operation
    • once: true on any hook handler: runs only once per session, subsequent triggers skipped

    For full event reference, schemas, and examples, see .claude/rules/hooks-reference.md.

    Common Issue: Hook Cancelled Error

    SessionEnd hook [bash ~/.claude/session-logger.sh] failed: Hook cancelled
    

    Root cause: Hook execution exceeds the configured timeout. With the 2.1.50 default of 10 minutes, this is now less common — but explicitly setting "timeout" in your hook config is still recommended.

    Solutions (in order of preference):

    1. Background subshell - Run slow operations in background, exit immediately
    2. Explicit timeout - Add timeout field to hook configuration

    Hook Configuration

    Location

    Hooks are configured in .claude/settings.json:

    • User-level: ~/.claude/settings.json
    • Project-level: <project>/.claude/settings.json

    Structure with Timeout

    {
      "hooks": {
        "SessionEnd": [
          {
            "matcher": "",
            "hooks": [
              {
                "type": "command",
                "command": "~/.claude/session-logger.sh",
                "timeout": 120
              }
            ]
          }
        ],
        "SessionStart": [
          {
            "matcher": "",
            "hooks": [
              {
                "type": "command",
                "command": "~/.claude/session-setup.sh",
                "timeout": 180
              }
            ]
          }
        ],
        "Stop": [
          {
            "matcher": "",
            "hooks": [
              {
                "type": "command",
                "command": "~/.claude/stop-hook-git-check.sh",
                "timeout": 30
              }
            ]
          }
        ]
      }
    }
    

    Timeout Guidelines

    Hook Type Recommended Timeout Use Case
    SessionStart 120–300s Tests, linters, dependency checks
    SessionEnd 60–120s Logging, cleanup, state saving
    Stop / SubagentStop 30–60s Git status checks, quick validations
    PreToolUse 10–30s Quick validations
    PostToolUse 30–120s Logging, notifications
    PermissionRequest 5–15s Keep fast for good UX

    Fixing Timeout Issues

    Recommended: Background Subshell Pattern

    The most portable and robust solution is to run slow operations in a background subshell and exit immediately:

    #!/bin/bash
    # ~/.claude/session-logger.sh
    # Exits instantly, work continues in background
    
    (
      # All slow operations go here
      echo "$(date): Session ended" >> ~/.claude/session.log
      curl -s -X POST "https://api.example.com/log" -d "session_end=$(date)"
      # Any other slow work...
    ) &>/dev/null &
    
    exit 0
    

    Why this works:

    • ( ) creates a subshell for the commands
    • & runs the subshell in background
    • &>/dev/null prevents stdout/stderr from blocking
    • exit 0 returns success immediately

    Comparison of approaches:

    Approach Portability Speed Notes
    ( ) & bash, zsh, sh Instant Recommended
    disown Bash-only Instant Not POSIX
    nohup POSIX Slight overhead Overkill for hooks

    Alternative: Increase Timeout

    If you need synchronous execution, add explicit timeout to settings:

    cat ~/.claude/settings.json | jq '.hooks'
    # Edit to add "timeout": <seconds> to each hook
    

    Script Optimization Patterns

    Optimization Pattern
    Background subshell ( commands ) &>/dev/null &
    Fast test modes --bail=1, -x, --dots
    Skip heavy operations Conditional execution
    Parallel execution Use & and wait

    Related: Starship Timeout

    If you see:

    [WARN] - (starship::utils): Executing command "...node" timed out.
    

    This is a separate starship issue. Fix by adding to ~/.config/starship.toml:

    command_timeout = 1000  # 1 second (default is 500ms)
    

    For slow node version detection:

    [nodejs]
    disabled = false
    detect_files = ["package.json"]  # Skip .nvmrc to speed up detection
    
    [command]
    command_timeout = 2000  # Increase if still timing out
    

    Agentic Optimizations

    Context Command
    View hooks config cat ~/.claude/settings.json | jq '.hooks'
    Test hook script time bash ~/.claude/session-logger.sh
    Find slow operations bash -x ~/.claude/session-logger.sh 2>&1 | head -50
    Check starship config starship config

    Quick Reference

    Setting Location Default
    Hook timeout .claude/settings.json → hook → timeout 10 minutes (600s) since 2.1.50
    Starship timeout ~/.config/starship.toml → command_timeout 500ms
    Node detection ~/.config/starship.toml → [nodejs] Auto

    Error Handling

    Error Cause Fix
    Hook cancelled Timeout exceeded Add explicit "timeout" (e.g. "timeout": 120)
    Hook failed Script error Check exit code, add error handling
    Command not found Missing script Verify script path and permissions
    Permission denied Script not executable chmod +x ~/.claude/script.sh

    Best Practices

    1. Use background subshell - Wrap slow operations in ( ) &>/dev/null & and exit 0
    2. Set explicit timeouts - Add timeout field for hooks requiring synchronous execution
    3. Test hook timing - Use time bash ~/.claude/script.sh to measure execution
    4. Redirect all output - Use &>/dev/null to prevent blocking on stdout/stderr
    5. Apply /hooks menu - Use Claude Code's hook menu to reload settings after changes
    Recommended Servers
    Vercel Grep
    Vercel Grep
    Cloudflare
    Cloudflare
    EasyWeek
    EasyWeek
    Repository
    laurigates/claude-plugins
    Files