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 · 03 of 03

Types

Every declaration in the file, verbatim, with the doc comment above it.

Declarations570over 12 pages
Mined from2.1.283the shipped binary

Every named declaration in the file, 570 of them, verbatim and in the order Claude Code wrote them, 50 to a page. This is the page to land on from a signature: a verb that returns ToolCallResult links here, at whichever page it is on, and what you get is the declaration itself rather than a description of it.

The source is 13,820 lines of TypeScript mined from build 2.1.283. Anything longer than 12 lines is folded; click the line count to open it. To find a name on another page, search every symbol.

Names on this page, 301 to 350 of 570

RenderComponent type # line 8025

In the first published surface (2.1.259) · changed in 2.1.265, 2.1.271, 2.1.277

Everything ui.render can draw: one name per component that has a render site; a matcher narrows on it.

The permission dialog is drawn by the engine alone, since its answer authorises an action; a plugin adds context with $.ui.notice. Pane is the one component whose instances a plugin opens ($.ui.open).

  export type RenderComponent = 'AskUserQuestion' | 'UserMessage' | 'AssistantMessage' | 'ToolUse' | 'ToolResult' | 'ToolGroup' | 'ToolProgress' | 'CommandOutput' | 'Spinner' | 'TurnDuration' | 'InfoNotice' | 'SessionMode' | 'PromptHint' | 'AbovePrompt' | 'Pane';

RenderElement type # line 8035

In the first published surface (2.1.259) · changed in 2.1.260, 2.1.265, 2.1.267, 2.1.271, 2.1.274, 2.1.275, 2.1.277, 2.1.282, 2.1.283

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 are an allowlisted subset of Ink's Box/Text props (the ones ElementProps declares); a tree with any other prop fails validation as a whole and the engine's own component is drawn with the original props.

321 lines
  export type RenderElement = StyledElement<'Box', BoxHoverProps> | StyledElement<'Text', TextHoverProps> | {
      /**
       * A button, on every surface: `[ label ]` on the terminal, a native
       * button on a desktop; a press raises `ui.press` (`e.element` the key).
       *
       * Built by `<Button>` or the table's `t.Button`. The `onPress` closure
       * stays in the plugin's own environment under `press.handle`; the host
       * holds the handle for the lifetime of the drawing. A leaf: no children.
       */
      type: 'Button';
      props: {
          /**
           * The element's address: what `e.element` carries and what a matcher
           * names (`{ element: "explain" }`).
           */
          key: string;
          /**
           * The text drawn on the button.
           */
          label: string;
          /**
           * One digit (`"1"`) or one lowercase letter (`"w"`) that presses it
           * while the plugin's site holds the focus; anything else is refused.
           *
           * The band after ctrl+x tab or a click, a focused `Pane`: on keydown,
           * lowercased; never from the composer, save a bare digit in an empty
           * one pressing a band Button. Two on one hotkey: the later wins.
           */
          hotkey?: string;
          /**
           * An engine keybinding action (`"app:cycleDiffBase"`) whose chord
           * presses the Button from the prompt; an unknown name is refused.
           *
           * Chords, or a modified key Global or an active context binds, on
           * the terminal while mounted, no dialog up, no engine handler of it
           * mounted; a pane's over the band's over another's, the last drawn.
           */
          action?: string;
          /**
           * Drawn without chrome: the hotkey in the accent color, a colon,
           * then the label (`1: Yes`); without a `hotkey`, the label alone.
           *
           * The focus still inverts it. In JSX the label may be the one string
           * child (`<Button hotkey="1" plain onPress={...}>Yes</Button>`); the
           * key defaults to the label.
           */
          plain?: true;
          /**
           * The label dim at rest, as `Text`'s `dimColor`, and at full strength
           * under the pointer or the focus; absent draws as false.
           */
          dimColor?: TextProps['dimColor'];
          /**
           * `"primary"` marks the main action of several, drawn as the surface
           * marks the one to press; `"secondary"`, and absent, draw as before.
           *
           * The terminal draws a primary in the accent color; `plain` wins over
           * it. Carried to every surface as written, never filled in.
           *
           * @example { key: 'save', label: 'Save', variant: 'primary' }
           */
          variant?: ButtonProps['variant'];
          /**
           * `"dismiss"` marks the Button that closes its site, a drawing hint
           * only: the terminal draws it as without, a desktop its close control.
           *
           * Carried to every surface as written, never filled in.
           *
           * @example { key: 'dismiss', label: 'Dismiss', role: 'dismiss' }
           */
          role?: ButtonProps['role'];
          /**
           * The site's ring starts on this element when the site takes the
           * keyboard; the first drawn of several. Absent draws as before.
           */
          autoFocus?: true;
      };
      /**
       * Where the handler lives: the plugin whose hook drew the element, and
       * the handle its environment keeps the `onPress` closure under.
       *
       * The runtime stamps the plugin as the tree leaves that hook.
       */
      press: {
          plugin: string;
          handle: number;
      };
      /**
       * Label style overrides (the Text set) the surface applies while the
       * nearest keyed Box, or the group `scope` names, is hovered; plain data.
       */
      hover?: TextHoverProps;
  } | {
      /**
       * A one-line text field on every surface; a change and Enter raise
       * `ui.input` (`e.element` the key, `e.kind` which, `e.value` the text).
       *
       * Built by `<Input>` or the table's `t.Input`. The `onInput` and
       * `onSubmit` closures stay in the plugin's own environment under
       * `press.handle`, held as a Button's is. A leaf: no children.
       */
      type: 'Input';
      props: {
          /**
           * The element's address: what `e.element` carries and what a matcher
           * names (`{ element: "reply" }`).
           */
          key: string;
          /**
           * Text drawn before the field.
           */
          label?: string;
          /**
           * Text drawn dim in an empty field.
           */
          placeholder?: string;
          /**
           * The text the field holds when drawn.
           */
          value?: string;
          /**
           * What Enter does, drawn beside the field while it has focus.
           */
          submitLabel?: string;
          /**
           * The site's ring starts on this element when the site takes the
           * keyboard; the first drawn of several. Absent draws as before.
           */
          autoFocus?: true;
      };
      /**
       * Where the handlers live: the plugin whose hook drew the element, and
       * the handle its environment keeps the closures under.
       *
       * The runtime stamps the plugin as the tree leaves that hook.
       */
      press: {
          plugin: string;
          handle: number;
      };
      children?: undefined;
  } | {
      /**
       * A one-of-several picker on every surface; a pick raises `ui.select`
       * (`e.element` the key, `e.value` the option's value).
       *
       * Built by `<Select>` or the table's `t.Select`. The `onSelect` closure
       * stays in the plugin's own environment under `press.handle`, held as
       * a Button's is. A leaf: no children.
       */
      type: 'Select';
      props: {
          /**
           * The element's address: what `e.element` carries and what a matcher
           * names (`{ element: "peer" }`).
           */
          key: string;
          /**
           * Text drawn before the current value.
           */
          label?: string;
          /**
           * What can be picked, in the order drawn: each a value and the text
           * drawn for it.
           */
          options: readonly SelectOption[];
          /**
           * Which option is selected when drawn.
           */
          value?: string;
          /**
           * The site's ring starts on this element when the site takes the
           * keyboard; the first drawn of several. Absent draws as before.
           */
          autoFocus?: true;
      };
      /**
       * Where the handler lives: the plugin whose hook drew the element, and
       * the handle its environment keeps the closure under.
       *
       * The runtime stamps the plugin as the tree leaves that hook.
       */
      press: {
          plugin: string;
          handle: number;
      };
      children?: undefined;
  } | {
      /**
       * A hyperlink every surface draws: an OSC 8 span on the terminal (its
       * text then the URL in dim where unsupported), an anchor on desktop.
       *
       * Inline: its children are the text, strings and inline elements;
       * absent children the label, absent both the URL. `href` is `https:`
       * (or `http://localhost`) and bounded, or the tree is refused.
       */
      type: 'Link';
      props: LinkProps;
      children?: RenderNode[];
  } | {
      /**
       * Source code every surface draws with the engine's highlighter, tokens
       * coloured by language; under `format: 'diff'`, unified-diff hunks.
       *
       * A leaf: a dim gutter numbers the lines from `startLine`; a diff has
       * both gutters, markers, add and remove backgrounds. `source` is
       * bounded as a Text's string is, or the tree is refused.
       */
      type: 'Code';
      props: CodeProps;
      children?: undefined;
  } | {
      /**
       * A block of markdown every surface draws as it draws an assistant
       * reply's text: its own renderer, theme, hyperlinks and highlighting.
       *
       * Built by `<Markdown>` or the table's `t.Markdown`. A leaf: `text` is
       * bounded as a Text's string is, or the tree is refused. Without a
       * `press` its links are the surface's own, opened as it opens links.
       */
      type: 'Markdown';
      props: MarkdownLeafProps;
      children?: undefined;
  } | {
      /**
       * A `Markdown` whose plugin answers the links it drew (`onLinkPress`):
       * a press on one raises `ui.press` with `e.link`, the surface opens none.
       */
      type: 'Markdown';
      props: MarkdownLeafProps;
      /**
       * Where the `onLinkPress` handler lives: the plugin whose hook drew
       * the element, and the handle its environment keeps the closure under.
       *
       * The runtime stamps the plugin as the tree leaves that hook.
       */
      press: {
          plugin: string;
          handle: number;
      };
      children?: undefined;
  } | {
      /**
       * A region one of the plugin's SURFACE MODULES, named by path, draws and
       * handles input for on the drawing thread, without `$` (ClientModule).
       *
       * `Client` from the table. One instance per plugin, drawing and `key`
       * lives while the node stays in the tree, and talks to the plugin's
       * hooks through `ui.message`. The desktop carries it as data.
       */
      type: 'Client';
      props: ClientProps;
      /**
       * Whose surface module `props.module` names: the plugin whose hook
       * drew the element, stamped by the runtime as the tree leaves it.
       */
      client: {
          plugin: string;
      };
      children?: undefined;
  } | {
      /**
       * A vector drawing, the remote surfaces' alone: the SVG markup is the
       * element's data, drawn in an isolated box, off the page.
       *
       * A leaf: hooks above wrap or replace it whole, nothing reaches inside;
       * a press other plugins should see goes on an enclosing Button. On a
       * surface whose table lacks it the tree is refused.
       */
      type: 'Svg';
      props: SvgProps;
      children?: undefined;
  } | {
      /**
       * A grid of terminal cells, the terminal surface's alone: each cell a
       * glyph, a foreground and a background, packed in `props.cells`.
       *
       * A leaf, one node however many cells; hooks above wrap or replace it
       * whole. A mounted one is repainted in place by its plugin's
       * `$.ui.blit`. On a surface whose table lacks it the tree is refused.
       */
      type: 'Raster';
      props: RasterProps;
      /**
       * Whose Raster: the plugin whose hook drew the element, stamped by the
       * runtime as the tree leaves it; the one plugin whose blit reaches it.
       */
      raster: {
          plugin: string;
      };
      children?: undefined;
  } | {
      /**
       * A picture, the terminal surface's alone: `props.source` drawn over a
       * box of cells where the terminal can, `props.alt` where it cannot.
       *
       * A leaf: hooks above wrap or replace it whole; a press other plugins
       * should see goes on an enclosing Button; keyed, its plugin's
       * `$.ui.blit` swaps it. On a surface without it the tree is refused.
       */
      type: 'Image';
      props: ImageProps;
      /**
       * Whose Image: the plugin whose hook drew the element, stamped by the
       * runtime as the tree leaves it; the one plugin whose blit reaches it.
       */
      image: {
          plugin: string;
      };
      children?: undefined;
  } | {
      /**
       * The component core draws itself, with the props held under `ref`.
       */
      type: 'engine';
      /**
       * Which drawing: the number core answered from `next(e)`, under which
       * it holds the props it received; 0 draws the original props.
       */
      ref: number;
  };

