## Events & Results


## Event


Hook lifecycle events that can trigger registered hooks.


Usage

``` python
Event()
```


Combinable with `|` to match multiple events in a single hook registration.


#### Example

``` python
>>> hook(Event.Stop | Event.SubagentStop, message="review first", block=True)
```


## BaseHookEvent


Base class for all hook events, providing access to raw payload, context, and convenience methods.


Usage

``` python
BaseHookEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


#### Attributes

| Name | Description |
|----|----|
| [agent_id](#captain_hook.BaseHookEvent.agent_id) | The subagent id attached to this event, or None for main-agent events. |
| [background_tasks](#captain_hook.BaseHookEvent.background_tasks) | The background tasks keeping this session alive, `()` when the payload omits them. |
| [cmd](#captain_hook.BaseHookEvent.cmd) | The event's Bash command as a walkable `~captain_hook.cmd.Cmd`. |
| [command](#captain_hook.BaseHookEvent.command) | The event's Bash command as a walkable `~captain_hook.cmd.Cmd` -- an alias for [cmd](events-results.md#captain_hook.BaseHookEvent.cmd). |
| [is_subagent](#captain_hook.BaseHookEvent.is_subagent) | Whether this event came from a subagent payload. |
| [session_crons](#captain_hook.BaseHookEvent.session_crons) | The scheduled prompts registered on this session, `()` when the payload omits them. |
| [skip_permissions](#captain_hook.BaseHookEvent.skip_permissions) | Whether the session's `claude` process was launched with permission bypass available. |
| [tasks](#captain_hook.BaseHookEvent.tasks) | The live task list for this session, read from Claude Code's native task store. |


##### agent_id


The subagent id attached to this event, or None for main-agent events.


`agent_id: str | None`


A missing, null, or empty [agent_id](events-results.md#captain_hook.BaseHookEvent.agent_id) all mean the main agent.


##### background_tasks


The background tasks keeping this session alive, `()` when the payload omits them.


`background_tasks: tuple[`<a href="events-results.html#captain_hook.BackgroundTask" class="gdls-link gdls-code"><code>BackgroundTask</code></a>`, …]`


Populated only on `Stop` and `SubagentStop` events from Claude Code v2.1.145+; a non-empty tuple means the session is paused waiting for background work to wake it, not done.


##### cmd


The event's Bash command as a walkable `~captain_hook.cmd.Cmd`.


`cmd: `<a href="files-commands.html#captain_hook.Cmd" class="gdls-link gdls-code"><code>Cmd</code></a>


Always a [Cmd](files-commands.md#captain_hook.Cmd) -- an empty or non-Bash command yields one with zero calls -- so a handler iterates `evt.cmd.calls(...)` or tests `evt.cmd.call(...)` without a preceding guard. The raw command text is `evt.cmd.raw` (or `str(evt.cmd)`); `evt.cmd.q` and `evt.cmd.line` expose the parsed structure. On a rewrite-capable event, rewrites composed via `~captain_hook.cmd.Call.sub()` splice back through it.


##### command


The event's Bash command as a walkable `~captain_hook.cmd.Cmd` -- an alias for [cmd](events-results.md#captain_hook.BaseHookEvent.cmd).


`command: `<a href="files-commands.html#captain_hook.Cmd" class="gdls-link gdls-code"><code>Cmd</code></a>


Always a [Cmd](files-commands.md#captain_hook.Cmd) (empty for a non-Bash or absent command). The raw command text is `evt.command.raw` or `str(evt.command)`.


##### is_subagent


Whether this event came from a subagent payload.


`is_subagent: bool`


##### session_crons


The scheduled prompts registered on this session, `()` when the payload omits them.


`session_crons: tuple[`<a href="events-results.html#captain_hook.SessionCron" class="gdls-link gdls-code"><code>SessionCron</code></a>`, …]`


Populated only on `Stop` and `SubagentStop` events from Claude Code v2.1.145+; a non-empty tuple means the session is paused for future scheduled work.


##### skip_permissions


Whether the session's `claude` process was launched with permission bypass available.


`skip_permissions: bool`


Walks the process tree to the nearest `claude` ancestor and reports whether that process was started with `--dangerously-skip-permissions` or `--allow-dangerously-skip-permissions`.


##### tasks


The live task list for this session, read from Claude Code's native task store.


`tasks: `<a href="tasks.html#captain_hook.Tasks" class="gdls-link gdls-code"><code>Tasks</code></a>


Unlike transcript-derived `task_ops()`, this reflects updates made by subagents, teammates, or resumed sessions, and is empty when the session has no task store -- it never falls back to another session's tasks.


#### Methods

| Name | Description |
|----|----|
| [as_input()](#captain_hook.BaseHookEvent.as_input) | Return `input` narrowed to `call_type`, or None when it is a different tool call. |
| [context()](#captain_hook.BaseHookEvent.context) | Emit advisory context exactly like [warn()](events-results.md#captain_hook.BaseHookEvent.warn), but without pre-approving the tool. |
| [llm()](#captain_hook.BaseHookEvent.llm) | Ask an LLM a question about this event and return a typed answer. |
| [warn()](#captain_hook.BaseHookEvent.warn) | Emit a warning whose parts are auto-rendered and joined with newlines. |


##### as_input()


Return `input` narrowed to `call_type`, or None when it is a different tool call.


Usage

``` python
as_input(call_type)
```


##### context()


Emit advisory context exactly like [warn()](events-results.md#captain_hook.BaseHookEvent.warn), but without pre-approving the tool.


Usage

``` python
context(*parts)
```


Renders and joins *parts* through the same path as [warn()](events-results.md#captain_hook.BaseHookEvent.warn), then returns a [warn](events-results.md#captain_hook.BaseHookEvent.warn)-action result with `approve=False`. On `PreToolUse` this drops the `permissionDecision: allow` rider a plain warn carries, so the message surfaces as pure `additionalContext` and Claude Code's own permission flow still decides the tool.


##### llm()


Ask an LLM a question about this event and return a typed answer.


Usage

``` python
llm(self, prompt: str | Prompt, model: None = None, contexts: Sequence[PromptContext] = (), signals: Sequence[Signal | NlpSignal] | Signals | None = None, when: Callable[[BaseHookEvent], bool] | None = None, hook: str | None = None, retries: int = 2, max_context: int = 2000, specialty: TSpecialty = 'review', size: TModel = 'small', agent: bool = False, transcript: bool | int | Literal['recent', 'full'] = False, diff: bool | str = False) -> str | None
llm(self, prompt: str | Prompt, model: type[bool], contexts: Sequence[PromptContext] = (), signals: Sequence[Signal | NlpSignal] | Signals | None = None, when: Callable[[BaseHookEvent], bool] | None = None, hook: str | None = None, retries: int = 2, max_context: int = 2000, specialty: TSpecialty = 'review', size: TModel = 'small', agent: bool = False, transcript: bool | int | Literal['recent', 'full'] = False, diff: bool | str = False) -> bool | None
llm(self, prompt: str | Prompt, model: type[int], contexts: Sequence[PromptContext] = (), signals: Sequence[Signal | NlpSignal] | Signals | None = None, when: Callable[[BaseHookEvent], bool] | None = None, hook: str | None = None, retries: int = 2, max_context: int = 2000, specialty: TSpecialty = 'review', size: TModel = 'small', agent: bool = False, transcript: bool | int | Literal['recent', 'full'] = False, diff: bool | str = False) -> int | None
llm(self, prompt: str | Prompt, model: type[M], contexts: Sequence[PromptContext] = (), signals: Sequence[Signal | NlpSignal] | Signals | None = None, when: Callable[[BaseHookEvent], bool] | None = None, hook: str | None = None, retries: int = 2, max_context: int = 2000, specialty: TSpecialty = 'review', size: TModel = 'small', agent: bool = False, transcript: bool | int | Literal['recent', 'full'] = False, diff: bool | str = False) -> M | None
```


The public sugar over the LLM stack: delegates to \[`llm_evaluate`\]\[captain_hook.llm_evaluate\] (contexts, signals, once-per-turn throttling, retries with validation feedback), which calls the backend through `ctx.call_llm`. `model` picks the answer shape: `None` returns the raw `str` reply, `bool`/`int` coerce through a single-field answer schema, and a `BaseModel` subclass returns its validated instance. `size` picks the model tier (`"small"`/`"medium"`/`"large"`).

A skipped call -- already fired this turn, or a `required` context came up empty -- returns `None`; a call that still fails after `retries` re-asks raises.


##### Example

``` python
>>> if evt.llm("Is this print() call debug leftovers?", bool):
...     return evt.warn("Drop the print before finishing.")
```


##### warn()


Emit a warning whose parts are auto-rendered and joined with newlines.


Usage

``` python
warn(*parts)
```


Each part is rendered by form: a plain `str` passes through verbatim; a `(label, value)` tuple becomes `"{label}: {json}"` with `value` JSON-encoded; any other object is JSON-encoded directly. Rendered parts are joined with `"\n"`.


##### Parameters


`*parts: str | tuple[str, object] | object`  
Warning fragments, each a `str`, a `(label, value)` tuple, or any JSON-serializable object.


##### Returns


<a href="events-results.html#captain_hook.HookResult" class="gdls-link gdls-code"><code>HookResult</code></a>  
A warn [HookResult](events-results.md#captain_hook.HookResult) carrying the joined message.


## ToolHookEvent


Event for tool-related hooks, adding tool name, input, command, and file access.


Usage

``` python
ToolHookEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


