Loading...
Loading...
Use when creating or publishing Claude Code hooks - covers executable format, event types, JSON I/O, exit codes, security requirements, and PRPM package structure
npx skill4agent add pr-pm/prpm creating-claude-hooks| Aspect | Requirement |
|---|---|
| Location | |
| Format | Executable file (shell, TypeScript, Python, etc.) |
| Permissions | Must be executable ( |
| Shebang | Required ( |
| Input | JSON via stdin |
| Output | Text via stdout (shown to user) |
| Exit Codes | |
| Event | When It Fires | Common Use Cases |
|---|---|---|
| New session begins | Environment setup, logging, checks |
| Before user input processes | Validation, enhancement, filtering |
| Before tool execution | Permission checks, logging, modification |
| After assistant responds | Formatting, logging, cleanup |
.claude/hooks/session-start
.claude/hooks/user-prompt-submit~/.claude/hooks/session-start
~/.claude/hooks/tool-call#!/bin/bash
# or
#!/usr/bin/env node
# or
#!/usr/bin/env python3chmod +x .claude/hooks/session-start#!/bin/bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')exit 0 # Success
exit 2 # Block operation
exit 1 # Error (logs but continues){
"event": "tool-call",
"timestamp": "2025-01-15T10:30:00Z",
"session_id": "abc123",
"current_dir": "/path/to/project",
"input": {
"file_path": "/path/to/file.ts",
"command": "npm test",
"old_string": "...",
"new_string": "..."
}
}>&2| Code | Meaning | Behavior |
|---|---|---|
| Success | Continue normally |
| Block | Stop operation, show error |
| Error | Log error, continue |
namedescriptioneventlanguagehookType: "hook"| Mistake | Problem | Solution |
|---|---|---|
| Not quoting variables | Breaks on spaces | Always use |
| Missing shebang | Won't execute | Add |
| Not executable | Permission denied | Run |
| Logging to stdout | Clutters transcript | Use stderr: |
| Wrong exit code | Doesn't block when needed | Use |
| No input validation | Security risk | Always validate JSON fields |
| Slow operations | Blocks Claude | Run in background or use PostToolUse |
| Absolute paths missing | Can't find scripts | Use |
#!/bin/bash
# .claude/hooks/session-start
# Log session start
echo "Session started at $(date)" >> ~/.claude/session.log
# Check environment
if ! command -v node &> /dev/null; then
echo "Warning: Node.js not installed" >&2
fi
# Output to user
echo "Development environment ready"
exit 0#!/usr/bin/env node
// .claude/hooks/user-prompt-submit
import { readFileSync } from 'fs';
// Read JSON from stdin
const input = readFileSync(0, 'utf-8');
const data = JSON.parse(input);
// Validate prompt
if (data.prompt.includes('API_KEY')) {
console.error('Warning: Prompt may contain secrets');
process.exit(2); // Block
}
console.log('Prompt validated');
process.exit(0);# Check dependencies exist
if ! command -v jq &> /dev/null; then
echo "jq not installed, skipping" >&2
exit 0
fi
# Validate input
FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')
if [[ -z "$FILE" ]]; then
echo "No file path provided" >&2
exit 1
fi#!/bin/bash
#!/usr/bin/env node
#!/usr/bin/env python3BLOCKED=(".env" ".env.*" "*.pem" "*.key")
for pattern in "${BLOCKED[@]}"; do
case "$FILE" in
$pattern)
echo "Blocked: $FILE is sensitive" >&2
exit 2
;;
esac
done# WRONG - breaks on spaces
prettier --write $FILE
# RIGHT - handles spaces
prettier --write "$FILE"LOG_FILE=~/.claude-hooks/debug.log
# Log to file
echo "[$(date)] Processing $FILE" >> "$LOG_FILE"
# Log to stderr (shows in transcript)
echo "Hook running..." >&2my-hook/
├── prpm.json # Package manifest
├── HOOK.md # Hook documentation
└── hook-script.sh # Hook executable{
"name": "@username/hook-name",
"version": "1.0.0",
"description": "Brief description shown in search",
"author": "Your Name",
"format": "claude",
"subtype": "hook",
"tags": ["automation", "security", "formatting"],
"main": "HOOK.md"
}---
name: session-logger
description: Logs session start/end times for tracking
event: SessionStart
language: bash
hookType: hook
---
# Session Logger Hook
Logs Claude Code session activity for tracking and debugging.
## Installation
This hook will be installed to `.claude/hooks/session-start`.
## Behavior
- Logs session start time to `~/.claude/session.log`
- Displays environment status
- Runs silent dependency checks
## Requirements
- bash 4.0+
- write access to `~/.claude/`
## Source Code
\`\`\`bash
#!/bin/bash
echo "Session started at $(date)" >> ~/.claude/session.log
echo "Environment ready"
exit 0
\`\`\`# Test locally first
prpm test
# Publish to registry
prpm publish
# Version bumps
prpm publish patch # 1.0.0 -> 1.0.1
prpm publish minor # 1.0.0 -> 1.1.0
prpm publish major # 1.0.0 -> 2.0.0# Parse JSON safely
INPUT=$(cat)
if ! FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty' 2>&1); then
echo "JSON parse failed" >&2
exit 1
fi
# Validate field exists
[[ -n "$FILE" ]] || exit 1# Prevent directory traversal
if [[ "$FILE" == *".."* ]]; then
echo "Path traversal detected" >&2
exit 2
fi
# Keep in project directory
if [[ "$FILE" != "$CLAUDE_PROJECT_DIR"* ]]; then
echo "File outside project" >&2
exit 2
fi| Feature | Hooks | Skills | Commands |
|---|---|---|---|
| Format | Executable code | Markdown | Markdown |
| Trigger | Automatic (events) | Automatic (context) | Manual ( |
| Language | Any executable | N/A | N/A |
| Use Case | Automation, validation | Reference, patterns | Quick tasks |
| Security | Requires confirmation | No special permissions | Inherits from session |
/review-prchmod +x