Skip to content
Skill Authoring
Skill

/create-hooks

Expert guidance for creating, configuring, and using Claude Code hooks. Use when working with hooks, setting up event listeners, validating commands, automating workflows, adding notifications, or understanding hook types (PreToolUse, PostToolUse, Stop, SessionStart,

BOOST
From plugin
taches-cc-resources
2k12 skills3 agents39 commands
Install
$ npx -y skills add glittercowboy/taches-cc-resources --skill create-hooks --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/create-hooks

Context preview

The summary Claude sees to decide when to auto-load this skill.

Expert guidance for creating, configuring, and using Claude Code hooks. Use when working with hooks, setting up event listeners, validating commands, automating workflows, adding notifications, or understanding hook types (PreToolUse, PostToolUse, Stop, SessionStart,

SKILL.md

create-hooks.SKILL.md
name: create-hooks
description: Expert guidance for creating, configuring, and using Claude Code hooks. Use when working with hooks, setting up event listeners, validating commands, automating workflows, adding notifications, or understanding hook types (PreToolUse, PostToolUse, Stop, SessionStart, UserPromptSubmit, etc).

<objective> Hooks are event-driven automation for Claude Code that execute shell commands or LLM prompts in response to tool usage, session events, and user interactions. This skill teaches you how to create, configure, and debug hooks for validating commands, automating workflows, injecting context, and implementing custom completion criteria.

Hooks provide programmatic control over Claude's behavior without modifying core code, enabling project-specific automation, safety checks, and workflow customization. </objective>

<context> Hooks are shell commands or LLM-evaluated prompts that execute in response to Claude Code events. They operate within an event hierarchy: events (PreToolUse, PostToolUse, Stop, etc.) trigger matchers (tool patterns) which fire hooks (commands or prompts). Hooks can block actions, modify tool inputs, inject context, or simply observe and log Claude's operations. </context>

<quick_start> <workflow> 1. Create hooks config file:

  • Project: `.claude/hooks.json`
  • User: `~/.claude/hooks.json`

2. Choose hook event (when it fires) 3. Choose hook type (command or prompt) 4. Configure matcher (which tools trigger it) 5. Test with `claude --debug` </workflow>

<example> **Log all bash commands**:

`.claude/hooks.json`:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \\\"No description\\\")\"' >> ~/.claude/bash-log.txt"
          }
        ]
      }
    ]
  }
}

This hook:

  • Fires before (`PreToolUse`) every `Bash` tool use
  • Executes a `command` (not an LLM prompt)
  • Logs command + description to a file

</example> </quick_start>

<hook_types> | Event | When it fires | Can block? | |-------|---------------|------------| | **PreToolUse** | Before tool execution | Yes | | **PostToolUse** | After tool execution | No | | **UserPromptSubmit** | User submits a prompt | Yes | | **Stop** | Claude attempts to stop | Yes | | **SubagentStop** | Subagent attempts to stop | Yes | | **SessionStart** | Session begins | No | | **SessionEnd** | Session ends | No | | **PreCompact** | Before context compaction | Yes | | **Notification** | Claude needs input | No |

Blocking hooks can return `"decision": "block"` to prevent the action. See [references/hook-types.md](references/hook-types.md) for detailed use cases. </hook_types>

<hook_anatomy> <hook_type name="command"> **Type**: Executes a shell command

**Use when**:

  • Simple validation (check file exists)
  • Logging (append to file)
  • External tools (formatters, linters)
  • Desktop notifications

**Input**: JSON via stdin **Output**: JSON via stdout (optional)

{
  "type": "command",
  "command": "/path/to/script.sh",
  "timeout": 30000
}

</hook_type>

<hook_type name="prompt"> **Type**: LLM evaluates a prompt

**Use when**:

  • Complex decision logic
  • Natural language validation
  • Context-aware checks
  • Reasoning required

**Input**: Prompt with `$ARGUMENTS` placeholder **Output**: JSON with `decision` and `reason`

{
  "type": "prompt",
  "prompt": "Evaluate if this command is safe: $ARGUMENTS\n\nReturn JSON: {\"decision\": \"approve\" or \"block\", \"reason\": \"explanation\"}"
}

</hook_type> </hook_anatomy>

<matchers> Matchers filter which tools trigger the hook:

{
  "matcher": "Bash",           // Exact match
  "matcher": "Write|Edit",     // Multiple tools (regex OR)
  "matcher": "mcp__.*",        // All MCP tools
  "matcher": "mcp__memory__.*" // Specific MCP server
}

**No matcher**: Hook fires for all tools

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [...]  // No matcher - fires on every user prompt
      }
    ]
  }
}

</matchers>

<input_output> Hooks receive JSON via stdin with session info, current directory, and event-specific data. Blocking hooks can return JSON to approve/block actions or modify inputs.

**Example output** (blocking hooks):

{
  "decision": "approve" | "block",
  "reason": "Why this decision was made"
}

See [references/input-output-schemas.md](references/input-output-schemas.md) for complete schemas for each hook type. </input_output>

<environment_variables> Available in hook commands:

| Variable | Value | |----------|-------| | `$CLAUDE_PROJECT_DIR` | Project root directory | | `${CLAUDE_PLUGIN_ROOT}` | Plugin directory (plugin hooks only) | | `$ARGUMENTS` | Hook input JSON (prompt hooks only) |

**Example**:

{
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/validate.sh"
}

</environment_variables>

<common_patterns> **Desktop notification when input needed**:

{
  "hooks": {
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude needs input\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

**Block destructive git commands**:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Check if this command is destructive: $ARGUMENTS\n\nBlock if it contains: 'git push --force', 'rm -rf', 'git reset --hard'\n\nReturn: {\"decision\": \"approve\" or \"block\", \"reason\": \"explanation\"}"
          }
        ]
      }
    ]
  }
}

**Auto-format code after edits**:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "prettier --write $CLAUDE_P
Read more
Ships withtaches-cc-resources

A growing collection of custom Claude Code resources built for real workflows.

Get the whole plugin

Other skills on taches-cc-resources.