---
name: captain-hook
description: >
  Declarative hook framework for Claude Code. Use when writing Python code that uses the captain_hook package.
license: PolyForm-Noncommercial-1.0.0
compatibility: Requires Python >=3.12.
---

# captain-hook

Declarative hook framework for Claude Code

## Installation

```bash
pip install captain-hook
```

## API overview

### Registration

Declaring and registering hooks.

- `hook`
- `on`
- `register`

### Primitives

One-line hooks for the common cases.

- `audit`: Register a hook that appends one JSONL record per matching event
- `gate`: Register a blocking gate — shorthand for ``nudge(message, block=True, ...)``
- `nudge`: Register a nudge that warns (or blocks) when conditions or signals match
- `lint`: Register a lint check that runs on Python file edits/writes
- `diff_lint`
- `block_command`: Register a declarative hook that blocks a Bash command matching a pattern
- `warn_command`: Register a declarative hook that warns on a Bash command matching a pattern
- `llm_gate`: Register an LLM-powered blocking gate
- `llm_nudge`: Register an LLM-powered advisory nudge
- `llm_evaluate`
- `prompt_check`: Run an LLM check with a formatted prompt and return block/warn/None
- `style.styleguide`
- `style.matchers`
- `style.StyleRule`
- `style.StyleDiffRule`
- `style.Violation`
- `GateVerdict`: LLM response model for ``llm_gate``. The LLM sets ``block=True`` to deny
- `NudgeVerdict`: LLM response model for ``llm_nudge``. The LLM sets ``fire=True`` to trigger the nudge
- `PromptCheckVerdict`: LLM response model for ``prompt_check``. Action is ``"ok"``, ``"warning"``, or ``"block"``

### Conditions

Typed filters that decide when hooks fire.

- `Tool`: Condition matching the current event's tool name against a regex pattern
- `FilePath`: Condition matching the current event's file path against glob patterns
- `TouchedFile`: Transcript-history condition: true when an Edit/Write targeted a file matching the glob
- `TestFile`: Condition that matches when the current event targets a test file (``test_*.py``, ``conftest.py``)
- `ReadFile`: Transcript-history condition: true when a Read tool use targeted a matching file
- `RanCommand`: Transcript-history condition: true when a Bash tool use with a matching command exists
- `UsedSkill`: Transcript-history condition: true when a Skill tool use with a matching name exists
- `InPlanMode`: Matches when the agent is in plan mode
- `Waiting`: Waiting()
- `Signal`: A regex-based signal pattern used in the scoring pipeline
- `Signals`: Bundle of signal patterns with a scoring threshold
- `CustomCondition`: Protocol for user-defined hook conditions

### Events & Results

Typed lifecycle events and hook outcomes.

- `Event`: Hook lifecycle events that can trigger registered hooks
- `BaseHookEvent`: Base class for all hook events, providing access to raw payload, context, and convenience methods
- `ToolHookEvent`: Event for tool-related hooks, adding tool name, input, command, and file access
- `PreToolUseEvent`: Fires before a tool is executed. Return a block result to prevent execution
- `PostToolUseEvent`: Fires after a tool completes successfully, with access to the tool response
- `PostToolUseFailureEvent`: Fires after a tool fails, providing the error message and interrupt status
- `UserPromptSubmitEvent`: Fires when the user submits a prompt, before the agent processes it
- `StopEvent`: Fires when the agent is about to stop. Return a block result to prevent stopping
- `SubagentStartEvent`: Fires when a subagent is launched. Provides ``agent_type`` for filtering
- `SubagentStopEvent`: Fires when a subagent finishes. Provides ``agent_type`` for filtering
- `PreCompactEvent`: Fires before context compaction, providing the trigger and custom instructions
- `NotificationEvent`: Fires on system notifications, providing message, title, and notification type
- `HookContext`: Runtime context injected into every hook event: session state, transcript, settings, and LLM/CLI helpers
- `HookResult`: The return value from a hook handler, specifying the action and optional message
- `Action`: Hook result action determining how the hook output is handled
- `Agent`: Condition matching the current event's subagent type against a name pattern
- `Content`: Condition matching the current event's file content against a regex

