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, 351 to 400 of 570

SessionMessagesValue type # line 9719

Added in 2.1.280

What a session.messages hook's { value } holds, for any call: the rows (SessionMessage), the Messages API form (ApiMessage), or { deny }.

  type SessionMessagesValue = SessionMessagesResult | SessionMessagesApiResult;

SessionRateLimit type # line 9724

Added in 2.1.267 · changed in 2.1.268

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

16 lines
  export type SessionRateLimit = {
      /**
       * Which window: `five_hour`, `seven_day`, or a Claude gateway's
       * `spend_limit`.
       */
      kind: string;
      /**
       * How much of the window is used, 0 to 100 with at most one decimal:
       * 23.5, or 7, never 7.000000000000001; past 100 on an exceeded spend limit.
       */
      percentUsed: number;
      /**
       * When the window resets, as an ISO 8601 timestamp.
       */
      resetsAt?: string;
  };

SessionReceiveEvent type # line 9745

Added in 2.1.267 · changed in 2.1.282

An external-event wake the delivery's text parsed as (a GitHub relay event, a signal's notice): the envelope's attributes and its JSON body.

27 lines
  export type SessionReceiveEvent = {
      /**
       * The producing service (`github`).
       */
      source: string;
      /**
       * The event's discriminator (`pull_request.closed`, `check_suite`).
       */
      kind: string;
      /**
       * The envelope's sender-kind attribute as the server stamped it (`system`
       * for a relay's own event, `rc_owner` for the user's own relayed message);
       * absent when the envelope carries none.
       */
      from?: string;
      /**
       * The envelope's JSON body (`{ pr: "acme/app#12", outcome: "merged" }`).
       */
      data: Record<string, unknown>;
      /**
       * The `data` keys whose values are free text a third party wrote (a
       * commenter's `author` and `comment`), as the producer marked them.
       *
       * Empty when none; the server asserts every other key's value, not these.
       */
      untrustedKeys: readonly string[];
  };

SessionReceiveInput type # line 9777

Added in 2.1.267 · changed in 2.1.280

The input of session.receive: one inbound delivery, sanitized, before it is queued (a relay's event, a peer's message, a message for an agent).

33 lines
  export type SessionReceiveInput = {
      /**
       * Where the delivery came from, as the bridge classified it; the key a
       * matcher narrows on. `next(e)` passes it on as received.
       */
      origin: SessionReceiveOrigin;
      /**
       * The delivery's body as the model would read it (a content-block
       * delivery's text blocks, joined).
       */
      text: string;
      /**
       * The external-event wake the text parsed as (`source` `github` for a
       * subscribed pull request's event); passed on as received.
       *
       * Present only for a delivery the server itself rendered as a wake (a
       * webhook relay, the session inbox), by its asserted origin; anyone else's
       * wake-shaped text stays `text`. Its `untrustedKeys` name third-party text.
       */
      event?: SessionReceiveEvent;
      /**
       * The id of the loop the delivery is for, when it is one of this session's
       * agents (`$.agent.list()` lists it); absent for the main conversation's.
       *
       * Pinned: a rewrite that changes it is refused. An agent's message raises
       * `session.send` with the sender's `agentId`, then this with the receiver's
       * inside its turn, where a hook awaiting its own `$.prompt.submit` hangs.
       *
       * @example
       * on("session.receive", { agentId: worker }, ($, e) => ({ consumed: "no" }))
       */
      agentId?: string;
  };

SessionReceiveOrigin type # line 9815

Added in 2.1.267 · changed in 2.1.268, 2.1.280

Where an inbound delivery came from, as the bridge classified it from the server's stamps: prompt.submit's e.origin, less what never arrives.

