/creating-claude-hooks-skill
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 -y skills add AgentWorkforce/relay --skill creating-claude-hooks-skill --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/creating-claude-hooks-skill
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when creating or publishing Claude Code hooks - covers executable format, event types, JSON I/O, exit codes, security requirements, and PRPM package structure
SKILL.md
creating-claude-hooks-skill.SKILL.mdname: creating-claude-hooks
description: Use when creating or publishing Claude Code hooks - covers executable format, event types, JSON I/O, exit codes, security requirements, and PRPM package structure
skillType: skill
allowed-tools: Read, Write, Edit, Grep, Glob, Bash
Creating Claude Code Hooks
Use this skill when creating, improving, or publishing Claude Code hooks. Provides essential guidance on hook format, event handling, I/O conventions, and package structure.
When to Use This Skill
Activate this skill when:
- User asks to create a new Claude Code hook
- User wants to publish a hook as a PRPM package
- User needs to understand hook format or events
- User is troubleshooting hook execution
- User asks about hook vs skill vs command differences
Quick Reference
Hook File Format
| Aspect | Requirement | | --------------- | ------------------------------------------------- | | **Location** | `.claude/hooks/<event-name>` | | **Format** | Executable file (shell, TypeScript, Python, etc.) | | **Permissions** | Must be executable (`chmod +x`) | | **Shebang** | Required (`#!/bin/bash` or `#!/usr/bin/env node`) | | **Input** | JSON via stdin | | **Output** | Text via stdout (shown to user) | | **Exit Codes** | `0` = success, `2` = block, other = error |
Available Events
| Event | When It Fires | Common Use Cases | | -------------------- | --------------------------- | ---------------------------------------- | | `session-start` | New session begins | Environment setup, logging, checks | | `user-prompt-submit` | Before user input processes | Validation, enhancement, filtering | | `tool-call` | Before tool execution | Permission checks, logging, modification | | `assistant-response` | After assistant responds | Formatting, logging, cleanup |
Hook Format Requirements
File Location
**Project hooks:**
.claude/hooks/session-start
.claude/hooks/user-prompt-submit
**User-global hooks:**
~/.claude/hooks/session-start
~/.claude/hooks/tool-call
Executable Requirements
Every hook MUST:
1. **Have a shebang line:**
#!/bin/bash
# or
#!/usr/bin/env node
# or
#!/usr/bin/env python3
2. **Be executable:**
chmod +x .claude/hooks/session-start
3. **Handle JSON input from stdin:**
#!/bin/bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')
4. **Exit with appropriate code:**
exit 0 # Success
exit 2 # Block operation
exit 1 # Error (logs but continues)
Input/Output Format
JSON Input Structure
Hooks receive JSON via stdin with event-specific data:
{
"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": "..."
}
}Stdout Output
- Normal output shows in transcript
- Empty output runs silently
- Use stderr (`>&2`) for errors
Exit Codes
| Code | Meaning | Behavior | | ------------ | ------- | -------------------------- | | `0` | Success | Continue normally | | `2` | Block | Stop operation, show error | | `1` or other | Error | Log error, continue |
Schema Validation
Hooks should validate against the JSON schema:
**Schema URL:** https://github.com/pr-pm/prpm/blob/main/packages/converters/schemas/claude-hook.schema.json
**Required frontmatter fields:**
- `name` - Hook identifier (lowercase, hyphens only)
- `description` - What the hook does
- `event` - Event type (optional, inferred from filename)
- `language` - bash, typescript, javascript, python, binary (optional)
- `hookType: "hook"` - For round-trip conversion
Common Mistakes
| Mistake | Problem | Solution | | ---------------------- | ------------------------- | ------------------------------------ | | Not quoting variables | Breaks on spaces | Always use `"$VAR"` | | Missing shebang | Won't execute | Add `#!/bin/bash` | | Not executable | Permission denied | Run `chmod +x hook-file` | | Logging to stdout | Clutters transcript | Use stderr: `echo "log" >&2` | | Wrong exit code | Doesn't block when needed | Use `exit 2` to block | | 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 `$CLAUDE_PLUGIN_ROOT` |
Basic Hook Examples
Shell Script Hook
#!/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
TypeScript Hook
#!/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);Best Practices
1. Keep Hooks Fast
Target < 100ms for PreToolUse hooks:
- Cache results where possible
- Run heavy operations in background
- Use specific matchers, not wildcards
Read more
name: creating-claude-hooks description: Use when creating or publishing Claude Code hooks - covers executable format, event types, JSON I/O, exit codes, security requirements, and PRPM package structure skillType: skill allowed-tools: Read, Write, Edit, Grep, Glob, Bash
Creating Claude Code Hooks
Use this skill when creating, improving, or publishing Claude Code hooks. Provides essential guidance on hook format, event handling, I/O conventions, and package structure.
When to Use This Skill
Activate this skill when:
- User asks to create a new Claude Code hook
- User wants to publish a hook as a PRPM package
- User needs to understand hook format or events
- User is troubleshooting hook execution
- User asks about hook vs skill vs command differences
Quick Reference
Hook File Format
| Aspect | Requirement | | --------------- | ------------------------------------------------- | | **Location** | `.claude/hooks/<event-name>` | | **Format** | Executable file (shell, TypeScript, Python, etc.) | | **Permissions** | Must be executable (`chmod +x`) | | **Shebang** | Required (`#!/bin/bash` or `#!/usr/bin/env node`) | | **Input** | JSON via stdin | | **Output** | Text via stdout (shown to user) | | **Exit Codes** | `0` = success, `2` = block, other = error |
Available Events
| Event | When It Fires | Common Use Cases | | -------------------- | --------------------------- | ---------------------------------------- | | `session-start` | New session begins | Environment setup, logging, checks | | `user-prompt-submit` | Before user input processes | Validation, enhancement, filtering | | `tool-call` | Before tool execution | Permission checks, logging, modification | | `assistant-response` | After assistant responds | Formatting, logging, cleanup |
Hook Format Requirements
File Location
**Project hooks:**
.claude/hooks/session-start .claude/hooks/user-prompt-submit
**User-global hooks:**
~/.claude/hooks/session-start ~/.claude/hooks/tool-call
Executable Requirements
Every hook MUST:
1. **Have a shebang line:**
#!/bin/bash # or #!/usr/bin/env node # or #!/usr/bin/env python3
2. **Be executable:**
chmod +x .claude/hooks/session-start
3. **Handle JSON input from stdin:**
#!/bin/bash INPUT=$(cat) FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')
4. **Exit with appropriate code:**
exit 0 # Success exit 2 # Block operation exit 1 # Error (logs but continues)
Input/Output Format
JSON Input Structure
Hooks receive JSON via stdin with event-specific data:
{
"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": "..."
}
}Stdout Output
- Normal output shows in transcript
- Empty output runs silently
- Use stderr (`>&2`) for errors
Exit Codes
| Code | Meaning | Behavior | | ------------ | ------- | -------------------------- | | `0` | Success | Continue normally | | `2` | Block | Stop operation, show error | | `1` or other | Error | Log error, continue |
Schema Validation
Hooks should validate against the JSON schema:
**Schema URL:** https://github.com/pr-pm/prpm/blob/main/packages/converters/schemas/claude-hook.schema.json
**Required frontmatter fields:**
- `name` - Hook identifier (lowercase, hyphens only)
- `description` - What the hook does
- `event` - Event type (optional, inferred from filename)
- `language` - bash, typescript, javascript, python, binary (optional)
- `hookType: "hook"` - For round-trip conversion
Common Mistakes
| Mistake | Problem | Solution | | ---------------------- | ------------------------- | ------------------------------------ | | Not quoting variables | Breaks on spaces | Always use `"$VAR"` | | Missing shebang | Won't execute | Add `#!/bin/bash` | | Not executable | Permission denied | Run `chmod +x hook-file` | | Logging to stdout | Clutters transcript | Use stderr: `echo "log" >&2` | | Wrong exit code | Doesn't block when needed | Use `exit 2` to block | | 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 `$CLAUDE_PLUGIN_ROOT` |
Basic Hook Examples
Shell Script Hook
#!/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
TypeScript Hook
#!/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);Best Practices
1. Keep Hooks Fast
Target < 100ms for PreToolUse hooks:
- Cache results where possible
- Run heavy operations in background
- Use specific matchers, not wildcards
Let Claude Code message Codex. Let your Hyperagent talk to your Hermes agent. Give your custom agents a way to message each other.
Repo: AgentWorkforce/relay
Other skills on relay.
- /browser-testing-with-screenshots
Use when testing web applications with visual verification - automates Chrome browser interactions, element selection, and screenshot capture for confirming UI functionality
Open skill - /choosing-swarm-patterns
Use when coordinating multiple AI agents with Agent Relay's workflow engine and need to pick the right orchestration pattern - covers the 10 core patterns (fan-out, pipeline, hub-spoke, consensus, mesh, handoff, cascade, dag, debate, hierarchical) plus 14 specialized ones, with
Open skill - /creating-claude-agents-skill
Use when creating or improving Claude Code agents. Expert guidance on agent file structure, frontmatter, persona definition, tool access, model selection, and validation against schema.
Open skill - /creating-claude-rules-skill
Use when creating or fixing .claude/rules/ files - provides correct paths frontmatter (not globs), glob patterns, and avoids Cursor-specific fields like alwaysApply
Open skill - /creating-skills-skill
Use when creating new Claude Code skills or improving existing ones - ensures skills are discoverable, scannable, and effective through proper structure, CSO optimization, and real examples
Open skill - /debugging-websocket-issues
Use when seeing WebSocket errors like "Invalid frame header", "RSV1 must be clear", or "WS_ERR_UNEXPECTED_RSV_1" - covers multiple WebSocketServer conflicts, compression issues, and raw frame debugging techniques
Open skill