RenderEventName type # line 8361

In the first published surface (2.1.259)

The render event: ui.render, one event for every component that has a render site.

  export type RenderEventName = 'ui.render';

RenderInput type # line 8367

In the first published surface (2.1.259)

The input of ui.render: a union discriminated by component, one member per RenderComponent and per RenderSurface.

  export type RenderInput<C extends RenderComponent = RenderComponent, P extends RenderSurface = RenderSurface> = C extends RenderComponent ? P extends RenderSurface ? RenderInputOf<C, P> : never : never;

RenderInputOf type # line 8372

In the first published surface (2.1.259)

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

34 lines
  export type RenderInputOf<C extends RenderComponent, P extends RenderSurface> = {
      /**
       * Where the tree will be drawn; one literal per member, so
       * `if (e.surface === "terminal")` narrows `e` and `$.ui.resolve(e)`.
       *
       * Over the wire it is what the client declared, a rendering fact and not a
       * trust signal: do not key policy on it.
       */
      surface: P;
      /**
       * Which component this instance is; the key a matcher narrows on.
       */
      component: C;
      /**
       * The instance: the tool_use_id for a dialog or tool row, the message id
       * for a message, the agent id for a spinner.
       *
       * Two drawings of one component are two instances.
       */
      requestId: string;
      /**
       * The size of what the surface draws into, in character cells, and whether
       * its layout docks a pane; absent where no surface has measured.
       *
       * Part of the envelope: a rewrite keeps it. On the terminal, the interactive
       * screen's, where a change of width re-draws every hooked site once the
       * resize settles; on a remote surface, what it reported.
       */
      viewport?: RenderViewport;
      /**
       * The component's plain-data props.
       */
      props: RenderPropsOf[C];
  };

RenderNode type # line 8410

In the first published surface (2.1.259)

A node of a render tree: an element, or a string (text).

  export type RenderNode = RenderElement | string;

RenderPropsOf type # line 8420

In the first published surface (2.1.259) · changed in 2.1.260, 2.1.265, 2.1.267, 2.1.268, 2.1.269, 2.1.271, 2.1.274, 2.1.275, 2.1.277

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

A rewrite is validated by the component and an invalid one draws the original. This table is the plugin-facing render contract; the author's file notes which surfaces raise each member (RENDER_SURFACES_OF).