54 lines
  export type SessionReceiveOrigin = {
      /**
       * `bridge` the user's own from a Remote Control client; `unclassified`
       * one nobody could place; the rest as at `prompt.submit`.
       *
       * `task-notification` a relay's event or a trigger.
       */
      kind: 'bridge' | 'task-notification' | 'scheduled-trigger' | 'peer-send-message' | 'projects-relay' | 'slack-ping' | 'unclassified';
  } | {
      /**
       * `peer` another session's or agent's model; `coordinator` the main
       * conversation to an agent of its own.
       */
      kind: 'peer' | 'coordinator';
      /**
       * Which plugin's `$.session.send` composed it, AS THE SENDER SAYS;
       * absent for a message the sending model wrote itself.
       *
       * A claim over a same-user channel, exactly as trustworthy as the
       * sender's name: name it in a log line, never key a guard on it.
       */
      plugin?: string;
  } | {
      /**
       * A delivery through this session's agent-team mailbox: `coordinator`
       * from the lead's harness, `peer` from a teammate's or when unverified.
       */
      kind: 'peer' | 'coordinator';
      /**
       * Which plugin's `$.session.send` composed it, as the mailbox entry
       * says; absent for a message the sending model wrote itself.
       */
      plugin?: string;
      /**
       * The sending member's name in the team (`team-lead` for the lead):
       * the harness's stamp when `isVerified`, else whatever the writer put.
       *
       * @example
       * on("session.receive", { origin: { teammate: "researcher" } }, hook)
       */
      teammate: string;
      /**
       * Whether this process's harness wrote the mailbox entry itself (an
       * in-process teammate's or the lead's own send).
       *
       * `false`: read from the team's inbox file with nothing to check it
       * against (a teammate in its own pane, the person editing the file, any
       * same-user process); in an all-in-process team, one no member sent.
       *
       * @example
       * on("session.receive", { origin: { isVerified: false } }, hook)
       */
      isVerified: boolean;
  };

SessionReceiveResult type # line 9877

Added in 2.1.267

What a session.receive hook returns and what next(e) resolves to: the delivery that was queued, { text }, or { consumed: reason }.

next(e) resolves once the delivery is queued; a hook answering without next queues nothing.

19 lines
  export type SessionReceiveResult = {
      /**
       * The body the delivery was queued with; from core, `e.text` as it
       * arrived at the bottom.
       *
       * A rewrite passes it down, `next({ ...e, text })`.
       */
      text: string;
      consumed?: undefined;
  } | {
      /**
       * Takes the delivery, answered without `next`: it is not queued, not
       * written to the transcript and never reaches the model.
       *
       * The reason is logged, the plugin named.
       */
      consumed: string;
      text?: undefined;
  };

SessionRepo type # line 9901

In the first published surface (2.1.259)

What $.session.repo() answers: the repository's root and its origin remote, when the session is in one.

28 lines
  export type SessionRepo = {
      /**
       * The repository's root, absolute: the main working tree's for a worktree.
       */
      root: string;
      /**
       * The `origin` remote's URL as git has it (push URL preferred), or null when
       * the repository has none.
       */
      remote: string | null;
      /**
       * Whether the remote is one of the repositories this build treats as its
       * own; false in a build that has none or when the remote is unrecognized.
       *
       * The engine matches the build's own list of repositories with its
       * hardened remote parser. A plugin reads this to behave differently in a
       * public repository; which repositories are the build's is its to say.
       */
      internal: boolean;
      /**
       * The repository the allowlist matched, as `owner/name`; null when
       * `internal` is false.
       *
       * A working copy without a remote that the engine still recognises is
       * named by its own checkout configuration; a remote's name is its path.
       */
      name: string | null;
  };

SessionResume type # line 9933

Added in 2.1.275

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

  export type SessionResume = {
      /**
       * What `claude --resume <id>` takes, the ending session's own.
       *
       * It resumes a session that wrote a transcript: one that never ran a
       * prompt, or ran with persistence off, left nothing under this id.
       */
      id: string;
  };

SessionSendAddress type # line 9951

Added in 2.1.280

Whom $.session.send addresses: a recipient as the SendMessage tool names one (a string), or a session or an agent of this session by id.

The engine spells the two id forms the tool's way before the send, and a session.send hook reads that spelling on e.to: { agentId } as the id, { sessionId } as the live local session's or remote one's address.

19 lines
  export type SessionSendAddress = string | {
      /**
       * One of the person's own sessions: what its `$.session.id()` answers
       * on this machine, or a Remote Control or cloud id (`session_...`).
       *
       * A session that is not running now is not delivered to: the result
       * says so.
       */
      sessionId: string;
  } | {
      /**
       * A subagent or teammate of this session: the id `$.agent.list()`
       * lists and `agent.spawn` answered.
       *
       * A finished subagent is resumed from its transcript with the message,
       * as the tool does.
       */
      agentId: string;
  };

