Skill Productivity

Hook Development

A Claude Code skill that guides you through creating and implementing plugin hooks. Hooks are event-driven automation that runs in response to Claude Code events such as PreToolUse, PostToolUse, Stop and SessionStart. The skill focuses on the advanced prompt-based hooks API.

  • 150k GitHub stars
claude --debug
Hook Development — illustration

What it is

Hook Development is a skill (version 0.1.0) that activates when a user asks to create a hook, add a PreToolUse/PostToolUse/Stop hook, validate tool use, implement prompt-based hooks, use ${CLAUDE_PLUGIN_ROOT}, set up event-driven automation, or block dangerous commands. It also activates when the user mentions hook events such as SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact or Notification. It describes hooks as event-driven automation scripts that execute in response to Claude Code events. You can use them to validate operations, enforce policies, add context and integrate external tools into workflows. The skill covers two hook types. Prompt-based hooks are the recommended type. They use LLM-driven decision making for context-aware validation and are supported on Stop, SubagentStop, UserPromptSubmit and PreToolUse. Command hooks execute bash commands and suit fast deterministic validations, file system operations, external tool integrations and performance-critical checks. The skill explains two configuration formats: - Plugins use a wrapper format in hooks/hooks.json, with an optional description field and a required hooks field. - User settings in .claude/settings.json use a direct format, with events at the top level. It documents each hook event along with its input JSON (received via stdin) and its output format. Output covers permissionDecision for PreToolUse, approve/block decisions for Stop, and the standard continue, suppressOutput and systemMessage fields. Exit codes work as follows: 0 means success, 2 means a blocking error with stderr fed back to Claude, and any other code is a non-blocking error. The skill also lists the environment variables available to command hooks: $CLAUDE_PROJECT_DIR, $CLAUDE_PLUGIN_ROOT, $CLAUDE_ENV_FILE and $CLAUDE_CODE_REMOTE. Beyond the basics, the skill covers: - Matcher syntax: exact, multiple, wildcard and regex, all case-sensitive. - Security practices: input validation, path safety, quoting variables and timeouts. - Parallel execution of all matching hooks. - Conditionally active hooks driven by flag files or configuration. - The hook lifecycle: hooks load at session start and cannot be hot-swapped. - Debugging with claude --debug. The skill points to reference files (patterns.md, migration.md, advanced.md), example scripts (validate-write.sh, validate-bash.sh, load-context.sh) and utility scripts (validate-hook-schema.sh, test-hook.sh, hook-linter.sh).

Who it's for

  • Claude Code plugin developers adding hooks to their plugins
  • Users who want to validate or block tool calls before execution, such as dangerous commands or unsafe file writes
  • Developers setting up event-driven automation like loading project context at session start
  • Anyone enforcing completion standards before Claude stops

Requirements

Requirements

  • Claude Code (hooks load when a session starts)
  • Bash for command hooks
  • jq, which the example scripts use to parse hook input and validate JSON output
  • Plugin hooks defined in hooks/hooks.json, or user hooks in .claude/settings.json

Setup

  1. Write hook configuration

    Write the hook configuration in hooks/hooks.json, using ${CLAUDE_PLUGIN_ROOT} for all file references. For command hooks, also create the hook scripts.

  2. Validate configuration

    Validate the hooks.json structure and syntax with the bundled utility script.

    bash
    scripts/validate-hook-schema.sh hooks/hooks.json
  3. Restart and test in debug mode

    Hooks load at session start, so exit Claude Code and restart it after any change. Then test the hooks with debug logging enabled. Use the /hooks command to review the hooks loaded in the current session.

    bash
    claude --debug

هاد الـskill بيساعدك تعمل hooks لإضافات Claude Code، يعني سكربتات أو prompts بتشتغل تلقائياً لما يصير حدث معيّن، متل قبل ما تنفّذ أداة أو لما يخلص الـagent. بيركّز كتير على الـhooks المبنية على الـprompt.

Examples

Prompt-based PreToolUse hook for file writes

json
json
{
  "PreToolUse": [
    {
      "matcher": "Write|Edit",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "Validate file write safety. Check: system paths, credentials, path traversal, sensitive content. Return 'approve' or 'deny'."
        }
      ]
    }
  ]
}

What it does: Runs an LLM-driven safety check before any Write or Edit tool call. For plugin hooks.json, wrap this in {"hooks": {...}}.

Plugin hooks.json with wrapper format

json
json
{
  "description": "Validation hooks for code quality",
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/hooks/validate.sh"
          }
        ]
      }
    ]
  }
}

What it does: The plugin-specific format, with an optional description and the required hooks wrapper. It runs a command hook before Write tool calls.

Persist environment variables in SessionStart

bash
bash
echo "export PROJECT_TYPE=nodejs" >> "$CLAUDE_ENV_FILE"

What it does: A SessionStart hook can persist environment variables by appending them to $CLAUDE_ENV_FILE.

Test a command hook directly

bash
bash
echo '{"tool_name": "Write", "tool_input": {"file_path": "/test"}}' | \
  bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh

echo "Exit code: $?"

What it does: Pipes sample JSON input into a hook script and prints its exit code, so you can test the hook outside a session.