551 lines
  export type RenderPropsOf = {
      /**
       * The dialog the AskUserQuestion tool opens.
       *
       * Raised on every surface.
       */
      AskUserQuestion: {
          /**
           * The name of the tool whose call opened the dialog (`AskUserQuestion`).
           */
          tool: string;
          /**
           * The tool's `questions` input, as the dialog will draw them; a rewrite
           * must still fit the tool's schema or the original is drawn.
           */
          questions: unknown[];
          /**
           * The call's `metadata.source` (who asked) when the model gave one.
           * Analytics only; never drawn.
           */
          metadataSource?: string;
      };
      /**
       * A user-role transcript row: the person's prompt (`> ...`), a background
       * task's notification, or a message another agent, teammate or session sent.
       *
       * `origin`, `task` and `from` tell them apart and are read-only; a rewrite
       * of `text` draws in the row alone: the stored message, and the model's
       * framing of another party's words as that party's, stay as they were.
       *
       * Raised on every surface.
       */
      UserMessage: {
          /**
           * What the row shows: the prompt as typed, a notification's summary, or
           * a message's body less the engine's framing (summary line included).
           *
           * A rewrite is printable, bounded text and draws where the engine draws
           * the body; a teammate block of several frames or with a summary line
           * keeps the engine's drawing, one string not being those parts.
           */
          text: string;
          /**
           * Where the stored message came from, as `prompt.submit` named it: the
           * composer's, a task notification's, a peer's, a channel's, a plugin's.
           *
           * `unclassified` for a teammate's (its drain stamps none) and for a
           * message stored before stamps. Read-only.
           */
          origin: PromptOrigin;
          /**
           * Whether the view draws the row in full: the ctrl+o transcript,
           * `--verbose`, a surface with no ctrl+o (an export). Read-only.
           *
           * False, a message row is one dim line naming its sender; a hook that
           * draws a compact row of its own passes when true, so ctrl+o shows all.
           */
          isExpanded: boolean;
          /**
           * What a notification row (`origin.kind` `task-notification`) reports
           * on: its background task; absent on every other row. Read-only.
           */
          task?: UserMessageTask;
          /**
           * Who sent the message the row carries: another agent of this session, a
           * teammate, another session, a channel; absent otherwise. Read-only.
           */
          from?: UserMessageFrom;
          /**
           * Which of its rows the transcript's viewport shows now: `null` while
           * drawn outside it, absent where the surface does not say. Read-only.
           *
           * Reported once drawn and again when it changes: on a scroll, for the
           * messages at the viewport's edges only. A rewrite carries it on as
           * received; one that changes or drops it is refused.
           */
          onScreen?: OnScreen | null;
      };
      /**
       * One text block of an assistant reply in the transcript; a rewrite
       * changes the drawing and leaves the stored message alone (ctrl+o).
       *
       * Raised on every surface.
       */
      AssistantMessage: {
          /**
           * The block's text, markdown, as the surface's transcript will draw it:
           * what it hides of a reply (the terminal's, a `<context>` block) is gone.
           */
          text: string;
          /**
           * True on the block that draws the bullet opening a reply.
           */
          isFirstOfReply: boolean;
          /**
           * Which of its rows the transcript's viewport shows now: `null` while
           * drawn outside it, absent where the surface does not say. Read-only.
           *
           * Reported once drawn and again when it changes: on a scroll, for the
           * messages at the viewport's edges only. A rewrite carries it on as
           * received; one that changes or drops it is refused.
           */
          onScreen?: OnScreen | null;
      };
      /**
       * A tool call's row in the transcript (`Bash(ls -la)` and its result); the
       * call was decided by `tool.call`, so a rewrite here changes the row alone.
       *
       * Raised on every surface.
       */
      ToolUse: {
          /**
           * The id `tool.call` carried for this call (`e.tool_use_id` there); the
           * same value as the row's `requestId`, where it is looked for. Read-only.
           */
          tool_use_id: string;
          /**
           * Which one the row draws (`Bash`, `Read`, a plugin's tool), as
           * `tool.call` named it.
           */
          tool: string;
          /**
           * The call's input, as the model sent it.
           */
          input: unknown;
          /**
           * True while the call is still running.
           */
          isRunning: boolean;
          /**
           * True when the call ended in an error (a refusal at the dialog is one).
           */
          isErrored: boolean;
          /**
           * True when an abort ended the call: the user's Esc or a plugin's
           * `$.turn.abort` cut it while it ran, or dropped it before it ran.
           *
           * The row draws `Interrupted` for it, as the transcript marker does.
           */
          isInterrupted: boolean;
          /**
           * The stored result once the call has resolved (`{ stdout, stderr, ... }`
           * for Bash: `BuiltinToolResults[tool]`); undefined while it runs.
           *
           * For a call that errored, was refused or an abort cut, it is the text
           * the model read (an `isInterrupted` call: the abort's own). An expanded
           * group's rows draw it inline; a standalone row's is its own `ToolResult`.
           */
          output?: unknown;
          /**
           * Which of its rows the transcript's viewport shows now: `null` while
           * drawn outside it, absent where the surface does not say. Read-only.
           *
           * Reported once drawn and again when it changes: on a scroll, for the
           * messages at the viewport's edges only. A rewrite carries it on as
           * received; one that changes or drops it is refused.
           */
          onScreen?: OnScreen | null;
      };
      /**
       * The result block drawn under a standalone tool row in the transcript,
       * which the tool's own result renderer draws from `output`.
       *
       * A rewrite of `output` is checked against the tool's output schema (one
       * that does not fit draws nothing; one the renderer cannot read hits the
       * row's error boundary). The stored result is untouched.
       *
       * Raised on every surface.
       */
      ToolResult: {
          /**
           * The id `tool.call` carried for the call this result belongs to
           * (`e.tool_use_id` there); the same value as `requestId`. Read-only.
           */
          tool_use_id: string;
          /**
           * Which one the result belongs to (`Bash`, `Read`, a plugin's tool).
           * Read-only.
           */
          tool: string;
          /**
           * The tool's own result object (`{ stdout, stderr, interrupted, ... }` for
           * Bash), the same one `ToolUse.output` carries; a rewrite is drawn.
           *
           * A built-in tool's is `BuiltinToolResults[tool]`, the record
           * `tool.call` resolved as `result`.
           */
          output: unknown;
          /**
           * True when the call ended in an error, which draws the error text and not
           * `output`. Read-only.
           */
          isErrored: boolean;
          /**
           * Which of its rows the transcript's viewport shows now: `null` while
           * drawn outside it, absent where the surface does not say. Read-only.
           *
           * Reported once drawn and again when it changes: on a scroll, for the
           * messages at the viewport's edges only. A rewrite carries it on as
           * received; one that changes or drops it is refused.
           */
          onScreen?: OnScreen | null;
      };
      /**
       * A run of tool calls the transcript folds into one count line (`Read 3
       * files, ran 2 shell commands`): reads, searches, listings.
       *
       * A hook that sets `isExpanded` unfolds the group where it is, and each row
       * it unfolds into is a `ToolUse` drawing a `ToolUse` hook then sees.
       *
       * Raised on every surface.
       */
      ToolGroup: {
          /**
           * In the order the model made them.
           */
          calls: ReadonlyArray<ToolGroupCall>;
          /**
           * True while the group is the live one: a call in it may still be
           * running and the model's next call may join it.
           */
          isActive: boolean;
          /**
           * Whether each call draws as its own `ToolUse` row (true under
           * `--verbose` and in the ctrl+o transcript) or the group draws one line.
           *
           * The one prop of the three a rewrite changes on the screen.
           */
          isExpanded: boolean;
          /**
           * Which of its rows the transcript's viewport shows now: `null` while
           * drawn outside it, absent where the surface does not say. Read-only.
           *
           * Reported once drawn and again when it changes: on a scroll, for the
           * messages at the viewport's edges only. A rewrite carries it on as
           * received; one that changes or drops it is refused.
           */
          onScreen?: OnScreen | null;
      };
      /**
       * The output row a slash command printed in the transcript, under its echo
       * (`/cost`'s lines, the `text` a `command.run` hook answered).
       *
       * What the run resolved as text, a `local` command's or a plugin's alike. A
       * rewrite of `text` draws there and the stored row keeps what the model
       * reads; a hook's own tree draws in the row's place, the transcript's width.
       *
       * Raised on every surface.
       */
      CommandOutput: {
          /**
           * Which one printed the row, as `command.run` named it (no slash); a
           * hook on its own command matches by it.
           *
           * Read-only: a rewrite carries it on as received; one that changes or
           * drops it is refused and the engine draws its own row.
           */
          command: string;
          /**
           * The arguments the run had, as the echo above the row shows them
           * (`***` for a command that marks its arguments sensitive). Read-only.
           */
          args: string;
          /**
           * The row's text: what the command printed, or the `text` a hook
           * answered under its plugin's name; markdown, as the row draws it.
           */
          text: string;
          /**
           * True when the row is the run's error line (a command that threw),
           * which draws in the error colour and not dim. Read-only.
           */
          isErrored: boolean;
          /**
           * Which of its rows the transcript's viewport shows now: `null` while
           * drawn outside it, absent where the surface does not say. Read-only.
           *
           * Reported once drawn and again when it changes: on a scroll, for the
           * messages at the viewport's edges only. A rewrite carries it on as
           * received; one that changes or drops it is refused.
           */
          onScreen?: OnScreen | null;
      };
      /**
       * One row of the live tool-progress region under a running tool call; today
       * the run-in-background pill. One instance per row.
       *
       * A union on `kind`: other progress kinds join as their props become plain
       * data, each with its own fields, so a hook matches `{ props: { kind:
       * "background_hint" } }` or branches on `e.props.kind` and stays right.
       *
       * Raised on the terminal surface only.
       */
      ToolProgress: {
          /**
           * The tool call the row belongs to, as `tool.call` and the `ToolUse` row
           * carry it. Read-only: a rewrite carries it on as received.
           *
           * While several foreground calls share one pill, the first of them.
           */
          tool_use_id: string;
          /**
           * Which progress row: the run-in-background pill. Read-only.
           */
          kind: 'background_hint';
          /**
           * The pill's text as the engine draws it, dim, under the tool call:
           * `(ctrl+b to run in background)`, or with the person's own binding.
           *
           * A rewrite is drawn in its place, dim; `""` draws nothing. A hook that
           * returns a tree draws that instead.
           */
          hint: string;
      };
      /**
       * The line that animates while a turn runs (`Sauteing... (12s, 300
       * tokens)`); on the desktop, the row that carries the turn's mark.
       *
       * Reads `word` (or `message` while one overrides it), `suffix`, then what
       * the surface keeps and no prop carries: elapsed time, tokens, effort. A
       * hook rewrites the first three, or draws a tree in place of all of it.
       *
       * Raised on the terminal and desktop surfaces only.
       */
      Spinner: {
          /**
           * Animated by the line (`Sauteing`), as sampled for this turn.
           *
           * On the desktop, what the row says its step is doing (`Creating
           * notes.md`), or `Working` while the row shows no words.
           */
          word: string;
          /**
           * The text drawn instead of the word while a state overrides it, else null.
           */
          message: string | null;
          /**
           * What the engine draws right after the word or message to say the turn is
           * still going: one ellipsis character.
           *
           * Left off a text that already ends in an ellipsis, so a rewritten
           * `message` ending in one shows one. A rewrite is drawn as given (`""`
           * draws the text bare, `" ~"` draws `Sauteing ~`); left out, the engine's.
           */
          suffix: string;
          /**
           * What the turn is doing. The desktop tells `thinking`, `requesting`,
           * `tool-use` and `responding` apart and never says `tool-input`.
           */
          mode: 'requesting' | 'responding' | 'thinking' | 'tool-input' | 'tool-use';
      };
      /**
       * The line that closes a turn in the transcript (`Baked for 3s`); a
       * remote surface draws its own footer.
       *
       * Raised on the terminal surface only.
       */
      TurnDuration: {
          /**
           * The past-tense word the line drew (`Baked`), as sampled for this line.
           */
          word: string;
          /**
           * The turn's duration in milliseconds, as the line formats it (`3s`,
           * `1m 4s`).
           */
          durationMs: number;
          /**
           * Which of its rows the transcript's viewport shows now: `null` while
           * drawn outside it, absent where the surface does not say. Read-only.
           *
           * Reported once drawn and again when it changes: on a scroll, for the
           * messages at the viewport's edges only. A rewrite carries it on as
           * received; one that changes or drops it is refused.
           */
          onScreen?: OnScreen | null;
      };
      /**
       * One dim status line under the logo (the model source, an experiment
       * enrollment, a settings hint), with a trailing `/command`.
       *
       * Raised on the terminal surface only.
       */
      InfoNotice: {
          /**
           * The notice's text, flattened to one string.
           */
          text: string;
          /**
           * The slash command appended after the text, or null when the notice has
           * none.
           */
          command: string | null;
          /**
           * Which of its rows the transcript's viewport shows now: `null` while
           * drawn outside it, absent where the surface does not say. Read-only.
           *
           * Reported once drawn and again when it changes: on a scroll, for the
           * messages at the viewport's edges only. A rewrite carries it on as
           * received; one that changes or drops it is refused.
           */
          onScreen?: OnScreen | null;
      };
      /**
       * The dim mode labels at the right of the prompt footer (`focus`, `memory
       * paused`), joined by ` & `. One instance.
       *
       * A hook adds a mode by rewriting `modes`, removes one by filtering, or
       * draws its own tree.
       *
       * Raised on the terminal and desktop surfaces only.
       */
      SessionMode: {
          /**
           * The labels the footer shows, in order; empty when there are none.
           */
          modes: readonly string[];
      };
      /**
       * The dim hint line under the prompt (`? for shortcuts`, `esc to
       * interrupt`, the pills beside them). One instance.
       *
       * A hook rewrites `hint`, drawn in the line's place, or draws its own tree;
       * `isDraft` and `isWorking` say what the line is for. On the terminal, until
       * a new answer lands the last keeps its row (the engine's line before any).
       *
       * Raised on the terminal and desktop surfaces only.
       */
      PromptHint: {
          /**
           * True while the prompt holds typed text. Read-only.
           */
          isDraft: boolean;
          /**
           * True while a model turn is running. Read-only.
           */
          isWorking: boolean;
          /**
           * The line's text as the engine draws it; one string, so a rewrite
           * replaces the line.
           *
           * Read from the drawn line the way the screen reader reads it, one space
           * between parts.
           */
          hint: string;
      };
      /**
       * The band directly above the prompt input, where the surveys draw; the
       * engine draws nothing of its own here.
       *
       * A hook draws a tree, or passes; one instance. The person collapses it
       * (ctrl+x ctrl+a, `[-]`) or focuses it (a click, ctrl+x tab): an Input
       * types, a Button arms the hotkeys, a tree taller than it scrolls.
       *
       * Raised on the terminal and desktop surfaces only.
       */
      AbovePrompt: {
          /**
           * True while a survey holds the band; a hook yields to it. Read-only.
           */
          hasSurvey: boolean;
          /**
           * True while a model turn is running. Read-only.
           */
          isWorking: boolean;
          /**
           * Rows the band may take: in fullscreen, what the bottom slot has left
           * above the prompt; otherwise the terminal's height. Read-only.
           *
           * That slot is capped at half the terminal's rows, the prompt's included.
           * A tree of at most `maxRows` rows shows whole; a taller one scrolls in a
           * window of `scroll.bodyRows`, and a bare digit arms no Button's hotkey.
           */
          maxRows: number;
          /**
           * Cells across the band: the terminal's width, or the transcript
           * column's while a `Pane` is docked beside it. Read-only.
           *
           * A tree wider than this wraps or truncates as its Text props say; size
           * a table or a rule to it rather than to `viewport.columns`.
           */
          bodyColumns: number;
          /**
           * The band's window over a tree taller than `maxRows`: engine-owned,
           * moved by the wheel, and by the person's keys while the band is focused.
           *
           * `bodyRows` is `maxRows` less the `n more` row. Read-only.
           */
          scroll: SiteScroll;
          /**
           * Which transcript is on screen above the band: the main conversation's
           * (no `agentId`) or one agent's, opened from the tasks list.
           *
           * The same band under either; a switch re-runs the hook with the new
           * view. Read-only: a rewrite carries it on as received; one that changes
           * or drops it is refused, the hook that passed it failing.
           */
          view: SiteView;
      };
      /**
       * The framed region a plugin opened with `$.ui.open({ id })`: one instance
       * per id (`requestId`), its body the hook's tree, one shown, the rest tabs.
       *
       * Placed by the surface (docked in fullscreen, else above the prompt) and
       * keyed by the person (ctrl+x tab, Esc), who closes it from the engine's mark
       * or ctrl+x x: `ui.close` with origin `person`, which a hook may refuse.
       *
       * Raised on every surface.
       */
      Pane: {
          /**
           * Its tab's label while more than one pane is open (with one, the engine
           * draws no title): the `title` it was opened with, or its id.
           *
           * A click on a tab, or Tab onto it and Enter, shows that pane. Read-only
           * here; another `$.ui.open` (or a hook on `ui.open`) retitles.
           */
          title: string;
          /**
           * True while the person has given the pane the keyboard: Tab walks its
           * elements, a Button's `hotkey` presses it, the arrows scroll. Read-only.
           */
          isFocused: boolean;
          /**
           * Cells across the body, inside the frame. Read-only.
           */
          bodyColumns: number;
          /**
           * Where the surface seated the pane: `dock` beside the transcript (the
           * terminal in fullscreen from 110 columns), or `inline` above the prompt.
           *
           * Read-only: a rewrite carries it on as received; one that changes or
           * drops it is refused, the hook that passed it failing.
           */
          placement: 'dock' | 'inline';
          /**
           * The body's window over the tree: engine-owned, moved by the person's
           * keys while the pane is focused. Read-only.
           */
          scroll: SiteScroll;
          /**
           * Which transcript is on screen beside the pane: the main conversation's
           * (no `agentId`) or one agent's, opened from the tasks list.
           *
           * The pane stays open across a switch, one instance re-rendered for the
           * view, so a hook draws for the agent in view. Read-only: a rewrite carries
           * it on as received; one that changes or drops it is refused.
           */
          view: SiteView;
      };
  };

