Follow Discord
Sweep 25 Sep 2026 · 19:33Z Build v2.1.283 504 read Stable v2.1.274 Latest v2.1.283 Next v2.1.283 Feeds RSS JSON llms.txt llms-full.txt Unofficial
Mods API changes

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.

Releases22 since 2.1.259
Newest2.1.283+0 added · 0 removed · 2 changed · 2 docs only
Machine readablechanges.jsonin pages: counts, and each release's items

v2.1.277

+32 added · 2 removed · 23 changed · 29 docs only since 2.1.276

The engine

  • changed $.fs.read verb may break

    Reads a file and returns its text, or with { as: "bytes" } its bytes as { base64 }.

    (path: string) => Promise<string>FsReadCall
  • changed $.fs.stat verb may break

    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

  • added prompt.attachment event

    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.

  • added prompt.attachment result

    { text } (null leaves the attachment out).

  • added prompt.edit event

    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.

  • added prompt.edit result

    { text, cursor }, the box the editor shows next.

Types

  • removed MountedClient type breaking

    A Client the test mounted: what its surface module drew, and the ways the terminal reaches it, each settling the event loop before it resolves.

  • removed PromptAttachment type breaking

    A pasted or attached non-text item of a prompt; its kind, never its bytes.

  • changed ClientPointerEvent type extended

    One pointer event over a Client's region, as surface.onPointer hands 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;
  • changed EngineMount type may break

    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>>;};
  • changed EventCalls type extended

    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>;
  • changed FsAncestorsRequest type extended

    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;};
  • changed FsEntry type extended

    One entry of $.fs.list: the entry itself, a link not followed.

        name: string;    kind: 'file' | 'dir' | 'other';    size: number;    isLink: boolean;};
  • changed FsStat type extended

    What $.fs.stat resolves 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;};
  • changed HttpInit type extended

    Options of $.http.fetch.

        headers?: Record<string, string>;    body?: string;    auth?: string;    socketPath?: string;};
  • changed ImageProps type extended

    The props of Image, the terminal surface's picture leaf: pixels over a box of cells where the terminal can (kitty, Ghostty), the alt elsewhere.

    export type ImageProps = {    key?: string;    source: ImageSource;    columns: number;    rows: number;
  • changed ImageSource type extended

    The picture an Image shows: 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;};
  • changed InvalidatableEventName type may break

    What $.ui.invalidate takes: 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';
  • changed MountTarget type may break

    What $.ui.mount takes: 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;};
  • changed OpValueOf type may break

    What each call on $ answers (the value of 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;
  • changed PaneOpenArgs type extended

    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;};
  • changed PressTarget type extended

    What $.ui.press takes: the plugin whose ui.render hook drew the element, the key it gave it, the instance and surface when several, a link.

        plugin: string;    key: string;    requestId?: string;    surface?: RenderSurface;    link?: PressedLink;};
  • changed PromptSubmitInput type may break

    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;
  • changed RenderComponent type may break

    Everything ui.render can 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';
  • changed RenderElement type extended

    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';
  • changed RenderPropsOf type extended

    The plain-data props of each renderable component, as ui.render sees them under e.props; a hook rewrites them with next({ ...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: {
  • changed ToolDescribeInput type extended

    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;};
  • changed ToolDescribeResult type extended

    What a tool.describe hook 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;};
  • changed UiBlitArgs type may break

    What a plugin's $.ui.blit(args) takes: a Raster's next cells (RasterBlitArgs) or a keyed Image's next source (ImageBlitArgs).

    export type UiBlitArgs = {    requestId: string;    key: string;    cells: string;    columns?: number;    rows?: number;};export type UiBlitArgs = RasterBlitArgs | ImageBlitArgs;
  • added ClientScope type

    Which Client of a mounted drawing an act or a read means, by the key its element carries; optional while the drawing holds exactly one.

  • added ElementOfAct type

    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.

  • added ElementQuery type

    What a mounted drawing's find and findAll match an element on, every field given at once: its tag, its key, and the text it shows.

  • added FoundElement type

    One element of a mounted drawing as find returns it: the description the plugin's hook (or a Client's module) built, read as plain data.

  • added FsBytes type

    What $.fs.read(path, { as: "bytes" }) resolves with: the file's bytes, base64, since only plain data crosses into a plugin's environment.

  • added FsReadAs type

    How $.fs.read answers: text (UTF-8, the default) or bytes (base64).

  • The options of $.fs.read that ask for the bytes: the call answers { base64 }.

  • added FsReadCall type

    $.fs.read: the file's text, or with { as: "bytes" } its bytes as { base64 }.

  • added FsReadOptions type

    The options of $.fs.read.

  • added FsStatOptions type

    The options of $.fs.stat.

  • added ImageBlitArgs type

    A $.ui.blit argument swapping one of the caller's mounted keyed Images to its next picture; every call sends it, so a stream needs no generation.

  • added MountInputTarget type

    What a mounted drawing's input takes: the Input's key, the text, which of the two inputs it is (submit when unsaid), another plugin's name.

  • added MountKeyEvent type

    What a mounted drawing's key takes: the key as a Client's onKey listener receives it (ClientKeyEvent), and which Client when several.

  • What a mounted drawing's pointer takes: the event as a Client's onPointer listener receives it, in its region's cells, and which one.

  • added MountPressTarget type

    What a mounted drawing's press takes: the Button's key, another plugin's name when the Button is not the mounted plugin's, a link.

  • What a mounted drawing's resize takes: a Client region's size in cells, as the surface measuring it hands it, and which Client.

  • What a mounted drawing's select takes: the Select's key, the picked option's value, another plugin's name when the Select is not its own.

  • added Mounted type

    A drawing of component C the test mounted on surface P: reads over its description, acts on its elements by key, Client acts where P has one.

  • added MountedMembers type

    Every member a mounted drawing of component C can have; Mounted<P, C> keeps the ones surface P has 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.attachment hook returns: the text the model reads for that attachment, or null to leave the attachment out of the request.

  • added PromptEditInput type

    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.

  • added PromptEditOrigin type

    Who edits the prompt box at prompt.edit, as the engine stamps it where the edit starts; a closed set a matcher narrows on.

  • added PromptEditResult type

    What a prompt.edit hook returns and what next(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.

  • added RasterBlitArgs type

    A $.ui.blit argument repainting one of the caller's mounted Rasters.

  • added ToolDeferral type

    Where a tool.describe answer places the tool: true behind ToolSearch (its schema loads when the model asks for it), false in the prompt's list.

29 docs only: reworded, same shape
  • $.fs noun

    The 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.

  • Reads the named instruction files in every directory above the session's original working directory, the way the engine reads CLAUDE.md.

  • Returns whether the path exists; rejects only a network location as spelled, which no fs call reaches.

  • Lists a directory: { name, kind, size, isLink } per entry, by name, each entry as it stands (a symbolic link is other with isLink).

  • Fetches url through the host (never the plugin's own network) and resolves { status, ok, headers, text } once the body is read.

  • Calls tool on one of the engine's connected MCP servers with the engine's own connection and credentials.

  • Repaints a mounted Raster this plugin's own render hook drew with new cells, or swaps a keyed Image it drew to a new source; no redraw.

  • Re-runs an event whose results the engine caches: ui.render draws the instances this plugin may draw again; the others drop the cached answers.

  • Opens a pane: a framed region the surface places, whose body this plugin draws by hooking ui.render for { component: "Pane" }.

  • Pins text as this plugin's status line under the prompt, beside the engine's own pinned notices, until the next call replaces it.

  • Shows text on the notification bar under the prompt for a few seconds, the way the engine's own "context left" notice appears.

  • The argument of $.fs.ancestors({ names, of, below }).

  • Fires once per process for each loaded plugin, before the first prompt, then once per fresh load of one (never /clear); next(e) is { cwd }.

  • Fires once per tool, when the engine first renders the tool's schema in a session; next(e) resolves to { description, isDeferred? }.

  • { description, isDeferred? }.

  • ui.blit event

    The argument of $.ui.blit(...): a Raster's cells or a keyed Image's source; a hook above may rewrite either with next, or { deny }.

  • The props of Button, every surface's pressable leaf: an address, a label, the closure a press runs, and the label styles a hover overrides.

  • The element table a surface module draws with, surface.elements: the terminal's (Elements) less Client (none nests), Raster and Image.

  • The component a surface module exports (default, or its one PascalCase export): from props and surface to the tree drawn (no nested Client).

  • What a surface module's function receives as its second argument: its elements, the instance's local state, its region, input, clock and port.

  • The element constructors each surface draws, by e.surface: what $.ui.resolve(e) returns and a ui.resolve hook passes on; no globals.

  • Engine type

    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.

  • The input of engine.create: the fold that builds $, once per load, core innermost.

  • A surface pressing a Button a test rendered, or a Markdown's link: the ui.press chain over every plugin hooked on it, its own closure last.

  • The MCP branch of a tool.call hook's e (and of $.tool.call's input): one variant per declared tool, else the loose McpToolCallInputFallback.

  • The e a tool.call (or classic.PreToolUse) hook receives for an MCP tool while no MCP tool is declared: every mcp__* name, loose arguments.

  • What $.tool.register takes.

  • What $.ui.blit resolves to and what a ui.blit hook's { value } holds: {} once the cells or source are the next frame's, or why not.

  • h const

    The JSX factory (classic runtime, @jsx h; the engine prepends the pragma): a plain-data element from a string tag or a component.

v2.1.276

No change to the surface since 2.1.275

v2.1.275

+35 added · 0 removed · 19 changed · 12 docs only since 2.1.274

The engine

  • changed $.prompt.fill verb may break

    Puts input.text in the prompt box as the draft, by mode: replace (the default) over it, append after it, insert at the cursor.

    EventCalls['prompt']['fill'](input: PromptFillArgs) => Promise<PromptFilled>
  • changed $.ui.log verb may break

    Appends one line to the transcript, drawn like a system notice (dim; not sent to the model), or with { to: "debug" } to the debug log alone.

    (text: string) => void(text: string, options?: UiLogOptions) => void
  • added $.prompt.read verb

    Returns the prompt box as it stands, the draft typed so far and the cursor's offset into it, so a fill can keep what the person typed.

  • added $.session.root verb

    Returns the session's project root, absolute: where it started, or where /cd, a host's directory change or a worktree move took it.

  • added $.ui.panes verb

    Lists this plugin's own open panes (UiPane): each one's id and title, and whether it is shown, holds the keyboard, and is placed.

Events

  • added prompt.read event

    The argument of $.prompt.read().

  • added session.end event

    Fires once when the session ends (exit, /clear, resume, logout, signal, a -p run done), after its SessionEnd settings hooks; e.reason says which.

  • added session.end result

    { sessionId }.

  • added session.measure event

    Fires when the engine measures the session and a unit moved: after each main-thread turn, and when a rate-limit window moves a whole point.

  • added session.measure result

    { changed }.

  • added session.root event

    The argument of $.session.root().

  • added ui.panes event

    The argument of $.ui.panes().

Types

  • changed ClientElements type may break

    The element table a surface module draws with, surface.elements: the terminal's (Elements) less Client (none nests), Raster and Image.

    export type ClientElements = Omit<Elements['terminal'], 'Client' | 'Raster'>;export type ClientElements = Omit<Elements['terminal'], 'Client' | 'Raster' | 'Image'>;
  • changed Elements type extended

    The element constructors each surface draws, by e.surface: what $.ui.resolve(e) returns and a ui.resolve hook passes on; no globals.

            Markdown: ElementConstructor<MarkdownProps>;        Client: ElementConstructor<ClientProps>;        Raster: ElementConstructor<RasterProps>;        Image: ElementConstructor<ImageProps>;    };    desktop: {        Box: ElementConstructor<BoxProps>;
  • changed Engine type may break

    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 : EngineNoun<N>;    [N in keyof EventCalls]: N extends 'ui' ? EngineNoun<N> & EnginePress & EngineMount : EngineNoun<N>;};
  • changed EventCalls type extended

    The engine's own events as calls on $, one signature each: $.<noun>.<event>(input) resolves to its result, or to its stream.

            compact: (input?: SessionCompactArgs) => Promise<SessionCompactResult>;        attach: (input: SessionAttachInput) => Promise<SessionAttachResult>;        detach: (input: SessionDetachInput) => Promise<SessionDetachResult>;        measure: (input: SessionMeasureInput) => Promise<SessionMeasureResult>;        end: (input: SessionEndInput) => Promise<SessionEndResult>;    };    turn: {        start: (input: TurnStartInput) => Promise<TurnStartResult>;
  • changed FsAncestor type extended

    One file $.fs.ancestors found: the directory it stands in, the name it was asked for by, and its text as the engine's memory loader reads it.

        dir: string;    name: string;    content: string;    parts: readonly FsAncestorPart[];};
  • changed GlobNext type extended

    next in a hook on a glob or a negation: an overload per selected event, then one over their union for an e not yet narrowed.

        readonly event: N;    readonly origin: Origin;    readonly trace: readonly TraceEntry<N, Args<N>, GlobNextResult<N>>[];    readonly budget: NextBudget;};
  • changed Next type extended

    The rest of the chain, as one hook receives it: made once per dispatch per hook, frozen; next(e) resolves to the downstream result.

        readonly event: N;    readonly origin: Origin;    readonly trace: readonly TraceEntry<N, E, O>[];    readonly budget: NextBudget;};
  • changed OpValueOf type extended

    What each call on $ answers (the value of its event's result), by event name.

        'audio.speak': SpeakResult;    'mcp.call': McpToolResult;    'session.cwd': string;    'session.root': string;    'session.model': string;    'session.turns': number;    'session.id': string;…    'session.authorize': SessionAuthorization;    'session.usage': SessionUsage;    'turn.abort': void;    'prompt.read': PromptBox;    'tool.list': ToolInfo[];    'tool.register': {        tool: string;…    'ui.invalidate': void;    'ui.open': void;    'ui.close': void;    'ui.panes': readonly UiPane[];    'ui.blit': UiBlitResult;    'fs.read': string;    'fs.write': void;
  • changed PromptContextInput type may break

    The input of prompt.context: the context blocks the engine prepends to a conversation's first user message, and the files behind claudeMd.

    export type PromptContextInput = PromptContextBlocks;export type PromptContextInput = {    blocks: readonly PromptContextBlock[];    instructionFiles?: readonly InstructionFile[];};
  • changed PromptContextResult type may break

    What a prompt.context hook returns: the blocks the conversation carries, in order; one left out is not sent.

    export type PromptContextResult = PromptContextBlocks;export type PromptContextResult = {    blocks: readonly PromptContextBlock[];    instructionFiles?: readonly InstructionFile[];};
  • changed PromptFillArgs type may break

    prompt.fill's input as a plugin's $.prompt.fill(args) takes it: no origin (the engine sets the calling plugin's), mode optional.

    export type PromptFillArgs = Omit<PromptFillInput, 'origin'>;export type PromptFillArgs = {    text: string;    mode?: PromptFillMode;};
  • changed PromptFillInput type extended

    The input of prompt.fill (prompt-fill/): a text about to be put in the prompt box as the person's draft, over it, after it, or at the cursor.

    export type PromptFillInput = {    text: string;    mode: PromptFillMode;    origin: PromptFillOrigin;};
  • changed RenderElement type extended

    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.

        };    children?: undefined;} | {    type: 'Image';    props: ImageProps;    children?: undefined;} | {    type: 'engine';    ref: number;};
  • changed RenderPropsOf type extended

    The plain-data props of each renderable component, as ui.render sees them under e.props; a hook rewrites them with next({ ...e, props }).

            isExpanded: boolean;        task?: UserMessageTask;        from?: UserMessageFrom;        onScreen?: OnScreen | null;    };    AssistantMessage: {        text: string;        isFirstOfReply: boolean;        onScreen?: OnScreen | null;    };    ToolUse: {        tool_use_id: string;…        isErrored: boolean;        isInterrupted: boolean;        output?: unknown;        onScreen?: OnScreen | null;    };    ToolResult: {        tool_use_id: string;        tool: string;        output: unknown;        isErrored: boolean;        onScreen?: OnScreen | null;    };    ToolGroup: {        calls: ReadonlyArray<ToolGroupCall>;        isActive: boolean;        isExpanded: boolean;        onScreen?: OnScreen | null;    };    CommandOutput: {        command: string;        args: string;        text: string;        isErrored: boolean;        onScreen?: OnScreen | null;    };    Spinner: {        word: string;…    TurnDuration: {        word: string;        durationMs: number;        onScreen?: OnScreen | null;    };    InfoNotice: {        text: string;        command: string | null;        onScreen?: OnScreen | null;    };    SessionMode: {        modes: readonly string[];
  • changed RenderViewport type extended

    The size of what a surface draws into, in character cells of the surface's monospace metric, and whether its layout docks a pane.

    export type RenderViewport = {    columns: number;    rows: number;    isFullscreen?: boolean;};
  • changed StarNext type extended

    next in a * hook: the set of events is open at runtime, so e is unknown until next.is(pattern, e) narrows it to events it knows.

        readonly event: EventName;    readonly origin: Origin;    readonly trace: readonly TraceEntry<EventName, unknown, unknown>[];    readonly budget: NextBudget;};
  • changed StreamNext type may break

    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.

        [K in N]?: unknown;} = {    [K in N]: Args<K>;}> = Pick<Next<N, E, O, S>, 'signal' | 'is' | 'event' | 'origin'> & {}> = Pick<Next<N, E, O, S>, 'signal' | 'is' | 'event' | 'origin' | 'budget'> & {    (e: E): HookStream<Chunk<N>, O>;    readonly to: (e: E, tier: TargetTier) => HookStream<Chunk<N>, O>;    readonly trace: readonly TraceEntry<N, E, O>[];
  • added EngineMount type

    The terminal mounting a Client a test rendered: its surface module read, loaded and drawn as a region does it, then driven by hand.

  • added FsAncestorPart type

    One file of an ancestor entry: the file itself or one it imported.

  • added HookBudget type

    The time bounds every hook runs under, in milliseconds: the engine's own constants are typed by these members, and next.budget reads the live one.

  • Every tier an instruction file can belong to, for checking a hook's answer; the kind type is derived from this list.

  • added ImageProps type

    The props of Image, the terminal surface's picture leaf: pixels over a box of cells where the terminal can (kitty, Ghostty), the alt text elsewhere.

  • added ImageSource type

    The picture an Image shows, as bytes the plugin already holds.

  • added InstructionFile type

    One instruction file behind the claudeMd block: where it was read, its tier, its text as loaded, and the file that @-imported it if one did.

  • What tier an instruction file belongs to: the organization's managed policy, the person's own, the project's checked-in or private ones, memory.

  • added MountTarget type

    What $.ui.mount takes: whose Client, the key its hook gave it, the drawing when it drew several, and the region's size in cells.

  • added MountedClient type

    A Client the test mounted: what its surface module drew, and the ways the terminal reaches it, each settling the event loop before it resolves.

  • added NextBudget type

    The budget the code reading next.budget runs under: the whole allowance and what is left of it now, plain data read fresh on each access.

  • added OnScreen type

    The part of a transcript message the surface that drew it has on screen: units first to last of the message's of, counted from its start.

  • added PromptBox type

    The person's prompt box as it stands: the draft and where the cursor is in it; what $.prompt.read() resolves and $.prompt.fill hands back.

  • added PromptFillMode type

    Where a prompt.fill puts its text: over the whole draft, after it, or into it at the cursor.

  • added PromptFilled type

    What $.prompt.fill resolves to: whether the box took the text, and the box afterwards (PromptBox) as the caller's own $.prompt.read() reads it.

  • added SessionEndInput type

    The input of session.end: the session is ending, why, and how to come back to it.

  • added SessionEndReason type

    Why the session ended: the classic SessionEnd hook's own reason, word for word.

  • added SessionEndResult type

    What a session.end hook returns and what next(e) resolves to: { sessionId }, echoed by core; a hook's own value changes nothing.

  • The input of session.measure: what $.session.usage() answers at this moment, and which of its units moved since the last measurement a hook saw.

  • What a session.measure hook returns and what next(e) resolves to: { changed }, echoed by core; a hook's own value changes nothing.

  • added SessionResume type

    How to come back to the session that ended: what claude --resume takes.

  • added UiLogOptions type

    Options of $.ui.log.

  • added UiLogSink type

    Where a $.ui.log line goes: transcript, a dim row of its own (and the debug log, as every line); debug, the debug log alone, nothing on screen.

  • added UiPane type

    One 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.

  • added UsageUnit type

    One unit of what $.session.usage() answers, by its key there: the context window's fill, the rate-limit windows, the session's cost.

12 docs only: reworded, same shape
  • Submitting a prompt the model reads as a user turn, and the person's prompt box: read as it stands, written, or proposed into.

  • $.ui noun

    Display: a line under an open dialog, a redraw or a repaint, a transcript or debug line, panes the surface places, a window or ring.

  • Fires when a text is about to be put in the prompt box as the person's draft (a plugin's $.prompt.fill); next(e) writes it by e.mode.

  • turn.step event

    Fires when the engine is about to send a model request of a turn, main's or a subagent's (e.agentId); next(e) resolves to the whole response.

  • Where a command's answer will show: which of the terminal's two layouts the surface renders, and how wide it is when the command runs.

  • What $.model.complete takes.

  • The input of prompt.submit: the prompt as typed, after the input became a user message and before it enters the session.

  • What on(...) returns for a hook of type F: the registration, which takes one .catch (CatchHandler); without it a failed hook is absent.

  • One ui.render input, for a component narrowed to one surface.

  • The input of session.attach: a surface joined the session's roster of attached clients (a phone opened the session; the desktop app connected).

  • One rate-limit window as the rate-limit notices read it.

  • What a tool.call hook returns and what next(e) and $.tool.call(input) resolve to: the tool's result ({ result, context? }) or { deny }.

