hook-development
Implementing event hooks for PreToolUse, PostToolUse, SessionStart, and other events
What this skill does
# Hook Development Skill
Guide to creating event-driven hooks for Claude Code plugins.
## When to Use
Activate when:
- Creating event hooks
- User asks about automation
- Implementing validation logic
- Questions about hook events
## What Are Hooks?
Hooks are **executable scripts** that respond to events:
- PreToolUse - Before any tool execution
- PostToolUse - After tool execution
- SessionStart - Session initialization
- SessionEnd - Session cleanup
- Stop - Before session ends
- SubagentStop - When agent completes
- UserPromptSubmit - After user input
- PreCompact - Before context compression
- Notification - System notifications
**When to use hooks**:
- Automatic validation before actions
- Event-driven automation
- Logging and auditing
- Safety checks and enforcement
**When NOT to use hooks**:
- User-invoked actions → Use Commands
- Guidance and workflows → Use Skills
- Focused analysis → Use Agents
## Hook Structure
### File Location
```
plugin-name/
└── hooks/
├── PreToolUse.sh
├── PostToolUse.sh
├── SessionStart.sh
└── Stop.sh
```
### Basic Hook Format
```bash
#!/bin/bash
# hooks/PreToolUse.sh
# Hook receives event data via environment variables
# Exit codes:
# 0 - Allow action to proceed
# 1 - Block action
# Output to stderr - shown to user
# Example: Block dangerous operations
if [[ "$TOOL_NAME" == "Bash" ]] && [[ "$COMMAND" == *"rm -rf"* ]]; then
echo "⛔ Dangerous command blocked: rm -rf" >&2
exit 1
fi
# Allow all other actions
exit 0
```
### Making Hooks Executable
**CRITICAL**: Hooks must be executable:
```bash
chmod +x hooks/PreToolUse.sh
chmod +x hooks/PostToolUse.sh
```
## Available Hooks
### PreToolUse
**Triggers**: Before any tool execution
**Use cases**:
- Validate tool arguments
- Block dangerous operations
- Enforce workflow rules
- Check prerequisites
**Environment variables**:
- `TOOL_NAME` - Tool being invoked (Bash, Read, Edit, etc.)
- `TOOL_ARGS` - Tool arguments (JSON)
- Additional tool-specific vars
**Example - Block destructive commands**:
```bash
#!/bin/bash
# hooks/PreToolUse.sh
if [[ "$TOOL_NAME" == "Bash" ]]; then
COMMAND=$(echo "$TOOL_ARGS" | jq -r '.command')
# Block force push to main
if [[ "$COMMAND" == *"git push"*"--force"* ]] && [[ "$COMMAND" == *"main"* ]]; then
echo "⛔ Force push to main blocked" >&2
echo "This is dangerous. Use a feature branch." >&2
exit 1
fi
fi
exit 0
```
### PostToolUse
**Triggers**: After tool execution
**Use cases**:
- Log operations
- Trigger follow-up actions
- Update external systems
- Collect metrics
**Environment variables**:
- `TOOL_NAME` - Tool that was executed
- `TOOL_RESULT` - Tool output
- `EXIT_CODE` - Tool exit code
**Example - Log all bash commands**:
```bash
#!/bin/bash
# hooks/PostToolUse.sh
if [[ "$TOOL_NAME" == "Bash" ]]; then
COMMAND=$(echo "$TOOL_ARGS" | jq -r '.command')
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "$TIMESTAMP | $COMMAND | Exit: $EXIT_CODE" >> ~/.claude/command.log
fi
exit 0
```
### SessionStart
**Triggers**: When Claude Code session begins
**Use cases**:
- Initialize environment
- Load configuration
- Check dependencies
- Set up workspace
**Example - Verify environment**:
```bash
#!/bin/bash
# hooks/SessionStart.sh
# Check required tools
MISSING=()
command -v git >/dev/null 2>&1 || MISSING+=("git")
command -v node >/dev/null 2>&1 || MISSING+=("node")
command -v jq >/dev/null 2>&1 || MISSING+=("jq")
if [ ${#MISSING[@]} -gt 0 ]; then
echo "⚠️ Missing tools: ${MISSING[*]}" >&2
echo "Some plugin features may not work." >&2
fi
# Load project config
if [ -f ".claude/config.json" ]; then
echo "✓ Loaded project configuration" >&2
fi
exit 0
```
### SessionEnd
**Triggers**: When session ends normally
**Use cases**:
- Cleanup temporary files
- Save session state
- Push uncommitted work
- Generate reports
**Example - Cleanup**:
```bash
#!/bin/bash
# hooks/SessionEnd.sh
# Clean up temp files
rm -rf /tmp/claude-session-*
# Save session summary
SUMMARY_FILE="$HOME/.claude/sessions/$(date +%Y%m%d-%H%M%S).log"
echo "Session ended at $(date)" > "$SUMMARY_FILE"
exit 0
```
### Stop
**Triggers**: Before session stops (user can cancel)
**Use cases**:
- Warn about uncommitted changes
- Prompt for cleanup
- Check for running processes
- Save work in progress
**Example - Check uncommitted changes**:
```bash
#!/bin/bash
# hooks/Stop.sh
# Check for uncommitted changes
if git rev-parse --git-dir > /dev/null 2>&1; then
if ! git diff-index --quiet HEAD --; then
echo "⚠️ You have uncommitted changes" >&2
echo "Consider committing or stashing before exiting." >&2
# Don't block, just warn
exit 0
fi
fi
exit 0
```
### SubagentStop
**Triggers**: When a spawned agent completes
**Use cases**:
- Process agent results
- Trigger next step in workflow
- Log agent completion
- Update task status
**Environment variables**:
- `AGENT_NAME` - Agent that completed
- `AGENT_RESULT` - Agent output
- `AGENT_STATUS` - Success/failure
**Example - Log agent completion**:
```bash
#!/bin/bash
# hooks/SubagentStop.sh
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "$TIMESTAMP | Agent: $AGENT_NAME | Status: $AGENT_STATUS" >> ~/.claude/agents.log
exit 0
```
### UserPromptSubmit
**Triggers**: After user submits a prompt
**Use cases**:
- Track user requests
- Analyze patterns
- Trigger automations
- Log interactions
**Environment variables**:
- `USER_PROMPT` - The user's input
**Example - Track prompts**:
```bash
#!/bin/bash
# hooks/UserPromptSubmit.sh
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "$TIMESTAMP | $USER_PROMPT" >> ~/.claude/prompts.log
exit 0
```
### PreCompact
**Triggers**: Before context window compression
**Use cases**:
- Save context snapshot
- Export important data
- Preserve state
- Generate checkpoint
**Example - Save context snapshot**:
```bash
#!/bin/bash
# hooks/PreCompact.sh
SNAPSHOT_DIR="$HOME/.claude/snapshots"
mkdir -p "$SNAPSHOT_DIR"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
SNAPSHOT_FILE="$SNAPSHOT_DIR/context-$TIMESTAMP.json"
# Save context metadata
cat > "$SNAPSHOT_FILE" <<EOF
{
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"working_directory": "$(pwd)",
"git_branch": "$(git branch --show-current 2>/dev/null || echo 'none')",
"git_commit": "$(git rev-parse HEAD 2>/dev/null || echo 'none')"
}
EOF
exit 0
```
### Notification
**Triggers**: System notifications
**Use cases**:
- Send alerts
- Update external systems
- Trigger integrations
- Custom notifications
**Example - Send notification**:
```bash
#!/bin/bash
# hooks/Notification.sh
# Forward to system notification
osascript -e "display notification \"$NOTIFICATION_MESSAGE\" with title \"Claude Code\""
exit 0
```
## Hook Patterns
### Validation Hook
**Purpose**: Enforce rules and prevent mistakes
```bash
#!/bin/bash
# hooks/PreToolUse.sh
# Enforce TDD: Block code changes without tests
if [[ "$TOOL_NAME" == "Edit" ]] || [[ "$TOOL_NAME" == "Write" ]]; then
FILE_PATH=$(echo "$TOOL_ARGS" | jq -r '.file_path')
# If editing source code
if [[ "$FILE_PATH" == *"/src/"* ]] && [[ "$FILE_PATH" != *".test."* ]]; then
# Check if corresponding test exists
TEST_FILE="${FILE_PATH/.ts/.test.ts}"
if [ ! -f "$TEST_FILE" ]; then
echo "⛔ TDD Violation" >&2
echo "No test file found for: $FILE_PATH" >&2
echo "Create test first: $TEST_FILE" >&2
exit 1
fi
fi
fi
exit 0
```
### Logging Hook
**Purpose**: Audit trail of operations
```bash
#!/bin/bash
# hooks/PostToolUse.sh
LOG_FILE="$HOME/.claude/audit.log"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Log all tool usage
echo "$TIMESTAMP | $TOOL_NAME | $TOOL_ARGS" >> "$LOG_FILE"
# Rotate log if too large
if [ -f "$LOG_FILE" ] && [ $(wc -l < "$LOG_FILE") -gt 10000 ]; then
mv "$LOG_FILE" "$LOG_FILE.old"
fi
exit 0
```
### Environment Setup Hook
**Purpose**: Prepare workspace
```bash
#!/bin/bash
# hooks/SessionStart.sh
# Load environment variables
if [ -f ".env" ]; then
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.