captain-hook captain-hook
  • Quickstart
  • Tutorial
  • Guides
  • Cheatsheet
  • 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: >
  Stop repeating yourself to Claude. Use when writing Python code that uses the captain_hook package.
license: PolyForm-Noncommercial-1.0.0
compatibility: Requires Python >=3.13.
---

# captain-hook

Stop repeating yourself to Claude.

## Installation

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

## API overview

### Registration

Declaring and registering hooks.

- `hook`
- `on`

### Primitives

One-line hooks for the common cases.

- `gate`: Register a blocking gate — ``nudge(message, block=True, ...)`` with an explicit signature
- `nudge`: Register a nudge that warns (or blocks) when conditions or signals match
- `lint`: Register a lint check that runs on source-file edits and writes
- `diff_lint`: Register a diff lint: flag only constructs the edit introduces
- `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
- `rewrite_command`: Register a ``PreToolUse`` hook that rewrites a matching Bash command
- `rewrite_code`: Register a ``PreToolUse`` hook that structurally rewrites edited code before it is written
- `llm_gate`: Register an LLM-powered blocking gate
- `llm_nudge`: Register an LLM-powered advisory nudge
- `prompt_check`: Run a two-stage check with a formatted prompt and return block/warn/None
- `Confirm`: Send a deterministic block through TypeSafe Jev before it lands
- `Tickets`: A hook's declaration of the tickets it accepts and the rules that mint them
- `Rule`: One way an action gets a ticket: the condition that, holding, supplies the ticket's evidence
- `Reach`: How far a ticket reaches: one action, or every later action at its place
- `Decide`: A judge's reading of the user's words: the evidence it cites as permitting the action, if any
- `Proposal`: What a hook asks a ticket to cover
- `Ticket`: A record that one action, or every later action at one place, goes ahead
- `Context`: The action a declaration decides, and everything the session tree knows that bears on it
- `Names`: Matches text that names the action's place: every non-empty value of *keys* as a whole name
- `Touched`: The tree's earlier tool calls whose input or result match any of *patterns*; by default, naming the place
- `UserAnswered`: The user's answers to questions matching any of *patterns*, on ``AskUserQuestion`` or the cc-present board
- `UserRuled`: The user's durable rulings, recorded as cc-notes answers before the acting session started
- `approve`: Register a hook that answers matching tool permissions with *allow*
- `deny`: Register a hook that answers matching tool permissions with *deny*
- `llm_approve`: Register an LLM safety judge that auto-approves permission dialogs it deems safe
- `style.styleguide`
- `style.matchers`
- `style.StyleRule`
- `style.StyleDiffRule`
- `style.ast_grep_rule`
- `style.ast_grep_diff_rule`
- `style.AstGrepStyleRule`
- `style.AstGrepStyleDiffRule`
- `style.Violation`
- `style.Change`
- `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"``
- `SafetyVerdict`: LLM response model for ``llm_approve``. The LLM sets ``safe=True`` to auto-approve

### Conditions

Typed filters that decide when hooks fire.

- `Tool`: Condition matching the current event's tool name against one or more names
- `FilePath`: Condition matching the current event's file path against glob patterns
- `types.Command`
- `Content`: Condition matching the current event's file content against a regex
- `Pattern`: Condition matching the edit's new content against an ast-grep **structural** pattern
- `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
- `ReadFile`: Transcript-history condition: true when a Read tool use targeted a matching file
- `RanCommand`: Transcript-history condition: true when a Bash tool use running ``argv`` exists
- `Runs`: Structural Bash condition: true when a parsed command's argv starts with ``argv``
- `UsedSkill`: Transcript-history condition: true when a Skill tool use named one of ``names``
- `UsedTool`: Transcript-history condition: true when a tool use named one of ``names`` exists
- `UserSaid`: Matches when a user prompt matches one of ``patterns``
- `Annotated`: Matches when the event carries the ``ccx:`` annotation ``key``, set to ``value`` when one is given
- `InPlanMode`: Matches when the agent is in plan mode
- `Waiting`: Condition matching while the session is parked on out-of-band work
- `FromSubagent`: Condition matching when the current event originates from a subagent or teammate
- `SkipPermissions`: Condition matching when the session was launched with permission bypass available
- `FromTeammate`: Matches when the current turn's in-flight subagent spawn is a named teammate
- `FreshSession`: Matches a ``SessionStart`` from a fresh ``startup`` or ``clear``, not a ``resume`` or ``compact``
- `Headless`: Matches a headless ``claude -p`` / SDK run (``CLAUDE_CODE_ENTRYPOINT`` in the ``sdk-*`` family)
- `RewritingExistingPlan`: Matches a ``Write`` to a plan file (``.md`` under ``plans/`` or ``specs/``) already written this
- `ScratchPath`: Matches a file-tool target resolving into a system temp root or a scratch-named directory
- `EditedSource`: Matches when the session edited a non-test, in-repo source file (docs and config excluded)
- `Commits`: Matches a command line whose primary command explicitly names a path ending in ``suffix``
- `Redirects`: Matches when any command in the line carries a shell redirect (input or output)
- `Or`: Match if any of the inner conditions matches
- `And`: Match only if every inner condition matches (useful nested inside ``Or``/``Not``)
- `Not`: Match only if the inner condition does not match
- `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
- `CustomCommandLineCondition`: CustomCondition that fires only when a parsed Bash command line is present
- `CustomInputTypeCondition`: CustomCondition that fires only for a specific typed tool call
- `workflow_script_source`: The pending ``Workflow`` call's script source, or ``None``
- `workflow_opt_values`: Best-effort raw-source scan for values pinned to `key` in agent() opts. Never raises

