hook-audit
from philoserf/claude-code-setup
Comprehensive Claude Code configuration with agents, skills, hooks, and automation
npx skills add https://github.com/philoserf/claude-code-setup --skill hook-auditSKILL.md
Reference Files
Advanced hook patterns and best practices:
- exit-codes.md - Exit code semantics (0=allow, 2=block) with examples
- json-handling.md - Safe JSON stdin parsing patterns
- error-patterns.md - Error handling and graceful degradation
- performance.md - Timeout guidelines and optimization
- examples.md - Good vs bad hook patterns with before/after examples
Hook Audit
Performs comprehensive security and quality audits of Claude Code hooks, ensuring correct JSON handling, exit code semantics, error handling, and performance.
Quick Start
Audit a single hook:
User: "Audit my validate-config.py hook"
Assistant: [Reads hook file, checks patterns, generates report]
Audit all hooks:
User: "Check all my hooks for best practices"
Assistant: [Finds all hooks, analyzes each, generates consolidated report]
Fix specific issues:
User: "My hook is blocking on errors"
Assistant: [Analyzes error handling, suggests fixes]
Hook Audit Checklist
Use this checklist to audit any Claude Code hook:
Critical Requirements
- Shebang Line: Correct interpreter for hook type (see Shebang Standards below)
- Python hooks:
#!/usr/bin/env python3 - Bash hooks:
#!/bin/bash(NOT#!/usr/bin/env bashor#!/bin/sh)
- Python hooks:
- JSON stdin Handling: Safe parsing with try/except and
.get()methods - Exit Codes: Correct semantics (0=allow, 2=block, never 1)
- Error Handling: Exit 0 on hook errors (never block on hook failures)
- Settings.json Registration: Hook is registered with correct matcher and timeout
High Priority
- Timeout: Configured appropriately for hook type (PreToolUse <500ms, PostToolUse <2s)
- File Type Validation: Checks file type before processing
- Error Messages: Clear messages to stderr
- Performance: Executes within reasonable time
Medium Priority
- Naming Convention: Uses kebab-case naming
- Documentation: Header comments explain purpose and usage
- Pattern Consistency: Follows existing hook patterns
- Security: No security vulnerabilities or unsafe operations
Audit Workflow
Step 1: Identify Hook Type
Determine the hook type from settings.json registration:
- PreToolUse: Runs before tool execution, can block operations
- PostToolUse: Runs after successful tool execution
- Notification: Runs on specific events (Idle, etc.)
- SessionStart: Runs once at session start
Hook type determines performance requirements and exit code handling.
Step 2: Read Hook File and Check Syntax
Read the hook file and verify basic syntax:
# For Python hooks
python3 -m py_compile hook-file.py
# For Bash hooks
bash -n hook-file.sh
Check for:
- Correct shebang line
- Executable permissions
- Valid syntax
Step 3: Verify JSON Handling Pattern
For hooks that receive JSON stdin (PreToolUse, PostToolUse), verify safe parsing:
Python Pattern:
try:
data = json.load(sys.stdin)
file_path = data.get("tool_input", {}).get("file_path", "")
content = data.get("tool_input", {}).get("content", "")
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(0) # Don't block on parsing errors
Bash Pattern:
# Read stdin to variable
stdin_data=$(cat)
# Parse specific fields with jq
file_path=$(echo "$stdin_data" | jq -r '.tool_input.file_path // empty')
Critical: Use .get() with defaults, never direct key access.
Step 4: Check Exit Code Usage
Verify exit codes follow correct semantics:
- Exit 0: Allow operation (or hook encountered error)
- Exit 2: Block operation (validation failed)
- Never Exit 1: Reserved, don't use
Pattern to Check:
# Good: Block on validation failure
if errors:
print(f"Validation errors:", file=sys.stderr)
sys.exit(2)
# Good: Allow on hook error
except Exception as e:
print(f"Hook error: {e}", file=sys.stderr)
sys.exit(0) # Don't block user
# Bad: Exit 1 or non-zero on errors
sys.exit(1) # ✗ Wrong, use 0 or 2
For details on exit code patterns, see exit-codes.md.
Step 5: Review Error Handling
Check that hooks degrade gracefully:
- Dependency Check: Missing dependencies exit 0 (don't block)
- Try/Except: All operations wrapped in try/except
- Error Exit: Exceptions exit 0, not 1 or other codes
- Clear Messages: Errors printed to stderr with context
Example Pattern:
try:
import yaml
except ImportError:
print("Warning: PyYAML not installed, skipping", file=sys.stderr)
sys.exit(0) # Don't block user
try:
# Hook logic here
...
except Exception as e:
print(f"Error in hook: {e}", file=sys.stderr)
sys.exit(0) # Don't block user
For error handling patterns, see [error-patterns.md]
...