RenderResultOf type # line 8976

In the first published surface (2.1.259)

What a ui.render hook returns and what next(e) resolves to: a RenderElement tree, the same for every component.

  export type RenderResultOf = {
      [C in RenderComponent]: RenderElement;
  };

RenderSurface type # line 8992

In the first published surface (2.1.259) · changed in 2.1.268, 2.1.273

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.

desktop is Claude Code Desktop, mobile the Claude mobile app, vscode Claude Code for VS Code. A remote surface asks over the wire (ui_render), draws with the props the hook handed core, and draws the tree where it has a slot for it.

Each surface's ask is its own evaluation, since a tree may hold an element only some surfaces draw (Svg, Client).

  export type RenderSurface = 'terminal' | 'desktop' | 'mobile' | 'vscode';

RenderViewport type # line 9002

In the first published surface (2.1.259) · changed in 2.1.275

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

On the terminal, the conversation's columns and screen rows; on a remote surface, the pane's width and height over the advance and line height of its code font. Cell-based until the first element lays out in pixels.

27 lines
  export type RenderViewport = {
      /**
       * Cells across. A tree wider than this wraps or truncates, as its Text
       * props say.
       */
      columns: number;
      /**
       * Cells down the whole surface, not the room left for this component.
       *
       * Informational: a change of height alone re-draws nothing and keys no
       * new evaluation, so a hook reads it as of the last width or props change.
       */
      rows: number;
      /**
       * Whether this surface docks a pane beside the transcript, so a pane a
       * plugin opens unasked is a sidebar, not a takeover; absent is unknown.
       *
       * What `command.run`'s `presentation.isFullscreen` says. The terminal always
       * says: `true` fullscreen, `false` on the main screen, fixed per session; a
       * remote surface once its client reports it with the size, absent before.
       *
       * @remarks A remote surface that reports it places panes (`$.ui.open` is
       *   placed there); the mobile app reports `false`. A change re-draws.
       * @example if (e.viewport?.isFullscreen === true) void $.ui.open({ id })
       */
      isFullscreen?: boolean;
  };