SessionSendArgs type # line 9975

Added in 2.1.280

session.send's input as a plugin's $.session.send(args) takes it: origin (the calling plugin) and agentId are the engine's to set.

  export type SessionSendArgs = {
      /**
       * The recipient: the tool's own spelling (a name, an agent id, a received
       * `from` address), or `{ sessionId }` / `{ agentId }`.
       */
      to: SessionSendAddress;
      /**
       * The message's text, non-empty.
       */
      text: string;
  };

SessionSendInput type # line 9991

Added in 2.1.280

The input of session.send: one plain-text message about to leave this conversation for another agent or session; the dual of session.receive.

30 lines
  export type SessionSendInput = {
      /**
       * Whom it goes to, as the SendMessage tool spells a recipient: a name as
       * ListAgents lists it, an agent id, or a received `from` address.
       *
       * A plugin's `{ sessionId }` or `{ agentId }` arrives already spelled so.
       * `next({ ...e, to })` readdresses it, judged again as the tool judges a
       * send there; a name nobody carries is refused after the hooks.
       */
      to: string;
      /**
       * The message's text as the recipient will read it inside the engine's
       * envelope; `next({ ...e, text })` is what is sent, with no new approval.
       */
      text: string;
      /**
       * Who is sending: the model through its SendMessage tool, or a plugin
       * through `$.session.send`. Pinned: a rewrite that changes it is refused.
       */
      origin: SessionSendOrigin;
      /**
       * The id of the loop sending, when a subagent's or teammate's model sends
       * (`$.agent.list()` lists it); absent for the main conversation's send.
       *
       * Pinned: the agent axis, not the origin. A message between two subagents
       * carries the sender's id here and reaches the receiver's
       * `session.receive` with that loop's own `agentId`.
       */
      agentId?: string;
  };

SessionSendOrigin type # line 10029

Added in 2.1.280

Who is sending at session.send: the model through its SendMessage tool, or a plugin through $.session.send; stamped by the engine, pinned.

The receiver's session.receive reads a plugin's name on its own e.origin.plugin, beside the peer or coordinator kind it keeps.

18 lines
  export type SessionSendOrigin = {
      /**
       * The model's own SendMessage tool call, in the main conversation or
       * in a subagent's or teammate's loop (`e.agentId` says which).
       */
      kind: 'model';
  } | {
      /**
       * A plugin's `$.session.send`, its `$.tool.call` of SendMessage, or the
       * model inside an agent it spawned; its other hooks still see it.
       */
      kind: 'plugin';
      /**
       * The sending plugin's name, which the receiver reads as its
       * `session.receive` origin's `plugin` and shows beside the sender.
       */
      name: string;
  };

SessionSendResult type # line 10059

Added in 2.1.280

What a session.send hook returns and next(e) and $.session.send resolve to: whether the message was delivered, and why not when not.

Delivered means queued at the recipient (an agent's inbox, another session's socket, the server for a remote session), never read: the receiver's turn is its own, and it may hold the message for its person.

const { isDelivered, reason } = await $.session.send({ to, text })
21 lines
  export type SessionSendResult = {
      /**
       * True: the message reached its recipient's queue or inbox.
       */
      isDelivered: true;
      reason?: undefined;
  } | {
      /**
       * False: nothing was delivered. A hook answering this without `next`
       * refuses the send, and the model reads `reason` as the tool's result.
       */
      isDelivered: false;
      /**
       * Why not, as the SendMessage tool words it: nobody by that name,
       * several by it, the recipient gone or refusing, or a hook's refusal.
       *
       * @example
       * on('session.send', { to: 'prod' }, () => NOT_FROM_HERE)
       */
      reason: string;
  };

SessionStartHookInput type # line 10081

Added in 2.1.265

23 lines
  type SessionStartHookInput = BaseHookInput & {
      hook_event_name: 'SessionStart';
      source: 'startup' | 'resume' | 'clear' | 'compact' | 'fork';
      agent_type?: string;
      model?: string;
      session_title?: string;
      /**
       * resume/fork: seconds since the resumed transcript's last assistant response
       */
      seconds_since_last_response?: number;
      /**
       * resume/fork: the resumed transcript's last response input + cache_read + cache_creation + output tokens (for a server-side tool loop, its last iteration's window, not the summed totals)
       */
      context_tokens?: number;
      /**
       * resume/fork: seconds_since_last_response exceeds the prompt-cache TTL, so the first request re-caches context_tokens
       */
      prompt_cache_likely_expired?: boolean;
      /**
       * resume/fork: estimated cost of re-caching context_tokens on the session model - the managed modelPricing when set, otherwise list price; excludes the response
       */
      estimated_cache_write_usd?: number;
  };

