Skip to content
Agent Orchestration
Hook

Hooks

What bkit runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.

From plugin
bkit
60644 skills34 agents2 commands21 hooks

Claude Code

> /plugin marketplace add ww-w-ai/bkit-claude-code

What fires, and when

SessionStart

Fires once when a session begins, and again after a context compaction. It is where a plugin sets up its environment, or restores state the compaction dropped.

  • node "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.js"

PreToolUse

  • MatchesWrite|Editnode "${CLAUDE_PLUGIN_ROOT}/scripts/pre-write.js"node "${CLAUDE_PLUGIN_ROOT}/scripts/lint-skill-md.js"node "${CLAUDE_PLUGIN_ROOT}/scripts/lint-skill-md.js"
  • MatchesBashnode "${CLAUDE_PLUGIN_ROOT}/scripts/unified-bash-pre.js"

PostToolUse

  • MatchesWrite|Editnode "${CLAUDE_PLUGIN_ROOT}/scripts/unified-write-post.js"node "${CLAUDE_PLUGIN_ROOT}/scripts/pdca-doc-changed-handler.js"node "${CLAUDE_PLUGIN_ROOT}/scripts/pdca-doc-changed-handler.js"
  • MatchesBashnode "${CLAUDE_PLUGIN_ROOT}/scripts/unified-bash-post.js"
  • MatchesSkillnode "${CLAUDE_PLUGIN_ROOT}/scripts/skill-post.js"

Stop

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/unified-stop.js"

StopFailure

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/stop-failure-handler.js"

UserPromptSubmit

Fires before Claude sees each prompt you send. A plugin can use it to inject context, so the same instruction reaches the model every turn instead of only at session start.

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/user-prompt-handler.js"

UserPromptExpansion

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/user-prompt-expansion-handler.js"

PreCompact

  • Matchesauto|manualnode "${CLAUDE_PLUGIN_ROOT}/scripts/context-compaction.js"

PostCompact

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/post-compaction.js"

TaskCompleted

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/pdca-task-completed.js"

SubagentStart

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/subagent-start-handler.js"

SubagentStop

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/subagent-stop-handler.js"

TeammateIdle

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/team-idle-handler.js"

SessionEnd

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/session-end-handler.js"

PostToolUseFailure

  • MatchesBash|Write|Editnode "${CLAUDE_PLUGIN_ROOT}/scripts/tool-failure-handler.js"

InstructionsLoaded

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/instructions-loaded-handler.js"

ConfigChange

  • Matchesproject_settings|skillsnode "${CLAUDE_PLUGIN_ROOT}/scripts/config-change-handler.js"

PermissionRequest

  • MatchesWrite|Edit|Bashnode "${CLAUDE_PLUGIN_ROOT}/scripts/permission-request-handler.js"

Notification

  • Matchespermission_prompt|idle_promptnode "${CLAUDE_PLUGIN_ROOT}/scripts/notification-handler.js"

CwdChanged

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/cwd-changed-handler.js"

TaskCreated

  • node "${CLAUDE_PLUGIN_ROOT}/scripts/task-created-handler.js"
Read hooks/hooks.json

In the plugin's words

How bkit describes its own hook set.

bkit Vibecoding Kit v2.1.41 - Claude Code. IMPORTANT: `timeout` is in SECONDS (Claude Code default 600 for command hooks). Values here were 1000x too large through v2.1.33 — a declared 10000 meant 2h46m, not 10s, which is why a hung Stop hook could stall a session for ~15