ResolveInput type # line 9038

Added in 2.1.267

The input of ui.resolve: which surface's elements, for which component; a union with one member per surface (ResolveInputOf).

Resolved when the plugins load, ahead of any drawing, so it names the surface and the component and not the props; a ui.render argument is one (it carries both), which is what $.ui.resolve(e) takes.

  export type ResolveInput<C extends RenderComponent = RenderComponent, P extends RenderSurface = RenderSurface> = P extends RenderSurface ? ResolveInputOf<C, P> : never;

ResolveInputOf type # line 9043

Added in 2.1.267

One ui.resolve input, for a component on one surface.

  export type ResolveInputOf<C extends RenderComponent, P extends RenderSurface> = {
      /**
       * Where the table draws; one literal per member, so a hook that narrows
       * it narrows the table `next(e)` resolves to.
       */
      surface: P;
      /**
       * Which drawing the table is resolved for; the key a matcher narrows on.
       */
      component: C;
  };

ResultOf type # line 9059

In the first published surface (2.1.259) · changed in 2.1.265

What each event's hook returns, and what its next(e) resolves to, by event name.

  export type ResultOf = EngineResultOf & ClassicResultOf & {
      [N in OpEventName]: OpEventResult<N>;
  } & {
      [N in NounEventName]: NounEventResult<N>;
  };

