aboutsummaryrefslogtreecommitdiffstats
path: root/.agents/skills/hook-development/references
diff options
context:
space:
mode:
authorsillylaird <sillyfanboy@gmail.com>2026-09-03 00:33:59 +0000
committersillylaird <sillyfanboy@gmail.com>2026-09-03 00:33:59 +0000
commit898b52edcb47bcb3e9d6106e74ca73e74ea01e70 (patch)
tree85c6ee5ad58b860144551184d4cf86b560c62b91 /.agents/skills/hook-development/references
downloadwww-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.tar.gz
www-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.zip
import live www.sillylaird.ca webrootHEADmain
Diffstat (limited to '')
-rw-r--r--.agents/skills/hook-development/references/advanced.md479
-rw-r--r--.agents/skills/hook-development/references/migration.md369
-rw-r--r--.agents/skills/hook-development/references/patterns.md346
3 files changed, 1194 insertions, 0 deletions
diff --git a/.agents/skills/hook-development/references/advanced.md b/.agents/skills/hook-development/references/advanced.md
new file mode 100644
index 0000000..a84a38f
--- /dev/null
+++ b/.agents/skills/hook-development/references/advanced.md
@@ -0,0 +1,479 @@
+# Advanced Hook Use Cases
+
+This reference covers advanced hook patterns and techniques for sophisticated automation workflows.
+
+## Multi-Stage Validation
+
+Combine command and prompt hooks for layered validation:
+
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Bash",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/quick-check.sh",
+ "timeout": 5
+ },
+ {
+ "type": "prompt",
+ "prompt": "Deep analysis of bash command: $TOOL_INPUT",
+ "timeout": 15
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Use case:** Fast deterministic checks followed by intelligent analysis
+
+**Example quick-check.sh:**
+```bash
+#!/bin/bash
+input=$(cat)
+command=$(echo "$input" | jq -r '.tool_input.command')
+
+# Immediate approval for safe commands
+if [[ "$command" =~ ^(ls|pwd|echo|date|whoami)$ ]]; then
+ exit 0
+fi
+
+# Let prompt hook handle complex cases
+exit 0
+```
+
+The command hook quickly approves obviously safe commands, while the prompt hook analyzes everything else.
+
+## Conditional Hook Execution
+
+Execute hooks based on environment or context:
+
+```bash
+#!/bin/bash
+# Only run in CI environment
+if [ -z "$CI" ]; then
+ echo '{"continue": true}' # Skip in non-CI
+ exit 0
+fi
+
+# Run validation logic in CI
+input=$(cat)
+# ... validation code ...
+```
+
+**Use cases:**
+- Different behavior in CI vs local development
+- Project-specific validation
+- User-specific rules
+
+**Example: Skip certain checks for trusted users:**
+```bash
+#!/bin/bash
+# Skip detailed checks for admin users
+if [ "$USER" = "admin" ]; then
+ exit 0
+fi
+
+# Full validation for other users
+input=$(cat)
+# ... validation code ...
+```
+
+## Hook Chaining via State
+
+Share state between hooks using temporary files:
+
+```bash
+# Hook 1: Analyze and save state
+#!/bin/bash
+input=$(cat)
+command=$(echo "$input" | jq -r '.tool_input.command')
+
+# Analyze command
+risk_level=$(calculate_risk "$command")
+echo "$risk_level" > /tmp/hook-state-$$
+
+exit 0
+```
+
+```bash
+# Hook 2: Use saved state
+#!/bin/bash
+risk_level=$(cat /tmp/hook-state-$$ 2>/dev/null || echo "unknown")
+
+if [ "$risk_level" = "high" ]; then
+ echo "High risk operation detected" >&2
+ exit 2
+fi
+```
+
+**Important:** This only works for sequential hook events (e.g., PreToolUse then PostToolUse), not parallel hooks.
+
+## Dynamic Hook Configuration
+
+Modify hook behavior based on project configuration:
+
+```bash
+#!/bin/bash
+cd "$CLAUDE_PROJECT_DIR" || exit 1
+
+# Read project-specific config
+if [ -f ".claude-hooks-config.json" ]; then
+ strict_mode=$(jq -r '.strict_mode' .claude-hooks-config.json)
+
+ if [ "$strict_mode" = "true" ]; then
+ # Apply strict validation
+ # ...
+ else
+ # Apply lenient validation
+ # ...
+ fi
+fi
+```
+
+**Example .claude-hooks-config.json:**
+```json
+{
+ "strict_mode": true,
+ "allowed_commands": ["ls", "pwd", "grep"],
+ "forbidden_paths": ["/etc", "/sys"]
+}
+```
+
+## Context-Aware Prompt Hooks
+
+Use transcript and session context for intelligent decisions:
+
+```json
+{
+ "Stop": [
+ {
+ "matcher": "*",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Review the full transcript at $TRANSCRIPT_PATH. Check: 1) Were tests run after code changes? 2) Did the build succeed? 3) Were all user questions answered? 4) Is there any unfinished work? Return 'approve' only if everything is complete."
+ }
+ ]
+ }
+ ]
+}
+```
+
+The LLM can read the transcript file and make context-aware decisions.
+
+## Performance Optimization
+
+### Caching Validation Results
+
+```bash
+#!/bin/bash
+input=$(cat)
+file_path=$(echo "$input" | jq -r '.tool_input.file_path')
+cache_key=$(echo -n "$file_path" | md5sum | cut -d' ' -f1)
+cache_file="/tmp/hook-cache-$cache_key"
+
+# Check cache
+if [ -f "$cache_file" ]; then
+ cache_age=$(($(date +%s) - $(stat -f%m "$cache_file" 2>/dev/null || stat -c%Y "$cache_file")))
+ if [ "$cache_age" -lt 300 ]; then # 5 minute cache
+ cat "$cache_file"
+ exit 0
+ fi
+fi
+
+# Perform validation
+result='{"decision": "approve"}'
+
+# Cache result
+echo "$result" > "$cache_file"
+echo "$result"
+```
+
+### Parallel Execution Optimization
+
+Since hooks run in parallel, design them to be independent:
+
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Write",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash check-size.sh", // Independent
+ "timeout": 2
+ },
+ {
+ "type": "command",
+ "command": "bash check-path.sh", // Independent
+ "timeout": 2
+ },
+ {
+ "type": "prompt",
+ "prompt": "Check content safety", // Independent
+ "timeout": 10
+ }
+ ]
+ }
+ ]
+}
+```
+
+All three hooks run simultaneously, reducing total latency.
+
+## Cross-Event Workflows
+
+Coordinate hooks across different events:
+
+**SessionStart - Set up tracking:**
+```bash
+#!/bin/bash
+# Initialize session tracking
+echo "0" > /tmp/test-count-$$
+echo "0" > /tmp/build-count-$$
+```
+
+**PostToolUse - Track events:**
+```bash
+#!/bin/bash
+input=$(cat)
+tool_name=$(echo "$input" | jq -r '.tool_name')
+
+if [ "$tool_name" = "Bash" ]; then
+ command=$(echo "$input" | jq -r '.tool_result')
+ if [[ "$command" == *"test"* ]]; then
+ count=$(cat /tmp/test-count-$$ 2>/dev/null || echo "0")
+ echo $((count + 1)) > /tmp/test-count-$$
+ fi
+fi
+```
+
+**Stop - Verify based on tracking:**
+```bash
+#!/bin/bash
+test_count=$(cat /tmp/test-count-$$ 2>/dev/null || echo "0")
+
+if [ "$test_count" -eq 0 ]; then
+ echo '{"decision": "block", "reason": "No tests were run"}' >&2
+ exit 2
+fi
+```
+
+## Integration with External Systems
+
+### Slack Notifications
+
+```bash
+#!/bin/bash
+input=$(cat)
+tool_name=$(echo "$input" | jq -r '.tool_name')
+decision="blocked"
+
+# Send notification to Slack
+curl -X POST "$SLACK_WEBHOOK" \
+ -H 'Content-Type: application/json' \
+ -d "{\"text\": \"Hook ${decision} ${tool_name} operation\"}" \
+ 2>/dev/null
+
+echo '{"decision": "deny"}' >&2
+exit 2
+```
+
+### Database Logging
+
+```bash
+#!/bin/bash
+input=$(cat)
+
+# Log to database
+psql "$DATABASE_URL" -c "INSERT INTO hook_logs (event, data) VALUES ('PreToolUse', '$input')" \
+ 2>/dev/null
+
+exit 0
+```
+
+### Metrics Collection
+
+```bash
+#!/bin/bash
+input=$(cat)
+tool_name=$(echo "$input" | jq -r '.tool_name')
+
+# Send metrics to monitoring system
+echo "hook.pretooluse.${tool_name}:1|c" | nc -u -w1 statsd.local 8125
+
+exit 0
+```
+
+## Security Patterns
+
+### Rate Limiting
+
+```bash
+#!/bin/bash
+input=$(cat)
+command=$(echo "$input" | jq -r '.tool_input.command')
+
+# Track command frequency
+rate_file="/tmp/hook-rate-$$"
+current_minute=$(date +%Y%m%d%H%M)
+
+if [ -f "$rate_file" ]; then
+ last_minute=$(head -1 "$rate_file")
+ count=$(tail -1 "$rate_file")
+
+ if [ "$current_minute" = "$last_minute" ]; then
+ if [ "$count" -gt 10 ]; then
+ echo '{"decision": "deny", "reason": "Rate limit exceeded"}' >&2
+ exit 2
+ fi
+ count=$((count + 1))
+ else
+ count=1
+ fi
+else
+ count=1
+fi
+
+echo "$current_minute" > "$rate_file"
+echo "$count" >> "$rate_file"
+
+exit 0
+```
+
+### Audit Logging
+
+```bash
+#!/bin/bash
+input=$(cat)
+tool_name=$(echo "$input" | jq -r '.tool_name')
+timestamp=$(date -Iseconds)
+
+# Append to audit log
+echo "$timestamp | $USER | $tool_name | $input" >> ~/.claude/audit.log
+
+exit 0
+```
+
+### Secret Detection
+
+```bash
+#!/bin/bash
+input=$(cat)
+content=$(echo "$input" | jq -r '.tool_input.content')
+
+# Check for common secret patterns
+if echo "$content" | grep -qE "(api[_-]?key|password|secret|token).{0,20}['\"]?[A-Za-z0-9]{20,}"; then
+ echo '{"decision": "deny", "reason": "Potential secret detected in content"}' >&2
+ exit 2
+fi
+
+exit 0
+```
+
+## Testing Advanced Hooks
+
+### Unit Testing Hook Scripts
+
+```bash
+# test-hook.sh
+#!/bin/bash
+
+# Test 1: Approve safe command
+result=$(echo '{"tool_input": {"command": "ls"}}' | bash validate-bash.sh)
+if [ $? -eq 0 ]; then
+ echo "✓ Test 1 passed"
+else
+ echo "✗ Test 1 failed"
+fi
+
+# Test 2: Block dangerous command
+result=$(echo '{"tool_input": {"command": "rm -rf /"}}' | bash validate-bash.sh)
+if [ $? -eq 2 ]; then
+ echo "✓ Test 2 passed"
+else
+ echo "✗ Test 2 failed"
+fi
+```
+
+### Integration Testing
+
+Create test scenarios that exercise the full hook workflow:
+
+```bash
+# integration-test.sh
+#!/bin/bash
+
+# Set up test environment
+export CLAUDE_PROJECT_DIR="/tmp/test-project"
+export CLAUDE_PLUGIN_ROOT="$(pwd)"
+mkdir -p "$CLAUDE_PROJECT_DIR"
+
+# Test SessionStart hook
+echo '{}' | bash hooks/session-start.sh
+if [ -f "/tmp/session-initialized" ]; then
+ echo "✓ SessionStart hook works"
+else
+ echo "✗ SessionStart hook failed"
+fi
+
+# Clean up
+rm -rf "$CLAUDE_PROJECT_DIR"
+```
+
+## Best Practices for Advanced Hooks
+
+1. **Keep hooks independent**: Don't rely on execution order
+2. **Use timeouts**: Set appropriate limits for each hook type
+3. **Handle errors gracefully**: Provide clear error messages
+4. **Document complexity**: Explain advanced patterns in README
+5. **Test thoroughly**: Cover edge cases and failure modes
+6. **Monitor performance**: Track hook execution time
+7. **Version configuration**: Use version control for hook configs
+8. **Provide escape hatches**: Allow users to bypass hooks when needed
+
+## Common Pitfalls
+
+### ❌ Assuming Hook Order
+
+```bash
+# BAD: Assumes hooks run in specific order
+# Hook 1 saves state, Hook 2 reads it
+# This can fail because hooks run in parallel!
+```
+
+### ❌ Long-Running Hooks
+
+```bash
+# BAD: Hook takes 2 minutes to run
+sleep 120
+# This will timeout and block the workflow
+```
+
+### ❌ Uncaught Exceptions
+
+```bash
+# BAD: Script crashes on unexpected input
+file_path=$(echo "$input" | jq -r '.tool_input.file_path')
+cat "$file_path" # Fails if file doesn't exist
+```
+
+### ✅ Proper Error Handling
+
+```bash
+# GOOD: Handles errors gracefully
+file_path=$(echo "$input" | jq -r '.tool_input.file_path')
+if [ ! -f "$file_path" ]; then
+ echo '{"continue": true, "systemMessage": "File not found, skipping check"}' >&2
+ exit 0
+fi
+```
+
+## Conclusion
+
+Advanced hook patterns enable sophisticated automation while maintaining reliability and performance. Use these techniques when basic hooks are insufficient, but always prioritize simplicity and maintainability.
diff --git a/.agents/skills/hook-development/references/migration.md b/.agents/skills/hook-development/references/migration.md
new file mode 100644
index 0000000..587cae3
--- /dev/null
+++ b/.agents/skills/hook-development/references/migration.md
@@ -0,0 +1,369 @@
+# Migrating from Basic to Advanced Hooks
+
+This guide shows how to migrate from basic command hooks to advanced prompt-based hooks for better maintainability and flexibility.
+
+## Why Migrate?
+
+Prompt-based hooks offer several advantages:
+
+- **Natural language reasoning**: LLM understands context and intent
+- **Better edge case handling**: Adapts to unexpected scenarios
+- **No bash scripting required**: Simpler to write and maintain
+- **More flexible validation**: Can handle complex logic without coding
+
+## Migration Example: Bash Command Validation
+
+### Before (Basic Command Hook)
+
+**Configuration:**
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Bash",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash validate-bash.sh"
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Script (validate-bash.sh):**
+```bash
+#!/bin/bash
+input=$(cat)
+command=$(echo "$input" | jq -r '.tool_input.command')
+
+# Hard-coded validation logic
+if [[ "$command" == *"rm -rf"* ]]; then
+ echo "Dangerous command detected" >&2
+ exit 2
+fi
+```
+
+**Problems:**
+- Only checks for exact "rm -rf" pattern
+- Doesn't catch variations like `rm -fr` or `rm -r -f`
+- Misses other dangerous commands (`dd`, `mkfs`, etc.)
+- No context awareness
+- Requires bash scripting knowledge
+
+### After (Advanced Prompt Hook)
+
+**Configuration:**
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Bash",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Command: $TOOL_INPUT.command. Analyze for: 1) Destructive operations (rm -rf, dd, mkfs, etc) 2) Privilege escalation (sudo) 3) Network operations without user consent. Return 'approve' or 'deny' with explanation.",
+ "timeout": 15
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Benefits:**
+- Catches all variations and patterns
+- Understands intent, not just literal strings
+- No script file needed
+- Easy to extend with new criteria
+- Context-aware decisions
+- Natural language explanation in denial
+
+## Migration Example: File Write Validation
+
+### Before (Basic Command Hook)
+
+**Configuration:**
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Write",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash validate-write.sh"
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Script (validate-write.sh):**
+```bash
+#!/bin/bash
+input=$(cat)
+file_path=$(echo "$input" | jq -r '.tool_input.file_path')
+
+# Check for path traversal
+if [[ "$file_path" == *".."* ]]; then
+ echo '{"decision": "deny", "reason": "Path traversal detected"}' >&2
+ exit 2
+fi
+
+# Check for system paths
+if [[ "$file_path" == "/etc/"* ]] || [[ "$file_path" == "/sys/"* ]]; then
+ echo '{"decision": "deny", "reason": "System file"}' >&2
+ exit 2
+fi
+```
+
+**Problems:**
+- Hard-coded path patterns
+- Doesn't understand symlinks
+- Missing edge cases (e.g., `/etc` vs `/etc/`)
+- No consideration of file content
+
+### After (Advanced Prompt Hook)
+
+**Configuration:**
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Write|Edit",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "File path: $TOOL_INPUT.file_path. Content preview: $TOOL_INPUT.content (first 200 chars). Verify: 1) Not system directories (/etc, /sys, /usr) 2) Not credentials (.env, tokens, secrets) 3) No path traversal 4) Content doesn't expose secrets. Return 'approve' or 'deny'."
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Benefits:**
+- Context-aware (considers content too)
+- Handles symlinks and edge cases
+- Natural understanding of "system directories"
+- Can detect secrets in content
+- Easy to extend criteria
+
+## When to Keep Command Hooks
+
+Command hooks still have their place:
+
+### 1. Deterministic Performance Checks
+
+```bash
+#!/bin/bash
+# Check file size quickly
+file_path=$(echo "$input" | jq -r '.tool_input.file_path')
+size=$(stat -f%z "$file_path" 2>/dev/null || stat -c%s "$file_path" 2>/dev/null)
+
+if [ "$size" -gt 10000000 ]; then
+ echo '{"decision": "deny", "reason": "File too large"}' >&2
+ exit 2
+fi
+```
+
+**Use command hooks when:** Validation is purely mathematical or deterministic.
+
+### 2. External Tool Integration
+
+```bash
+#!/bin/bash
+# Run security scanner
+file_path=$(echo "$input" | jq -r '.tool_input.file_path')
+scan_result=$(security-scanner "$file_path")
+
+if [ "$?" -ne 0 ]; then
+ echo "Security scan failed: $scan_result" >&2
+ exit 2
+fi
+```
+
+**Use command hooks when:** Integrating with external tools that provide yes/no answers.
+
+### 3. Very Fast Checks (< 50ms)
+
+```bash
+#!/bin/bash
+# Quick regex check
+command=$(echo "$input" | jq -r '.tool_input.command')
+
+if [[ "$command" =~ ^(ls|pwd|echo)$ ]]; then
+ exit 0 # Safe commands
+fi
+```
+
+**Use command hooks when:** Performance is critical and logic is simple.
+
+## Hybrid Approach
+
+Combine both for multi-stage validation:
+
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Bash",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/quick-check.sh",
+ "timeout": 5
+ },
+ {
+ "type": "prompt",
+ "prompt": "Deep analysis of bash command: $TOOL_INPUT",
+ "timeout": 15
+ }
+ ]
+ }
+ ]
+}
+```
+
+The command hook does fast deterministic checks, while the prompt hook handles complex reasoning.
+
+## Migration Checklist
+
+When migrating hooks:
+
+- [ ] Identify the validation logic in the command hook
+- [ ] Convert hard-coded patterns to natural language criteria
+- [ ] Test with edge cases the old hook missed
+- [ ] Verify LLM understands the intent
+- [ ] Set appropriate timeout (usually 15-30s for prompt hooks)
+- [ ] Document the new hook in README
+- [ ] Remove or archive old script files
+
+## Migration Tips
+
+1. **Start with one hook**: Don't migrate everything at once
+2. **Test thoroughly**: Verify prompt hook catches what command hook caught
+3. **Look for improvements**: Use migration as opportunity to enhance validation
+4. **Keep scripts for reference**: Archive old scripts in case you need to reference the logic
+5. **Document reasoning**: Explain why prompt hook is better in README
+
+## Complete Migration Example
+
+### Original Plugin Structure
+
+```
+my-plugin/
+├── .claude-plugin/plugin.json
+├── hooks/hooks.json
+└── scripts/
+ ├── validate-bash.sh
+ ├── validate-write.sh
+ └── check-tests.sh
+```
+
+### After Migration
+
+```
+my-plugin/
+├── .claude-plugin/plugin.json
+├── hooks/hooks.json # Now uses prompt hooks
+└── scripts/ # Archive or delete
+ └── archive/
+ ├── validate-bash.sh
+ ├── validate-write.sh
+ └── check-tests.sh
+```
+
+### Updated hooks.json
+
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Bash",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Validate bash command safety: destructive ops, privilege escalation, network access"
+ }
+ ]
+ },
+ {
+ "matcher": "Write|Edit",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Validate file write safety: system paths, credentials, path traversal, content secrets"
+ }
+ ]
+ }
+ ],
+ "Stop": [
+ {
+ "matcher": "*",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Verify tests were run if code was modified"
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Result:** Simpler, more maintainable, more powerful.
+
+## Common Migration Patterns
+
+### Pattern: String Contains → Natural Language
+
+**Before:**
+```bash
+if [[ "$command" == *"sudo"* ]]; then
+ echo "Privilege escalation" >&2
+ exit 2
+fi
+```
+
+**After:**
+```
+"Check for privilege escalation (sudo, su, etc)"
+```
+
+### Pattern: Regex → Intent
+
+**Before:**
+```bash
+if [[ "$file" =~ \.(env|secret|key|token)$ ]]; then
+ echo "Credential file" >&2
+ exit 2
+fi
+```
+
+**After:**
+```
+"Verify not writing to credential files (.env, secrets, keys, tokens)"
+```
+
+### Pattern: Multiple Conditions → Criteria List
+
+**Before:**
+```bash
+if [ condition1 ] || [ condition2 ] || [ condition3 ]; then
+ echo "Invalid" >&2
+ exit 2
+fi
+```
+
+**After:**
+```
+"Check: 1) condition1 2) condition2 3) condition3. Deny if any fail."
+```
+
+## Conclusion
+
+Migrating to prompt-based hooks makes plugins more maintainable, flexible, and powerful. Reserve command hooks for deterministic checks and external tool integration.
diff --git a/.agents/skills/hook-development/references/patterns.md b/.agents/skills/hook-development/references/patterns.md
new file mode 100644
index 0000000..4475386
--- /dev/null
+++ b/.agents/skills/hook-development/references/patterns.md
@@ -0,0 +1,346 @@
+# Common Hook Patterns
+
+This reference provides common, proven patterns for implementing Claude Code hooks. Use these patterns as starting points for typical hook use cases.
+
+## Pattern 1: Security Validation
+
+Block dangerous file writes using prompt-based hooks:
+
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Write|Edit",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "File path: $TOOL_INPUT.file_path. Verify: 1) Not in /etc or system directories 2) Not .env or credentials 3) Path doesn't contain '..' traversal. Return 'approve' or 'deny'."
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Use for:** Preventing writes to sensitive files or system directories.
+
+## Pattern 2: Test Enforcement
+
+Ensure tests run before stopping:
+
+```json
+{
+ "Stop": [
+ {
+ "matcher": "*",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Review transcript. If code was modified (Write/Edit tools used), verify tests were executed. If no tests were run, block with reason 'Tests must be run after code changes'."
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Use for:** Enforcing quality standards and preventing incomplete work.
+
+## Pattern 3: Context Loading
+
+Load project-specific context at session start:
+
+```json
+{
+ "SessionStart": [
+ {
+ "matcher": "*",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh"
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Example script (load-context.sh):**
+```bash
+#!/bin/bash
+cd "$CLAUDE_PROJECT_DIR" || exit 1
+
+# Detect project type
+if [ -f "package.json" ]; then
+ echo "📦 Node.js project detected"
+ echo "export PROJECT_TYPE=nodejs" >> "$CLAUDE_ENV_FILE"
+elif [ -f "Cargo.toml" ]; then
+ echo "🦀 Rust project detected"
+ echo "export PROJECT_TYPE=rust" >> "$CLAUDE_ENV_FILE"
+fi
+```
+
+**Use for:** Automatically detecting and configuring project-specific settings.
+
+## Pattern 4: Notification Logging
+
+Log all notifications for audit or analysis:
+
+```json
+{
+ "Notification": [
+ {
+ "matcher": "*",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/log-notification.sh"
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Use for:** Tracking user notifications or integration with external logging systems.
+
+## Pattern 5: MCP Tool Monitoring
+
+Monitor and validate MCP tool usage:
+
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "mcp__.*__delete.*",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Deletion operation detected. Verify: Is this deletion intentional? Can it be undone? Are there backups? Return 'approve' only if safe."
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Use for:** Protecting against destructive MCP operations.
+
+## Pattern 6: Build Verification
+
+Ensure project builds after code changes:
+
+```json
+{
+ "Stop": [
+ {
+ "matcher": "*",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Check if code was modified. If Write/Edit tools were used, verify the project was built (npm run build, cargo build, etc). If not built, block and request build."
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Use for:** Catching build errors before committing or stopping work.
+
+## Pattern 7: Permission Confirmation
+
+Ask user before dangerous operations:
+
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Bash",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Command: $TOOL_INPUT.command. If command contains 'rm', 'delete', 'drop', or other destructive operations, return 'ask' to confirm with user. Otherwise 'approve'."
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Use for:** User confirmation on potentially destructive commands.
+
+## Pattern 8: Code Quality Checks
+
+Run linters or formatters on file edits:
+
+```json
+{
+ "PostToolUse": [
+ {
+ "matcher": "Write|Edit",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/check-quality.sh"
+ }
+ ]
+ }
+ ]
+}
+```
+
+**Example script (check-quality.sh):**
+```bash
+#!/bin/bash
+input=$(cat)
+file_path=$(echo "$input" | jq -r '.tool_input.file_path')
+
+# Run linter if applicable
+if [[ "$file_path" == *.js ]] || [[ "$file_path" == *.ts ]]; then
+ npx eslint "$file_path" 2>&1 || true
+fi
+```
+
+**Use for:** Automatic code quality enforcement.
+
+## Pattern Combinations
+
+Combine multiple patterns for comprehensive protection:
+
+```json
+{
+ "PreToolUse": [
+ {
+ "matcher": "Write|Edit",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Validate file write safety"
+ }
+ ]
+ },
+ {
+ "matcher": "Bash",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Validate bash command safety"
+ }
+ ]
+ }
+ ],
+ "Stop": [
+ {
+ "matcher": "*",
+ "hooks": [
+ {
+ "type": "prompt",
+ "prompt": "Verify tests run and build succeeded"
+ }
+ ]
+ }
+ ],
+ "SessionStart": [
+ {
+ "matcher": "*",
+ "hooks": [
+ {
+ "type": "command",
+ "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh"
+ }
+ ]
+ }
+ ]
+}
+```
+
+This provides multi-layered protection and automation.
+
+## Pattern 9: Temporarily Active Hooks
+
+Create hooks that only run when explicitly enabled via flag files:
+
+```bash
+#!/bin/bash
+# Hook only active when flag file exists
+FLAG_FILE="$CLAUDE_PROJECT_DIR/.enable-security-scan"
+
+if [ ! -f "$FLAG_FILE" ]; then
+ # Quick exit when disabled
+ exit 0
+fi
+
+# Flag present, run validation
+input=$(cat)
+file_path=$(echo "$input" | jq -r '.tool_input.file_path')
+
+# Run security scan
+security-scanner "$file_path"
+```
+
+**Activation:**
+```bash
+# Enable the hook
+touch .enable-security-scan
+
+# Disable the hook
+rm .enable-security-scan
+```
+
+**Use for:**
+- Temporary debugging hooks
+- Feature flags for development
+- Project-specific validation that's opt-in
+- Performance-intensive checks only when needed
+
+**Note:** Must restart Claude Code after creating/removing flag files for hooks to recognize changes.
+
+## Pattern 10: Configuration-Driven Hooks
+
+Use JSON configuration to control hook behavior:
+
+```bash
+#!/bin/bash
+CONFIG_FILE="$CLAUDE_PROJECT_DIR/.claude/my-plugin.local.json"
+
+# Read configuration
+if [ -f "$CONFIG_FILE" ]; then
+ strict_mode=$(jq -r '.strictMode // false' "$CONFIG_FILE")
+ max_file_size=$(jq -r '.maxFileSize // 1000000' "$CONFIG_FILE")
+else
+ # Defaults
+ strict_mode=false
+ max_file_size=1000000
+fi
+
+# Skip if not in strict mode
+if [ "$strict_mode" != "true" ]; then
+ exit 0
+fi
+
+# Apply configured limits
+input=$(cat)
+file_size=$(echo "$input" | jq -r '.tool_input.content | length')
+
+if [ "$file_size" -gt "$max_file_size" ]; then
+ echo '{"decision": "deny", "reason": "File exceeds configured size limit"}' >&2
+ exit 2
+fi
+```
+
+**Configuration file (.claude/my-plugin.local.json):**
+```json
+{
+ "strictMode": true,
+ "maxFileSize": 500000,
+ "allowedPaths": ["/tmp", "/home/user/projects"]
+}
+```
+
+**Use for:**
+- User-configurable hook behavior
+- Per-project settings
+- Team-specific rules
+- Dynamic validation criteria