SessionStartInput type # line 10109

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

The input of session.start: the session the process starts with, read the way $.session reads it at that moment.

16 lines
  export type SessionStartInput = {
      /**
       * The directory the session runs in, absolute (`$.session.cwd()`).
       */
      cwd: string;
      /**
       * Where the session draws at start (`$.session.surfaces()[0]`): `terminal`
       * under the REPL; null for a `-p` run or the SDK, which draw nowhere yet.
       */
      surface: RenderSurface | null;
      /**
       * Whether a person is at the prompt: true under the REPL, false for a `-p`
       * run or the SDK.
       */
      isInteractive: boolean;
  };

SessionStartResult type # line 10130

In the first published surface (2.1.259)

What a session.start hook returns and what next(e) resolves to: { cwd }, echoed by core; a hook's own value does not change the session.

  export type SessionStartResult = {
      cwd: string;
  };

SessionUsage type # line 10142

Added in 2.1.267 · changed in 2.1.268, 2.1.280

What $.session.usage() answers: when the session began, the context window's fill, the account's rate-limit windows and the session's cost.

The status line's figures. One the engine does not have is left out, never zeroed: rateLimits is empty off a subscription, cost absent where the host keeps no ledger.

28 lines
  export type SessionUsage = {
      /**
       * When the session these figures count from began, in `$.clock.now()`'s
       * milliseconds: its launch, or for a resumed session its first launch.
       *
       * So what happened while a resumed or continued session was away still
       * counts as its own; `/clear` starts it over at that moment. The line the
       * engine's diff panel draws between this session's edits and earlier ones.
       *
       * @example
       * const isOlder = stat.mtimeMs < (await $.session.usage()).startedAt
       */
      startedAt: number;
      /**
       * The live context window: the status line's `context_window` figures.
       */
      context: SessionContextUsage;
      /**
       * The rate-limit windows the last API response reported (`five_hour`,
       * `seven_day`, a gateway's `spend_limit`); empty when none has a reading.
       */
      rateLimits: SessionRateLimit[];
      /**
       * What the session has cost so far, as /cost totals it; absent only where
       * the host keeps no cost ledger (the CLI always has one).
       */
      cost?: SessionCost;
  };

SessionUsageArgs type # line 10175

Added in 2.1.271

What $.session.usage(args) takes: nothing for the status line's figures alone; breakdown to have the window broken down as /context breaks it.

18 lines
  export type SessionUsageArgs = {
      /**
       * Asks for `context.breakdown` and says how it is counted
       * (ContextBreakdownDetail); absent, none is computed and the call is free.
       *
       * `full` sends one token-count request per tool and memory file, as
       * /context does; `summary` estimates locally and sends none.
       */
      breakdown?: ContextBreakdownDetail;
      /**
       * The width the breakdown's grid will be drawn in, in terminal columns;
       * absent, the full-width grid. Read only with `breakdown`.
       *
       * Under 80 the grid is the narrow one /context draws there, 5 wide. A thin
       * client's breakdown is the remote workspace's, whose grid ignores this.
       */
      columns?: number;
  };

SessionVersion type # line 10202

Added in 2.1.281

What $.session.version() answers: the version of the engine the session runs on, the release that version is built from, and when it was built.

The three are what the engine's own analytics rows carry as version, version_base and build_time, so a row a plugin sends and a row the engine sends from the same binary agree.

21 lines
  export type SessionVersion = {
      /**
       * The engine's full version, as `claude --version` prints it.
       *
       * A release's is `2.1.280`; a development build's adds the build's date,
       * time and commit (`2.1.280-dev.20260920.t101500.sha1a2b3c4`).
       */
      version: string;
      /**
       * The release the version is built from, its semantic core and channel:
       * `2.1.280` for that release, `2.1.280-dev` for a development build of it.
       *
       * Absent when the version is not spelled as a release.
       */
      base?: string;
      /**
       * When the binary was built, an ISO 8601 timestamp
       * (`2026-09-20T10:15:00Z`). Absent in a run from source that stamps none.
       */
      builtAt?: string;
  };

