Skip to main content

Hooks Framework

The hooks framework allows you to execute custom shell commands in response to specific events during Claude Code's operation, enabling powerful workflow automation and integrations.

Overview

Hooks are user-defined shell commands that trigger automatically when specific events occur. They enable:

  • Workflow Automation: Automate repetitive tasks
  • External Integrations: Connect with other tools and services
  • Custom Notifications: Get notified about important events
  • Quality Gates: Enforce standards before actions complete

Hook Types

Lifecycle Hooks

Execute during major workflow events:

{
"hooks": {
"session-start": "echo 'Session started at $(date)'",
"session-end": "cleanup.sh",
"project-init": "setup-project-environment.sh",
"git-commit": "run-pre-commit-checks.sh"
}
}

Tool Hooks

Execute before/after specific tool usage:

{
"hooks": {
"pre-tool-call": "log-tool-usage.sh '$TOOL_NAME'",
"post-tool-call": "validate-tool-result.sh",
"tool-error": "notify-team.sh 'Tool error: $ERROR'"
}
}

File Hooks

Trigger on file system operations:

{
"hooks": {
"file-create": "index-new-file.sh '$FILE_PATH'",
"file-edit": "backup-file.sh '$FILE_PATH'",
"file-delete": "archive-deleted-file.sh '$FILE_PATH'"
}
}

Configuration

Global Hooks

Configure in ~/.claude/config.json:

{
"hooks": {
"session-start": [
"echo 'Welcome back!'",
"git status --porcelain | wc -l | xargs echo 'Changed files:'"
],
"git-commit": [
"npm run lint",
"npm run test",
"npm run build"
]
}
}

Project-Specific Hooks

Configure in .claude/config.json:

{
"hooks": {
"file-edit": "./scripts/format-on-save.sh",
"git-commit": "./scripts/pre-commit.sh",
"deployment": [
"./scripts/run-tests.sh",
"./scripts/security-scan.sh",
"./scripts/deploy.sh"
]
}
}

Hook Environment

Available Variables

Hooks have access to environment variables:

  • $CLAUDE_PROJECT_PATH: Current project directory
  • $CLAUDE_SESSION_ID: Unique session identifier
  • $TOOL_NAME: Name of the tool being executed
  • $FILE_PATH: Path of file being operated on
  • $USER_MESSAGE: Latest user message
  • $ERROR: Error message (for error hooks)

Custom Variables

{
"hooks": {
"git-commit": {
"command": "deploy.sh",
"env": {
"DEPLOY_ENV": "staging",
"SLACK_WEBHOOK": "$SLACK_URL",
"BUILD_NUMBER": "$(git rev-parse --short HEAD)"
}
}
}
}

Hook Examples

Development Workflow

#!/bin/bash
# scripts/dev-workflow.sh

echo "🚀 Starting development workflow..."

# Format code
npm run format

# Run linting
if ! npm run lint; then
echo "❌ Linting failed"
exit 1
fi

# Run tests
if ! npm run test; then
echo "❌ Tests failed"
exit 1
fi

echo "✅ Code ready for commit"

Deployment Automation

#!/bin/bash
# scripts/deploy.sh

ENV=${1:-staging}
echo "🚀 Deploying to $ENV..."

# Build application
npm run build

# Run security scan
npm audit --audit-level high

# Deploy to environment
case $ENV in
staging)
docker build -t myapp:staging .
docker push registry.com/myapp:staging
kubectl set image deployment/myapp myapp=registry.com/myapp:staging
;;
production)
# Additional production checks
npm run test:e2e
docker build -t myapp:prod .
docker push registry.com/myapp:prod
kubectl set image deployment/myapp myapp=registry.com/myapp:prod
;;
esac

echo "✅ Deployed to $ENV"

Notification System

#!/bin/bash
# scripts/notify.sh

MESSAGE="$1"
SEVERITY="${2:-info}"

# Slack notification
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"[$SEVERITY] $MESSAGE\"}" \
$SLACK_WEBHOOK

# Email notification for errors
if [ "$SEVERITY" = "error" ]; then
echo "$MESSAGE" | mail -s "Claude Code Error" admin@company.com
fi

