Hook Commands

Commands for running and managing hooks.

Commands for running validation hooks and managing hook execution.

han hook run

Run a validation hook from an installed plugin.

Usage

# New format: Run a plugin's hook
han hook run <plugin-name> <hook-name>

# With options
han hook run <plugin-name> <hook-name> --verbose

# Disable caching or fail-fast
han hook run <plugin-name> <hook-name> --no-cache --no-fail-fast

# Legacy format: Run custom command across directories
han hook run --dirs-with <file> -- <command>

Options

OptionDescription
--no-cacheDisable caching (caching is ON by default in v2.0.0+)
--no-fail-fastContinue on failures (fail-fast is ON by default in v2.0.0+)
--no-checkpointsDisable checkpoint filtering (checkpoints are ON by default)
--verboseShow full command output in real-time
--directory <path>Limit execution to specific directory
--checkpoint-type <type>Filter against checkpoint type (session or agent)
--checkpoint-id <id>Filter against specific checkpoint ID

Legacy options:

OptionDescription
--dirs-with <file>Only run in directories containing the specified file
--test-dir <command>Only include directories where this command exits 0

Breaking Change (v2.0.0): Caching and fail-fast are now enabled by default. Use --no-cache or --no-fail-fast to disable them.

Caching Behavior

Caching is enabled by default (since v2.0.0):

  1. Han creates a checkpoint with file modification times
  2. On subsequent runs, compares current file times to checkpoint
  3. Skips execution if no files have changed
  4. Clears checkpoint on failure (ensures retry on next run)

Checkpoints are session-scoped by default, meaning they're cleared when the Claude Code session ends. Use --no-checkpoints to disable checkpoint filtering entirely.

Examples

# Run Bun tests (caching enabled by default)
han hook run jutsu-bun test

# Run without caching
han hook run jutsu-bun test --no-cache

# Run TypeScript type checking verbosely
han hook run jutsu-typescript typecheck --verbose

# Run Biome lint in specific directory
han hook run jutsu-biome lint --directory packages/core

# Continue on failures instead of stopping
han hook run jutsu-playwright test --no-fail-fast

# Legacy: Run npm test in directories with package.json
han hook run --dirs-with package.json -- npm test

Plugin Hook Configuration

Hooks are defined in plugin han-plugin.yml files:

hooks:
  test:
    command: bun test --only-failures
    dirsWith: [bun.lock, bun.lockb]
    description: Run Bun tests
    ifChanged: ["**/*.ts", "**/*.test.ts"]

When you run han hook run jutsu-bun test, Han:

  1. Finds directories containing bun.lock or bun.lockb
  2. Checks if files matching **/*.ts or **/*.test.ts have changed (caching is enabled by default)
  3. Runs bun test --only-failures in each directory
  4. Records the result and updates checkpoints
  5. Stops on first failure (fail-fast is enabled by default)

han hook list

List available hooks from installed plugins.

Usage

# List all available hooks
han hook list

# Filter by plugin
han hook list --plugin jutsu-bun

# Show detailed information
han hook list --verbose

Options

OptionDescription
--plugin <name>Filter hooks by plugin name
--verboseShow detailed hook configuration
--jsonOutput as JSON for scripting

Output

Available Hooks:

  jutsu-bun:
    test - Run Bun tests
    build - Build the Bun project

  jutsu-typescript:
    typecheck - Type-check TypeScript code for type errors

  jutsu-biome:
    lint - Lint Biome code for issues and style violations

Examples

# List all hooks
han hook list

# List only Bun hooks
han hook list --plugin jutsu-bun

# Get JSON output for scripting
han hook list --json | jq '.[] | select(.plugin == "jutsu-bun")'

han hook explain

Show detailed explanation of a hook's configuration and behavior.

Usage

# Explain a specific hook
han hook explain <plugin-name> <hook-name>

Example

han hook run jutsu-bun test

Output:

Hook: jutsu-bun/test

Description: Run Bun tests

Command: bun test --only-failures

Directories: Runs in directories containing:
  - bun.lock
  - bun.lockb

File Patterns: Triggers when these files change:
  - **/*.ts
  - **/*.test.ts

Cache: Enabled by default (use --no-cache to disable)

Usage:
  han hook run jutsu-bun test
  han hook run jutsu-bun test --no-cache
  han hook run jutsu-bun test --verbose --directory packages/core

han hook verify

Verify hook configuration for all installed plugins.

Usage

# Verify all plugin hooks
han hook verify

# Verify specific plugin
han hook verify --plugin jutsu-bun

Options

OptionDescription
--plugin <name>Verify hooks for specific plugin only
--fixAttempt to fix common issues

Checks for:

  • Valid hook configuration syntax
  • Command executability
  • File pattern validity
  • Directory detection logic

han hook test

Test a hook configuration without actually running it.

Usage

# Test which directories a hook would run in
han hook test <plugin-name> <hook-name>

# Test with specific directory
han hook test <plugin-name> <hook-name> --directory packages/core

Shows:

  • Detected directories
  • Files that would trigger execution (if ifChanged is set)
  • Checkpoint status (if --cache would skip)

Environment Variables

Hook execution respects these environment variables:

VariableDescription
HAN_DISABLE_HOOKSSet to 1 or true to disable all hooks
HAN_HOOK_RUN_VERBOSESet to 1 or true to enable verbose output globally
HAN_MCP_TIMEOUTHook timeout in milliseconds (default: 600000 = 10 minutes)

Example

# Disable all hooks temporarily
export HAN_DISABLE_HOOKS=1
han hook run jutsu-bun test  # Exits immediately without running

# Enable verbose output globally
export HAN_HOOK_RUN_VERBOSE=1
han hook run jutsu-bun test  # Always shows full output

Integration with Claude Code

Hooks run automatically at lifecycle events when configured in plugin hooks.json:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "han hook run jutsu-bun test" }
        ]
      }
    ],
    "SubagentStop": [
      {
        "hooks": [
          { "type": "command", "command": "han hook run jutsu-typescript typecheck" }
        ]
      }
    ]
  }
}

Hook Lifecycle

Han supports these Claude Code hook points:

HookWhen It FiresCheckpoint TypePurpose
SessionStartClaude Code session beginsCreates session checkpointInitialize session state
SubagentStartSubagent is spawnedCreates agent checkpointCapture pre-subagent state
UserPromptSubmitUser submits a promptN/APre-process user input
PreToolUseBefore each tool callN/AValidate tool usage
PostToolUseAfter each tool callN/APost-process tool results
StopAgent about to respondValidates using session checkpointValidate all session changes
SubagentStopSubagent completesValidates using agent checkpointValidate subagent changes
SessionEndSession endsN/ACleanup session state

Checkpoint Filtering

Hooks automatically filter what files they check based on when they run:

  • Stop hooks validate against the session checkpoint (created at SessionStart)

    • Only checks files modified during the entire session
    • Use for session-wide validations (tests, builds, linting)
  • SubagentStop hooks validate against the agent checkpoint (created at SubagentStart)

    • Only checks files modified by that specific subagent
    • Use for focused validations (type checking, unit tests)

This ensures hooks only validate relevant changes and skip unchanged files automatically.

Learn More