Where it lives

  • hooks/session-start.jsRunsGitHub
    Read the script
    #!/usr/bin/env node
    /**
     * bkit Vibecoding Kit - SessionStart Hook (v2.1.41, uses BKIT_VERSION from lib/core/version)
     *
     * Thin orchestrator that delegates to startup modules:
     *   1. migration   - Legacy path migration (docs/ -> .bkit/)
     *   2. restore     - PLUGIN_DATA backup restoration
     *   3. contextInit - Context Hierarchy, Memory Store, Import Resolver, Fork cleanup, ensureBkitDirs
     *   4. onboarding  - Onboarding message generation, env vars, trigger table
     *   5. sessionCtx  - additionalContext string building for hook output
     *   6. dashboard   - PDCA progress bar rendering (prepended to additionalContext)
     *   7. workflowMap - v2.0.0 Workflow map rendering (PDCA phase visualization)
     *   8. controlPanel- v2.0.0 Control panel rendering (automation level display)
     *   9. staleDetect - v2.0.0 Stale feature detection (lifecycle.js)
     */
    
    const { BKIT_PLATFORM } = require('../lib/core/platform');
    const { debugLog } = require('../lib/core/debug');
    const { readStdinSync } = require('../lib/core/io');
    
    /*
     * v2.1.34: read the hook payload.
     *
     * This handler previously ignored stdin entirely, which cost it two things.
     *
     * First, `source` — Claude Code reports whether the session began via
     * `startup`, `resume`, `clear`, `compact` or `fork`. bkit had no way to tell
     * them apart, and the `once: true` flag it carried in hooks.json to approximate
     * "only on a fresh session" was never honoured there in the first place (it is
     * read only from skill frontmatter). Confirmed by resuming a session and
     * watching this hook fire a second time.
     *
     * Second, dispatch observability: reading through the shared reader stamps
     * `.bkit/runtime/hook-dispatch.ndjson`, which is how the host-integration test
     * proves from the outside that Claude Code really invokes this hook. A hook
     * nobody can observe is how eight bkit features stayed dead across releases.
     *
     * The reader is bounded (issue #139), so this cannot stall the session.
     */
    const hookPayload = readStdinSync() || {};
    const sessionSource = typeof hookPayload.source === 'string' ? hookPayload.source : null;
    
    // Log session start
    debugLog('SessionStart', 'Hook executed', {
      cwd: process.cwd(),
      platform: BKIT_PLATFORM,
      source: sessionSource,
    });
    
    // --- ENH-148: Defensive cleanup for env vars that should reset on /clear ---
    // CC /clear resets conversation but env vars persist across sessions.
    // Clean up bkit-specific runtime env vars to prevent stale state (#37729).
    const BKIT_RUNTIME_ENV_VARS = [
      'BKIT_PDCA_PHASE',
      'BKIT_PRIMARY_FEATURE',
      'BKIT_AUTOMATION_LEVEL',
      'BKIT_SESSION_ID',
      'BKIT_AGENT_ACTIVE',
      'BKIT_CHECKPOINT_PENDING',
    ];
    
    for (const envVar of BKIT_RUNTIME_ENV_VARS) {
      if (process.env[envVar]) {
        debugLog('SessionStart', 'Cleaning stale env var', { envVar, value: process.env[envVar] });
        delete process.env[envVar];
      }
    }
    
    // --- 1. Migration: Legacy path migration ---
    const migration = require('./startup/migration');
    try {
      migration.run();
    } catch (e) {
      debugLog('SessionStart', 'Migration module failed', { error: e.message });
    }
    
    // --- 2. Restore: PLUGIN_DATA backup restoration ---
    const restore = require('./startup/restore');
    try {
      restore.run();
    } catch (e) {
      debugLog('SessionStart', 'Restore module failed', { error: e.message });
    }
    
    // --- 3. Context Init: Hierarchy, Memory, Imports, Forks ---
    const contextInit = require('./startup/context-init');
    try {
      contextInit.run();
    } catch (e) {
      debugLog('SessionStart', 'Context init module failed', { error: e.message });
    }
    
    // --- 4. Onboarding: Messages, env vars, trigger table ---
    const onboarding = require('./startup/onboarding');
    let onboardingContext = { onboardingData: { type: 'new_user', hasExistingWork: false }, triggerTable: '' };
    try {
      onboardingContext = onboarding.run();
    } catch (e) {
      debugLog('SessionStart', 'Onboarding module failed', { error: e.message });
    }
    
    // --- 5. Session Context: Build additionalContext string ---
    const sessionContext = require('./startup/session-context');
    let additionalContext = '';
    try {
      additionalContext = sessionContext.build(null, onboardingContext);
    } catch (e) {
      debugLog('SessionStart', 'Session context module failed', { error: e.message });
    }
    
    // --- v2.1.1 UI-02: Build dashboard sections in correct display order ---
    // Order: Session Context → Progress Bar → Workflow Map → Impact View → Agent Panel → Control Panel
    const dashboardSections = [];
    
    // ENH-226 (Issue #77 Phase A): dashboard opt-out gate
    // When ui.dashboard.enabled=false, skip rendering all 5 boxes
    // (progress / workflow / impact / agent / control).
    let _uiDashboardEnabled = true;
    let _uiDashboardSections = ['progress', 'workflow', 'impact', 'agent', 'control', 'sqm'];
    try {
      const { getUIConfig } = require('../lib/core/config');
      const _ui = getUIConfig();
      if (_ui && _ui.dashboard) {
        _uiDashboardEnabled = _ui.dashboard.enabled !== false;
        if (Array.isArray(_ui.dashboard.sections)) _uiDashboardSections = _ui.dashboard.sections;
      }
    } catch (_e) {
      // keep default (true)
    }
    
    // Session Context is already in additionalContext (base content)
    // It will be placed first in the final output
    
    let pdcaStatus = null;
    let agentState = null;
    
    // Load shared state once
    try {
      const { getPdcaStatusFull } = require('../lib/pdca/status');
      pdcaStatus = getPdcaStatusFull();
    } catch (_) {}
    
    try {
      const fs = require('fs');
      const agentStatePath = require('path').resolve(process.cwd(), '.bkit/runtime/agent-state.json');
      if (fs.existsSync(agentStatePath)) {
        agentState = JSON.parse(fs.readFileSync(agentStatePath, 'utf-8'));
    
        // v2.1.12 Sprint C-1 (#15 fix): reset stale agent-state when last update
        // is older than `staleFeatureTimeoutDays` (default 7 days from
        // control-state.json guardrails). Previous behaviour: agent-state kept
        // referencing a 13-days-idle feature ("cc-version-issue-response") with
        // an empty sessionId — every new session started by inheriting that
        // stale lifecycle. We now zero t

Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.

@ww-w-ai
Ships withbkit

A Claude Code plugin that verifies AI-generated code against its own design specs. Three commands. Anyone — even someone vibe-coding for the first time — can ship robust, production-quality software.

60644 skills34 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
606
Star history of ww-w-ai/bkit-claude-code on GitHub, a chart by star-history.com

More plugins that ship hooks.

oh-my-claudecode

oh-my-claudecode

Splits a complex task across several specialized Claude Code agents working in parallel, then keeps going until the result is checked. You describe what you want in plain language instead of memorizing commands.

84 skills+441k
@yeachan-heo@yeachan-heo
Install Plugin
ouroboros

ouroboros

Turns a rough feature idea into a written spec through guided questions, then has the agent build it and checks the result against that spec. Instead of hand-checking whether the work is finished, you get an automatic evaluation gate that runs in your coding agent.

26 skills+36.3k
@q00@q00
Install Plugin
myclaude

myclaude

A plugin that runs coding tasks through multiple AI backends (Codex, Claude, Gemini, OpenCode) with a structured development workflow, parallel execution, browser automation and multi-session task checkpointing.

11 skills+32.8k
@stellarlinkco@stellarlinkco
Install Plugin
harmonist

harmonist

Coordinates AI agents with mechanical protocol enforcement, a workflow gate, memory validation and a session hook. Includes a catalog of specialist agents and has no runtime dependencies.

199 agents+12.2k
@gammalabtechnologies@gammalabtechnologies
Install Plugin
bernstein

bernstein

Bernstein is a Claude Code plugin for orchestrating AI agents. It adds skills to list and inspect agents, review and approve tasks, create tasks, track costs and budgets, and show alerts for failed or stalled work.

26 skills+41.2k
@sipyourdrink-ltd@sipyourdrink-ltd
Install Plugin
fablize

fablize

A Claude Code plugin that enforces finishing multi-step tasks with evidence and verification at each stage. It works as a procedure for Opus or any Claude model, not as chance.

1 skill+2894
@fivetaku@fivetaku
Install Plugin
hello2cc

hello2cc

Adjusts how third-party models behave inside Claude Code so they run closer to a native Opus session, covering subagent lifecycle, session hooks and tool interception. It does not replace your gateway, provider mapping or account setup.

1 agent11 hooks689
@hellowind777@hellowind777
Install Plugin
fusion-fable

fusion-fable

Fusion-Fable is a Claude Code plugin that answers hard questions by sending them to a panel of models working in parallel, then having a judge model combine their answers. It also includes a planning skill that runs an OMC requirements interview before producing an implementation plan.

2 skills+2473
@duolahypercho@duolahypercho
Install Plugin

Questions about the hooks in bkit.

Which coding agents can use the hooks in bkit?
The hooks in bkit install in Claude Code and Cursor: each runs Claude Code hooks from .claude/settings.json, so copy the hooks there.