Awesome-omni-skill claude-code-hook-development

This skill should be used when the user asks to "create a hook", "add a hook", "write a hook", or mentions Claude Code hooks. Also suggest this skill when the user asks to "automatically do X" or "run X before/after Y" as these are good candidates for hooks.

install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/claude-code-hook-development" ~/.claude/skills/diegosouzapw-awesome-omni-skill-claude-code-hook-development && rm -rf "$T"
manifest: skills/development/claude-code-hook-development/SKILL.md
source content

Claude Code Hook Development

Create hooks that run shell commands on specific events to add guardrails, automations, and policy enforcement.

Quick Reference

You MUST read the reference files for detailed schemas and examples:

Core Concepts

Hook Types

  1. Command hooks - Run bash scripts
  2. Prompt hooks - Query LLM for context-aware decisions

Exit Codes

CodeMeaningBehavior
0SuccessAction proceeds; stdout shown in verbose mode
2BlockAction blocked; stderr fed to Claude
OtherErrorNon-blocking; stderr shown to user

File Locations

  • Settings:
    .claude/settings.json
  • Scripts:
    .claude/hooks/
    (mark executable)

Settings Structure

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/my-script.sh",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

Hook Events Summary

EventWhenCan Block?
PreToolUseBefore tool executesYes (exit 2)
PostToolUseAfter tool completesFeedback only
PermissionRequestUser sees permission dialogYes
UserPromptSubmitUser submits promptYes
StopMain agent finishesYes (continue)
SubagentStopSubagent finishesYes (continue)
SessionStartSession beginsAdd context
SessionEndSession endsCleanup only
NotificationNotifications sentNo
PreCompactBefore compactNo

Common Matchers

For PreToolUse/PostToolUse/PermissionRequest:

  • Bash
    - Shell commands
  • Edit
    ,
    Write
    ,
    Read
    - File operations
  • Glob
    ,
    Grep
    - Search operations
  • Task
    - Subagent tasks
  • mcp__<server>__<tool>
    - MCP tools
  • Regex patterns supported

Wildcard Permissions

Use wildcards for flexible matching patterns:

  • Bash(npm *)
    - Match any npm command
  • Bash(*-h*)
    - Match commands containing
    -h
  • Bash(git:*)
    - Match any git subcommand

This reduces configuration overhead and avoids mismatched permissions blocking legitimate workflows.

Script Template

#!/usr/bin/env bash
set -euo pipefail

# Read JSON input
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name // ""')
command=$(echo "$input" | jq -r '.tool_input.command // ""')

# Your validation logic here
if [[ "$command" =~ dangerous_pattern ]]; then
  echo "Blocked: reason here" >&2
  exit 2
fi

exit 0

Critical: Activating Hook Changes

Hooks are snapshotted at startup. After creating or modifying hooks:

⚠️ Changes won't take effect until you either:

  1. Restart Claude Code (exit and re-run
    claude
    ), OR
  2. Run
    /hooks
    to review and apply the updated configuration

This is a security feature - it prevents malicious hook modifications from affecting your current session.

Verifying Hooks Are Loaded

After restart, run

/hooks
to confirm your hook appears in the list. If it doesn't show up:

  • Check JSON syntax in settings file
  • Verify file is in correct location (
    .claude/settings.json
    )
  • Look for
    disableAllHooks: true
    in any settings file

Troubleshooting

Hook Not Triggering

  1. Did you restart? Hooks are snapshotted at startup - run
    /hooks
    or restart Claude Code
  2. Check
    /hooks
    output
    - Your hook should be listed with correct matcher
  3. Validate JSON - Run
    cat .claude/settings.json | jq .
    to check syntax
  4. Check matcher - Tool names are case-sensitive (
    Bash
    not
    bash
    )

Testing Hooks Safely

When creating hooks that block operations (like preventing push to main):

  1. Test on a safe branch first - Modify the hook to block a test branch
  2. Verify the block works - Attempt the blocked operation
  3. Update to production config - Change to block the actual target (e.g., main)
  4. Restart and verify - Run
    /hooks
    to confirm the updated hook is loaded

Debugging

Use

claude --debug
to see hook execution details, or add logging to your hook:

echo "[DEBUG] Hook triggered: $cmd" >> /tmp/hook-debug.log

Attribution

Examples adapted from Steve Kinney's Claude Code Hook Examples.