### 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
- `ToolRewriteEvent`: Tool event whose input can be rewritten before it runs
- `PreToolUseEvent`: Fires before a tool is executed. Return a block result to prevent execution
- `PermissionRequestEvent`: Fires when a permission dialog would be shown
- `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
- `BackgroundTask`: A background task keeping the session alive, from a ``Stop``/``SubagentStop`` payload
- `SessionCron`: A scheduled prompt registered on the session, from a ``Stop``/``SubagentStop`` payload
- `PreCompactEvent`: Fires before context compaction, providing the trigger and custom instructions
- `NotificationEvent`: Fires on system notifications, providing message, title, and notification type
- `MessageDisplayEvent`: Fires once per streamed chunk of an assistant message; a ``rewrite`` replaces the chunk's displayed text
- `ResourcePressureEvent`: Fired by the capt-hookd host, not Claude Code, when a session's child process stays resource-heavy
- `SessionStartEvent`: Fires when a session starts, providing what triggered it. Warns inject context; it cannot block
- `SessionEndEvent`: Fires when the session ends, providing the termination reason. Output is ignored, so it cannot block
- `HookContext`: Runtime context injected into every hook event
- `Model`: The model a session runs on, parsed from the id its transcript records
- `Turn`: The current turn as a one-turn :class:`~cc_transcript.query.Session` view
- `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 one or more names
- `BaseHookEvent.as_input`

### 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`
- `util.fs.read_json`
- `util.fs.resolve_binary`
- `util.fs.binary_supports`
- `Cmd`: The parsed command line behind ``evt.cmd`` — a walk over every command invocation it contains
- `Call`: One command invocation reached by walking a command line — a top-level occurrence, a
- `CommandSchema`: Bind parsed shell words using declarative option and positional definitions
- `Operand`: Bind positional words to a role, optionally collecting a variable-length group
- `Option`: Bind option aliases to a named, typed value or a flag
- `Arguments`: Named bindings from one invocation, retaining source words and unknown values
- `CommandMatches`: Apply argument predicates to each matching invocation, including nested calls
- `PathsMatch`: Match when any path in a named argument role satisfies a path predicate
- `PathMatches`: Match complete path globs against lexical and resolved targets
- `OptionIs`: Match a completely parsed invocation's last value for a named option
- `Target`: One operand of a command — a literal path or a glob — with resolution and blast-radius predicates
- `Targets`: The operand targets of a command, in order — iterable, sized, and expandable as a whole
- `Expansion`: The paths a target's glob resolves to, plus whether the walk budget was exhausted
- `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``)
- `Word`: One structural word of a parsed command (``Command.words``)

### Tool Calls

Typed tool-call inputs reached via evt.input and evt.as_input().

- `ToolCall`: Represent a PEP 604 union type
- `ToolCallBase`: Common shape of every typed tool call
- `ReadCall`: A Read of a file, optionally windowed
- `BashCall`: A Bash/Execute shell invocation
- `EditCall`: An Edit replacement of ``old`` with ``new`` in one file
- `MultiEditCall`: A MultiEdit applying ``edits`` to one file, in order
- `WriteCall`: A Write/Create of a whole file
- `NotebookEditCall`: A NotebookEdit replacing a cell's source
- `GlobCall`: A Glob file-pattern search
- `GrepCall`: A Grep content search
- `SkillCall`: A Skill invocation
- `TaskCall`: An Agent/Task subagent dispatch
- `TaskCreateCall`: A TaskCreate tracker entry
- `TaskUpdateCall`: A TaskUpdate tracker change
- `ExitPlanModeCall`: An ExitPlanMode/ExitSpecMode plan submission
- `OtherCall`: A tool the platform does not type: unknown names, MCP tools, and — under

### Tasks

The native task list, read via evt.tasks.

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

### Signals

NLP signal scoring over transcript text.

- `Clause`: One dependency-aware pattern matched against each sentence of a text
- `NlpSignal`: A transcript signal that scores ``weight`` when any clause matches a sentence
- `Phrase`: A set of lowercased lemmas naming one concept, matched against tokens by lemma
- `is_past_predicate`: Whether ``tok`` reports a completed action
- `has_nominal_subject`: Whether ``tok`` has a substantive active subject
- `subject_kind`: The shape of ``tok``'s subject, as :class:`Clause`'s ``subject`` constraint sees it

### 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 nudge/gate state shared across all hooks in a session
- `SourceEdits`: Condition matching an ``Edit``/``Write`` of a non-test source file in one language
- `WorkflowState`: Base for a pydantic model that bundles one session workflow across several hooks
- `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
- `DurableState`: Base for a model persisted across sessions, scoped by the ``scope`` class keyword
- `DurableSlot`: A :class:`SessionSlot` rooted in a durable directory; inherits the locked :meth:`mutate`
- `DurableStore`: Class-keyed durable store providing typed :class:`DurableSlot` access via ``store[Model]``
- `Deque`: A bounded ``deque`` field type whose ``maxlen`` survives JSON round-trips
- `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`: One step of a :func:`workflow` guard: ``check`` gates progress, ``message`` is shown when it fails
- `Artifact`: Artifact(*, path: 'str', model: 'type[M]', validate: 'Callable[[M], str | None]' = <function Artifact.<lambda> at 0x7f6d77618a40>)
- `text_matches`
- `workflow`