SDKAssistantMessageError type # line 9065

Added in 2.1.265 · changed in 2.1.267, 2.1.268

  type SDKAssistantMessageError = 'authentication_failed' | 'oauth_org_not_allowed' | 'account_on_hold' | 'verification_required' | 'billing_error' | 'rate_limit' | 'overloaded' | 'invalid_request' | 'model_not_found' | 'server_error' | 'unknown' | 'max_output_tokens' | 'cloud_credential_error';

Select type # line 9070

In the first published surface (2.1.259)

The members of T assignable to S; all of T when none is.

  type Select<T, S> = [Extract<T, S>] extends [never] ? T : Extract<T, S>;

Selected type # line 9076

Added in 2.1.265

The events a pattern selects, as a union of names: the one named, every one under a glob's namespace, or every one a negation does not exclude.

  export type Selected<P extends string> = P extends '*' ? EventName : P extends `!${infer Negated}` ? Exclude<EventName, Selected<Negated>> : P extends `${infer Prefix}.*` ? Extract<EventName, `${Prefix}.${string}`> : Extract<EventName, P>;

Selection type # line 9082

In the first published surface (2.1.259)

The literal each tag key of I is held to by matcher M: one-of arrays flattened, RegExps widened to unknown.

  type Selection<I, M> = {
      [K in keyof M & TagKeys<I>]: Literal<M[K] extends readonly (infer One)[] ? One : M[K]>;
  };

SelectOption type # line 9090

Added in 2.1.260

One option of a Select: the value onSelect and ui.select carry, and the text drawn for it (the value when absent).

  export type SelectOption = {
      value: string;
      label?: string;
  };

SelectProps type # line 9103

Added in 2.1.260 · changed in 2.1.271

The props of Select, every surface's one-of-several picker: an address, a label, the options, the one selected, the closure a pick runs. A leaf.

Focused through the same ring as Button (abovePrompt:focus); keys reach it only while it has focus (arrows move, Enter picks) and Esc always returns to the prompt; a pick raises ui.select, its bottom onSelect.

33 lines
  export type SelectProps = {
      /**
       * The element's address: `e.element` at `ui.select`, what a matcher names.
       */
      key: string;
      /**
       * Text drawn before the current value.
       */
      label?: string;
      /**
       * What can be picked, in the order drawn; at least one, values unique.
       */
      options: readonly SelectOption[];
      /**
       * Which option is selected when drawn; the person's pick replaces it
       * until the hook draws another.
       */
      value?: string;
      /**
       * The site's focus ring starts here when the site takes the keyboard,
       * instead of on nothing, as the DOM's `autofocus`: Enter acts on it at once.
       *
       * A pane opened with `focus`, or the person's focus chord or click, is the
       * take. Of several in one site the first drawn wins; it raises `ui.focus`,
       * origin this plugin. A ring the person has moved stays where it was put.
       */
      autoFocus?: true;
      /**
       * Runs on a pick with the option's value, in the plugin's own environment:
       * the bottom of a `ui.select` chain. No model turn unless it asks one.
       */
      onSelect: (value: string, e: UiSelectArgument) => void;
  };

SessionAttachInput type # line 9145

Added in 2.1.269

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

A remote client attaches by saying so (ui_attach) or by its first ask to draw; the terminal's attachment is the REPL's binding and raises nothing. Every field is the engine's: a hook observes, next(e) passes them on.

16 lines
  export type SessionAttachInput = {
      /**
       * Where the client draws: what it declared, a rendering fact.
       */
      surface: RenderSurface;
      /**
       * The client's own id, unique in the roster; two phones are two clients on
       * one surface. A client that never named itself is `<surface>:default`.
       */
      clientId: string;
      /**
       * The size the client draws into, in character cells, and whether its
       * layout docks a pane, when it said.
       */
      viewport?: RenderViewport;
  };

SessionAttachResult type # line 9166

Added in 2.1.269

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

  export type SessionAttachResult = {
      clientId: string;
  };

SessionAuthorization type # line 9177

Added in 2.1.268

What $.session.authorize() answers: an opaque handle for the session's Anthropic credential and its kind, or null when there is none to hold.

The secret itself stays with the engine; the handle is its plugin-side face, spent through $.http.fetch(url, { auth: handle }).

  export type SessionAuthorization = {
      handle: string;
      kind: 'bearer' | 'api-key';
  } | null;

SessionCompactArgs type # line 9186

Added in 2.1.267

session.compact's input as a plugin's $.session.compact(args) takes it: trigger (plugin), messages and agentId are the engine's.

  export type SessionCompactArgs = {
      /**
       * What the summary should keep or stress, as typed after `/compact`;
       * absent, the engine's own compaction prompt alone.
       */
      instructions?: string;
  };

SessionCompacted type # line 9198

Added in 2.1.267 · changed in 2.1.280

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.

34 lines
  export type SessionCompacted = {
      /**
       * The conversation after the compaction, oldest first: from core, its
       * summary and the messages it kept; from a hook, whatever it hands up.
       *
       * What the transcript becomes (kept, on `precompute`, for the compaction
       * that comes). A message with the engine's `handle` stands as the engine
       * has it; one without is built from its `role`, `text` and tool blocks.
       */
      messages: readonly SessionMessage[];
      /**
       * The conversation's size before, in tokens; absent when core did not
       * record it.
       */
      tokensBefore?: number;
      /**
       * Its size afterwards, in tokens; absent on `precompute` and when core
       * did not record it.
       */
      tokensAfter?: number;
      /**
       * What the compaction's own model request cost (ModelUsage), when core
       * made one: the summarizer's token counts as the API reported them.
       *
       * Absent when a hook answered in core's place, when core reused a summary
       * already computed, and when the response reported none. Accounting only:
       * the session's cost ledger (`session.measure`'s `cost`) already holds it.
       *
       * @example
       * const { usage } = await next(e); if (usage) spent += usage.output_tokens
       */
      usage?: ModelUsage;
      skip?: undefined;
  };

SessionCompactInput type # line 9237

Added in 2.1.267

The input of session.compact: one compaction of the conversation, about to run; messages is the transcript it runs over.

31 lines
  export type SessionCompactInput = {
      /**
       * What is compacting (SessionCompactTrigger); the key a matcher narrows
       * on. Pinned: `next(e)` passes it on as received.
       */
      trigger: SessionCompactTrigger;
      /**
       * The id of the loop compacting, for a subagent's or a fork's own
       * transcript; absent for the main conversation (tool.call's `agentId`).
       *
       * Pinned: left out of a rewrite it is put back, changed it fails the hook.
       * `e.messages` is this loop's transcript; `$.session.messages()` stays the
       * main conversation, and `$.session.messages({ agentId })` reads this one.
       */
      agentId?: string;
      /**
       * What the summary should keep or stress: the text after `/compact`, a
       * plugin's, or absent.
       *
       * `next({ ...e, instructions })` changes what the summarizer is told.
       */
      instructions?: string;
      /**
       * The transcript being compacted, in `$.session.messages()`'s shape, each
       * message carrying the engine's `handle`; a subagent's own under `agentId`.
       *
       * `next({ ...e, messages })` changes what is summarized: a message kept
       * with its handle is the engine's own, whole; one without is read as built.
       */
      messages: readonly SessionMessage[];
  };

