Use the mods API changedplugins/mods/api
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+10added
Lines−10removed
From line
86
where the diff opens
First seen
1 Oct 2026
this site's first read of the page
Recorded edits2to this page, all time
The whole hunk
from line 86, old and new numbered
/
from line 86
8686
8787When you run `/triage the export button does nothing`, the mod sends that text to the model and prints its answer, such as `Label: bug`. Claude's conversation isn't part of the request. When the model doesn't answer, the label is `unknown`.
8888
89A Claude API failure doesn't reject the call, so check `r.isAnswered`, and read `r.reason` when it's `false`. The call rejects only for a request Claude Code won't send, such as a model your organization blocks. [The types for your build](/docs/en/plugins/mods/create#get-the-types-for-your-build) list the other options, such as `effort`, and the [limits](/docs/en/plugins/mods/reference#limits) give the `maxTokens` default.
89A Claude API failure doesn't reject the call, so check `r.isAnswered`, and read `r.reason` when it's `false`. The call rejects for a request Claude Code won't send, such as a model your organization blocks. [The types for your build](/docs/en/plugins/mods/create#get-the-types-for-your-build) list the other options, such as `effort`, and the [limits](/docs/en/plugins/mods/reference#limits) give the `maxTokens` default.
9090
9191`$.model.fork({ prompt })` asks one question over the current conversation instead, with the same model and system prompt, so the Claude API serves most of it from the prompt cache.
9292
from line 94
9494
9595## Run work in the background
9696
97Work that outlives one event, such as checking on something once a minute, runs on a timer you start from `session.start`. A hook itself runs for one event and has a time limit of 10 seconds of its own running time. Time spent waiting on `next` or on a mods API call doesn't count, except a `$.clock.sleep`. `$.clock.every` and `$.clock.after` take the place of `setInterval` and `setTimeout`, with the delay in milliseconds first: `$.clock.after(5000, fn)` calls `fn` once, five seconds from now. Each returns a timer with a `cancel()` method, and `await $.clock.now()` gives the time in milliseconds.
97Work that outlives one event, such as checking on something once a minute, runs on a timer you start from `session.start`. A hook itself runs for one event and has a [time limit](/docs/en/plugins/mods/reference#limits) on its own execution time. Time spent waiting on `next` or on a mods API call doesn't count, except a `$.clock.sleep`. `$.clock.every` and `$.clock.after` take the place of `setInterval` and `setTimeout`, with the delay in milliseconds first: `$.clock.after(5000, fn)` calls `fn` once, five seconds from now. Each returns a timer with a `cancel()` method, and `await $.clock.now()` gives the time in milliseconds.
9898
9999This hook looks up a pull request's checks once a minute and shows the result under the prompt. `summarize` is a function of your own that turns the command's JSON output into a few words:
100100
from line 120
120120| Call | What the user sees |
121121| :- | :- |
122122| `$.ui.status(text)` | One line under the prompt that stays until you change it. It starts with `⚠` and the mod's name, as in `⚠ my-mod: checks: 3 passing`. |
123| `$.ui.toast(text)` | A small box at the top right, with the mod's name above the text, that disappears after a few seconds |
123| `$.ui.toast(text)` | A toast notification at the top right, with the mod's name above the text, that disappears after a few seconds |
124124| `$.ui.log(text)` | A dim line in the transcript that Claude doesn't read. It starts with `●` and the mod's name, as in `● my-mod: build finished`. |
125125
126126### Start a turn from a background job
from line 129
129129
130130### Stop background work
131131
132Background work stops in two ways. Timers stop when the module reloads. For long-running work inside a hook, [`next.signal`](/docs/en/plugins/mods/reference#the-hook-function) is an `AbortSignal` that aborts when the event your hook is handling is abandoned, for example when the user interrupts, so pass it to anything long-running.
132Timers stop when the module reloads. For long-running work inside a hook, [`next.signal`](/docs/en/plugins/mods/reference#the-hook-function) is an `AbortSignal` that aborts when the event your hook is handling is abandoned, for example when the user interrupts, so pass it to anything long-running.
133133
134134## Send and receive messages between sessions
135135
from line 148
148148})
149149```
150150
151When the message is queued, nothing appears in your session, and the other session's Claude reads `Status? One line.` When nothing was delivered, a small box at the top right gives the reason and disappears after a few seconds.
151When the message is queued, nothing appears in your session, and the other session's Claude reads `Status? One line.` When nothing was delivered, a toast notification gives the reason.
152152
153Two events let a mod observe the messages. Return `next(e)` from both to pass each message through unchanged:
153`session.receive` and `session.send` let a mod observe the messages. Return `next(e)` from both to pass each message through unchanged:
154154
155155| Event | Fires when | Useful fields |
156156| :- | :- | :- |
from line 171
171171| `$.process` | `run(['git', 'status'])` starts a command and resolves when it exits. `spawn` streams a long-running command's output. |
172172| `$.http` | `fetch(url, init)` over `http` or `https`. It resolves to `{ status, ok, headers, text }` once the body is read. |
173173| `$.store` | A JSON key-value store of your plugin's own, kept between sessions |
174| `$.env` | `get` and `set` environment variables. Write the name as a literal string. |
174| `$.env` | `get` and `set` environment variables. Write the name as a string literal. |
175175| `$.settings` | `read` what the settings files and managed policy hold |
176176| `$.session` | `messages()` returns the transcript as a list of `{ role, text, toolUses }`. Also the working directory, model, and more. [`usage()`](/docs/en/plugins/mods/reference#mods-api-methods) returns context window use and plan limits. |
177177| `$.mcp` | `call` a tool on a connected MCP server |
from line 178
178178
179179Files and processes have a few rules of their own:
180180
181* **Paths**: a relative path is under the session's working directory
182* **`$.fs.list`**: returns one directory's entries as `{ name, kind, size, isLink }` and doesn't descend into subdirectories
181* **Paths**: a relative path resolves against the session's working directory
182* **`$.fs.list`**: returns one directory's entries as `{ name, kind, size, isLink }` and isn't recursive
183183* **`$.process.run`**: takes an argument list and uses no shell. It resolves to `{ exitCode, stdout, stderr }` whatever the exit code. It rejects if the program can't start or is still running at the timeout, which is 30 seconds by default, so wrap it in `try` and `catch`.
184184
185185Every one of these calls is itself an event, named for its namespace and method without the `$.`, such as `fs.read` for `$.fs.read`. A mod [earlier in the chain](/docs/en/plugins/mods/events#the-order-mods-run-in) can observe, rewrite, or refuse your call, which is how an organization restricts what mods reach.
from line 189
189189* [React to events](/docs/en/plugins/mods/events): hook tool calls, prompts, and turns
190190* [Draw in the interface](/docs/en/plugins/mods/interface): show what your mod collects in a pane or above the prompt
191191* [Test a mod](/docs/en/plugins/mods/test): stub any of these calls in a test
192* [Mods reference](/docs/en/plugins/mods/reference): every event, every mods API method, and the limits
192* [Mods reference](/docs/en/plugins/mods/reference): events, mods API methods, and limits
193193
No line in this hunk matches that.