### BaseHookEvent Methods

Methods for the BaseHookEvent class

- `BaseHookEvent.event`
- `BaseHookEvent.is_subagent`
- `BaseHookEvent.session_id`
- `BaseHookEvent.tasks`
- `BaseHookEvent.user_prompt`
- `BaseHookEvent.stop_hook_active`
- `BaseHookEvent.transcript_path`
- `BaseHookEvent.permission_mode`
- `BaseHookEvent.parent_agent_type`
- `BaseHookEvent.tool_name`
- `BaseHookEvent.input`
- `BaseHookEvent.command`
- `BaseHookEvent.command_line`
- `BaseHookEvent.file`
- `BaseHookEvent.content`
- `BaseHookEvent.old`
- `BaseHookEvent.agent_type`
- `BaseHookEvent.command_matches`
- `BaseHookEvent.file_matches`
- `BaseHookEvent.content_matches`
- `BaseHookEvent.allow`
- `BaseHookEvent.warn`
- `BaseHookEvent.block`

### ToolHookEvent Methods

Methods for the ToolHookEvent class

- `ToolHookEvent.tool_name`
- `ToolHookEvent.command_line`
- `ToolHookEvent.content`
- `ToolHookEvent.old`
- `ToolHookEvent.agent_type`
- `ToolHookEvent.command_matches`
- `ToolHookEvent.file_matches`
- `ToolHookEvent.content_matches`

### HookContext Methods

Methods for the HookContext class

- `HookContext.t`
- `HookContext.s`
- `HookContext.state`
- `HookContext.conf`
- `HookContext.c`
- `HookContext.turn`
- `HookContext.prior`
- `HookContext.call_cli`
- `HookContext.git`
- `HookContext.changed_paths`
- `HookContext.repo_root`
- `HookContext.current_branch`
- `HookContext.call_llm`
- `HookContext.resolve_schema_path`

### Files & Commands

Path matching and AST-level command inspection.

- `File`: A file path wrapper with glob matching, prefix checks, and test-file detection
- `file.PathMatcher`
- `file.categorize_files`
- `utils.read_json`
- `Command`: A single parsed shell command with executable, arguments, env vars, and redirects
- `CommandLine`: A full parsed bash command line, potentially containing multiple commands joined by operators
- `Redirect`: A shell redirect parsed from a bash command (e.g. ``> file.txt``, ``2>&1``)
- `EditOp`: A parsed Edit tool operation extracted from a transcript tool use
- `WriteOp`: A parsed Write/Create tool operation extracted from a transcript tool use
- `TaskOp`: A parsed task-tracker operation (create/update/get/list) extracted from a transcript tool use

### File Methods

Methods for the File class

- `File.__getattr__`
- `File.__str__`
- `File.__fspath__`
- `File.__eq__`
- `File.__hash__`
- `File.is_test`
- `File.matches`
- `File.under`
- `File.exists`
- `File.read_text`
- `File.contains`

### Command Methods

Methods for the Command class

- `Command.parse`
- `Command.empty`
- `Command.argv`
- `Command.program`
- `Command.env_dict`
- `Command.matches`
- `Command.has_arg`
- `Command.__str__`
- `Command.__contains__`
- `Command.__bool__`

### CommandLine Methods

Methods for the CommandLine class

- `CommandLine.parse`
- `CommandLine.commands`
- `CommandLine.primary`
- `CommandLine.head`
- `CommandLine.__iter__`
- `CommandLine.__len__`
- `CommandLine.__str__`
- `CommandLine.__contains__`
- `CommandLine.__bool__`
- `CommandLine.q`
- `CommandLine.node_text`
- `CommandLine.word_text`
- `CommandLine.extract_redirect`
- `CommandLine.extract_command`
- `CommandLine.collect_parts`
- `CommandLine.walk_redirected`
- `CommandLine.walk_node`
- `CommandLine.fallback`

### Transcript

Typed access to conversation history.