Settings type # line 10232

Added in 2.1.267 · changed in 2.1.268

What $.settings.read answers: an object keyed as a settings.json is (permissions, env, hooks, model, enabledPlugins, ...).

Each key is as https://code.claude.com/docs/en/settings documents it and https://json.schemastore.org/claude-code-settings.json types it. A snapshot in plain data: a write to it changes nothing the engine reads.

  export type Settings = Readonly<Record<string, unknown>>;

SettingsReadArgs type # line 10237

Added in 2.1.267 · changed in 2.1.268

What $.settings.read(args) takes.

  export type SettingsReadArgs = {
      /**
       * The one source read, as loaded; absent, the settings merged over every
       * source, as the engine runs under them.
       */
      source?: SettingsSource;
  };

SettingsSource type # line 10254

Added in 2.1.267 · changed in 2.1.268

One source of settings by the name a plugin gives it, lowest precedence first; the engine's own name is the same word with Settings appended.

user is ~/.claude/settings.json, project .claude/settings.json, local .claude/settings.local.json, flag what --settings and the SDK's inline settings carry, and policy the managed settings, every managed tier merged.

  export type SettingsSource = 'user' | 'project' | 'local' | 'flag' | 'policy';

SetupHookInput type # line 10256

Added in 2.1.265

  type SetupHookInput = BaseHookInput & {
      hook_event_name: 'Setup';
      trigger: 'init' | 'maintenance';
  };

Shaped type # line 10271

Added in 2.1.281

A value kept with a shape tag, as an atom given { shape } keeps it: a reload whose code names another tag reads the value as absent.

Declare the key as Shaped<T> in PluginState when its atom names a shape; the atom reads and takes T.

interface PluginState { board: { cells: Shaped<Cell[]> } }
  export type Shaped<T> = {
      shape: string;
      value: T;
  };

ShapedValue type # line 10280

Added in 2.1.281

What an atom given a shape reads and takes for a key declared Shaped<T>: T; never for a key declared otherwise, so that atom does not compile.

  export type ShapedValue<V> = V extends Shaped<infer T> ? T : never;

SiteScroll type # line 10286

Added in 2.1.267 · changed in 2.1.268

Where a site's window sits over the tree a hook drew in it (a pane's body, the band): the engine's to move (the person scrolls), the plugin's to read.

  export type SiteScroll = {
      /**
       * The first row of the tree the window shows; 0 at the top. Read-only.
       */
      offset: number;
      /**
       * How many rows of the tree the window shows at once: the rows the
       * surface gave the body. Read-only.
       */
      bodyRows: number;
  };

SiteView type # line 10305

Added in 2.1.271

Which transcript the person has on screen where a site draws: the main conversation's, or one agent's, opened from the tasks list.

The person's to switch, the plugin's to read: a switch re-runs the site's hooks with the new view, the site itself staying where it is.

  export type SiteView = {
      /**
       * The agent whose transcript is in view: the `id` `$.agent.list()` gives
       * it, the `agentId` its `turn.step` and `tool.call` events carry.
       *
       * Absent while the main conversation is in view. Read-only.
       */
      agentId?: string;
  };

SkillPromptInput type # line 10322

In the first published surface (2.1.259)

The input of skill.prompt: one skill's prompt, at the moment the engine expanded it for the model.

Typed as /name, called through the Skill tool, or preloaded into a subagent: the same event at each.

  export type SkillPromptInput = {
      /**
       * Which skill (`commit`); the key a matcher narrows on.
       */
      skill: string;
      /**
       * The prompt's text as the skill computed it (its text blocks, joined).
       */
      text: string;
  };

SkillPromptResult type # line 10337

In the first published surface (2.1.259)

What a skill.prompt hook returns: the text the model reads for that skill.

  export type SkillPromptResult = {
      text: string;
  };

SleepOptions type # line 10344

In the first published surface (2.1.259)

Options of $.clock.sleep.

  export type SleepOptions = {
      /**
       * Aborting it rejects the sleep at once.
       */
      signal?: AbortSignal;
  };

