|
Download plugins/plugin-dev/skills/hook-development/references/patterns.md from SaylorTwift/claude-code: direct link, hf CLI and curl.
- Browser
- Download file 7.14 kB
-
https://huggingface.co/SaylorTwift/claude-code/resolve/main/plugins/plugin-dev/skills/hook-development/references/patterns.md
- Command line
-
hf download hf://SaylorTwift/claude-code/plugins/plugin-dev/skills/hook-development/references/patterns.md
-
curl -L -o patterns.md https://huggingface.co/SaylorTwift/claude-code/resolve/main/plugins/plugin-dev/skills/hook-development/references/patterns.md
7.14 kB
| # 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 | |