# Log to file
echo "$(date): [$SEVERITY] $MESSAGE" >> ~/.claude/hooks.log

Advanced Hook Patterns

Conditional Execution

{
"hooks": {
"git-commit": {
"command": "if git diff --name-only | grep -q '\\.ts$'; then npm run typecheck; fi",
"description": "Run TypeScript checks only if TS files changed"
}
}
}

Parallel Execution

{
"hooks": {
"pre-deployment": [
{
"command": "npm run test",
"parallel": true
},
{
"command": "npm run lint",
"parallel": true
},
{
"command": "npm run security-scan",
"parallel": true
}
]
}
}

Error Handling

{
"hooks": {
"deployment": {
"command": "deploy.sh",
"on_error": "rollback.sh",
"retry": 3,
"timeout": 300000
}
}
}

Hook Debugging

Enable Debug Mode

# Enable hook debugging
export CLAUDE_HOOKS_DEBUG=true

# Verbose hook output
export CLAUDE_HOOKS_VERBOSE=true

Hook Logs

# View hook execution logs
claude-code hooks logs

# Real-time hook monitoring
claude-code hooks logs --follow

# Hook performance metrics
claude-code hooks stats

Testing Hooks

# Test hook manually
claude-code hooks test session-start

# Validate hook configuration
claude-code hooks validate

# Dry run mode
claude-code hooks --dry-run

Security Considerations

Safe Scripting

#!/bin/bash
# Use strict mode
set -euo pipefail

# Validate inputs
if [[ ! "$FILE_PATH" =~ ^/safe/path/ ]]; then
echo "Error: Invalid file path"
exit 1
fi

# Sanitize variables
SAFE_NAME=$(echo "$FILE_NAME" | tr -cd '[:alnum:]._-')

Permission Management

{
"hooks": {
"sensitive-operation": {
"command": "secure-script.sh",
"require_confirmation": true,
"allowed_users": ["admin", "devops"],
"allowed_projects": ["/work/project1", "/work/project2"]
}
}
}

Hook Performance

Optimization Tips

  1. Minimize Hook Execution Time: Keep hooks fast to avoid blocking
  2. Background Processes: Use & for non-blocking operations
  3. Caching: Cache expensive computations
  4. Early Exit: Exit early when conditions aren't met
#!/bin/bash
# Optimized hook example

# Early exit if not applicable
[[ "$FILE_PATH" == *.ts ]] || exit 0

# Background processing
heavy-analysis.sh "$FILE_PATH" &

# Quick validation
quick-check.sh "$FILE_PATH"

Performance Monitoring

{
"hooks": {
"performance": {
"max_execution_time": 30000,
"memory_limit": "256MB",
"monitoring": true
}
}
}

Integration Examples

CI/CD Integration

#!/bin/bash
# hooks/ci-integration.sh

# Trigger CI pipeline
curl -X POST \
-H "Authorization: Bearer $CI_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"branch\":\"$(git branch --show-current)\"}" \
https://ci.company.com/api/pipelines/trigger

Team Notifications

#!/bin/bash
# hooks/team-notify.sh

BRANCH=$(git branch --show-current)
AUTHOR=$(git config user.name)

# Notify team of deployment
slack-send "#dev-team" "🚀 $AUTHOR deployed $BRANCH to staging"

# Update project dashboard
curl -X POST dashboard.company.com/api/deployments \
-d "{\"branch\":\"$BRANCH\",\"author\":\"$AUTHOR\",\"env\":\"staging\"}"

Quality Gates

#!/bin/bash
# hooks/quality-gate.sh

echo "🔍 Running quality checks..."

# Code coverage check
COVERAGE=$(npm run test:coverage | grep "All files" | awk '{print $10}' | sed 's/%//')
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
echo "❌ Coverage too low: $COVERAGE%"
exit 1
fi

# Security scan
if ! npm audit --audit-level high; then
echo "❌ Security vulnerabilities found"
exit 1
fi

# Performance check
if ! npm run test:performance; then
echo "❌ Performance tests failed"
exit 1
fi

echo "✅ All quality checks passed"

Next Steps