Install
$ agentstack add skill-evan043-claude-cli-advanced-starter-pack-hook-creator ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Hook Creator Skill
Expert-level Claude Code hook creation following official Anthropic best practices.
When to Use This Skill
This skill is automatically invoked when:
- Creating new hooks for Claude Code CLI
- Modifying existing hook configurations
- Writing hook scripts (JS, Python, PowerShell)
- Configuring hook matchers and event types
Hook Architecture Overview
Configuration Files (Priority Order)
~/.claude/settings.json- Global user settings (all projects).claude/settings.json- Project settings (checked into git).claude/settings.local.json- Local overrides (gitignored)
Hook Directory Structure
.claude/
settings.local.json # Hook configurations (JSON)
hooks/
README.md # Hook system documentation
lifecycle/ # SessionStart, SessionEnd, Stop hooks
README.md
session-start.js
tools/ # PreToolUse, PostToolUse hooks
README.md
validate-files.js
notifications/ # Notification hooks
README.md
alert-handler.js
security/ # Security-focused hooks
README.md
block-dangerous-ops.js
Supported Hook Events
| Event | Trigger | Can Block | Primary Use Cases | |-------|---------|-----------|-------------------| | SessionStart | Session begins | No | Setup, notifications, load context | | SessionEnd | Session ends | No | Cleanup, save state | | Stop | Claude stops responding | No | Notifications, state saving | | PreToolUse | Before tool executes | Yes | Security gates, input validation | | PostToolUse | After tool completes | No | Logging, validation, sync | | Notification | Attention needed | No | Custom alerts, sounds | | UserPromptSubmit | Before prompt processes | Yes | Input validation | | SubagentStop | Subagent completes | No | Aggregate results | | PreCompact | Before transcript compaction | No | Archive, cleanup | | PermissionRequest | Permission dialog shown | No | Custom handling |
JSON Configuration Schema
Basic Hook Configuration
{
"hooks": {
"EventType": [
{
"matcher": "pattern",
"hooks": [
{
"type": "command",
"command": "your-command-here",
"timeout": 60
}
]
}
]
}
}
Configuration Fields
| Field | Required | Type | Description | |-------|----------|------|-------------| | matcher | No | string (regex) | Filter which tools/events trigger hook | | hooks | Yes | array | List of hook commands to execute | | type | Yes | "command" or "prompt" | Hook execution type | | command | For type:command | string | Shell command to execute | | timeout | No | number | Seconds before timeout (default: 60) |
Matcher Patterns
// Single tool
"matcher": "Write"
// Multiple tools (regex OR)
"matcher": "Write|Edit|MultiEdit"
// MCP namespace
"matcher": "mcp__browserbase__.*"
// Specific MCP tool
"matcher": "mcp__browserbase__browserbase_stagehand_act"
// No matcher = all tools
// Just omit the matcher field
Hook Input/Output
Environment Variables (Available to Hooks)
| Variable | Description | |----------|-------------| | CLAUDE_HOOK_INPUT | JSON string of tool input | | CLAUDE_TOOL_NAME | Name of tool being called | | CLAUDE_SESSION_ID | Unique session identifier | | CLAUDE_PROJECT_PATH | Path to project root | | CLAUDE_PERMISSION_MODE | Current permission mode |
Hook Output Format
{
"decision": "approve", // "approve", "block", or "ask"
"reason": "Optional explanation",
"systemMessage": "Warning to show user",
"updatedInput": {} // Modified tool input
}
Exit Codes
| Code | Meaning | Behavior | |------|---------|----------| | 0 | Success | Allow action to proceed | | 2 | Blocking error | Block action, show stderr to Claude | | Other | Non-blocking error | Show stderr to user, allow action | | Timeout | >60s (default) | Kill process, use default behavior |
Hook Templates
Template: JavaScript Tool Hook
#!/usr/bin/env node
/**
* Hook Name: [Description]
* Event: PreToolUse | PostToolUse
* Trigger: When [condition]
* Purpose: [What this hook accomplishes]
*/
const fs = require('fs');
const path = require('path');
// Parse hook input from environment
const hookInput = JSON.parse(process.env.CLAUDE_HOOK_INPUT || '{}');
const toolName = process.env.CLAUDE_TOOL_NAME || '';
const projectPath = process.env.CLAUDE_PROJECT_PATH || process.cwd();
async function main() {
try {
// Your validation/processing logic here
const shouldBlock = false; // Set based on your logic
if (shouldBlock) {
console.error('Blocked: [reason]');
process.exit(2); // Exit code 2 = blocking error
}
// Success - allow action
console.log(JSON.stringify({
decision: 'approve',
reason: 'Validation passed'
}));
process.exit(0);
} catch (error) {
// CRITICAL: Always default to allowing on error
console.error('Hook error:', error.message);
console.log(JSON.stringify({
decision: 'approve',
reason: `Error in hook: ${error.message}`
}));
process.exit(0);
}
}
main();
Template: Python Security Hook
#!/usr/bin/env python3
"""
Hook Name: [Description]
Event: PreToolUse
Trigger: Write|Edit|Bash
Purpose: Block dangerous operations
"""
import json
import os
import sys
# Parse hook input
try:
hook_input = json.loads(os.environ.get('CLAUDE_HOOK_INPUT', '{}'))
tool_name = os.environ.get('CLAUDE_TOOL_NAME', '')
project_path = os.environ.get('CLAUDE_PROJECT_PATH', os.getcwd())
except json.JSONDecodeError:
hook_input = {}
tool_name = ''
project_path = os.getcwd()
# Dangerous patterns to block
DANGEROUS_PATTERNS = [
'.env',
'secrets/',
'credentials',
'private_key',
]
def is_dangerous(file_path: str) -> bool:
"""Check if file path matches dangerous patterns."""
return any(pattern in file_path.lower() for pattern in DANGEROUS_PATTERNS)
def main():
try:
file_path = hook_input.get('file_path', '')
if is_dangerous(file_path):
sys.stderr.write(f"Blocked: Dangerous file pattern detected: {file_path}\n")
sys.exit(2) # Exit 2 = blocking error
print(json.dumps({
'decision': 'approve',
'reason': 'File path validated'
}))
sys.exit(0)
except Exception as e:
# CRITICAL: Default to allowing on error
sys.stderr.write(f"Hook error: {str(e)}\n")
print(json.dumps({
'decision': 'approve',
'reason': f'Error in hook: {str(e)}'
}))
sys.exit(0)
if __name__ == '__main__':
main()
Best Practices
Performance
- Keep hooks fast - Target <5 seconds execution
- Use timeouts - Set appropriate timeouts for longer operations
- Async when possible - Background non-critical work
- Minimize I/O - Cache frequently accessed data
Security
- Quote variables - Prevent command injection
- Validate inputs - Never trust hook input blindly
- Scope credentials - Hooks run with your full environment
- Block sensitive files - Use PreToolUse to protect secrets
Error Handling
- Always default to
approve- Don't block on hook errors - Log errors - Write to stderr for debugging
- Graceful degradation - Hooks should fail safely
- Test locally - Verify hooks before deploying
Organization
- Use subdirectories - Group hooks by purpose
- Document everything - README.md in each directory
- Consistent naming -
{purpose}-{action}-hook.{ext} - Version control - Track hook changes in git
Workflows
Creating a New Hook
- Determine event type - Which lifecycle event triggers your hook?
- Design matcher - What tools/actions should trigger it?
- Choose language - JS for complex logic, Python for security
- Write hook script - Use templates above
- Configure in settings - Add to
.claude/settings.local.json - Document - Update README.md in appropriate directory
- Test locally - Run hook manually before enabling
Modifying Existing Hooks
- Review current config - Check
.claude/settings.local.json - Understand impact - What tools/events are affected?
- Make changes - Update configuration or hook script
- Test thoroughly - Verify both success and error paths
- Update documentation - Keep README.md current
References
- Official Docs: https://docs.anthropic.com/en/docs/claude-code/hooks
- Project Hooks:
.claude/hooks/README.md - Settings:
.claude/settings.local.json
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: evan043
- Source: evan043/claude-cli-advanced-starter-pack
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.