| name | hook-creator |
| description | Create Claude Code hooks with proper schemas, RBAC integration, and performance requirements. Use when implementing PreToolUse, PostToolUse, SessionStart, or any of the 10 hook event types for automation, validation, or security enforcement. |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep, Task, TodoWrite |
| model | sonnet |
SKILL: Hook Creator
LIBRARY-FIRST PROTOCOL (MANDATORY)
Before writing ANY code, you MUST check:
Step 1: Library Catalog
- Location:
.claude/library/catalog.json
- If match >70%: REUSE or ADAPT
Step 2: Patterns Guide
- Location:
.claude/docs/inventories/LIBRARY-PATTERNS-GUIDE.md
- If pattern exists: FOLLOW documented approach
Step 3: Existing Projects
- Location:
D:\Projects\*
- If found: EXTRACT and adapt
Decision Matrix
| Match | Action |
|---|
| Library >90% | REUSE directly |
| Library 70-90% | ADAPT minimally |
| Pattern exists | FOLLOW pattern |
| In project | EXTRACT |
| No match | BUILD (add to library after) |
Purpose
Create production-ready Claude Code hooks that integrate with our RBAC security system,
follow official schemas, and meet performance requirements (<20ms for pre-hooks).
When to Use This Skill
- Creating new automation hooks (pre/post operations)
- Implementing security validation hooks
- Building audit/logging hooks
- Extending the RBAC permission system
- Adding custom session management hooks
8-Stage Hook Creation Methodology
Stage 1: Hook Type Selection
Identify which of the 10 hook event types you need:
| Category | Hook Type | Purpose |
|---|
| Blocking | UserPromptSubmit | Validate/modify user prompts |
| Blocking | SessionStart | Initialize session state |
| Blocking | PreToolUse | Validate tool operations |
| Blocking | PermissionRequest | Auto-approve/deny permissions |
| Observational | PostToolUse | Log tool results |
| Observational | Notification | Forward notifications |
| Observational | Stop | Cleanup on agent stop |
| Observational | SubagentStop | Track subagent completion |
| Observational | PreCompact | Preserve context during compaction |
| Observational | SessionEnd | Final session cleanup |
Stage 2: Schema Definition
Define input/output schemas based on hook type.
PreToolUse Input:
{
"session_id": "string",
"tool_name": "Bash|Read|Write|Edit|...",
"tool_input": { "...tool-specific..." }
}
Blocking Output:
{
"continue": true|false,
"decision": "approve|block|modify",
"reason": "string (if blocked)",
"suppressOutput": false,
"updatedInput": { "..." }
}
Non-Blocking Output:
{
"suppressOutput": false
}
Stage 3: Template Selection
Use our pre-built templates:
pre-hook-template.js - For blocking hooks (PreToolUse, UserPromptSubmit)
post-hook-template.js - For observational hooks (PostToolUse, SessionEnd)
session-hook-template.js - For session lifecycle hooks
Generate from templates:
node hook-template-generator.js --type pre --name my-validator --event PreToolUse
Stage 4: Core Logic Implementation
Implement the hook's core logic:
#!/usr/bin/env node
const fs = require('fs');
const input = JSON.parse(fs.readFileSync(0, 'utf-8'));
function processHook(input) {
return { continue: true, decision: "approve" };
}
try {
const result = processHook(input);
console.log(JSON.stringify(result));
} catch (error) {
console.error(`[HOOK ERROR] ${error.message}`);
console.log(JSON.stringify({ continue: true }));
process.exit(1);
}
Stage 5: RBAC Integration
For security hooks, integrate with our identity system:
const { validateAgentIdentity, loadAgentIdentityByName } = require('../utils/identity');
const identity = loadAgentIdentityByName(input.agent_name);
const validation = validateAgentIdentity(identity);
if (!validation.valid) {
return {
continue: false,
decision: "block",
reason: `Invalid agent identity: ${validation.errors.join(', ')}`
};
}
Stage 6: Performance Optimization
Meet performance targets:
| Hook Type | Target | Max |
|---|
| Pre-hooks | <20ms | 100ms |
| Post-hooks | <100ms | 1000ms |
Optimization Patterns:
- Cache identity lookups
- Avoid synchronous I/O in hot paths
- Use matchers to filter events
- Batch logging operations
Stage 7: Testing
Create test scenarios:
const testCases = [
{
name: "Should approve valid operation",
input: { tool_name: "Read", tool_input: { file_path: "/src/app.js" } },
expectedOutput: { continue: true, decision: "approve" }
},
{
name: "Should block dangerous command",
input: { tool_name: "Bash", tool_input: { command: "rm -rf /" } },
expectedOutput: { continue: false, decision: "block" }
}
];
Stage 8: Registration
Register in settings.json:
{
"hooks": {
"PreToolUse": [
{
"type": "command",
"command": "node /path/to/your/hook.js",
"timeout": 5000,
"matcher": { "tool_name_regex": "^(Bash|Write|Edit)$" }
}
]
}
}
Hook Templates
Pre-Hook Template (Blocking)
Location: resources/templates/pre-hook-template.js
Features:
- Input validation
- Error handling with fail-open
- Performance timing
- RBAC integration point
Post-Hook Template (Observational)
Location: resources/templates/post-hook-template.js
Features:
- Async-safe logging
- Metric collection
- Non-blocking execution
- Error isolation
Output Artifacts
{hook-name}.js - Main hook script
{hook-name}.test.js - Test file
- Settings entry for
.claude/settings.json
Integration Points
- RBAC System:
hooks/12fa/utils/identity.js
- Permission Checker:
hooks/12fa/permission-checker.js
- Budget Tracker:
hooks/12fa/budget-tracker.js
- Reference Docs:
hooks/12fa/docs/CLAUDE-CODE-HOOKS-REFERENCE.md
Agents Used
| Agent | Role |
|---|
| hook-creator | Generate hook code from templates |
| coder | Implement custom logic |
| reviewer | Validate hook implementation |
| tester | Create and run test scenarios |
Example Invocations
Create a command validator hook:
User: "Create a hook that blocks any Bash command containing 'sudo'"
hook-creator:
1. Hook Type: PreToolUse (blocking)
2. Schema: PreToolUse input, blocking output
3. Template: pre-hook-template.js
4. Logic: Check tool_input.command for 'sudo'
5. RBAC: Not required (simple validation)
6. Performance: Target <10ms (regex only)
7. Tests: Valid command, sudo command, edge cases
8. Register in settings.json with Bash matcher
Create an audit logging hook:
User: "Create a hook that logs all file writes to an audit trail"
hook-creator:
1. Hook Type: PostToolUse (observational)
2. Schema: PostToolUse input, non-blocking output
3. Template: post-hook-template.js
4. Logic: Append to audit JSONL file
5. RBAC: Load agent identity for WHO tag
6. Performance: Target <50ms (file append)
7. Tests: Successful write, failed write, large file
8. Register with Write/Edit matcher
Security Considerations
- Never log sensitive data - Filter passwords, API keys, tokens
- Validate all input - Treat hook input as untrusted
- Fail open for non-security hooks - Don't block on errors
- Fail closed for security hooks - Block on validation errors
- Use absolute paths - Avoid path traversal vulnerabilities
Shell Script Best Practices (Codex Recommendations)
When creating bash/shell hooks, follow these best practices:
1. Enable Strict Mode
Always start shell hooks with strict mode:
#!/bin/bash
set -euo pipefail
2. Proper Variable Quoting
Always quote variable expansions to prevent word splitting:
FILE_PATH="${HOME}/.claude/state.json"
if [[ -f "$FILE_PATH" ]]; then
cat "$FILE_PATH"
fi
FILE_PATH=${HOME}/.claude/state.json
if [ -f $FILE_PATH ]; then
cat $FILE_PATH
fi
3. Defensive jq Usage
Handle jq failures gracefully:
VALUE=$(echo "$JSON" | jq -r '.key // "default"' 2>/dev/null || echo "default")
VALUE=$(echo "$JSON" | jq -r '.key')
4. Ensure Directories Exist
Create directories before writing:
STATE_DIR="${HOME}/.claude/my-hook"
mkdir -p "$STATE_DIR" 2>/dev/null
5. Use Environment Variables for Paths
Never hardcode project paths:
PROJECT_PATH="${MY_PROJECT_PATH:-/default/path}"
PROJECT_PATH="/c/Users/john/projects/myapp"
ANTI-PATTERNS TO AVOID
These patterns caused real bugs in production hooks. NEVER use them:
ANTI-PATTERN 1: Using grep -P (Perl Regex)
Problem: grep -P requires Perl regex support, not available on all systems.
FOUND=$(echo "$TEXT" | grep -oP '(?<=<tag>).*?(?=</tag>)')
if [[ "$TEXT" =~ \<tag\>([^\<]+)\</tag\> ]]; then
FOUND="${BASH_REMATCH[1]}"
fi
ANTI-PATTERN 2: Using sed -i Directly
Problem: sed -i behaves differently on macOS (requires ''), Linux, and Windows Git Bash.
sed -i 's/old/new/' "$FILE"
if [[ "$(uname -s)" == "Darwin" ]]; then
sed -i '' 's/old/new/' "$FILE"
else
sed -i 's/old/new/' "$FILE"
fi
sed_inplace() {
local pattern="$1"
local file="$2"
local temp_file="${file}.tmp.$$"
sed "$pattern" "$file" > "$temp_file" && mv "$temp_file" "$file"
}
sed_inplace 's/old/new/' "$FILE"
ANTI-PATTERN 3: Hardcoded Paths
Problem: Hardcoded paths break on other systems or when projects move.
cd D:/Projects/connascence
python analyze.py
CONNASCENCE_PATH="${CONNASCENCE_PROJECT_PATH:-D:/Projects/connascence}"
if [[ -d "$CONNASCENCE_PATH" ]]; then
cd "$CONNASCENCE_PATH"
python analyze.py
else
echo "ERROR: Connascence project not found at $CONNASCENCE_PATH" >&2
exit 1
fi
ANTI-PATTERN 4: Missing Directory Creation
Problem: Writing to directories that don't exist causes silent failures.
echo "$DATA" > ~/.claude/my-hook/state.json
STATE_DIR="${HOME}/.claude/my-hook"
mkdir -p "$STATE_DIR" 2>/dev/null
echo "$DATA" > "$STATE_DIR/state.json"
ANTI-PATTERN 5: Blocking cat Reads
Problem: Using cat without timeout can block indefinitely if stdin never closes.
INPUT=$(cat)
INPUT=$(timeout 5 cat 2>/dev/null || echo "{}")
if [[ -t 0 ]]; then
INPUT="{}"
else
INPUT=$(cat)
fi
ANTI-PATTERN 6: Silent Failures
Problem: Errors are silently swallowed, making debugging impossible.
jq '.key' "$FILE" 2>/dev/null
if ! VALUE=$(jq -r '.key' "$FILE" 2>&1); then
echo "[HOOK ERROR] Failed to parse $FILE: $VALUE" >&2
VALUE="default"
fi
Hook Validation Checklist
Before deploying a hook, verify:
Performance Monitoring
Add performance logging to all hooks:
const start = process.hrtime.bigint();
const durationMs = Number(process.hrtime.bigint() - start) / 1_000_000;
console.error(`[PERF] ${hookName} completed in ${durationMs.toFixed(2)}ms`);
Related Skills
hooks-automation - General hook automation patterns
cicd-intelligent-recovery - Error recovery patterns
cascade-orchestrator - Multi-hook coordination
Last Updated: 2025-12-30
Integrated with: Claude Code Hooks v1.0.0