- `Transcript`: The full session transcript: a sequence of messages with tool-use querying, slicing, and history checks
- `TranscriptMessage`: A single message in a transcript with parsed content blocks, tool-use extraction, and text access
- `TranscriptSlice`: A contiguous slice of a Transcript, returned by slicing operations like ``recent``, ``after``, ``before``
- `ToolUse`: A transcript tool invocation with typed input parsing, file/command access, and result linkage
- `ToolUseQuery`: Chainable query builder for filtering and inspecting transcript tool uses
- `ToolUseSequence`: Sequence of tool uses that filters out errors by default
- `Turn`: The current conversation turn starting from the last user message, with edited-file tracking
- `Task`: A task read from Claude Code's native task store (``~/.claude/tasks/<list-id>/<id>.json``)
- `Tasks`: The live task list for one session, read from the native store rather than the transcript

### Transcript Methods

Methods for the Transcript class

- `Transcript.is_user_message`
- `Transcript.__len__`
- `Transcript.__bool__`
- `Transcript.__getitem__`
- `Transcript.__str__`
- `Transcript.from_path`
- `Transcript.from_simple_messages`
- `Transcript.from_messages`
- `Transcript.from_parsed`
- `Transcript.tool_uses`
- `Transcript.count_tools`
- `Transcript.has_tool`
- `Transcript.commands`
- `Transcript.has_command`
- `Transcript.has_edit_to`
- `Transcript.user_said`
- `Transcript.all_edits_under`
- `Transcript.first_user_message`
- `Transcript.after`
- `Transcript.before`
- `Transcript.prior`
- `Transcript.recent`
- `Transcript.full_text`
- `Transcript.assistant_text`
- `Transcript.extract_files`
- `Transcript.has_read`
- `Transcript.has_skill`
- `Transcript.subagents`
- `Transcript.count_failures`
- `Transcript.has_override`
- `Transcript.edit_ops`
- `Transcript.write_ops`
- `Transcript.task_ops`
- `Transcript.turn_start`
- `Transcript.current_turn`
- `Transcript.since_last_user`

### TranscriptMessage Methods

Methods for the TranscriptMessage class

- `TranscriptMessage.from_raw`
- `TranscriptMessage.is_async_tool_use`
- `TranscriptMessage.notification`
- `TranscriptMessage.tool_uses`
- `TranscriptMessage.tool_results`
- `TranscriptMessage.text`

### ToolUse Methods

Methods for the ToolUse class

- `ToolUse.is_error`
- `ToolUse.input`
- `ToolUse.file`
- `ToolUse.command`
- `ToolUse.command_line`
- `ToolUse.agent_type`

### ToolUseQuery Methods

Methods for the ToolUseQuery class

- `ToolUseQuery.where`
- `ToolUseQuery.count`
- `ToolUseQuery.any`
- `ToolUseQuery.list`
- `ToolUseQuery.first`
- `ToolUseQuery.last`
- `ToolUseQuery.files`
- `ToolUseQuery.__iter__`
- `ToolUseQuery.__len__`
- `ToolUseQuery.__bool__`

### ToolUseSequence Methods

Methods for the ToolUseSequence class

- `ToolUseSequence.where`
- `ToolUseSequence.__getitem__`
- `ToolUseSequence.__iter__`
- `ToolUseSequence.__len__`
- `ToolUseSequence.__bool__`
- `ToolUseSequence.with_errors`

### Tasks Methods

Methods for the Tasks class

- `Tasks.resolve_root`
- `Tasks.for_session`
- `Tasks.__getitem__`
- `Tasks.__len__`
- `Tasks.get`
- `Tasks.with_status`
- `Tasks.pending`
- `Tasks.in_progress`
- `Tasks.completed`
- `Tasks.open`
- `Tasks.all_completed`

### Tool Inputs

Parsed tool-input models.

