captain-hook
  • Getting Started
  • Guide
  • Examples
  • Reference
  • Development
  • Changelog

Skills

A skill is a package of structured files that teaches an AI coding agent how to work with a specific tool or framework. The skill below was generated by Great Docs from this project’s documentation. Install it in your agent and it will be able to run commands, edit configuration, write content, and troubleshoot problems without step-by-step guidance from you.

Any agent — install with npx:

npx skills add https://yasyf.github.io/captain-hook/

Codex / OpenCode

Tell the agent:
Fetch the skill file at https://yasyf.github.io/captain-hook/skill.md and follow the instructions.

Manual — download the skill file:

curl -O https://yasyf.github.io/captain-hook/skill.md

Or browse the SKILL.md file.

SKILL.md

---
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)

Developed by Yasyf Mohamedali.
Site created with Great Docs.