Back to skills
SKILL.md
Creating Hooks
BSecurityCreates Claude Code hooks for automation and workflow customization. Guides through hook events, configuration, and script creation. Use when user wants to create a hook, automate Claude Code, or asks about hook events.
- 416 stars
- 0 votes
- 0 copies
- 1 view
- Added February 9, 2026
Works with
Security analysis
88/100- Pipes output to a shell interpreter
Pro scans all 6 files and shows the line behind each finding
npx -y skills add aiskillstore/marketplace --skill creating-hooks --agent claude-codeAre you the author of Creating Hooks?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/aiskillstore-creating-hooks)---
name: creating-hooks
description: |
Creates Claude Code hooks for automation and workflow customization.
Guides through hook events, configuration, and script creation.
Use when user wants to create a hook, automate Claude Code, or asks about hook events.
---
# Creating Hooks
Guides creation of Claude Code hooks for automation and workflow customization.
## Quick Start
1. Choose hook event (when should it trigger?)
2. Configure in settings.json
3. Create hook script
4. Test the hook
## Workflow: Create New Hook
```
Progress:
- [ ] Select hook event
- [ ] Add to settings.json
- [ ] Create hook script
- [ ] Test and validate
```
### Step 1: Select Hook Event
| Event | When It Triggers | Common Use |
|-------|------------------|------------|
| `PreToolUse` | Before tool runs | Block/modify tools |
| `PostToolUse` | After tool succeeds | Validate, log, feedback |
| `UserPromptSubmit` | User sends message | Inject context, validate |
| `SessionStart` | Session begins | Load context, init state |
| `SessionEnd` | Session ends | Cleanup, save state |
| `Stop` | Agent finishes | Decide if should continue |
Full event reference: [reference.md](reference.md)
### Step 2: Configure settings.json
Location priority (highest wins):
1. `.claude/settings.local.json` (local, not committed)
2. `.claude/settings.json` (project)
3. `~/.claude/settings.json` (user)
Basic structure:
```json
{
"hooks": {
"EventName": [
{
"matcher": "ToolPattern",
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/my-hook.sh\""
}
]
}
]
}
}
```
### Step 3: Create Hook Script
Use templates from [templates/](templates/) directory.
Key requirements:
- Read JSON from stdin
- Use exit codes for control (0=success, 2=block)
- Output JSON for decisions
### Step 4: Test
Run hook manually with test input:
```bash
echo '{"tool_name":"Write"}' | bash .claude/hooks/my-hook.sh
```
## Hook Configuration
### Matcher Patterns
```json
"matcher": "Write" // Exact match
"matcher": "Edit|Write" // Multiple tools
"matcher": "mcp__.*" // MCP tools (regex)
"matcher": "*" // All tools
```
Matchers apply to: `PreToolUse`, `PostToolUse`, `PermissionRequest`
### Timeout
```json
{
"type": "command",
"command": "...",
"timeout": 120
}
```
Default: 60 seconds. Max recommended: 300 seconds.
## Exit Codes
| Code | Meaning | Behavior |
|------|---------|----------|
| 0 | Success | Continue normally |
| 2 | Block | Stop action, show error |
| Other | Non-blocking error | Log only (verbose mode) |
## JSON Output
Return JSON to stdout for decisions:
```json
{
"decision": "block",
"reason": "Why blocked",
"additionalContext": "Info for Claude"
}
```
Decision values by event:
- `PreToolUse`: `allow`, `deny`, `ask`
- `PostToolUse`: `block` (with reason)
- `UserPromptSubmit`: `block` (with reason)
- `Stop`: `block` (requires reason)
## Security Best Practices
1. **Quote all variables**: `"$VAR"` not `$VAR`
2. **Use absolute paths**: `"$CLAUDE_PROJECT_DIR/..."`
3. **Validate inputs**: Check before processing
4. **Block path traversal**: Reject paths with `..`
5. **Set timeouts**: Prevent runaway scripts
## Environment Variables
Available in all hooks:
- `CLAUDE_PROJECT_DIR` - Project root path
- `CLAUDE_CODE_REMOTE` - "true" if web environment
SessionStart only:
- `CLAUDE_ENV_FILE` - Path to persist env vars
## Common Patterns
### Inject Context on Session Start
```bash
#!/bin/bash
# Output context for Claude
echo '{"additionalContext": "Project uses TypeScript"}'
exit 0
```
### Block Dangerous File Edits
```bash
#!/bin/bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
if [[ "$FILE" == *".env"* ]]; then
echo "Blocking edit to sensitive file" >&2
exit 2
fi
exit 0
```
### Log All Tool Usage
```bash
#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
echo "$(date -Iseconds) $TOOL" >> "$CLAUDE_PROJECT_DIR/.claude/tool.log"
exit 0
```
See [reference.md](reference.md) for complete event details and more examples.
Files in this skill
- SKILL.md
- reference.md
- skill-report.json
- templates/basic.sh
- templates/context-injector.sh
- templates/file-protector.sh
Attribution
Comments
Loading comments…