React to events with a mod changedplugins/mods/events
Nearest release: v2.1.287, published 11 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 2 Oct 2026 04:34 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 2 Oct 2026 04:37 UTC.
Upstream edited
Recorded here
Lines+14added
Lines−12removed
From line
42
where the diff opens
First seen
1 Oct 2026
this site's first read of the page
Recorded edits3to this page, all time
### Hook the settings hook events
The whole hunk
from line 42, old and new numbered
/
from line 42
4242
4343### Rewrite an event
4444
45To change what Claude Code acts on, such as the text of a prompt, call `next` with a modified copy of the event. The event itself is immutable: it's frozen at every depth, and assigning to a field throws. This hook trims each prompt before it's sent:
45To change what Claude Code acts on, such as the text of a prompt, call `next` with a modified copy of the event. The event itself is immutable: it's deeply frozen, and assigning to a field throws. This hook trims each prompt before it's sent:
4646
4747```javascript theme={null}
4848on('prompt.submit', async ($, e, next) => {
from line 83
8383
8484`hook` runs once for a Bash, Edit, or Write call, and once for a call to a tool whose name starts with `mcp__github__`. A call to any other tool, such as Read, matches none of the three, so `hook` doesn't run for it.
8585
86The event name can be a wildcard. `'classic.*'` matches every [settings hook event](#hook-the-settings-hook-events). `'*'` matches every event except the [telemetry events](/docs/en/plugins/mods/reference#telemetry), which you hook by name or as `'telemetry.*'`.
86The event name can be a wildcard. `'classic.*'` matches every [settings hook event](#hook-the-settings-hook-events). `'*'` matches every event except the [telemetry events](/docs/en/plugins/mods/reference#telemetry), which take their own name and a `{ to: 'collector' }` filter.
8787
8888Register each event once per matcher. If you call `on` twice for `session.start` with no matcher, the module fails to load with `on("session.start") is registered twice without a matcher`. Put everything your mod does at session start in one hook.
8989
9090## Hook what Claude is doing
9191
92Hook these events to see or change a tool call, a prompt, or a turn as it happens. For every event and what a hook can return, see the [events reference](/docs/en/plugins/mods/reference#events).
92Handle these events to see or change a tool call, a prompt, or a turn as it happens. For every event and what a hook can return, see the [events reference](/docs/en/plugins/mods/reference#events).
9393
9494### Guard or change a tool call
9595
from line 168
168168* **The user types an answer**: `$.ui.ask` resolves to the typed text. The hook compares it with `Run it`, so any other text refuses the command.
169169* **Nobody answers**: `$.ui.ask` rejects when the user dismisses the question or picks **Chat about this**, and in a `claude -p` run, so the `catch` block leaves the answer at `Refuse`
170170
171Keep the wait inside a mods API call such as `$.ui.ask`, because that time doesn't count against the hook's [10-second time limit](/docs/en/plugins/mods/reference#limits). Time spent awaiting a promise of your own does count. Claude Code skips a hook that times out, so the held command would run.
171Keep the wait inside a mods API call such as `$.ui.ask`, because that time doesn't count against the hook's [time limit](/docs/en/plugins/mods/reference#limits). Time spent awaiting a promise of your own does count. Claude Code skips a hook that times out, so the held command would run.
172172
173173#### Approve or refuse a tool call before the user is asked
174174
from line 193
193193
194194The hook matches the text of the command, so treat it as a reminder for Claude. To block pushes to `main` for everyone, protect the branch on your Git host.
195195
196A hook can return any of the three decisions, so it can also approve a call that a `PreToolUse` hook outside managed settings blocked. [Extend permissions with hooks](/docs/en/permissions#extend-permissions-with-hooks) lists which decisions hold over a mod.
196A hook can return `allow`, `ask`, or `deny`, so it can also approve a call that a `PreToolUse` hook outside managed settings blocked. [Extend permissions with hooks](/docs/en/permissions#extend-permissions-with-hooks) lists which decisions hold over a mod.
197197
198198### Rewrite or add to a prompt
199199
from line 225
225225
226226### Follow a turn
227227
228A turn is everything Claude does in answer to one prompt. Hook `turn.start`, `turn.step`, and `turn.complete` to follow one:
228A turn is everything Claude does in answer to one prompt. Handle `turn.start`, `turn.step`, and `turn.complete` to follow one:
229229
230230| Event | When it fires | What a hook can do |
231231| :- | :- | :- |
from line 251
251251
252252Claude's response streams to the screen as it does without the mod. After each request finishes, a dim line in the transcript gives the number of tokens read from the cache and the number written to it. A turn with tool calls has several requests, so it adds several lines.
253253
254`result.usage` holds the four token counts the Claude API reports for a request, plus the `model` that answered: `input_tokens`, `output_tokens`, `cache_read_input_tokens`, and `cache_creation_input_tokens`. The hook runs for subagents' requests too, so check `e.agentId` when you want only the main conversation.
254`result.usage` holds the token counts the Claude API reports for a request, plus the `model` that answered: `input_tokens`, `output_tokens`, `cache_read_input_tokens`, and `cache_creation_input_tokens`. The hook runs for subagents' requests too, so check `e.agentId` when you want only the main conversation.
255255
256### Hook the settings hook events
256<h3 id="hook-the-settings-hook-events">
257 Handle the settings hook events
258</h3>
257259
258260Settings hooks are the command, HTTP, prompt, and agent hooks you configure in settings files. Each [settings hook event](/docs/en/hooks#hook-events), such as `Stop`, `SessionEnd`, or `PostToolUse`, is also an event named `classic.` followed by the settings hook event's name, such as `classic.Stop`. `e` is the JSON a settings hook receives on stdin, including `transcript_path`.
259261
from line 274
272274
273275## Run alongside other mods
274276
275Several mods can hook the same event, and any one of them can fail. If your mod blocks tool calls, check its position in the chain and what happens when its hook fails.
277Several mods can handle the same event, and any one of them can fail. If your mod blocks tool calls, check its position in the chain and what happens when its hook fails.
276278
277279### The order mods run in
278280
from line 317
315317})
316318```
317319
318While `guard` works, the handler never runs. When `guard` throws or times out on a Bash call, Claude Code calls the handler with the same event. The handler returns `{ deny }`, so the command doesn't run, and Claude reads the text with `throw` or `timeout` at the end. Without the handler, Claude Code would skip `guard` and run the command. The handler has [one second](/docs/en/plugins/mods/reference#limits) to answer.
320While `guard` works, the handler never runs. When `guard` throws or times out on a Bash call, Claude Code calls the handler with the same event. The handler returns `{ deny }`, so the command doesn't run, and Claude reads the text with `throw` or `timeout` at the end. Without the handler, Claude Code would skip `guard` and run the command. The handler has a shorter [time limit](/docs/en/plugins/mods/reference#limits) of its own.
319321
320322## Next steps
321323
322324* [Use the mods API](/docs/en/plugins/mods/api): add commands and tools, call a model, and run work on a timer
323325* [Draw in the interface](/docs/en/plugins/mods/interface): show what your hooks collect in a pane or above the prompt
324* [Test a mod](/docs/en/plugins/mods/test): raise any of these events from a test
326* [Test a mod](/docs/en/plugins/mods/test): fire any of these events from a test
325327* [Mods reference](/docs/en/plugins/mods/reference): every event, every mods API method, and the limits
326328
No line in this hunk matches that.