#### Attributes

| Name | Description |
|----|----|
| [edit](#captain_hook.ToolHookEvent.edit) | Structured before/after view of the pending edit, or `None`. |
| [post_image](#captain_hook.ToolHookEvent.post_image) | The full post-edit file image an Edit/MultiEdit/Write would produce, at PreToolUse. |
| [pre_image](#captain_hook.ToolHookEvent.pre_image) | The full pre-edit file image for an Edit/MultiEdit/Write/span-edit, read from disk at PreToolUse. |
| [replaced](#captain_hook.ToolHookEvent.replaced) | The pre-image of the text this call overwrites, when knowable. |


##### edit


Structured before/after view of the pending edit, or `None`.


`edit: `<a href="prompt-contexts.html#captain_hook.Edit" class="gdls-link gdls-code"><code>Edit</code></a>` | None`


`None` for non-edit tools, files without a supported grammar, and Writes off `PreToolUse` (their pre-image is unknowable once the write lands -- the same rule as [replaced](events-results.md#captain_hook.ToolHookEvent.replaced)). The pre side is [replaced](events-results.md#captain_hook.ToolHookEvent.replaced); the post side is `content`.


##### post_image


The full post-edit file image an Edit/MultiEdit/Write would produce, at PreToolUse.


`post_image: str | None`


A Write is its `content`; an Edit applies `old`→`new` to [pre_image](events-results.md#captain_hook.ToolHookEvent.pre_image) (once, or every occurrence when `replace_all`); a MultiEdit folds its spans in order. A registered MCP span-edit tool yields `None`: its opaque locator can't be resolved to a position without the tool, so the post-image can't be simulated. `None` too when a span's `old` is absent from the running image (the tool call would fail), off `PreToolUse`, or for other tools.


##### pre_image


The full pre-edit file image for an Edit/MultiEdit/Write/span-edit, read from disk at PreToolUse.


`pre_image: str | None`


`None` off `PreToolUse` -- disk already holds the post-edit text -- and for other tools. Unlike [replaced](events-results.md#captain_hook.ToolHookEvent.replaced) (an Edit's `old` fragment), this is always the whole file, so a comment run's full extent is visible even when the edit touched only part of it.


##### replaced


The pre-image of the text this call overwrites, when knowable.


`replaced: str | None`


An Edit's `old` and a MultiEdit's newline-joined olds carry the pre-image at any event. A Write's pre-image is the file's current on-disk content -- `""` for a new file, lossily decoded for non-UTF-8 bytes, `None` for a directory or unreadable path -- and only at `PreToolUse`: once the Write lands, disk already holds the new text, so any other event yields `None`. A registered MCP span-edit tool follows the Write arm -- its opaque locator carries no `old` fragment, so the whole on-disk file stands in as a conservative pre-image (a superset only suppresses, never misreports, an introduced construct). `None` for other tools.


## ToolRewriteEvent


Tool event whose input can be rewritten before it runs.


Usage

``` python
ToolRewriteEvent(_raw, ctx)
```


Base for the events where Claude Code accepts an `updatedInput` decision (`PreToolUse` and `PermissionRequest`), adding the `rewrite*` helpers.


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


#### Methods

| Name | Description |
|----|----|
| [rewrite()](#captain_hook.ToolRewriteEvent.rewrite) | Allow the tool but replace its input with `updated_input` (Claude Code's `updatedInput`). |
| [rewrite_command()](#captain_hook.ToolRewriteEvent.rewrite_command) | Rewrite a Bash command in place, replacing [command](files-commands.md#captain_hook.Call.command) while preserving the rest of the tool input. |
| [rewrite_content()](#captain_hook.ToolRewriteEvent.rewrite_content) | Rewrite each editable-content field through `transform`, allowing the tool with the result. |


##### rewrite()


Allow the tool but replace its input with `updated_input` (Claude Code's `updatedInput`).


Usage

``` python
rewrite(updated_input, *, note=None)
```


`updated_input` must satisfy the same tool's schema; `note` surfaces as `additionalContext` so the model sees that its input was rewritten.


##### rewrite_command()


Rewrite a Bash command in place, replacing [command](files-commands.md#captain_hook.Call.command) while preserving the rest of the tool input.


Usage

``` python
rewrite_command(new_command, *, note=None)
```


##### rewrite_content()


Rewrite each editable-content field through `transform`, allowing the tool with the result.


Usage

``` python
rewrite_content(transform, *, note=None)
```


Maps the transform onto whichever field holds new source for this tool -- an Edit's `new_string`, a Write's `content`, a NotebookEdit's `new_source`, or every span of a MultiEdit's `edits` -- and preserves the rest of the input. Returns None (a no-op) when `transform` leaves every field unchanged, so callers stay idempotent.


## PreToolUseEvent


Fires before a tool is executed. Return a block result to prevent execution.


Usage

``` python
PreToolUseEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## PermissionRequestEvent


Fires when a permission dialog would be shown.


Usage

``` python
PermissionRequestEvent(_raw, ctx)
```


`allow`/[block](prompt-contexts.md#captain_hook.Excerpts.block)/[rewrite](events-results.md#captain_hook.ToolRewriteEvent.rewrite) answer the dialog (block maps to a deny with the message shown to the user); `None` and [warn](events-results.md#captain_hook.BaseHookEvent.warn) fall through, so the dialog shows normally.


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## PostToolUseEvent


Fires after a tool completes successfully, with access to the tool response.


Usage

``` python
PostToolUseEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## PostToolUseFailureEvent


Fires after a tool fails, providing the error message and interrupt status.


Usage

``` python
PostToolUseFailureEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## UserPromptSubmitEvent


Fires when the user submits a prompt, before the agent processes it.


Usage

``` python
UserPromptSubmitEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## StopEvent


Fires when the agent is about to stop. Return a block result to prevent stopping.


Usage

``` python
StopEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## SubagentStartEvent


Fires when a subagent is launched. Provides `agent_type` for filtering.


Usage

``` python
SubagentStartEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## SubagentStopEvent


Fires when a subagent finishes. Provides `agent_type` for filtering.


Usage

``` python
SubagentStopEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## BackgroundTask


A background task keeping the session alive, from a `Stop`/`SubagentStop` payload.


Usage

``` python
BackgroundTask(id, type, status, description, raw)
```


Since Claude Code v2.1.145 a stopping session reports the work still running so a hook can tell "the session is done" from "the session is paused waiting for background work to wake it back up". Each task carries the common fields below plus type-specific extras -- a `shell` task's [command](files-commands.md#captain_hook.Call.command), a `subagent`'s `agent_type`, an `MCP task`'s `server` and [tool](testing.md#captain_hook.T.tool) -- preserved in `raw`.


#### Attributes


`id: str`  
The task's stable identifier.

`type: str`  
The task kind, one of `shell`, `subagent`, `monitor`, [workflow](state-sessions.md#captain_hook.workflow), `teammate`, `cloud session`, or `MCP task`.

`status: str`  
The task's reported lifecycle status.

`description: str`  
A human-readable summary of the task.

`raw: Mapping[str, Any]`  
The full task mapping, including the type-specific fields.


## SessionCron


A scheduled prompt registered on the session, from a `Stop`/`SubagentStop` payload.


Usage

``` python
SessionCron(id, schedule, recurring, prompt)
```


A cron keeps a session alive to re-run `prompt` on `schedule`; its presence means the session is paused for future scheduled work rather than finished.


#### Attributes


`id: str`  
The cron's stable identifier.

`schedule: str`  
The cron schedule expression.

`recurring: bool`  
Whether the cron fires repeatedly rather than once.

`prompt: str`  
The prompt replayed to the agent when the cron fires.


## PreCompactEvent


Fires before context compaction, providing the trigger and custom instructions.


Usage

``` python
PreCompactEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## NotificationEvent


Fires on system notifications, providing message, title, and notification type.


Usage

``` python
NotificationEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## SessionStartEvent


Fires when a session starts, providing what triggered it. Warns inject context; it cannot block.


Usage

``` python
SessionStartEvent(_raw, ctx)
```


is one of `"startup"`, `"resume"`, `"clear"`, or `"compact"`.


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## SessionEndEvent


Fires when the session ends, providing the termination reason. Output is ignored, so it cannot block.


Usage

``` python
SessionEndEvent(_raw, ctx)
```


#### Parameter Attributes


`_raw: dict[str, Any]`  

`ctx: `<a href="events-results.html#captain_hook.HookContext" class="gdls-link gdls-code"><code>HookContext</code></a>  


## HookContext


Runtime context injected into every hook event.


Usage

``` python
HookContext(session, transcript, settings, project_root=None)
```


Holds session state, the transcript `Session`, settings, and LLM/CLI helpers.


#### Parameter Attributes


`session: `<a href="state-sessions.html#captain_hook.SessionStore" class="gdls-link gdls-code"><code>SessionStore</code></a>  

`transcript: Session`  

`settings: `<a href="configuration-prompts.html#captain_hook.HooksSettings" class="gdls-link gdls-code"><code>HooksSettings</code></a>` | None`  

`project_root: Path | None = None`  


#### Attributes

| Name | Description |
|----|----|
| [c](#captain_hook.HookContext.c) | Alias for `settings` (shortest form). |
| [conf](#captain_hook.HookContext.conf) | Alias for `settings`. |
| [prior](#captain_hook.HookContext.prior) | The session window before the current turn's last exchange (cached). |
| [s](#captain_hook.HookContext.s) | Alias for `session`. |
| [state](#captain_hook.HookContext.state) | Alias for `session`. |
| [t](#captain_hook.HookContext.t) | Alias for `transcript`. |
| [turn](#captain_hook.HookContext.turn) | The one-turn view of the current turn (cached), with prompt matching via [matches](events-results.md#captain_hook.Turn.matches). |


##### c


Alias for `settings` (shortest form).


`c: `<a href="configuration-prompts.html#captain_hook.HooksSettings" class="gdls-link gdls-code"><code>HooksSettings</code></a>` | None`


##### conf


Alias for `settings`.


`conf: `<a href="configuration-prompts.html#captain_hook.HooksSettings" class="gdls-link gdls-code"><code>HooksSettings</code></a>` | None`


##### prior


The session window before the current turn's last exchange (cached).


`prior: Session`


##### s


Alias for `session`.


`s: `<a href="state-sessions.html#captain_hook.SessionStore" class="gdls-link gdls-code"><code>SessionStore</code></a>


##### state


Alias for `session`.


`state: `<a href="state-sessions.html#captain_hook.SessionStore" class="gdls-link gdls-code"><code>SessionStore</code></a>


##### t


Alias for `transcript`.


`t: Session`


##### turn


The one-turn view of the current turn (cached), with prompt matching via [matches](events-results.md#captain_hook.Turn.matches).


`turn: `<a href="events-results.html#captain_hook.Turn" class="gdls-link gdls-code"><code>Turn</code></a>


#### Methods

| Name | Description |
|----|----|
| [diff()](#captain_hook.HookContext.diff) | A compact diff via `ccx vcs diff` when available, else plain `git`. |
| [nlp()](#captain_hook.HookContext.nlp) | Whether `text` matches any pattern -- the escape hatch for matching arbitrary prose. |
| [transcript_block()](#captain_hook.HookContext.transcript_block) | The rendered transcript wrapped in a `<transcript>` tag carrying its source path. |
| [transcript_text()](#captain_hook.HookContext.transcript_text) | The transcript rendered turn by turn under the default budget. |


##### diff()


A compact diff via `ccx vcs diff` when available, else plain `git`.


Usage

``` python
diff(source="uncommitted", *, commit=None, scope=None, budget=4000)
```


Prefers cc-context's token-budgeted `ccx vcs diff` and falls back to `git` when `ccx` is absent or failing, so a hook gets a real diff in any repo. The git fallback is bounded to roughly `budget` tokens with a trailing marker when truncated, so a large diff can't blow the caller's context.


##### Parameters


`source: str = ``"uncommitted"`  
`"uncommitted"` (the default), `"staged"`, or any git ref. Ignored when `commit` is set.

`commit: str | None = None`  
When set, the diff *introduced by* this commit (root-commit-safe), overriding [source](files-commands.md#captain_hook.Call.source); its git fallback is `git show --stat -p`, so it carries the commit header + diffstat ahead of the patch.

`scope: str | None = None`  
Restrict the diff to this path.

`budget: int = ``4000`  
Token budget for both the `ccx` output and the bounded git fallback.


##### nlp()


Whether `text` matches any pattern -- the escape hatch for matching arbitrary prose.


Usage

``` python
nlp(text, *patterns)
```


A string pattern is a case-insensitive regex; a `~captain_hook.Clause` runs the dependency-clause scan. For the current turn's prompt, prefer `evt.ctx.turn.matches(*patterns)`.


##### Example

``` python
>>> evt.ctx.nlp(evt.ctx.t.assistant_text(), Clause(noun=Phrase("test"), verb=Phrase("skip")))
```


##### transcript_block()


The rendered transcript wrapped in a `<transcript>` tag carrying its source path.


Usage

``` python
transcript_block(*, window=RECENT_WINDOW)
```


Defaults to a recent-event window rather than the whole session. The render clips long turns and tool calls under `Budget`, so an agent-mode LLM uses the path to read the untruncated content (e.g. a full `ExitPlanMode` plan) or earlier history.


##### Parameters


`window: int | None = RECENT_WINDOW`    
Render only the most recent `window` events; `None` renders the whole session.


##### transcript_text()


The transcript rendered turn by turn under the default budget.


Usage

``` python
transcript_text(*, window=None)
```


##### Parameters


`window: int | None = None`  
Render only the most recent `window` events; `None` renders the whole session.


## Turn


The current turn as a one-turn `~cc_transcript.query.Session` view.


Usage

``` python
Turn(turns, path=None, attachments=())
```


What `evt.ctx.turn` returns: the full windowed transcript surface (`user_text`, `has_tool`, `tool_calls`, …) plus prompt matching, so hooks can test the turn's opening prompt without importing the NLP machinery.


#### Methods

| Name | Description |
|----|----|
| [matches()](#captain_hook.Turn.matches) | Whether the turn's opening prompt matches any pattern. |


##### matches()


Whether the turn's opening prompt matches any pattern.


Usage

``` python
matches(*patterns)
```


A string pattern is a case-insensitive regex; a `~captain_hook.Clause` runs the dependency-clause scan.


##### Example

``` python
>>> evt.ctx.turn.matches(Clause(noun=Phrase("work"), verb=Phrase("stop", "halt")))
```


## HookResult


The return value from a hook handler, specifying the action and optional message.


Usage

``` python
HookResult(
    *, action, message=None, updated_input=None, note=None, approve=True
)
```


`updated_input` and `note` carry the [rewrite](events-results.md#captain_hook.ToolRewriteEvent.rewrite) action's replacement tool input and the advisory context surfaced alongside it. [approve](primitives.md#captain_hook.approve) gates the `PreToolUse` `permissionDecision: allow` rider a [warn](events-results.md#captain_hook.BaseHookEvent.warn) normally carries: `False` surfaces the message as pure `additionalContext` without pre-approving the tool (the `evt.context` variant).


#### Parameter Attributes


`action: `<a href="events-results.html#captain_hook.Action" class="gdls-link gdls-code"><code>Action</code></a>  

`message: str | None = None`  

`updated_input: dict[str, Any] | None = None`  

`note: str | None = None`  

`approve: bool = ``True`  


#### Methods

| Name | Description |
|----|----|
| [of()](#captain_hook.HookResult.of) | Build a [HookResult](events-results.md#captain_hook.HookResult), dedenting and stripping `message` for readable triple-quoted handler returns. |


##### of()


Build a [HookResult](events-results.md#captain_hook.HookResult), dedenting and stripping `message` for readable triple-quoted handler returns.


Usage

``` python
of(action, message=None)
```


## Action


Hook result action determining how the hook output is handled.


Usage

``` python
Action()
```


- [block](prompt-contexts.md#captain_hook.Excerpts.block): Prevents the tool use or stops the agent.
- [warn](events-results.md#captain_hook.BaseHookEvent.warn): Adds advisory context without blocking.
- `allow`: Explicitly permits the action.
- [rewrite](events-results.md#captain_hook.ToolRewriteEvent.rewrite): Replaces a `PreToolUse` tool's input with `updated_input` and allows it.


## Agent


Condition matching the current event's subagent type against one or more names.


Usage

``` python
Agent(*names)
```


Exact membership (not a regex). Pass names variadically, or as a single `|`-joined string for back-compat (`Agent("Explore|claude-code-guide")` is `Agent("Explore", "claude-code-guide")`).


#### Parameter Attributes


`names: str = ()`
