plugins/plugin-master/skills/hook-development/SKILL.md
Canonical guide to authoring Claude Code hooks, both prompt-based and command-based. PROACTIVELY activate for: (1) creating a hook, (2) adding PreToolUse or PostToolUse hooks, (3) validating tool use, (4) implementing prompt-based hooks, (5) blocking dangerous commands, (6) event-driven automation, (7) configuring hooks.json, (8) using ${CLAUDE_PLUGIN_ROOT}, (9) hook matchers and filtering, (10) debugging hooks that do not fire. Provides: hooks.json schema, event reference, security guidance, and examples.
npx skillsauth add JosiahSiegel/claude-plugin-marketplace 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.
Hooks are event-driven automation that execute in response to Claude Code events. Use hooks to validate operations, enforce policies, load context, and integrate external tools.
Two hook types:
| Event | When | Common Use | |-------|------|------------| | PreToolUse | Before tool executes | Validate, approve/deny, modify input | | PostToolUse | After tool completes | Test, lint, log, provide feedback | | Stop | Main agent stopping | Verify task completeness | | SubagentStop | Subagent stopping | Validate subagent work | | UserPromptSubmit | User sends prompt | Add context, validate, preprocess | | SessionStart | Session begins | Load context, set environment | | SessionEnd | Session ends | Cleanup, logging | | PreCompact | Before context compaction | Preserve critical information | | Notification | Notification shown | Custom alert reactions |
hooks/hooks.json)Uses wrapper format with hooks field:
{
"description": "What these hooks do (optional)",
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
"timeout": 10
}
]
}
]
}
}
.claude/settings.json)Direct format, no wrapper:
{
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{ "type": "command", "command": "script.sh" }]
}
]
}
Critical difference: Plugin hooks.json wraps events inside {"hooks": {...}}. Settings format puts events at top level.
Use LLM reasoning for context-aware decisions:
{
"type": "prompt",
"prompt": "Evaluate if this tool use is appropriate. Check for: system paths, credentials, path traversal. Return 'approve' or 'deny'.",
"timeout": 30
}
Supported events: PreToolUse, PostToolUse, Stop, SubagentStop, UserPromptSubmit
Benefits: Context-aware, flexible, better edge case handling, easier to maintain.
Execute shell commands for deterministic checks:
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
"timeout": 60
}
Always use ${CLAUDE_PLUGIN_ROOT} for portable paths.
| Code | Meaning | |------|---------| | 0 | Success (stdout shown in transcript) | | 2 | Blocking error (stderr fed back to Claude) | | Other | Non-blocking error |
Control which tools trigger hooks:
"matcher": "Write" // Exact match
"matcher": "Write|Edit|Bash" // Multiple tools
"matcher": "mcp__.*__delete.*" // Regex (all MCP delete tools)
"matcher": "*" // All tools (use sparingly)
Matchers are case-sensitive.
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/current/working/dir",
"hook_event_name": "PreToolUse",
"tool_name": "Write",
"tool_input": { "file_path": "/path/to/file" }
}
Event-specific fields: tool_name, tool_input, tool_result, user_prompt, reason
Access in prompts: $TOOL_INPUT, $TOOL_RESULT, $USER_PROMPT
Standard (all hooks):
{
"continue": true,
"suppressOutput": false,
"systemMessage": "Message for Claude"
}
PreToolUse decisions:
{
"hookSpecificOutput": {
"permissionDecision": "allow|deny|ask",
"updatedInput": { "field": "modified_value" }
}
}
Stop/SubagentStop decisions:
{
"decision": "approve|block",
"reason": "Explanation"
}
| Variable | Available | Purpose |
|----------|-----------|---------|
| $CLAUDE_PLUGIN_ROOT | All hooks | Plugin directory (portable paths) |
| $CLAUDE_PROJECT_DIR | All hooks | Project root path |
| $CLAUDE_ENV_FILE | SessionStart only | Persist env vars for session |
SessionStart can persist variables:
echo "export PROJECT_TYPE=nodejs" >> "$CLAUDE_ENV_FILE"
{
"PreToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "prompt",
"prompt": "Check if this file write is safe. Deny writes to: .env, credentials, system paths, or files with path traversal (..). Return 'approve' or 'deny' with reason."
}]
}]
}
{
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "npm test -- --bail",
"timeout": 60
}]
}]
}
{
"Stop": [{
"matcher": "*",
"hooks": [{
"type": "prompt",
"prompt": "Verify: tests run, build succeeded, all questions answered. Return 'approve' to stop or 'block' with reason to continue."
}]
}]
}
{
"SessionStart": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh",
"timeout": 10
}]
}]
}
#!/bin/bash
set -euo pipefail
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path')
# Always validate inputs
if [[ ! "$file_path" =~ ^[a-zA-Z0-9_./-]+$ ]]; then
echo '{"decision": "deny", "reason": "Invalid path"}' >&2
exit 2
fi
# Block path traversal
if [[ "$file_path" == *".."* ]]; then
echo '{"decision": "deny", "reason": "Path traversal detected"}' >&2
exit 2
fi
# Block sensitive files
if [[ "$file_path" == *".env"* ]]; then
echo '{"decision": "deny", "reason": "Sensitive file"}' >&2
exit 2
fi
# Always quote variables
echo "$file_path"
Hooks load at session start. Changes to hook configuration require restarting Claude Code.
hooks/hooks.json won't affect the current sessionTo test changes: Exit Claude Code, restart with claude or claude --debug.
# Enable debug mode to see hook execution
claude --debug
# Test hook scripts directly
echo '{"tool_name": "Write", "tool_input": {"file_path": "/test"}}' | \
bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh
# Validate hook JSON output
output=$(./hook-script.sh < test-input.json)
echo "$output" | jq .
# View loaded hooks in session
# Use /hooks command
${CLAUDE_PLUGIN_ROOT} (no hardcoded paths)set -euo pipefail)* unless necessary)claude --debugdevelopment
This skill should be used when the user asks to train, debug, scale, or improve ML models. PROACTIVELY activate for: (1) PyTorch, TensorFlow/Keras, JAX, Flax, Hugging Face Trainer/Accelerate training loops, (2) distributed training, DDP/FSDP/DeepSpeed, TPU/GPU setup, (3) mixed precision AMP/bf16, gradient accumulation, checkpointing, seeding, (4) overfitting, imbalance, loss functions, regularization, LR schedules, warmup, (5) memory optimization, gradient checkpointing, offloading, quantization-aware training. Provides: reproducible training best practices across deep learning and classical ML.
development
This skill should be used when the user asks to productionize, track, version, govern, monitor, or automate ML systems. PROACTIVELY activate for: (1) MLflow, Weights & Biases, Neptune, Comet, ClearML experiment tracking, (2) model registry, model versioning, artifact lineage, reproducibility, (3) Kubeflow, SageMaker Pipelines, Vertex AI Pipelines, Azure ML pipelines, Databricks workflows, (4) CI/CD, continuous training/evaluation, A/B tests, canary/shadow deployments, (5) drift detection, model monitoring, data validation, responsible AI governance. Provides: end-to-end MLOps architecture and operational safeguards.
development
This skill should be used when the user asks to optimize, export, serve, compress, or accelerate ML inference. PROACTIVELY activate for: (1) latency, throughput, p95/p99, batching, concurrency, KV cache, memory, or cost issues, (2) quantization INT8/INT4, GPTQ, AWQ, bitsandbytes, pruning, sparsity, distillation, (3) ONNX export, ONNX Runtime, TensorRT, TorchScript, torch.compile, XLA, OpenVINO, Core ML, TFLite, (4) Triton, TorchServe, TF Serving, BentoML, Seldon, KServe configuration, (5) edge deployment, CPU/GPU/TPU/Inferentia serving. Provides: hardware-aware inference optimization and safe benchmarking.
testing
This skill should be used when the user asks to tune hyperparameters, run sweeps, optimize search spaces, or use AutoML. PROACTIVELY activate for: (1) Optuna, Ray Tune, FLAML, AutoGluon, Hyperopt, Nevergrad, KerasTuner, W&B sweeps, (2) grid search, random search, Bayesian optimization, TPE, Gaussian processes, evolutionary search, (3) ASHA, Hyperband, successive halving, multi-fidelity optimization, population-based training, (4) learning-rate finder, batch-size search, early stopping, pruning, (5) reproducible sweep design and experiment analysis. Provides: budget-aware hyperparameter search strategy.