Receber por email
← Voltar para o catálogo

hooks-reference

Use this skill when asked about "hooks", "PreToolUse", "PostToolUse", "SessionStart", "hook events", "validate tool use", "block commands", "add context on session start", or implementing event-driven automation.

12estrelas
Atualizado há 7 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add a-ariff/ariff-claude-plugins

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/hooks-reference/svg)](https://www.skillteca.com.br/skills/hooks-reference)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Hooks Reference Skill

This skill provides comprehensive guidance for implementing Claude Code hooks - event handlers that automate validation, context loading, and workflow enforcement.

Hook Events Overview

| Event | When Triggered | Use Cases | |-------|----------------|-----------| | PreToolUse | Before tool executes | Validate, block, modify | | PostToolUse | After tool completes | Audit, react, verify | | PermissionRequest | Permission dialog shown | Auto-allow, auto-deny | | Stop | Claude finishes | Force continue, verify | | SubagentStop | Subagent finishes | Verify task complete | | SessionStart | Session begins | Load context, setup | | SessionEnd | Session ends | Cleanup, save state | | UserPromptSubmit | Prompt submitted | Validate, add context | | PreCompact | Before compaction | Preserve info | | Notification | Notification sent | Alert, log |

hooks.json Structure

Basic structure:

{
  "description": "What these hooks do",
  "hooks": {
    "EventName": [
      {
        "matcher": "Pattern",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/handler.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

Matcher Patterns

For tool events (PreToolUse, PostToolUse, PermissionRequest):

  • "Write" - Match exact tool name
  • "Write|Edit" - Match multiple tools (regex)
  • "Notebook.*" - Regex pattern
  • "*" or "" - Match all tools

For SessionStart:

  • "startup" - Initial startup
  • "resume" - From --resume, --continue, /resume
  • "clear" - From /clear
  • "compact" - From auto/manual compact

For Notification:

  • "permission_prompt" - Permission requests
  • "idle_prompt" - Claude waiting for input

Hook Types

Command Hooks (type: "command")

Execute a bash script:

{
  "type": "command",
  "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
  "timeout": 30
}

Prompt Hooks (type: "prompt")

LLM-based evaluation (Stop, SubagentStop only):

{
  "type": "prompt",
  "prompt": "Evaluate if Claude should stop: $ARGUMENTS. Check if all tasks are complete.",
  "timeout": 30
}

Exit Codes

| Exit Code | Meaning | Behavior | |-----------|---------|----------| | 0 | Success | Action proceeds, stdout to user (verbose) | | 2 | Block | Action blocked, stderr shown to Claude | | Other | Error | Non-blocking, stderr to user (verbose) |

Hook Input (stdin JSON)

Common fields:

{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.jsonl",
  "cwd": "/current/working/directory",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse"
}

PreToolUse specific:

{
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_use_id": "toolu_01ABC..."
}

SessionStart specific:

{
  "source": "startup"
}

Stop specific:

{
  "stop_hook_active": false
}

Advanced JSON Output

Return structured decisions via stdout (exit code 0):

PreToolUse Decision Control

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "Auto-approved documentation file",
    "updatedInput": {
      "field_to_modify": "new value"
    }
  }
}

Decision values: "allow", "deny", "ask"

Stop Decision Control

{
  "decision": "block",
  "reason": "Not all tasks complete - still need to run tests"
}

UserPromptSubmit Context

{
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "Current time: 2024-01-15 10:30:00"
  }
}

SessionStart Context

{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "Project context loaded..."
  }
}

Example Hooks

1. Validate File Writes (PreToolUse)

hooks/hooks.json:

{
  "description": "Validate file write operations",
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate-write.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

scripts/validate-write.sh:

#!/usr/bin/env bash

INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // empty')

# Block writes to sensitive files
if [[ "$FILE_PATH" == *.env* ]] || [[ "$FILE_PATH" == *secret* ]]; then
  echo "Cannot write to sensitive files: $FILE_PATH" >&2
  exit 2
fi

# Block writes outside project
if [[ ! "$FILE_PATH" == "$CLAUDE_PROJECT_DIR"* ]]; then
  echo "Cannot write outside project directory" >&2
  exit 2
fi

exit 0

2. Block Dangerous Commands (PreToolUse)

hooks/hooks.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate-bash.sh"
          }
        ]
      }
    ]
  }
}

scripts/validate-bash.sh:

#!/usr/bin/env bash

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

# Block destructive commands
DANGEROUS_PATTERNS=(
  "rm -rf /"
  "rm -rf ~"
  ":(){ :|:& };:"
  "> /dev/sda"
)

for pattern in "${DANGEROUS_PATTERNS[@]}"; do
  if [[ "$COMMAND" == *"$pattern"* ]]; then
    echo "Blocked dangerous command pattern: $pattern" >&2
    exit 2
  fi
done

exit 0

3. Load Project Context (SessionStart)

hooks/hooks.json:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup|resume",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh"
          }
        ]
      }
    ]
  }
}

scripts/load-context.sh:

#!/usr/bin/env bash

CONTEXT=""

# Load CLAUDE.md if exists
if [ -f "$CLAUDE_PROJECT_DIR/CLAUDE.md" ]; then
  CONTEXT+="Project instructions from CLAUDE.md have been loaded.\n"
fi

# Add git status
if [ -d "$CLAUDE_PROJECT_DIR/.git" ]; then
  BRANCH=$(git -C "$CLAUDE_PROJECT_DIR" branch --show-current 2>/dev/null)
  CONTEXT+="Current git branch: $BRANCH\n"
fi

# Output as JSON for structured context
cat << EOF
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "$CONTEXT"
  }
}
EOF

exit 0

4. Verify Before Stop (Stop)

Using prompt-based hook:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Evaluate if Claude should stop. Context: $ARGUMENTS\n\nCheck if:\n1. All requested tasks are complete\n2. No errors need addressing\n3. No tests need running\n\nRespond with: {\"decision\": \"approve\" or \"block\", \"reason\": \"explanation\"}"
          }
        ]
      }
    ]
  }
}

5. Add Timestamp to Prompts (UserPromptSubmit)

hooks/hooks.json:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/add-timestamp.sh"
          }
        ]
      }
    ]
  }
}

scripts/add-timestamp.sh:

#!/usr/bin/env bash

# Plain text stdout is added as context
echo "Current time: $(date '+%Y-%m-%d %H:%M:%S %Z')"

exit 0

Environment Variables

Available in hooks:

  • ${CLAUDE_PLUGIN_ROOT} - Absolute path to plugin directory
  • $CLAUDE_PROJECT_DIR - Project root directory
  • $CLAUDE_ENV_FILE - (SessionStart only) File to persist env vars
  • $CLAUDE_CODE_REMOTE - "true" if running in web environment

Persisting Environment (SessionStart)

#!/usr/bin/env bash

if [ -n "$CLAUDE_ENV_FILE" ]; then
  echo 'export NODE_ENV=development' >> "$CLAUDE_ENV_FILE"
  echo 'export API_URL=http://localhost:3000' >> "$CLAUDE_ENV_FILE"
fi

exit 0

Best Practices

  1. Always quote variables: Use `"$VA
Compartilhar X LinkedIn