SessionCompactResult type # line 9275

Added in 2.1.267

What a session.compact hook returns and what next(e) resolves to: the compaction ({ messages, tokensBefore?, tokensAfter?, usage? }) or a skip.

There is no summary string: the summary is a message.

  export type SessionCompactResult = SessionCompacted | SessionCompactSkipped;

SessionCompactSkipped type # line 9283

Added in 2.1.267

A compaction vetoed: on precompute nothing is computed or kept; on any other trigger the conversation stays as it is and one line says why.

Core answers it too, when a classic PreCompact hook blocks.

  export type SessionCompactSkipped = {
      /**
       * Why, as the notice reads.
       */
      skip: string;
      messages?: undefined;
  };

SessionCompactTrigger type # line 9298

Added in 2.1.267

Who compacts: the person's /compact (manual), the engine at its threshold or on a prompt too long (auto), a plugin, or a precompute.

precompute is the one dispatch that installs nothing: its result is kept for the compaction that comes, if the conversation it ran over still leads.

  export type SessionCompactTrigger = 'manual' | 'auto' | 'plugin' | 'precompute';

SessionContextBreakdown type # line 9308

Added in 2.1.271 · changed in 2.1.280

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_usage shape.

Less that reply's internal-build sections. Token counts are the engine's estimates as numbers, never formatted: a full breakdown counts with the token-count API where it can, a summary one estimates throughout.

75 lines
  export type SessionContextBreakdown = {
      /**
       * One row per category, the free space and the compaction buffer among
       * them; `kind` says which is which.
       */
      categories: ContextCategory[];
      /**
       * Tokens in use, unclamped: past `rawMaxTokens` when over the window.
       */
      totalTokens: number;
      /**
       * The window measured against, the same figure as `rawMaxTokens`.
       */
      maxTokens: number;
      /**
       * The window measured against, in tokens: the model's limit, or a smaller
       * compaction window (`autocompactSource` says which).
       */
      rawMaxTokens: number;
      /**
       * How that window was settled (ContextWindowSource); the SDK's reply
       * carries it under this name too, outside its typed schema.
       */
      autocompactSource: ContextWindowSource;
      /**
       * `totalTokens` over `rawMaxTokens` as a whole percentage, 0 to 100 and
       * past it when over.
       */
      percentage: number;
      /**
       * The grid, row by row: 10 by 10, 20 by 10 for a window of a million or
       * more, 5 wide when asked for under 80 `columns`.
       */
      gridRows: ContextGridSquare[][];
      /**
       * Which model the breakdown was computed for, as `/model` shows it.
       */
      model: string;
      /**
       * Each memory file in the context, with its path and tokens.
       */
      memoryFiles: ContextMemoryFile[];
      /**
       * Each MCP tool's schema, with its server and tokens.
       */
      mcpTools: ContextMcpTool[];
      /**
       * The custom agents the Agent tool describes, each with its tokens.
       */
      agents: ContextAgent[];
      /**
       * The slash-command listing, counted; absent when the session lists none.
       */
      slashCommands?: ContextSlashCommands;
      /**
       * The skill listing, counted, with one entry per skill; absent when the
       * session lists none.
       */
      skills?: ContextSkills;
      /**
       * The token count at which auto-compaction runs; absent when it is off.
       */
      autoCompactThreshold?: number;
      /**
       * Whether auto-compaction is on for the session.
       */
      isAutoCompactEnabled: boolean;
      /**
       * The token counts (ModelUsage) the live window's last API response
       * reported, or null before one came back.
       *
       * The breakdown's `Messages` row is reconciled to it.
       */
      apiUsage: ModelUsage | null;
  };

SessionContextUsage type # line 9392

Added in 2.1.267 · changed in 2.1.268, 2.1.271

The live context window as the status line reads it, and by category as /context breaks it down when the call asked ({ breakdown }).

tokens and percent are the last API response's input side against the model's window, absent until the first response of the live window: a fresh session, or one just compacted, until its next response.

26 lines
  export type SessionContextUsage = {
      /**
       * Input tokens the last response was answered over: uncached, cache-written
       * and cache-read together (the status line's `total_input_tokens`).
       */
      tokens?: number;
      /**
       * The context window of the session's model, in tokens (the status line's
       * `context_window_size`).
       */
      window: number;
      /**
       * `tokens` over `window` as a whole percentage, 0 to 100 (the status
       * line's `used_percentage`).
       */
      percent?: number;
      /**
       * The window by category, as /context breaks it down: present only when
       * the call passed `breakdown`, and only with a session bound.
       *
       * It measures against the compaction window (`rawMaxTokens`), which may be
       * smaller than `window`, and estimates every category, so its
       * `totalTokens` need not equal `tokens`.
       */
      breakdown?: SessionContextBreakdown;
  };

SessionCost type # line 9422

Added in 2.1.267 · changed in 2.1.268

What the session has cost, as /cost and the status line total it.

  export type SessionCost = {
      /**
       * US dollars, summed over every priced API response this session.
       */
      usd: number;
  };

SessionCronSummary type # line 9429

Added in 2.1.265

15 lines
  type SessionCronSummary = {
      id: string;
      /**
       * Cron expression, e.g. "0 9 * * 1-5".
       */
      schedule: string;
      /**
       * False for one-shot wakeups whose cron field encodes a single fire time; true for tasks that re-fire on every match.
       */
      recurring: boolean;
      /**
       * Prompt text submitted when the cron fires. Capped at 1000 chars; clipped values append an in-string "... [+N chars]" marker.
       */
      prompt: string;
  };

SessionDetachInput type # line 9449

Added in 2.1.269

The input of session.detach: a client left the session's roster. Every field is the engine's: a hook observes, and next(e) passes them on.

14 lines
  export type SessionDetachInput = {
      /**
       * Where the client drew.
       */
      surface: RenderSurface;
      /**
       * The id it attached under.
       */
      clientId: string;
      /**
       * Why it left: it detached, or the session ended under it.
       */
      reason: SessionDetachReason;
  };

SessionDetachReason type # line 9468

Added in 2.1.269

Why a client left the roster: detach, it said so (ui_detach); end, the session ended with it still attached.

  export type SessionDetachReason = 'detach' | 'end';

SessionDetachResult type # line 9474

Added in 2.1.269

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

  export type SessionDetachResult = {
      clientId: string;
  };

SessionEndHookInput type # line 9478

Added in 2.1.265

  type SessionEndHookInput = BaseHookInput & {
      hook_event_name: 'SessionEnd';
      reason: ExitReason;
  };

SessionEndInput type # line 9491

Added in 2.1.275

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

