skills/hook-development/SKILL.md
Use when user asks to create a hook, add PreToolUse/PostToolUse/Stop/SubagentStop/SessionStart/SessionEnd/UserPromptSubmit/PreCompact/Notification hook, validate tool use, implement prompt-based hooks, use ${CLAUDE_PLUGIN_ROOT}, set up event-driven automation in Claude Code, block dangerous commands via hooks, build a Claude Code plugin with hooks, or configure hooks.json. NEVER use for general webhook/API endpoint development, GitHub Actions, CI/CD pipelines, or non-Claude-Code event systems.
npx skillsauth add sharkitect-solutions/sharkitect-claude-toolkit hook-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| File | Purpose | When to Load |
|------|---------|--------------|
| examples/load-context.sh | SessionStart context-loading script | Building SessionStart hooks or detecting project type |
| examples/validate-bash.sh | Bash command validation patterns | Building PreToolUse hooks for Bash tool |
| examples/validate-write.sh | File write validation patterns | Building PreToolUse hooks for Write/Edit tools |
| references/advanced.md | Multi-stage validation, cross-event workflows, caching, external integrations | Complex hook architectures, performance optimization, state sharing |
| references/migration.md | Converting command hooks to prompt hooks | Refactoring existing hooks or choosing between hook types |
| references/patterns.md | 10 proven hook patterns (security, test enforcement, context loading, MCP monitoring, etc.) | Starting a new hook -- find the closest pattern first |
| scripts/hook-linter.sh | Lint hook scripts for common issues | Before deploying any command hook script |
| scripts/README.md | Usage guide for all utility scripts | First time using the development tools |
| scripts/test-hook.sh | Test hooks with sample input | Before deploying hooks to Claude Code |
| scripts/validate-hook-schema.sh | Validate hooks.json structure | After editing any hooks.json configuration |
This skill covers hooks within the Claude Code plugin system ONLY. Hooks are bash scripts or LLM prompts triggered by Claude Code events.
| In Scope | Out of Scope | |----------|-------------| | Plugin hooks.json configuration | General webhook/API development | | Prompt-based and command hooks | GitHub Actions / CI pipelines | | Hook event lifecycle | Server-side event systems | | Matcher patterns for Claude tools | MCP server development (use mcp skill) | | ${CLAUDE_PLUGIN_ROOT} usage | Claude Desktop configuration |
| Signal | Choose Prompt Hook | Choose Command Hook | |--------|-------------------|-------------------| | Needs context-aware reasoning | Yes | No | | Catches intent, not just patterns | Yes | No | | Needs to run in < 50ms | No | Yes | | Purely deterministic check (file size, regex) | No | Yes | | Integrates external CLI tool | No | Yes | | Needs to set environment vars | No | Yes (SessionStart only) | | Complex multi-criteria validation | Yes | No |
Prompt hooks support: PreToolUse, PostToolUse, Stop, SubagentStop, UserPromptSubmit. Command hooks support: ALL events (including SessionStart, SessionEnd, PreCompact, Notification).
Plugin hooks and settings hooks use DIFFERENT JSON structures. Confusing them is the most common hook bug.
Plugin format -- hooks/hooks.json in a plugin directory:
{
"description": "Optional description",
"hooks": {
"PreToolUse": [{ "matcher": "Write", "hooks": [{ "type": "prompt", "prompt": "..." }] }]
}
}
The "hooks" wrapper key is REQUIRED. Events nest inside it.
Settings format -- .claude/settings.json or .claude.json:
{
"hooks": {
"PreToolUse": [{ "matcher": "Write", "hooks": [{ "type": "prompt", "prompt": "..." }] }]
}
}
Events go directly under "hooks" alongside other settings keys.
Both formats merge at runtime. Plugin hooks and settings hooks run in parallel.
| Event | Fires When | Best For | Output Controls |
|-------|-----------|----------|----------------|
| PreToolUse | Before tool executes | Approve/deny/modify tool calls | permissionDecision: allow, deny, ask; updatedInput |
| PostToolUse | After tool completes | Feedback, logging, quality checks | systemMessage to Claude |
| Stop | Main agent wants to stop | Completeness verification | decision: approve or block |
| SubagentStop | Subagent wants to stop | Subagent task validation | decision: approve or block |
| UserPromptSubmit | User submits prompt | Context injection, prompt validation | systemMessage, can block |
| SessionStart | Session begins | Load context, set env vars | $CLAUDE_ENV_FILE for persisting env |
| SessionEnd | Session ends | Cleanup, logging | Fire-and-forget |
| PreCompact | Before context compaction | Preserve critical information | systemMessage survives compaction |
| Notification | Claude sends notification | External integrations, logging | Fire-and-forget |
scripts/validate-hook-schema.sh./hooks command to inspect which hooks are loaded in the current session.claude --debug to see hook registration, execution logs, input/output JSON, and timing.| Exit Code | Meaning | Behavior | |-----------|---------|----------| | 0 | Success | stdout shown in transcript | | 2 | Blocking error | stderr fed back to Claude as context | | Other | Non-blocking error | Logged but does not block |
For PreToolUse: exit 2 with permissionDecision: "deny" blocks the tool call.
For Stop: exit 2 with decision: "block" prevents the agent from stopping.
All hooks receive JSON via stdin. Common fields:
session_id, transcript_path, cwd, permission_mode, hook_event_nameEvent-specific fields:
tool_name, tool_input, tool_result (PostToolUse only)user_promptreasonIn prompt hooks, access via: $TOOL_INPUT, $TOOL_RESULT, $USER_PROMPT.
In command hooks, parse with: input=$(cat) then jq -r '.tool_name'.
"Write" -- exact tool name
"Write|Edit" -- multiple tools (pipe-separated)
"*" -- all tools (wildcard)
"mcp__.*" -- regex: all MCP tools
"mcp__asana__.*" -- regex: specific MCP server's tools
"mcp__.*__delete.*" -- regex: all MCP delete operations
Matchers are case-sensitive. Regex uses standard patterns (no delimiters).
| Variable | Available In | Purpose |
|----------|-------------|---------|
| $CLAUDE_PROJECT_DIR | All events | Project root path |
| $CLAUDE_PLUGIN_ROOT | All events | Plugin directory (use for portable paths) |
| $CLAUDE_ENV_FILE | SessionStart ONLY | Append export KEY=val to persist env vars |
| $CLAUDE_CODE_REMOTE | All events | Set if running in remote context |
ALWAYS use ${CLAUDE_PLUGIN_ROOT} in hooks.json commands. Never hardcode paths.
#!/bin/bash
set -euo pipefail
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name // empty')
# ... validation logic ...
# Approve: exit 0
# Block: echo '{"hookSpecificOutput":{"permissionDecision":"deny"},"systemMessage":"reason"}' >&2 && exit 2
exit 0
See examples/ for complete working scripts. Run scripts/hook-linter.sh before deploying.
references/patterns.md for a matching patternhooks/hooks.json (use correct format -- plugin wrapper)scripts/hook-linter.sh, test with scripts/test-hook.shscripts/validate-hook-schema.sh hooks/hooks.jsonclaude --debug| Concept | Why It Earns Space | |---------|--------------------| | Two JSON configuration formats | Most common hook bug -- plugin wrapper vs settings direct structure | | Hook lifecycle (load-once, parallel execution) | Non-obvious runtime behavior that causes debugging confusion | | Exit code semantics (0 vs 2 vs other) | Determines whether hooks block operations or just log | | Event selection guide with output controls | Each event has unique output capabilities that affect what hooks can do | | Matcher regex patterns for MCP tools | MCP tool naming convention is not documented elsewhere | | File Index with load conditions | 10 companion files need clear routing to avoid information overload |
"hooks" wrapper key${CLAUDE_PLUGIN_ROOT} for portabilityset -euo pipefail in bash hook scripts -- silent failures on errors"$var" not $var)development
When the user wants help with paid advertising campaigns on Google Ads, Meta (Facebook/Instagram), LinkedIn, Twitter/X, or other ad platforms. Also use when the user mentions 'PPC,' 'paid media,' 'ad copy,' 'ad creative,' 'ROAS,' 'CPA,' 'ad campaign,' 'retargeting,' or 'audience targeting.' This skill covers campaign strategy, ad creation, audience targeting, and optimization.
testing
--- name: using-sharkitect-methodology description: Use when starting any conversation in a Sharkitect workspace OR before any task involving NEW pricing, positioning, proposal, strategy, plan-execution, or schema-design work — mandates invocation of Sharkitect-specific methodology skills (pricing-strategy, marketing-strategy-pmm, smb-cfo, hq-revenue-ops, executing-plans, brainstorming) under the same anti-rationalization discipline as using-superpowers. Documentation has failed 4 times across H
testing
Use when user says 'end session', 'wrap up', 'stop for the day', 'done for today', 'close out', 'save session', 'wrapping up', or invokes /end-session. Runs the full 9-step end-of-session protocol: resource audit, MEMORY.md update, lessons capture, plan status, pending items, workspace checklist, .tmp/ audit, git commit+push, Supabase brain sync, session brief, summary. Final step schedules a detached self-kill of the current session ONLY (3s delay) so the window closes cleanly. Other claude.exe processes (active workspaces) are NOT touched -- orphan cleanup is handled separately by Claude-Orphan-Cleanup-Hourly with proper age safeguards. Do NOT use for: mid-session quick saves (use session-checkpoint), skill syncing (use sync-skills.py), brain memory queries (use supabase-sync.py pull), document freshness reviews (use document-lifecycle), resource gap detection (use resource-auditor).
testing
Remove signs of AI-generated writing from text. Use when editing or reviewing text to make it sound more natural and human-written. Based on Wikipedia's comprehensive "Signs of AI writing" guide. Detects and fixes patterns including: inflated symbolism, promotional language, superficial -ing analyses, vague attributions, em dash overuse, rule of three, AI vocabulary words, passive voice, negative parallelisms, and filler phrases.