- `InputBase`: Base class for typed tool inputs. Provides ``from_raw()`` parsing and ``as_()`` type narrowing
- `FileInputBase`: Base for tool inputs that reference a file, providing a cached ``file`` property returning a ``File``
- `AgentInput`: Parsed Agent/Task tool input
- `BashInput`: Parsed Bash/Execute tool input
- `EditInput`: Parsed Edit tool input with old/new content for replacements
- `GenericInput`: Fallback typed input for unrecognized tools, providing dict-like ``get()`` access to raw data
- `GlobInput`: Parsed Glob tool input
- `GrepInput`: Parsed Grep tool input
- `ReadInput`: Parsed Read tool input
- `SkillInput`: Parsed Skill tool input
- `TaskCreateInput`: Parsed TaskCreate tool input
- `TaskUpdateInput`: Parsed TaskUpdate tool input
- `WriteInput`: Parsed Write/Create tool input
- `ToolResult`: A tool-result content block linking back to its tool use via ``tool_use_id``

### Signals

NLP signal scoring over transcript text.

- `Clause`: Clause(noun: 'Phrase', verb: 'Phrase | None' = None, adj: 'Phrase | None' = None, negated: 'bool' = False)
- `NlpSignal`: NlpSignal(*, clauses: 'Sequence[Clause]', weight: 'int' = 1)
- `Phrase`: Phrase(*terms: 'str') -> 'None'

### State & Sessions

Session state, workflow state, and multi-step workflows.

- `HookState`: Per-hook persistent state tracked across events in a session (``fire_count`` for ``max_fires``)
- `PrimitiveState`: Per-primitive state for nudges/gates: last fire index, consumed-signal hashes, and echo-window lemmas
- `SourceEdits`: SourceEdits(lang: 'str' = 'py', include_tests: 'bool' = False, paths: 'str | None' = None)
- `workflow_state`
- `SessionSlot`: A typed slot for reading/writing a single Pydantic model in a session directory
- `SessionStore`: Class-keyed store providing typed ``SessionSlot`` access via ``store[ModelClass]``
- `session_state`: Decorator that registers a Pydantic model for collective ``SessionStore`` introspection
- `Workflow`: Workflow(*, label: 'str', marker: 'str', steps: 'list[Step]', artifacts: 'list[Artifact[BaseModel]]' = <factory>, post_complete: 'Callable[[BaseHookEvent], HookResult | None] | None' = None, on_start: 'Callable[[BaseHookEvent], HookResult | None] | None' = None)
- `Step`: Step(*, name: 'str', check: 'Callable[[Transcript], bool]', stopped_at: 'str', next_step: 'str')
- `Artifact`: Artifact(*, path: 'str', model: 'type[M]', validate: 'Callable[[M], str | None]' = <function Artifact.<lambda> at 0x7f5d0f7647c0>)
- `text_matches`
- `workflow`

### SessionStore Methods

Methods for the SessionStore class

- `SessionStore.__getitem__`
- `SessionStore.load`
- `SessionStore.track`
- `SessionStore.untrack`
- `SessionStore.tracked_models`
- `SessionStore.tracked_paths`

### Testing

Inline tests for hooks.

- `Input`: Inline test input descriptor modeling an event payload. Set fields based on the target event type
- `Allow`: Inline test expectation: the hook should allow (return None or action ``"allow"``)
- `Block`: Inline test expectation: the hook should block. Optional regex ``pattern`` matches the block message
- `Warn`: Inline test expectation: the hook should warn. Optional regex ``pattern`` matches the warning message
- `TranscriptFixture`: A lightweight transcript stub for use in inline tests

### Configuration & Prompts

Settings, scaffolding, and LLM prompt helpers.

- `HooksSettings`: Base settings class for hook configuration, backed by environment variables with ``HOOKS_`` prefix
- `build_settings`: Build settings from a conf module via an explicit ``HooksSettings`` subclass or auto-inferred fields
- `Prompt`: Fluent builder for structured LLM prompts with system text, XML context sections, and a question

### Prompt Methods

Methods for the Prompt class

- `Prompt.system`
- `Prompt.context`
- `Prompt.ask`
- `Prompt.from_template`
- `Prompt.load`
- `Prompt.__str__`

## Resources

- [Full documentation](https://yasyf.github.io/captain-hook/)
- [llms.txt](llms.txt) — Indexed API reference for LLMs
- [llms-full.txt](llms-full.txt) — Comprehensive documentation for LLMs
- [Source code](https://github.com/yasyf/captain-hook)
