What changed, release by release.
Every release's mods API against the one before it: which nouns, verbs, events and types it added, which it removed, and which changed shape, with the lines that moved. A removal is marked breaking; a change that took something out may break a mod; one that only added to a shape is marked extended.
v2.1.281
+41 added · 0 removed · 2 changed · 6 docs only since 2.1.280The engine
-
Returns the version of the engine the session runs on, the release it is built from, and when it was built.
-
Named values held by the host for the session, each with a version: plain data that survives a hot reload of the plugin's code.
-
Resolves the value under
refand the version it stands at; a value never written isundefinedat version 0. -
Writes
valueunderref, which must be this plugin's own; the sites that read it while drawing are drawn again, at the redraw rate.
Events
-
The argument of
$.session.version(). -
The argument of
$.state.get(ref): the reference itself,plugin,keyand a family member'sid; identity, pinned. -
The argument of
$.state.set(ref, value, { ifVersion }): the reference, the value, the condition, andprevious, what stood there (the host's).
Types
-
What each call on
$answers (thevalueof its event's result), by event name.'session.surfaces': readonly RenderSurface[]; 'session.authorize': SessionAuthorization; 'session.usage': SessionUsage; 'session.version': SessionVersion; 'turn.abort': void; 'prompt.read': PromptBox; 'tool.list': ToolInfo[];… 'store.set': void; 'store.delete': void; 'store.keys': string[]; 'state.get': StateRead; 'state.set': StateSetResult; 'clock.now': number; 'clock.sleep': void; 'clock.after': void; -
What a hooks module uses, as the host scanned its source before loading it: the same lists
claude plugin validateprints and the host's rule reads.reads: readonly string[]; writes: readonly string[]; }; state?: { reads: readonly StateName[]; writes: readonly StateName[]; };}; -
A named value with its initial, as
atom(ref, initial)makes it: read, it is neverundefined; while nothing is written it reads as the initial. -
atom(ref, initial): a named value with its initial, so a read is neverundefined; given{ shape }, for a key declaredShaped<T>. -
The options of
atom:shape, a tag the value is kept under, so a reload of the plugin's code that names another tag finds the value absent. -
The state events of each declared value in a union of
[plugin, key]pairs, one variant per pair (it distributes), so a matcher narrowse. -
eofstate.getand ofstate.setfor one declared value: its typed reference, and for a write the change, of the declared type. -
Every named value the enabled contracts declare, as one union of
[plugin, key]pairs;neverwhile PluginState is empty. -
What a
state.seton one declared value carries beside its reference: the value being written and the one that stood there, of the declared type. -
derive(sources, fn): a value computed from atoms and references, cached by their versions:readrunsfnagain only when one moved. -
A value computed from other values, as
derive(sources, fn)makes it:readrunsfnagain only when a source's version moved. -
memberOf(family, e): the member of a family for the instance being drawn, keyed bye.requestId; of an atom over a family, that member's. -
The named values plugins keep in the session (
$.state), by plugin name then key, for declaration merging; empty by default. -
read($, source): the value of an atom (its initial while absent), of a derived value, or under a plain reference; one$.state.getper value. -
What
$.session.version()answers: the version of the engine the session runs on, the release that version is built from, and when it was built. -
A value kept with a shape tag, as an
atomgiven{ shape }keeps it: a reload whose code names another tag reads the value as absent. -
What an atom given a shape reads and takes for a key declared
Shaped<T>:T;neverfor a key declared otherwise, so that atom does not compile. -
The values
derive's function receives for its sources, in their order: an atom's or a derived value's own, a plain reference's orundefined. -
Which named value a
$.statecall is about, as it crosses to the host: the owning plugin, the key, and a family member'sid. -
What the state library's
readandupdatetake of$: itsstatenoun, on which they make the calls a hook would make itself. -
A key of PluginState that holds one value of type
Tperid(one per drawn row, per worker): its reference must carryid: string. -
eofstate.get: one variant per value a contract declares, so a matcher onpluginandkeynarrows it; the untyped address while none does. -
Which named value: the plugin that owns it and its key there, both literals where a contract declares the value.
-
What
$.state.getanswers: the value and the version it stands at; a value never written isundefinedat version 0. -
A typed reference to one named value: the owning plugin and the key, both literals, and for a StateFamily key the member's
id. -
eofstate.set: one variant per value a contract declares, so a matcher onpluginandkeynarrowse.value; the untyped write while none does. -
The options of
$.state.set:ifVersionmakes the write conditional on the value still standing at that version (compare-and-set). -
What
$.state.setanswers: whether the write landed, and the version the value stands at now (a landed write's own, a missed one's the current). -
The type of the value under key
Kof pluginP, as its contract declares it in PluginState; a StateFamily's member type for a family key. -
A
$.state.setas it crosses to the host and as its hooks see it when no contract declares the value: the address, the value, and the condition. -
update($, target, fn): reads the value, appliesfnhere in the plugin's environment, writes withifVersion, and tries again on a miss. -
A named value with its initial:
readanswers the initial while nothing is written, so neverundefined. Pure; runs in the plugin's environment. -
A value computed from atoms and references, cached by their versions.
-
A family's member for the instance being drawn, keyed by
e.requestId. -
Reads an atom, a derived value or a reference through
$.state.get; while aui.renderhook draws, that subscribes the drawing. -
Reads, applies
fnin the plugin's environment, writes withifVersion, and tries again on a miss: what a handler closure calls.
6 docs only: reworded, same shape
$.ui.toastverbShows
textfor a few seconds under the plugin's name: a small box on the stack of plugin toasts over the transcript's top right corner.ElementstypeThe element constructors each surface draws, by
e.surface: what$.ui.resolve(e)returns and aui.resolvehook passes on; no globals.PaneOpenArgstypeThe argument of
$.ui.open: which pane, its title, whether it asks the person's keyboard, its dialog manners, its size: rows inline, columns docked.RenderPropsOftypeThe plain-data props of each renderable component, as
ui.rendersees them undere.props; a hook rewrites them withnext({ ...e, props }).RenderViewporttypeThe size of what a surface draws into, in character cells of the surface's monospace metric, and whether its layout docks a pane.
UiOpenResulttypeWhat
$.ui.openresolves to and what aui.openhook's{ value }holds.
v2.1.280
+40 added · 2 removed · 21 changed · 27 docs only since 2.1.278The engine
-
Runs one text completion through the session's own API client and resolves a result: the reply's text and cost, or why there is no text.
(request: ModelCompleteRequest) => Promise<string>(request: ModelCompleteRequest) => Promise<ModelCompleteResult> -
Runs one tool-less completion over the session's OWN transcript as the main thread last sent it, so the API serves that prefix from its cache.
(request: ModelForkRequest) => Promise<ModelForkResult | null>(request: ModelForkRequest) => Promise<ModelForkResult> -
Returns the transcript so far, one SessionMessage per user or assistant message; progress rows,
$.ui.loglines and notices are not messages.() => Promise<SessionMessage[]>SessionMessagesCall -
Opens a pane, a framed region the surface places and this plugin draws by hooking
ui.renderfor{ component: "Pane" }; says if it is drawn.(pane: PaneOpenArgs) => Promise<void>(pane: PaneOpenArgs) => Promise<UiOpenResult> -
Starts a command on the host by its argument vector (no shell) and streams what it writes, piece by piece, then how it ended.
-
Sends a plain-text message to another agent or session: the event
session.send, the model's SendMessage tool's own call and delivery. -
Puts
texton the clipboard of a surface the session draws on, as the DOM'snavigator.clipboard.writeText, and says whether it took.
Events
-
The argument of
$.session.messages(args):{}for the main conversation,{ agentId }for one of its agents,asfor the form.NoArgsSessionMessagesArgs -
The argument of
$.process.spawn(request): the request itself. -
Fires when a plain-text message is about to leave this conversation for another agent or session (the SendMessage tool, or
$.session.send). -
{ isDelivered: true }, or{ isDelivered: false, reason }. -
The argument of
$.ui.copy({ text, surface }),surfacefilled with the session's first when left out; rewritable, deniable, answerable.
Types
- removed
ContextApiUsagetype breakingThe token counts the last API response of the live window reported, as the API spells them; the breakdown's
Messagesrow is reconciled to it. - removed
ModelForkUsagetype breakingWhat one fork cost, as the API counted it: the four token counts of the fork's completions summed.
-
The chunk type of each streaming event, by name: what its stream yields.
export type ChunkOf = { 'turn.step': TurnStepChunk; 'process.spawn': ProcessSpawnChunk;}; -
What a test holds as
$, the engine's own: every call on it is made as the REPL, the query loop and the render sites make theirs, over every plugin.export type Engine = { [N in keyof EventCalls]: N extends 'ui' ? EngineNoun<N> & EnginePress & EngineMount : EngineNoun<N>; [N in keyof EventCalls]: N extends 'ui' ? EngineNoun<N> & EnginePress & EngineInput & EngineSelect & EngineMount : EngineNoun<N>;} & { classic: EngineClassic;}; -
The engine's own events as calls on
$, one signature each:$.<noun>.<event>(input)resolves to its result, or to its stream.session: { start: (input: SessionStartInput) => Promise<SessionStartResult>; receive: (input: SessionReceiveInput) => Promise<SessionReceiveResult>; send: (input: SessionSendArgs) => Promise<SessionSendResult>; compact: (input?: SessionCompactArgs) => Promise<SessionCompactResult>; attach: (input: SessionAttachInput) => Promise<SessionAttachResult>; detach: (input: SessionDetachInput) => Promise<SessionDetachResult>; -
What
$.model.completetakes.prompt: string; system?: string; maxTokens?: number; effort?: ModelEffort; timeoutMs?: number;}; -
What
$.model.forkresolves to: a completion's result (ModelCompleteResult) or that there was nothing to fork yet.export type ModelForkResult = { text: string; usage: ModelForkUsage;export type ModelForkResult = ModelCompleteResult | { isAnswered: false; reason: 'nothing-to-fork';}; -
What each call on
$answers (thevalueof its event's result), by event name.export type OpValueOf = { 'model.complete': string; 'model.complete': ModelCompleteResult; 'model.classify': string | undefined; 'model.fork': ModelForkResult | null; 'model.fork': ModelForkResult; 'audio.play': void; 'audio.speak': SpeakResult; 'mcp.call': McpToolResult;… 'session.model': string; 'session.turns': number; 'session.id': string; 'session.messages': SessionMessage[]; 'session.messages': SessionMessagesValue; 'session.repo': SessionRepo | null; 'session.surface': RenderSurface | null; 'session.surfaces': readonly RenderSurface[];… 'ui.log': void; 'ui.notice': void; 'ui.invalidate': void; 'ui.open': void; 'ui.open': UiOpenResult; 'ui.close': void; 'ui.panes': readonly UiPane[]; 'ui.copy': UiCopyResult; 'ui.blit': UiBlitResult; 'fs.read': string | FsBytes; 'fs.write': void;… 'clock.every': void; 'http.fetch': HttpResponse; 'process.run': ProcessRunResult; 'process.spawn': ProcessSpawnResult; 'settings.read': Settings; 'env.get': string | undefined; 'env.set': void; -
A compaction that stands: the conversation as it reads afterwards, and the counts and request usage the engine recorded when it was the one compacting.
messages: readonly SessionMessage[]; tokensBefore?: number; tokensAfter?: number; usage?: ModelUsage; skip?: undefined;}; -
The context window broken down as /context breaks it down: the rows, the grid and the lists beneath it, in the SDK's
get_context_usageshape.skills?: ContextSkills; autoCompactThreshold?: number; isAutoCompactEnabled: boolean; apiUsage: ContextApiUsage | null; apiUsage: ModelUsage | null;}; -
The input of
session.receive: one inbound delivery, sanitized, before it is queued (a relay's event, a peer's message, a message for an agent).origin: SessionReceiveOrigin; text: string; event?: SessionReceiveEvent; agentId?: string;}; -
Where an inbound delivery came from, as the bridge classified it from the server's stamps:
prompt.submit'se.origin, less what never arrives.export type SessionReceiveOrigin = { kind: 'bridge' | 'task-notification' | 'scheduled-trigger' | 'peer' | 'peer-send-message' | 'projects-relay' | 'slack-ping' | 'unclassified'; kind: 'bridge' | 'task-notification' | 'scheduled-trigger' | 'peer-send-message' | 'projects-relay' | 'slack-ping' | 'unclassified';} | { kind: 'peer' | 'coordinator'; plugin?: string;} | { kind: 'peer' | 'coordinator'; plugin?: string; teammate: string; isVerified: boolean;}; -
What
$.session.usage()answers: when the session began, the context window's fill, the account's rate-limit windows and the session's cost.export type SessionUsage = { startedAt: number; context: SessionContextUsage; rateLimits: SessionRateLimit[]; cost?: SessionCost; -
The rest of the chain as a hook on a streaming event receives it: Next, except that
next(e)is the stream beneath (HookStream), not a promise.export type StreamNext<N extends StreamingEventName = StreamingEventName, E = Args<N>, O = NextResult<N>, S extends {export type StreamNext<N extends StreamingEventName = StreamingEventName, E = Args<N>, O = EventResult<N>, S extends { [K in N]?: unknown;} = { [K in N]: Args<K>; -
The events that stream: their hooks are async generators,
next(e)is the stream of everything beneath, and the result is what it returns.export type StreamingEventName = 'turn.step';export type StreamingEventName = 'turn.step' | 'process.spawn'; -
What a
tool.callhook returns and whatnext(e)and$.tool.call(input)resolve to: the tool's result ({ result, context? }) or{ deny }.ref?: undefined; text?: undefined; isError?: undefined; isReadOnly?: undefined;} | { result: ToolResultOf<Name>; context?: readonly string[]; ref?: number; text?: string; isReadOnly?: true; isError?: undefined; deny?: undefined;} | {… text?: string; ref?: number; context?: readonly string[]; isReadOnly?: true; deny?: undefined;}; -
One tool_use block of an assistant message, with its outcome once the transcript holds the call's tool_result (paired by
tool_use_id).result?: unknown; text?: string; isError?: true; agentId?: string; durationMs?: number;}; -
What a model turn, or one response inside it, cost as the API reported it: the four token counts (ModelUsage) and the model's id.
export type TurnUsage = ModelForkUsage & {export type TurnUsage = ModelUsage & { model: string;}; -
One content block of an ApiMessage:
typenames its kind (text,tool_use,tool_result,image,document,thinking, ...). -
One message of the conversation in Messages API form, as
$.session.messages({ as: "api" })returns it. -
A classic hook event the engine raises on its own, by its own name (
SessionStart,Stop): all butPreToolUse, which ridestool.call. -
What
$.classic.<Event>takes: the event's own fields as its hook sees them one, less what the engine stamps at every call site. -
The classic (settings) hook events as the engine raises them: each a call running the
classic.<Event>chain over every plugin hooked on it. -
A surface typing into an Input a test rendered: the
ui.inputchain over every plugin hooked on it, the Input's own handler last. -
A surface picking an option of a Select a test rendered: the
ui.selectchain over every plugin hooked on it, the Select's ownonSelectlast. -
What
$.ui.inputtakes: the plugin whose hook drew the Input, itskey, the field's text, which input it is, instance and surface when several. -
Which kind of API failure ended a model call (a completion, a fork), in the word Claude Code classifies every API error with (StopFailure's).
-
What one model call resolves to: the reply when the model answered (
isAnswered), else which of three things left it without text (reason). -
How hard a request asks the model to think, by the levels the engine and
turn.stepname:lowtomax,xhighbetweenhighandmax. -
What one model call cost, as the API counted it: the four token counts in the API's spelling, summed over the call's responses when it made several.
-
One piece of a spawned child's output as
$.process.spawnstreams it: which pipe it came from, and the text. -
The argument of
$.process.spawn(request), and theeits hooks see: the command by its argument vector and how the child is started. -
How a spawned child ended, as the stream of
$.process.spawnreturns it once every piece has been read: its exit code, or the signal that did it. -
What
$.ui.selecttakes: the plugin whose hook drew the Select, itskey, the picked option's value, instance and surface when several. -
A
$.session.messagescall for the rows (SessionMessage) of the main conversation or of one agent's:agentIdalone, noas. -
A
$.session.messagescall for the Messages API form (ApiMessage) of the main conversation or, withagentId, of one of this session's agents'. -
What
$.session.messages({ as: "api", agentId })resolves to: the agent's conversation as ApiMessage, or{ deny }(SessionMessagesDeny). -
What
$.session.messages(args)takes and asession.messageshook reads one: whose conversation (agentId) and in which form (as). -
$.session.messages: the main conversation's rows with no argument, with{ as: "api" }its Messages API form; withagentIdan agent's, or deny. -
What
$.session.messages({ agentId })resolves to when the id names no conversation this session can read: why not, indeny. -
A
$.session.messages({ as: "api" })call naming no agent: the main conversation, whose answer is always the messages (ApiMessage). -
What
$.session.messages({ agentId })resolves to: the messages (SessionMessage), or{ deny }(SessionMessagesDeny). -
What a
session.messageshook's{ value }holds, for any call: the rows (SessionMessage), the Messages API form (ApiMessage), or{ deny }. -
Whom
$.session.sendaddresses: a recipient as the SendMessage tool names one (a string), or a session or an agent of this session by id. -
session.send's input as a plugin's$.session.send(args)takes it:origin(the calling plugin) andagentIdare the engine's to set. -
The input of
session.send: one plain-text message about to leave this conversation for another agent or session; the dual ofsession.receive. -
Who is sending at
session.send: the model through its SendMessage tool, or a plugin through$.session.send; stamped by the engine, pinned. -
What a
session.sendhook returns andnext(e)and$.session.sendresolve to: whether the message was delivered, and why not when not. -
The argument of
$.ui.copyand the input ofui.copy: the text, and which surface's clipboard takes it, the caller's choice. -
What
$.ui.copyresolves to and what aui.copyhook's{ value }holds: whether the text reached a clipboard (isCopied), else why not. -
What
$.ui.openresolves to and what aui.openhook's{ value }holds.
27 docs only: reworded, same shape
$.clock.sleepverbResolves after
msmilliseconds; rejects at once whensignalaborts.$.prompt.submitverbSubmits a prompt: the event
prompt.submit, the same call the engine makes for a typed prompt; a turn of its own, once the session is idle.$.sessionnounThe running session, read as plain data; compacting it; and sending a message from it to another agent or session.
$.session.authorizeverbHolds the session's Anthropic credential on the host and answers an opaque handle and its kind; the secret never reaches the plugin.
$.session.usageverbReturns when the session began, and the context window's fill, the rate-limit windows and the cost as the status line has them, itemized.
$.uinounDisplay: a line under an open dialog, a redraw or a repaint, a log line, panes the surface places, a window or ring, a surface's clipboard.
$.ui.focusverbMoves the focus ring of one of this plugin's sites onto an element it drew there, as the DOM's
element.focus(), while it holds the keys.session.detacheventFires when a client leaves the roster: it detached, or the session ended with it attached (
e.reason). Observe;next(e)echoes{ clientId }.session.endeventFires once when the session ends (exit, /clear, resume, logout, signal, a
-prun done), after its SessionEnd settings hooks;e.reasonsays which.session.receiveeventFires when a delivery reaches the session (a relay's event, a peer's message, a Remote Control prompt), before it is queued;
{ text }.ButtonPropstypeThe props of
Button, every surface's pressable leaf: an address, a label, the closure a press runs, and the label styles a hover overrides.ClassicEventOftypeThe classic (settings) hook events, one per classic event name:
eis the hook's whole stdin input, base fields (transcript_path,cwd) included.EnginePresstypeA surface pressing a Button a test rendered, or a Markdown's link: the
ui.presschain over every plugin hooked on it, its own closure last.HookBudgettypeThe time bounds every hook runs under, in milliseconds: the engine's own constants are typed by these members, and
next.budgetreads the live one.HookOftypeThe hook event
Etakes: an async generator over its chunks for a streaming event (StreamingEventName),($, e, next) => resultotherwise.ModelForkRequesttypeWhat
$.model.forktakes.MountedMemberstypeEvery member a mounted drawing of component
Ccan have;Mounted<P, C>keeps the ones surfacePhas the element for (ElementOfAct).NexttypeThe rest of the chain, as one hook receives it: made once per dispatch per hook, frozen;
next(e)resolves to the downstream result.NextBudgettypeThe budget the code reading
next.budgetruns under: the whole allowance and what is left of it now, plain data read fresh on each access.PaneOpenArgstypeThe argument of
$.ui.open: which pane, its title, whether it asks the person's keyboard, its dialog manners, its size: rows inline, columns docked.SessionCompactInputtypeThe input of
session.compact: one compaction of the conversation, about to run;messagesis the transcript it runs over.SessionCompactResulttypeWhat a
session.compacthook returns and whatnext(e)resolves to: the compaction ({ messages, tokensBefore?, tokensAfter?, usage? }) or a skip.SessionEndInputtypeThe input of
session.end: the session is ending, why, and how to come back to it; every field is the engine's: a hook observes,next(e)passes it on.ToolResultSummarytypeOne tool_result block of a user message.
TurnStepInputtypeThe input of
turn.step: one model request inside a turn, at the moment the engine is about to send it; the bottom of the chain sends it.UiFocusArgstypeWhat a plugin's
$.ui.focus(args)takes: one of its own elements, by thekeyit drew it under, in one of its sites that holds the keyboard now.UiPanetypeOne of this plugin's open panes as
$.ui.panes()lists it: the pane's id and title, and where it stands with the person right now.
v2.1.278
No change to the surface since 2.1.277v2.1.277
+32 added · 2 removed · 23 changed · 29 docs only since 2.1.276The engine
-
Reads a file and returns its text, or with
{ as: "bytes" }its bytes as{ base64 }.(path: string) => Promise<string>FsReadCall -
Returns
{ kind, size, mtimeMs, isLink }of the path: what it leads to, and whether it is itself a symbolic link. Rejects when missing.(path: string) => Promise<FsStat>(path: string, options?: FsStatOptions) => Promise<FsStat>
Events
-
Fires once per message the engine injects for the model on its own (a reminder, a mode transition, a mentioned file), as a request carries it.
-
{ text }(null leaves the attachment out). -
Fires when the person edits the main prompt box: a key the editor took as an edit, or a paste;
next(e)resolves the box the editor shows. -
{ text, cursor }, the box the editor shows next.
Types
- removed
MountedClienttype breakingA
Clientthe test mounted: what its surface module drew, and the ways the terminal reaches it, each settling the event loop before it resolves. - removed
PromptAttachmenttype breakingA pasted or attached non-text item of a prompt; its kind, never its bytes.
-
One pointer event over a
Client's region, assurface.onPointerhands it: region-relative cells, and the sub-cell position where known.type: ClientPointerType; x: number; y: number; fine?: { x: number; y: number; }; button?: 'left' | 'middle' | 'right'; shift?: true; alt?: true; -
A surface drawing a component instance through the plugins, then driven by key through a handle typed by that surface (Mounted).
export type EngineMount = { mount: (target: MountTarget) => Promise<MountedClient>; mount: <P extends RenderSurface, C extends RenderComponent>(target: MountTarget<P, C>) => Promise<Mounted<P, C>>;}; -
The engine's own events as calls on
$, one signature each:$.<noun>.<event>(input)resolves to its result, or to its stream.suggest: (input: PromptSuggestArgs) => Promise<PromptSuggestResult>; section: (input: PromptSectionInput) => Promise<PromptSectionResult>; context: (input: PromptContextInput) => Promise<PromptContextResult>; attachment: (input: PromptAttachmentInput) => Promise<PromptAttachmentResult>; }; skill: { prompt: (input: SkillPromptInput) => Promise<SkillPromptResult>; -
The argument of
$.fs.ancestors: the file names to look for in each directory, the file to walk down to, and the directory to walk beneath.export type FsAncestorsRequest = { names: readonly string[]; of?: string; below?: string;}; -
One entry of
$.fs.list: the entry itself, a link not followed.name: string; kind: 'file' | 'dir' | 'other'; size: number; isLink: boolean;}; -
What
$.fs.statresolves with: what the path leads to, whether the path itself is a symbolic link, and where it lands when asked.kind: 'file' | 'dir' | 'other'; size: number; mtimeMs: number; isLink: boolean; realPath?: string;}; -
Options of
$.http.fetch.headers?: Record<string, string>; body?: string; auth?: string; socketPath?: string;}; -
The props of
Image, the terminal surface's picture leaf: pixels over a box of cells where the terminal can (kitty, Ghostty), thealtelsewhere.export type ImageProps = { key?: string; source: ImageSource; columns: number; rows: number; -
The picture an
Imageshows: base64 bytes the plugin holds (at most 2 MiB decoded), or the name of a file or POSIX shared-memory object it does not.rgba: string; width: number; height: number;} | { file: string; format: 'png'; generation?: number;} | { file: string; format: 'rgba' | 'rgb'; width: number; height: number; generation?: number;} | { shm: string; format: 'rgba' | 'rgb'; width: number; height: number; generation?: number;}; -
What
$.ui.invalidatetakes: a render event, or one of the six events whose answers the engine caches for the session.export type InvalidatableEventName = RenderEventName | 'prompt.section' | 'prompt.context' | 'tool.describe' | 'command.describe' | 'config.describe';export type InvalidatableEventName = RenderEventName | 'prompt.section' | 'prompt.context' | 'prompt.attachment' | 'tool.describe' | 'command.describe' | 'config.describe'; -
What
$.ui.mounttakes: whose elements the test will act on, the surface that draws, and the component instance the engine asks the plugins for.export type MountTarget = {export type MountTarget<P extends RenderSurface = RenderSurface, C extends RenderComponent = RenderComponent> = { plugin: string; key: string; surface: P; component: C; props: RenderPropsOf[C]; requestId?: string; columns?: number; rows?: number; viewport?: RenderViewport;}; -
What each call on
$answers (thevalueof its event's result), by event name.'ui.close': void; 'ui.panes': readonly UiPane[]; 'ui.blit': UiBlitResult; 'fs.read': string; 'fs.read': string | FsBytes; 'fs.write': void; 'fs.list': FsEntry[]; 'fs.exists': boolean; -
The argument of
$.ui.open: which pane, its title, whether it asks the person's keyboard, its dialog manners, its size: rows inline, columns docked.closeOnEscape?: true; holdToasts?: true; rows?: number; columns?: number;}; -
What
$.ui.presstakes: the plugin whoseui.renderhook drew the element, thekeyit gave it, the instance and surface when several, alink.plugin: string; key: string; requestId?: string; surface?: RenderSurface; link?: PressedLink;}; -
The input of
prompt.submit: the prompt as typed, after the input became a user message and before it enters the session.export type PromptSubmitInput = { text: string; attachments?: readonly PromptAttachment[]; attachments?: readonly PromptSubmitAttachment[]; context?: readonly string[]; turnId?: string; wait: boolean; -
Everything
ui.rendercan draw: one name per component that has a render site; a matcher narrows on it.export type RenderComponent = 'AskUserQuestion' | 'UserMessage' | 'AssistantMessage' | 'ToolUse' | 'ToolResult' | 'ToolGroup' | 'CommandOutput' | 'Spinner' | 'TurnDuration' | 'InfoNotice' | 'SessionMode' | 'PromptHint' | 'AbovePrompt' | 'Pane';export type RenderComponent = 'AskUserQuestion' | 'UserMessage' | 'AssistantMessage' | 'ToolUse' | 'ToolResult' | 'ToolGroup' | 'ToolProgress' | 'CommandOutput' | 'Spinner' | 'TurnDuration' | 'InfoNotice' | 'SessionMode' | 'PromptHint' | 'AbovePrompt' | 'Pane'; -
What a render hook returns, and what
next(e)resolves to: a plain-data tree of elements (a Box or Text is a StyledElement), strings as children.} | { type: 'Image'; props: ImageProps; image: { plugin: string; }; children?: undefined;} | { type: 'engine'; -
The plain-data props of each renderable component, as
ui.rendersees them undere.props; a hook rewrites them withnext({ ...e, props }).isErrored: boolean; onScreen?: OnScreen | null; }; ToolProgress: { tool_use_id: string; kind: 'background_hint'; hint: string; }; Spinner: { word: string; message: string | null; suffix: string; mode: 'requesting' | 'responding' | 'thinking' | 'tool-input' | 'tool-use'; }; TurnDuration: { -
The input of
tool.describe: one tool's description, at the moment the engine first renders the tool's schema for the model.export type ToolDescribeInput = { tool: string; description: string; isDeferred?: true; provider: Origin;}; -
What a
tool.describehook returns: the description the model sees for that tool and, when the hook moves it, where the tool waits (ToolDeferral).export type ToolDescribeResult = { description: string; isDeferred?: ToolDeferral;}; -
What a plugin's
$.ui.blit(args)takes: a Raster's nextcells(RasterBlitArgs) or a keyed Image's nextsource(ImageBlitArgs).export type UiBlitArgs = { requestId: string; key: string; cells: string; columns?: number; rows?: number;};export type UiBlitArgs = RasterBlitArgs | ImageBlitArgs; -
Which
Clientof a mounted drawing an act or a read means, by thekeyits element carries; optional while the drawing holds exactly one. -
The element each surface-dependent act of a mounted drawing reaches: a handle carries the act only where the surface's table has the element.
-
What a mounted drawing's
findandfindAllmatch an element on, every field given at once: its tag, itskey, and the text it shows. -
One element of a mounted drawing as
findreturns it: the description the plugin's hook (or aClient's module) built, read as plain data. -
What
$.fs.read(path, { as: "bytes" })resolves with: the file's bytes, base64, since only plain data crosses into a plugin's environment. -
How
$.fs.readanswers:text(UTF-8, the default) orbytes(base64). -
The options of
$.fs.readthat ask for the bytes: the call answers{ base64 }. -
$.fs.read: the file's text, or with{ as: "bytes" }its bytes as{ base64 }. -
The options of
$.fs.read. -
The options of
$.fs.stat. -
A
$.ui.blitargument swapping one of the caller's mounted keyed Images to its next picture; every call sends it, so a stream needs no generation. -
What a mounted drawing's
inputtakes: the Input's key, the text, which of the two inputs it is (submitwhen unsaid), another plugin's name. -
What a mounted drawing's
keytakes: the key as aClient'sonKeylistener receives it (ClientKeyEvent), and whichClientwhen several. -
What a mounted drawing's
pointertakes: the event as aClient'sonPointerlistener receives it, in its region's cells, and which one. -
What a mounted drawing's
presstakes: the Button's key, another plugin's name when the Button is not the mounted plugin's, a link. -
What a mounted drawing's
resizetakes: aClientregion's size in cells, as the surface measuring it hands it, and whichClient. -
What a mounted drawing's
selecttakes: the Select's key, the picked option's value, another plugin's name when the Select is not its own. -
A drawing of component
Cthe test mounted on surfaceP: reads over its description, acts on its elements by key,Clientacts wherePhas one. -
Every member a mounted drawing of component
Ccan have;Mounted<P, C>keeps the ones surfacePhas the element for (ElementOfAct). -
The input of
prompt.attachment: one message the engine injects into the conversation for the model on its own, as a request is about to carry it. -
Who authored the text an injected attachment carries, as the engine knows it from the attachment itself; a closed set, pinned on the event.
-
What a
prompt.attachmenthook returns: the text the model reads for that attachment, or null to leave the attachment out of the request. -
The input of
prompt.edit(prompt-edit/): one edit the person makes in the prompt box, as the draft before it and the splice the editor made of it. -
Who edits the prompt box at
prompt.edit, as the engine stamps it where the edit starts; a closed set a matcher narrows on. -
What a
prompt.edithook returns and whatnext(e)resolves to: the box after the edit (PromptBox), which the editor then shows. -
A pasted or attached non-text item of a submitted prompt; its kind, never its bytes.
-
A
$.ui.blitargument repainting one of the caller's mounted Rasters. -
Where a
tool.describeanswer places the tool:truebehind ToolSearch (its schema loads when the model asks for it),falsein the prompt's list.
29 docs only: reworded, same shape
$.fsnounThe file system as the engine's own process reaches it; a relative path is under the session's working directory, and text is UTF-8.
$.fs.ancestorsverbReads the named instruction files in every directory above the session's original working directory, the way the engine reads CLAUDE.md.
$.fs.existsverbReturns whether the path exists; rejects only a network location as spelled, which no
fscall reaches.$.fs.listverbLists a directory:
{ name, kind, size, isLink }per entry, by name, each entry as it stands (a symbolic link isotherwithisLink).$.http.fetchverbFetches
urlthrough the host (never the plugin's own network) and resolves{ status, ok, headers, text }once the body is read.$.mcp.callverbCalls
toolon one of the engine's connected MCP servers with the engine's own connection and credentials.$.ui.blitverbRepaints a mounted
Rasterthis plugin's own render hook drew with new cells, or swaps a keyedImageit drew to a new source; no redraw.$.ui.invalidateverbRe-runs an event whose results the engine caches:
ui.renderdraws the instances this plugin may draw again; the others drop the cached answers.$.ui.openverbOpens a pane: a framed region the surface places, whose body this plugin draws by hooking
ui.renderfor{ component: "Pane" }.$.ui.statusverbPins
textas this plugin's status line under the prompt, beside the engine's own pinned notices, until the next call replaces it.$.ui.toastverbShows
texton the notification bar under the prompt for a few seconds, the way the engine's own "context left" notice appears.fs.ancestorseventThe argument of
$.fs.ancestors({ names, of, below }).session.starteventFires once per process for each loaded plugin, before the first prompt, then once per fresh load of one (never
/clear);next(e)is{ cwd }.tool.describeeventFires once per tool, when the engine first renders the tool's schema in a session;
next(e)resolves to{ description, isDeferred? }.tool.describeresult{ description, isDeferred? }.ui.bliteventThe argument of
$.ui.blit(...): a Raster'scellsor a keyed Image'ssource; a hook above may rewrite either withnext, or{ deny }.ButtonPropstypeThe props of
Button, every surface's pressable leaf: an address, a label, the closure a press runs, and the label styles a hover overrides.ClientElementstypeThe element table a surface module draws with,
surface.elements: the terminal's (Elements) lessClient(none nests),RasterandImage.ClientModuletypeThe component a surface module exports (default, or its one PascalCase export): from props and surface to the tree drawn (no nested
Client).ClientSurfacetypeWhat a surface module's function receives as its second argument: its elements, the instance's local state, its region, input, clock and port.
ElementstypeThe element constructors each surface draws, by
e.surface: what$.ui.resolve(e)returns and aui.resolvehook passes on; no globals.EnginetypeWhat a test holds as
$, the engine's own: every call on it is made as the REPL, the query loop and the render sites make theirs, over every plugin.EngineCreateInputtypeThe input of
engine.create: the fold that builds$, once per load, core innermost.EnginePresstypeA surface pressing a Button a test rendered, or a Markdown's link: the
ui.presschain over every plugin hooked on it, its own closure last.McpToolCallInputtypeThe MCP branch of a
tool.callhook'se(and of$.tool.call's input): one variant per declared tool, else the loose McpToolCallInputFallback.-
The
eatool.call(orclassic.PreToolUse) hook receives for an MCP tool while no MCP tool is declared: everymcp__*name, loose arguments. ToolSpectypeWhat
$.tool.registertakes.UiBlitResulttypeWhat
$.ui.blitresolves to and what aui.blithook's{ value }holds:{}once the cells or source are the next frame's, or why not.hconstThe JSX factory (classic runtime,
@jsx h; the engine prepends the pragma): a plain-data element from a string tag or a component.