v2.1.274

+9 added · 0 removed · 14 changed · 4 docs only since 2.1.273

The engine

  • added $.agent.register verb

    Defines an agent type the Agent tool dispatches from the next turn on, named <plugin>:<name>: the event agent.register.

Events

  • added agent.register event

    The argument of $.agent.register(spec): the agent type as the plugin defined it. A hook above rewrites any of it; the type stays the caller's.

Types

  • changed BoxHoverProps type extended

    The Box props a hover may override, none of which moves the Box's siblings, and scope, which names the hover group the Box joins.

        borderDimColor?: boolean;    backgroundColor?: string;    display?: 'flex';    top?: number;    left?: number;    right?: number;    bottom?: number;};
  • changed BoxProps type extended

    The props of Box: the layout, position, margin, padding and border props of Ink's Box a tree may set, and the two of hover.

    export type BoxProps = {    key?: string;    hover?: BoxHoverProps;    position?: 'relative' | 'absolute';    top?: number;    left?: number;    right?: number;    bottom?: number;    flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse';    flexGrow?: number;    flexShrink?: number;
  • changed CommandRunResult type extended

    What a command.run hook returns and what next(e) and $.command.run resolve to: the command's output text and the notes it leaves the model.

    export type CommandRunResult = {    text?: string;    context?: readonly string[];    ref?: number;};
  • changed Elements type extended

    The element constructors each surface draws, by e.surface: what $.ui.resolve(e) returns and a ui.resolve hook passes on; no globals.

            Select: ElementConstructor<SelectProps>;        Link: ElementConstructor<LinkProps>;        Code: ElementConstructor<CodeProps>;        Markdown: ElementConstructor<MarkdownProps>;        Client: ElementConstructor<ClientProps>;        Raster: ElementConstructor<RasterProps>;    };…        Svg: ElementConstructor<SvgProps>;        Link: ElementConstructor<LinkProps>;        Code: ElementConstructor<CodeProps>;        Markdown: ElementConstructor<MarkdownProps>;        Client: ElementConstructor<ClientProps>;    };    mobile: {…        Svg: ElementConstructor<SvgProps>;        Link: ElementConstructor<LinkProps>;        Code: ElementConstructor<CodeProps>;        Markdown: ElementConstructor<MarkdownProps>;    };    vscode: {        Box: ElementConstructor<BoxProps>;…        Svg: ElementConstructor<SvgProps>;        Link: ElementConstructor<LinkProps>;        Code: ElementConstructor<CodeProps>;        Markdown: ElementConstructor<MarkdownProps>;    };};
  • changed OpValueOf type extended

    What each call on $ answers (the value of its event's result), by event name.

        };    'config.list': ConfigRow[];    'agent.list': AgentInfo[];    'agent.register': {        agent: string;    };    'ui.toast': void;    'ui.status': void;    'ui.log': void;
  • changed PermissionDeniedHookInput type extended
        tool_input: unknown;    tool_use_id: string;    reason: string;    mcp_server?: McpServerProvenance;};
  • changed PermissionRequestHookInput type extended
        tool_name: string;    tool_input: unknown;    permission_suggestions?: PermissionUpdate[];    mcp_server?: McpServerProvenance;};
  • changed PostToolUseFailureHookInput type extended
        error: string;    is_interrupt?: boolean;    duration_ms?: number;    mcp_server?: McpServerProvenance;};
  • changed PostToolUseHookInput type extended
        tool_response: unknown;    tool_use_id: string;    duration_ms?: number;    mcp_server?: McpServerProvenance;};
  • changed PreToolUseHookInput type extended
        tool_name: string;    tool_input: unknown;    tool_use_id: string;    mcp_server?: McpServerProvenance;};
  • changed PressTarget type extended

    What $.ui.press takes: the plugin whose ui.render hook drew the element, the key it gave it, the instance when several, and a Markdown's link.

        plugin: string;    key: string;    requestId?: string;    link?: PressedLink;};
  • changed RenderElement type extended

    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.

        props: CodeProps;    children?: undefined;} | {    type: 'Markdown';    props: MarkdownLeafProps;    children?: undefined;} | {    type: 'Markdown';    props: MarkdownLeafProps;    press: {        plugin: string;        handle: number;    };    children?: undefined;} | {    type: 'Client';    props: ClientProps;    client: {
  • changed RenderPropsOf type extended

    The plain-data props of each renderable component, as ui.render sees them under e.props; a hook rewrites them with next({ ...e, props }).

        UserMessage: {        text: string;        origin: PromptOrigin;        isExpanded: boolean;        task?: UserMessageTask;        from?: UserMessageFrom;    };    AssistantMessage: {        text: string;
  • changed UiPressArgument type extended

    The argument of ui.press: a press on a Button a render hook drew, or on an answered Markdown link. Flat and frozen like every event's.

        component: RenderComponent;    requestId: string;    surface: RenderSurface;    link?: PressedLink;};
  • added AgentSpec type

    What $.agent.register takes: an agent type this plugin defines, spelled as an agent definition in settings JSON is, plus its name.

  • What a Markdown carries across the boundary: its address, text, dimness and which links it answers; onLinkPress stays behind, a press instead.

  • added MarkdownProps type

    The props of Markdown, a block of markdown every surface draws as it draws an assistant reply's text: its own renderer, links, tables, fences.

  • The MCP server serving this tool, for mcp__* tools: name is the server's config key (for source: "sdk", exactly the name the SDK host registered in sdkMcpServers / mcp_set_servers; for any other source, the key as authored in that configuration - untrusted text, the same value mcp_status and system/init report, to be escaped before display), source is where its definition came from - sdk (an in-process server the SDK host runs; only the host can register one, so a configured server of the same name never reads sdk), plugin (a server a plugin ships or registers at runtime), or a config scope (user, project, local, dynamic for --mcp-config / mcp_set_servers process servers, managed, enterprise, claudeai, agent). Key trust on source, not on the name or the tool-name prefix. Absent for non-MCP tools.

  • added PressedLink type

    The link a press landed on: one a Markdown drew, pressed where the surface reports presses (a plain click in the fullscreen terminal).

  • added UserMessageFrom type

    Who sent the message a UserMessage row carries, when someone other than the person did: another agent, a teammate, another session, a channel.

  • added UserMessageTask type

    The background task a UserMessage notification row reports on: a subagent, a background shell, a workflow, a remote agent, a monitor.

4 docs only: reworded, same shape
  • The input of agent.offer: one agent type, at the moment the engine offers it to the model.

  • The element table a surface module draws with, surface.elements: the terminal's (Elements) less Client (none nests) and Raster (needs $).

  • The terminal pressing a Button a test rendered, or a Markdown's link: the ui.press chain over every plugin hooked on it, its own closure last.

  • The shape a Box and a Text share in a render tree: allowlisted props, an optional hover, the group stamp a hover.scope earns, and children.

v2.1.273

+0 added · 0 removed · 2 changed · 4 docs only since 2.1.272

Types

  • changed Elements type extended

    The element constructors each surface draws, by e.surface: what $.ui.resolve(e) returns and a ui.resolve hook passes on; no globals.

            Link: ElementConstructor<LinkProps>;        Code: ElementConstructor<CodeProps>;    };    vscode: {        Box: ElementConstructor<BoxProps>;        Text: ElementConstructor<TextProps>;        Button: ElementConstructor<ButtonProps>;        Input: ElementConstructor<InputProps>;        Select: ElementConstructor<SelectProps>;        Svg: ElementConstructor<SvgProps>;        Link: ElementConstructor<LinkProps>;        Code: ElementConstructor<CodeProps>;    };};
  • changed RenderSurface type may break

    Where a render event's component is drawn: terminal is Ink, which draws the hook's whole tree; the rest are remote surfaces drawing it themselves.

    export type RenderSurface = 'terminal' | 'desktop' | 'mobile';export type RenderSurface = 'terminal' | 'desktop' | 'mobile' | 'vscode';
4 docs only: reworded, same shape
  • Returns every surface the session draws on, each once: terminal under the REPL first, then the remote ones in the order they attached.

  • The props of Button, every surface's pressable leaf: an address, a label, the closure a press runs, and the label styles a hover overrides.

  • 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.

  • The props of Svg, the remote surfaces' vector leaf: the markup is the element's data, as a string is a Text's, drawn isolated.

Feedback