### Transcripts

Registering external transcripts into a session's deep view.

- `register_transcript`: Register an external transcript against ``session_id`` so it folds into the deep view
- `RegisteredTranscript`: An external transcript folded into a session's deep view — a codex thread id or a file path
- `RegisteredTranscripts`: The external transcripts registered against one session, in registration order

### Testing

Inline tests for hooks.

- `Input`: Inline test input descriptor modeling an event payload
- `T`: Namespaced transcript-fixture builders for ``Input(transcript=[...])`` in inline tests
- `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
- `Rewrite`: Inline test expectation: the hook should rewrite the tool input
- `Ask`: Inline test expectation: the hook returned no result (``None``)
- `FileFixture`: Inline-test file descriptor: materialized to a real temp file so size/stat-based guards run for real
- `TranscriptFixture`: A lightweight transcript stub for use in inline tests
- `CONFIRMED`: dict() -> new empty dictionary
- `UNCONFIRMED`: dict() -> new empty dictionary

### 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 Contexts

Declarative evidence blocks attached to LLM primitive prompts.

- `PromptContext`: One declarative XML block attached to an LLM primitive's prompt
- `apply_contexts`: Append each context's block to ``prompt`` in order, each clipped to ``max_len`` characters
- `BeforeEdit`: The pending edit's pre-image, as a ``<before_edit>`` block
- `AfterEdit`: The pending edit's new text, as an ``<after_edit>`` block
- `PendingToolCall`: The call a ``PreToolUse`` or ``PermissionRequest`` event is deciding, as a ``<pending_tool_call>`` block
- `Introduced`: Constructs the pending edit newly introduces, as an auto-tagged block
- `WorkflowScriptSource`: Gating context: the pending ``Workflow`` call's script source, headed by its model pins
- `UserMessages`: The session's user prompts as a ``<user_messages>`` request/authorization record
- `Excerpts`: Verbatim excerpts pulled from a text under a character budget
- `excerpt_around`: Verbatim excerpts of ``text`` around each ``(start, end)`` character span
- `COMMENT_TYPES`: Build an immutable unordered collection of unique elements
- `Edit`: The pending edit's before/after source, parsed for structural queries
- `SyntaxNode`: One node of a parsed syntax tree — the framework's face over the ast-grep binding node
- `Match`: A structural match, located by 1-based line to align with ``Violation`` and changed-line scoping

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

captain-hook · Stop repeating yourself to Claude.

Developed by Yasyf Mohamedali.
Site created with Great Docs.

PyPI · Source · Issues · Changelog · llms.txt · llms-full.txt · Skills