SourceValues type # line 10355

Added in 2.1.281

The values derive's function receives for its sources, in their order: an atom's or a derived value's own, a plain reference's or undefined.

  export type SourceValues<S extends readonly unknown[]> = {
      [I in keyof S]: S[I] extends Atom<infer V> ? V : S[I] extends Derived<infer V> ? V : S[I] extends StateName<infer P, infer K> ? P extends keyof PluginState & string ? K extends keyof PluginState[P] & string ? StateValue<P, K> | undefined : unknown : unknown : unknown;
  };

SpeakOptions type # line 10362

In the first published surface (2.1.259)

Options of $.audio.speak.

  export type SpeakOptions = {
      /**
       * The system voice's exact name as the platform lists it (`Samantha`, or the
       * name of a voice you installed). Absent: the synthesizer's default voice.
       */
      voice?: string;
  };

SpeakRequest type # line 10373

In the first published surface (2.1.259)

The argument of $.audio.speak(text, options) as the event carries it.

  type SpeakRequest = SpeakOptions & {
      /**
       * What to say, as plain text, of at most 4096 characters.
       */
      text: string;
  };

SpeakResult type # line 10383

In the first published surface (2.1.259)

What $.audio.speak resolves with once the utterance has ended.

  export type SpeakResult = {
      /**
       * Which synthesizer spoke: `system`, the platform's own (`say` on macOS).
       */
      via: 'system';
  };

StarNext type # line 10398

In the first published surface (2.1.259) · changed in 2.1.265, 2.1.267, 2.1.268, 2.1.275

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.

The callable is an overload per known event (OrderedOverloads), then (e: unknown) => Promise<unknown> last: next(e) with e still unknown resolves to unknown.

14 lines
  export type StarNext = OrderedOverloads<EventName> & {
      (e: unknown): Promise<unknown>;
      /**
       * Continues this dispatch at a tier, as Next's `to` (a managed hook's):
       * `e` still unknown resolves to `unknown`.
       */
      readonly to: (e: unknown, tier: TargetTier) => Promise<unknown>;
      readonly signal: AbortSignal;
      readonly is: <M extends Pattern>(pattern: M, e: unknown) => e is Frozen<Args<Selected<M>>>;
      readonly event: EventName;
      readonly origin: Origin;
      readonly trace: readonly TraceEntry<EventName, unknown, unknown>[];
      readonly budget: NextBudget;
  };

StateAddress type # line 10419

Added in 2.1.281

Which named value a $.state call is about, as it crosses to the host: the owning plugin, the key, and a family member's id.

The untyped form of a StateRef; identity, pinned on every next.

  export type StateAddress = {
      plugin: string;
      key: string;
      id?: string;
  };

StateDollar type # line 10429

Added in 2.1.281

What the state library's read and update take of $: its state noun, on which they make the calls a hook would make itself.

  export type StateDollar = Pick<CoreEngineInterface, 'state'>;

StateFamily type # line 10442

Added in 2.1.281

A key of PluginState that holds one value of type T per id (one per drawn row, per worker): its reference must carry id: string.

Only a marker in the registry; no value has this shape. $.state.get on a member answers T, and a reference to the family without an id does not compile.

interface PluginState { notes: { isOpen: StateFamily<boolean> } }
  export type StateFamily<T> = {
      readonly byId: T;
  };

StateGetEvent type # line 10453

Added in 2.1.281

e of state.get: one variant per value a contract declares, so a matcher on plugin and key narrows it; the untyped address while none does.

on("state.get", { plugin: "swarm" }, ($, e, next) => next(e))
  export type StateGetEvent = [DeclaredPair] extends [never] ? StateAddress : DeclaredEvents<DeclaredPair>['get'];

StateName type # line 10459

Added in 2.1.281

Which named value: the plugin that owns it and its key there, both literals where a contract declares the value.

  type StateName<P extends string = string, K extends string = string> = {
      readonly plugin: P;
      readonly key: K;
  };

StateRead type # line 10471

Added in 2.1.281

What $.state.get answers: the value and the version it stands at; a value never written is undefined at version 0.

The version goes up by one on every write that lands; hand it back as ifVersion to write only if nobody wrote in between.

  export type StateRead<T = unknown> = {
      value: T | undefined;
      version: number;
  };

