creating-claude-hooks

Creating Claude Code Hooks

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "creating-claude-hooks" with this command: npx skills add pr-pm/prpm/pr-pm-prpm-creating-claude-hooks

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:

  • Have a shebang line:

#!/bin/bash

or

#!/usr/bin/env node

or

#!/usr/bin/env python3

  • Be executable:

chmod +x .claude/hooks/session-start

  • Handle JSON input from stdin:

#!/bin/bash INPUT=$(cat) FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')

  • 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

  1. Handle Errors Gracefully

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

  1. Use Shebangs

Always start with shebang:

#!/bin/bash #!/usr/bin/env node #!/usr/bin/env python3

  1. Secure Sensitive Files

BLOCKED=(".env" ".env." ".pem" "*.key") for pattern in "${BLOCKED[@]}"; do case "$FILE" in $pattern) echo "Blocked: $FILE is sensitive" >&2 exit 2 ;; esac done

  1. Quote All Variables

WRONG - breaks on spaces

prettier --write $FILE

RIGHT - handles spaces

prettier --write "$FILE"

  1. Log for Debugging

LOG_FILE=~/.claude-hooks/debug.log

Log to file

echo "[$(date)] Processing $FILE" >> "$LOG_FILE"

Log to stderr (shows in transcript)

echo "Hook running..." >&2

Publishing as PRPM Package

Package Structure

my-hook/ ├── prpm.json # Package manifest ├── HOOK.md # Hook documentation └── hook-script.sh # Hook executable

prpm.json

{ "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" }

HOOK.md Format


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 ```

Publishing Process

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

Security Requirements

Input Validation

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

Path Sanitization

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

User Confirmation

Claude Code automatically:

  • Requires confirmation before installing hooks

  • Shows hook source code to user

  • Warns about hook execution

  • Displays hook output in transcript

Hooks vs Skills vs Commands

Feature Hooks Skills Commands

Format Executable code Markdown Markdown

Trigger Automatic (events) Automatic (context) Manual (/command )

Language Any executable N/A N/A

Use Case Automation, validation Reference, patterns Quick tasks

Security Requires confirmation No special permissions Inherits from session

Examples:

  • Hook: Auto-format files on save

  • Skill: Reference guide for testing patterns

  • Command: /review-pr quick code review

Related Resources

  • claude-hook-writer skill - Detailed hook development guidance

  • typescript-hook-writer skill - TypeScript-specific hook development

  • Claude Code Docs

  • Schema

Checklist for New Hooks

Before publishing:

  • Shebang line included

  • File is executable (chmod +x )

  • Validates all stdin input

  • Quotes all variables

  • Handles missing dependencies gracefully

  • Uses appropriate exit codes

  • Logs errors to stderr or file

  • Tests with edge cases (spaces, Unicode, missing fields)

  • Documents dependencies in HOOK.md

  • Includes installation instructions

  • Source code included in documentation

  • Clear description and tags in prpm.json

  • Version number is semantic

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

creating-opencode-agents

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

creating-opencode-plugins

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

typescript-type-safety

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

github-actions-testing

No summary provided by upstream source.

Repository SourceNeeds Review