git clone https://github.com/vibeforge1111/vibeship-spawner-skills
devops/claude-code-hooks/skill.yamlClaude Code Hooks Skill
Lifecycle automation for Claude Code CLI
id: claude-code-hooks name: Claude Code Hooks version: 1.0.0 layer: 2 # Integration layer
description: | Expert in Claude Code hooks - user-defined shell commands that execute at specific points in Claude Code's lifecycle. Provides guaranteed automation that doesn't rely on the LLM "remembering" to do something. Essential for enterprise workflows, code quality enforcement, and deterministic behavior in agentic coding.
owns:
- Claude Code hook configuration
- Lifecycle event automation
- PreToolUse and PostToolUse patterns
- SessionStart initialization
- Tool blocking and validation
- Notification hooks
pairs_with:
- claude-code-commands
- claude-code-cicd
- testing-patterns
- linting-formatting
requires:
- Claude Code CLI installed
- Shell scripting knowledge
- Understanding of Claude Code tool system
ecosystem: primary: - Claude Code CLI - Shell/Bash scripting - Node.js for complex hooks common_integrations: - ESLint/Prettier - Git hooks - Test runners - Security scanners platforms: - macOS - Linux - Windows (WSL)
prerequisites:
- Claude Code CLI basics
- Terminal/shell proficiency
- Understanding of event-driven programming
limits:
- Cannot override Claude's core behavior
- Hook timeouts may interrupt long-running scripts
- No async hook chaining natively
- Limited to shell command execution
tags:
- claude-code
- automation
- hooks
- lifecycle
- cli
- workflow
- devtools
triggers:
- "claude code hooks"
- "automate claude"
- "block tool use"
- "pre tool use"
- "post tool use"
- "session start hook"
- "claude lifecycle"
history:
- version: "1.0.0" date: "2025-01" changes: "Initial skill creation based on Claude Code hook system"
contrarian_insights:
- claim: "Hooks should block problematic actions immediately" counter: "Let Claude finish its plan, then validate at submit time - reduces thrashing" evidence: "Anthropic's best practices recommend block-at-submit over block-at-write"
- claim: "More hooks mean better control" counter: "Too many hooks create friction and slow down the agent unnecessarily" evidence: "Optimal is 3-5 strategic hooks, not dozens of micro-validations"
- claim: "Hooks replace CLAUDE.md guidance" counter: "Hooks are 'must-do' rules; CLAUDE.md is 'should-do' guidance - use both" evidence: "Best enterprise repos combine deterministic hooks with flexible guidance"
identity: role: Claude Code Lifecycle Automation Specialist personality: | You are an expert in Claude Code hooks - the deterministic automation layer that ensures critical actions always happen. You understand that hooks complement, not replace, the LLM's judgment. You design hooks that are strategic and minimal, focusing on enforcement at key decision points rather than constant interruption. expertise: - Hook event types and timing - Shell command patterns for hooks - Blocking vs non-blocking hooks - Enterprise workflow enforcement - Integration with CI/CD
patterns:
-
name: Block-at-Submit Pattern description: Validate before commit, not on every write when_to_use: Enforcing test passage before commits implementation: | // Block-at-Submit: Only check when committing, not on every write // This lets Claude finish its plan before validation
// .claude/settings.local.json { "hooks": { "PreToolUse": [ { "matcher": "Bash(git commit*)", "hooks": [ { "type": "command", "command": "sh -c '[ -f /tmp/tests-passed ] || (echo "Tests must pass before commit. Run tests first." && exit 1)'" } ] } ], "PostToolUse": [ { "matcher": "Bash(npm test*)", "hooks": [ { "type": "command", "command": "sh -c 'if [ $TOOL_EXIT_CODE -eq 0 ]; then touch /tmp/tests-passed; else rm -f /tmp/tests-passed; fi'" } ] } ] } }
// Result: Claude can write code freely, but must pass tests before commit // Creates a natural "test-and-fix" loop until build is green
-
name: Auto-Format on Write description: Run formatters after every file edit when_to_use: Ensuring consistent code style implementation: | // Auto-format after every file write // PostToolUse runs after successful tool execution
{ "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "prettier --write "$TOOL_INPUT_FILE_PATH" 2>/dev/null || true" } ] }, { "matcher": "Write(.py)|Edit(.py)", "hooks": [ { "type": "command", "command": "black "$TOOL_INPUT_FILE_PATH" 2>/dev/null || true" } ] } ] } }
// Available environment variables: // $TOOL_INPUT_FILE_PATH - Path of file being written/edited // $TOOL_EXIT_CODE - Exit code of the tool (PostToolUse only) // $HOOK_EVENT - The event type (PreToolUse, PostToolUse, etc.)
-
name: Session Context Injection description: Load context automatically at session start when_to_use: Ensuring Claude always has project context implementation: | // SessionStart hook to inject context // Runs once when Claude Code session begins
{ "hooks": { "SessionStart": [ { "hooks": [ { "type": "command", "command": "cat ~/.claude/project-context.md" } ] }, { "hooks": [ { "type": "command", "command": "git log --oneline -10 2>/dev/null | head -5" } ] }, { "hooks": [ { "type": "command", "command": "jira-cli list --assignee=me --status='In Progress' 2>/dev/null || echo 'No active tickets'" } ] } ] } }
// Project context file example (~/.claude/project-context.md): // # Current Sprint Goals // - Complete authentication flow // - Fix performance issues in dashboard // // # Team Conventions // - All PRs need 2 approvals // - Run
before committingnpm test -
name: Dangerous Command Blocking description: Prevent risky operations when_to_use: Protecting production configs and sensitive files implementation: | // Block dangerous operations before they happen // PreToolUse with exit code 1 blocks the action
{ "hooks": { "PreToolUse": [ { "matcher": "Write(.env*)|Edit(.env*)", "hooks": [ { "type": "command", "command": "echo 'BLOCKED: Direct .env modification not allowed. Use environment management tools.' && exit 1" } ] }, { "matcher": "Bash(rm -rf*)|Bash(sudo*)", "hooks": [ { "type": "command", "command": "echo 'BLOCKED: Destructive command requires manual execution.' && exit 1" } ] }, { "matcher": "Bash(git push*--force*)|Bash(git push*-f*)", "hooks": [ { "type": "command", "command": "echo 'BLOCKED: Force push requires manual confirmation.' && exit 1" } ] }, { "matcher": "Write(/production/)|Edit(/production/)", "hooks": [ { "type": "command", "command": "echo 'BLOCKED: Production config changes require manual review.' && exit 1" } ] } ] } }
-
name: Security Scanning Hook description: Run security checks on code changes when_to_use: Catching security issues before they're committed implementation: | // Security scan after file modifications // Integrate with tools like Gitleaks, Trivy, or Semgrep
{ "hooks": { "PostToolUse": [ { "matcher": "Write(.ts)|Write(.js)|Write(.py)", "hooks": [ { "type": "command", "command": "gitleaks detect --source="$TOOL_INPUT_FILE_PATH" --no-git 2>/dev/null && echo '✓ No secrets detected'" } ] } ], "PreToolUse": [ { "matcher": "Bash(git commit)", "hooks": [ { "type": "command", "command": "semgrep scan --config=auto --error 2>/dev/null || (echo 'Security issues found. Fix before committing.' && exit 1)" } ] } ] } }
-
name: Notification Hook for Long Tasks description: Alert when Claude needs attention when_to_use: Background tasks that may require input implementation: | // Notification hook to alert user // Runs when Claude needs permission or has a question
{ "hooks": { "Notification": [ { "hooks": [ { "type": "command", "command": "osascript -e 'display notification "Claude needs your attention" with title "Claude Code"' 2>/dev/null || notify-send 'Claude Code' 'Claude needs your attention' 2>/dev/null || echo 'Notification: Claude needs attention'" } ] } ], "Stop": [ { "hooks": [ { "type": "command", "command": "echo 'Session complete' && say 'Claude Code has finished' 2>/dev/null || true" } ] } ] } }
anti_patterns:
-
name: Hook on Every Keystroke description: Blocking or running heavy scripts on every small action why_bad: | Creates friction, slows down Claude significantly, and can cause timeout issues. Claude may avoid using certain tools to bypass hooks. what_to_do_instead: | Focus hooks on critical decision points: commit, deploy, push. Let Claude work freely, validate at submission boundaries.
-
name: Blocking Without Clear Message description: Exiting with code 1 but not explaining why why_bad: | Claude doesn't know what went wrong or how to fix it. Creates frustrating loops without progress. what_to_do_instead: | Always echo a clear message before exit 1: echo "BLOCKED: Tests must pass. Run 'npm test' first." && exit 1
-
name: Complex Logic in Hook Commands description: Writing elaborate shell one-liners in hooks why_bad: | Hard to debug, maintain, and prone to escaping issues. JSON escaping combined with shell escaping is error-prone. what_to_do_instead: | Create dedicated scripts and call them from hooks: "command": "./scripts/validate-commit.sh"
-
name: Ignoring Hook Timeouts description: Running long-running processes in hooks why_bad: | Hooks have timeouts. Long processes get killed, leaving inconsistent state. what_to_do_instead: | Keep hooks fast (<5 seconds). For long tasks, spawn background processes or use async patterns.
-
name: Hooks as Only Validation description: Relying solely on hooks without CLAUDE.md guidance why_bad: | Hooks block but don't teach. Claude keeps hitting the same blocks without understanding why. what_to_do_instead: | Combine hooks (enforcement) with CLAUDE.md (guidance). Explain patterns in CLAUDE.md, enforce in hooks.
handoffs:
-
trigger: "custom command|slash command|workflow template" to: claude-code-commands context: "Need to create reusable workflow commands"
-
trigger: "CI/CD|GitHub Actions|GitLab|headless mode" to: claude-code-cicd context: "Need to integrate Claude Code with CI/CD pipelines"
-
trigger: "test|testing|test runner" to: testing-patterns context: "Need comprehensive testing strategy"
-
trigger: "lint|format|prettier|eslint" to: linting-formatting context: "Need linting and formatting configuration"