StateRef type # line 10487

Added in 2.1.281

A typed reference to one named value: the owning plugin and the key, both literals, and for a StateFamily key the member's id.

Written once as a constant and passed to $.state.get and $.state.set; plugin and key must be literals in source so claude plugin validate lists what a module reads and writes. Only id may be computed.

const workers = { plugin: "swarm", key: "workers" } as const
  export type StateRef<P extends keyof PluginState & string, K extends keyof PluginState[P] & string> = StateName<P, K> & (PluginState[P][K] extends StateFamily<unknown> ? Readonly<Required<Pick<StateAddress, 'id'>>> : Readonly<Partial<Record<'id', undefined>>>);

StateSetEvent type # line 10499

Added in 2.1.281

e of state.set: one variant per value a contract declares, so a matcher on plugin and key narrows e.value; the untyped write while none does.

plugin, key and id are identity, pinned; value is a hook's to rewrite, which is how a plugin that does not own a value changes it.

on("state.set", DRIVE, ($, e, next) => next({ ...e, value: false }))
  export type StateSetEvent = [DeclaredPair] extends [never] ? StateWrite : DeclaredEvents<DeclaredPair>['set'];

StateSetOptions type # line 10505

Added in 2.1.281

The options of $.state.set: ifVersion makes the write conditional on the value still standing at that version (compare-and-set).

  export type StateSetOptions = {
      ifVersion?: number;
  };

StateSetResult type # line 10516

Added in 2.1.281

What $.state.set answers: whether the write landed, and the version the value stands at now (a landed write's own, a missed one's the current).

isSet is false only for a write given ifVersion that another write beat; nothing changed then, and a $.state.get reads what stands.

  export type StateSetResult = {
      isSet: true;
      version: number;
  } | {
      isSet: false;
      version: number;
  };

StateValue type # line 10528

Added in 2.1.281

The type of the value under key K of plugin P, as its contract declares it in PluginState; a StateFamily's member type for a family key.

  export type StateValue<P extends keyof PluginState & string, K extends keyof PluginState[P] & string> = PluginState[P][K] extends StateFamily<infer Member> ? Member : PluginState[P][K];

StateWrite type # line 10537

Added in 2.1.281

A $.state.set as it crosses to the host and as its hooks see it when no contract declares the value: the address, the value, and the condition.

previous is the host's, put on e ahead of every hook: what stood there when the write was raised.

  export type StateWrite = StateAddress & {
      value: unknown;
      previous?: unknown;
      ifVersion?: number;
  };

StopFailureHookInput type # line 10543

Added in 2.1.265

  type StopFailureHookInput = BaseHookInput & {
      hook_event_name: 'StopFailure';
      error: SDKAssistantMessageError;
      error_details?: string;
      last_assistant_message?: string;
  };

StopHookInput type # line 10550

Added in 2.1.265

16 lines
  type StopHookInput = BaseHookInput & {
      hook_event_name: 'Stop';
      stop_hook_active: boolean;
      /**
       * Text content of the last assistant message before stopping. Avoids the need to read and parse the transcript file.
       */
      last_assistant_message?: string;
      /**
       * In-flight background work (running/pending + backgrounded) registered in this session. Lets hooks distinguish "session is done" from "session is paused waiting for background work to wake it". Empty array when nothing is in flight.
       */
      background_tasks?: BackgroundTaskSummary[];
      /**
       * Session-scoped cron tasks (CronCreate, ScheduleWakeup, /loop) that will wake this session later. Empty array when none are scheduled.
       */
      session_crons?: SessionCronSummary[];
  };

StreamHook type # line 10578

Added in 2.1.269

The hook a streaming event takes: async function* ($, e, next) {}, yielding the event's chunks and returning its result.

return yield* next(e) passes; for await (const c of next(e)) yield f(c) transforms; yielding without next answers alone. A chunk yielded stays: a hook that fails mid-stream is left, the rest from beneath it.

on('turn.step', async function* ($, e, next) {
  const r = yield* next(e); return { ...r } })
  export type StreamHook<N extends StreamingEventName> = ($: EngineInterface, e: Frozen<Args<N>>, next: StreamNext<N>) => StreamHookBody<Chunk<N>, EventResult<N>>;
Feedback