One short wall-clock bound (1.5 s by default) covers every hook, its $ waits and core, and next.budget reads it: at it next.signal aborts, a $ call in flight with it; only a process a command let go of outlives it.

19 lines
  export type SessionEndInput = {
      /**
       * Why it ends (SessionEndReason), the word the classic SessionEnd hook
       * receives as its `reason`.
       *
       * `clear` is how a hook sees a `/clear`: the conversation ends, the process
       * goes on under a new session id, and no `session.start` fires for it.
       */
      reason: SessionEndReason;
      /**
       * The ending session's id (`$.session.id()` until now); after a `/clear`
       * or a resume the process goes on under another.
       */
      sessionId: string;
      /**
       * What `claude --resume` takes to return to it.
       */
      resume: SessionResume;
  };

SessionEndReason type # line 9519

Added in 2.1.275

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

prompt_input_exit, the person left (/exit, ctrl+c, ctrl+d); clear, a /clear started a fresh one; resume, another took its place; logout; other, a -p run finished or the process got SIGINT, SIGTERM or SIGHUP.

  export type SessionEndReason = ClassicHookInputs['SessionEnd']['reason'];

SessionEndResult type # line 9525

Added in 2.1.275

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

  export type SessionEndResult = {
      sessionId: string;
  };

SessionMeasureInput type # line 9537

Added in 2.1.275

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.

The same figures the op reads, without context.breakdown: call $.session.usage({ breakdown }) from the hook when the categories matter. Every field is the engine's: a hook observes, and next(e) passes them on.

27 lines
  export type SessionMeasureInput = {
      /**
       * The live context window (`$.session.usage()`'s `context`): the window,
       * and its fill once a response of the live window reported one.
       *
       * Never carries `breakdown` here.
       */
      context: SessionContextUsage;
      /**
       * The rate-limit windows the last response reported, each with its
       * `percentUsed`; empty off a subscription or before the first reading.
       */
      rateLimits: SessionRateLimit[];
      /**
       * What the session has cost so far; absent where the host keeps no ledger.
       */
      cost?: SessionCost;
      /**
       * Which units differ from the last measurement raised (UsageUnit), never
       * empty; the first measurement names every unit it has a figure for.
       *
       * `context`: the fill moved; `rateLimits`: a window moved a whole point,
       * appeared or left, or the account's limit status changed; `cost`: the
       * total grew.
       */
      changed: UsageUnit[];
  };

SessionMeasureResult type # line 9569

Added in 2.1.275

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

  export type SessionMeasureResult = {
      changed: UsageUnit[];
  };

SessionMessage type # line 9576

In the first published surface (2.1.259) · changed in 2.1.267

One message of the transcript as $.session.messages() returns it.

27 lines
  export type SessionMessage = {
      /**
       * Who wrote it.
       */
      role: 'user' | 'assistant';
      /**
       * Its text blocks joined; '' when it has none.
       */
      text: string;
      /**
       * The tool_use blocks of an assistant message, each with its outcome
       * (`result`, `text`, `isError`) once the transcript holds it.
       */
      toolUses: ToolUseSummary[];
      /**
       * The tool_result blocks of a user message: `{ tool_use_id, text, isError,
       * result }`.
       */
      toolResults?: ToolResultSummary[];
      /**
       * An opaque token the engine stamps on a message it hands a
       * `session.compact` hook, so a list handed back maps to its own messages.
       *
       * Absent on `$.session.messages()` and on a message a hook built.
       */
      handle?: string;
  };

SessionMessagesAgentArgs type # line 9608

Added in 2.1.280

A $.session.messages call for the rows (SessionMessage) of the main conversation or of one agent's: agentId alone, no as.

  type SessionMessagesAgentArgs = {
      /**
       * Whose conversation; absent, the main one.
       */
      agentId?: string;
      /**
       * Left out: the rows.
       */
      as?: undefined;
  };

SessionMessagesApiArgs type # line 9623

Added in 2.1.280

A $.session.messages call for the Messages API form (ApiMessage) of the main conversation or, with agentId, of one of this session's agents'.

  type SessionMessagesApiArgs = {
      /**
       * `"api"`.
       */
      as: 'api';
      /**
       * Whose conversation; absent, the main one.
       */
      agentId?: string;
  };

SessionMessagesApiResult type # line 9641

Added in 2.1.280

What $.session.messages({ as: "api", agentId }) resolves to: the agent's conversation as ApiMessage, or { deny } (SessionMessagesDeny).

Array.isArray tells the two apart; without agentId it is always the messages.

  type SessionMessagesApiResult = ApiMessage[] | SessionMessagesDeny;

SessionMessagesArgs type # line 9647

Added in 2.1.280

What $.session.messages(args) takes and a session.messages hook reads on e: whose conversation (agentId) and in which form (as).

16 lines
  type SessionMessagesArgs = {
      /**
       * Whose conversation to read: the id `tool.call`, `turn.step` and
       * `turn.complete` carry inside that agent's loop. Absent, the main one.
       *
       * A subagent (foreground or background), a fork, or a teammate running in
       * this process; `$.agent.list()` lists it, an Agent tool use's `toolUses`
       * entry names it. Not an agent a workflow run filed under the run.
       */
      agentId?: string;
      /**
       * `"api"` for the Messages API form (ApiMessage: `{ role, content }` with
       * the content blocks intact); absent, the rows (SessionMessage).
       */
      as?: 'api';
  };

SessionMessagesCall type # line 9668

Added in 2.1.280

$.session.messages: the main conversation's rows with no argument, with { as: "api" } its Messages API form; with agentId an agent's, or deny.

  type SessionMessagesCall = {
      (): Promise<SessionMessage[]>;
      (args: SessionMessagesMainApiArgs): Promise<ApiMessage[]>;
      (args: SessionMessagesApiArgs): Promise<SessionMessagesApiResult>;
      (args: SessionMessagesAgentArgs): Promise<SessionMessagesResult>;
      (args: SessionMessagesArgs): Promise<SessionMessagesValue>;
  };

SessionMessagesDeny type # line 9684

Added in 2.1.280

What $.session.messages({ agentId }) resolves to when the id names no conversation this session can read: why not, in deny.

The id is not one of this session's agents, the agent runs in another process (a pane-hosted teammate), or it finished and the session reads no saved transcript back for it (none saved; a workflow run's). Never main.

  type SessionMessagesDeny = {
      /**
       * Why no conversation was read, naming the id.
       */
      deny: string;
  };

SessionMessagesMainApiArgs type # line 9695

Added in 2.1.280

A $.session.messages({ as: "api" }) call naming no agent: the main conversation, whose answer is always the messages (ApiMessage).

  type SessionMessagesMainApiArgs = {
      /**
       * `"api"`.
       */
      as: 'api';
      /**
       * Left out: the main conversation.
       */
      agentId?: undefined;
  };

SessionMessagesResult type # line 9713

Added in 2.1.280

What $.session.messages({ agentId }) resolves to: the messages (SessionMessage), or { deny } (SessionMessagesDeny).

Without agentId it is always the messages; with one the session cannot read, the deny. Array.isArray tells the two apart.

  type SessionMessagesResult = SessionMessage[] | SessionMessagesDeny;
Feedback