hook-authoring
Writing and modifying Claude Code hooks. Auto-applies when editing files in hooks/, creating new hooks, or debugging hook behavior.
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Hook Authoring Patterns
This skill auto-applies when you're working with Claude Code hooks. Follow these patterns for consistent, reliable hooks.
Hook Lifecycle
Session Start
│
├── SessionStart hook
│
▼
┌─────────────────────────────────┐
│ User sends prompt │
│ │ │
│ ├── UserPromptSubmit hooks │
│ ▼ │
│ Claude processes... │
│ │ │
│ ├── Stop hook │
│ ▼ │
│ (repeat) │
└─────────────────────────────────┘
│
├── PreCompact hook
│
▼
Session End
│
└── SessionEnd hook
Required Patterns
1. Script Header
Always start with:
#!/bin/bash
set -euo pipefail
2. Consume stdin
Critical: All hooks MUST consume stdin to avoid broken pipe errors:
# Read stdin (required even if not used)
input=$(cat)
# Or if you need the JSON:
input=$(cat)
session_id=$(echo "$input" | jq -r '.session_id // empty')
3. Graceful Degradation
Hooks should work even when dependencies are missing:
# Check for jq
if ! command -v jq &>/dev/null; then
exit 0 # Silent exit, don't break Claude
fi
# Check for agent-event-bus-cli
if ! command -v agent-event-bus-cli &>/dev/null; then
cli_path="$HOME/.local/bin/agent-event-bus-cli"
[[ -x "$cli_path" ]] || exit 0
fi
# Check for tmux
if [[ -z "${TMUX:-}" ]]; then
exit 0 # Not in tmux, skip tmux operations
fi
4. Exit Codes
-
exit 0- Success (normal completion) - Non-zero exits don't block Claude but may show error messages
- Prefer silent
exit 0for graceful degradation
Input JSON Format
All hooks receive JSON on stdin:
{
"session_id": "uuid",
"transcript_path": "/path/to/transcript.jsonl",
"cwd": "/current/working/directory"
}
Additional fields by trigger:
-
SessionStart:
permission_mode,source("user" or "resume") -
SessionEnd:
permission_mode,reason -
PreCompact:
trigger
Output Patterns
Structured Data
Use XML tags for data Claude should parse:
echo "<recent-events>"
echo "$events"
echo "</recent-events>"
Status Messages
Simple text output works:
echo "Hook completed successfully"
Silent Hooks
For hooks that only have side effects (like tmux renaming):
# No output needed - tmux commands are the action
tmux rename-window "name"
Tmux Integration
When modifying tmux state:
# Check if in tmux first
[[ -z "${TMUX:-}" ]] && exit 0
# Disable automatic rename before setting custom name
tmux set-window-option -q allow-rename off
tmux set-window-option -q automatic-rename off
# Now set custom name
tmux rename-window "$window_name"
For worktree paths, show repo (branch) format:
if [[ "$cwd" == */.worktrees/* ]]; then
repo=$(basename "$(dirname "$(dirname "$cwd")")")
branch=$(basename "$cwd")
window_name="$repo ($branch)"
fi
Event Bus Integration
For hooks that interact with the event bus:
# Find CLI
if command -v agent-event-bus-cli &>/dev/null; then
cli="agent-event-bus-cli"
elif [[ -x "$HOME/.local/bin/agent-event-bus-cli" ]]; then
cli="$HOME/.local/bin/agent-event-bus-cli"
else
exit 0
fi
# Register session
"$cli" register --name "$session_name" --client-id "$session_id"
# Publish events
"$cli" publish --type "event_type" --payload "message" --session-id "$session_id"
# Get events with resume (incremental)
"$cli" events --resume --session-id "$session_id"
Testing
Run make test-hooks to test all hooks. Tests verify:
- Script syntax is valid
- Scripts are executable
- Graceful degradation works (missing deps don't crash)
Add new test cases in tests/test-hooks.sh.
Configuration
Register hooks in settings.json:
{
"hooks": {
"SessionStart": [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/your-hook.sh" }] }]
}
}
Available triggers:
-
SessionStart- Session begins -
SessionEnd- Session ends -
UserPromptSubmit- User sends message -
Stop- Claude finishes response -
PreCompact- Before context summarization
Reference
See existing hooks in home/.claude/hooks/ for examples:
-
session-start.sh- Event bus registration, tmux setup -
session-end.sh- Cleanup -
prompt-events.sh- Incremental event polling -
tmux-status.sh- Visual state indicator -
pre-compact.sh- WIP checkpointing
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!