# zidane/extensions

> The extension API and the registry that discovers, installs and runs extensions in a zidane host.

Import: `import { … } from 'zidane/extensions'`. Source: [src/extensions/index.ts](https://github.com/Tahul/zidane/blob/main/src/extensions/index.ts).

Use `defineExtension` to write a module whose `setup(ctx)` registers tools, hooks, commands, settings, catalog edits, integrations and UI in a running host, without changing zidane itself. Every registration returns a Disposable. The registry functions discover extensions on disk, load them into a runtime and report each one's status. Hosts call those through the terminal app, the desktop app, the daemon and the server, so authors need only `defineExtension`, the UI tokens and the types; see [Extensions](https://zidane.si/docs/extensions.md). In an extension module, import them from `zidane`: hosts map that specifier to their own copy, while `zidane/extensions` resolves only where the package is installed.

```ts
import { defineExtension, Slot } from 'zidane'

export default defineExtension({
  apiVersion: 1,
  id: 'tool-logger',
  version: '0.1.0',
  description: 'Counts tool calls in the statusbar',
  setup(ctx) {
    let calls = 0
    const status = ctx.add(Slot, { at: 'app.statusbar', text: 'no tool calls yet' })
    ctx.hooks.on('tool:after', ({ name }) => {
      calls += 1
      status.update({ text: `${calls} tool calls, last ${name}` })
    })
  },
})
```

`installExtensionFromSpec` installs an extension from GitHub or npm ([publishing](https://zidane.si/docs/extensions-publishing.md)). The extensions of the zidane repository install from `nativeExtensionSource(entry, version)`. It pins them to the tag of the running version, so they match the API of the host. `NATIVE_EXTENSIONS` in [`zidane/chat/pure`](https://zidane.si/docs/reference/chat-pure.md) lists them, and the setup wizard installs each one in one click. `zidane/extensions/testing` holds `createTestHost` ([testing](https://zidane.si/docs/extensions-testing.md)).

## Functions

### `applyExtensionsConfigReport`

Function.

Applies a report to a live registry, one extension at a time: changed
folders through `reloadChangedExtensions` (loaded, reloaded or unloaded
in place), linked folders it does not hold yet loaded, unlinked ones
unloaded, each held entry's `enabled` set to what the config and
`allowed` say (a reload of that extension), and the report's failures
listed as inactive rows (`config:<scope>`). Never rejects for an
extension's fault.

```ts
function applyExtensionsConfigReport(
  registry: ExtensionRegistry,
  report: ExtensionsConfigSyncReport,
  options?: ApplyConfigReportOptions,
): Promise<ReloadChangedResult>
```

**Parameters**

- `registry` (`ExtensionRegistry`): A registry from `buildExtensionRegistry` (or a view of one).
- `report` (`ExtensionsConfigSyncReport`): From an [`ExtensionsConfigSync`](https://zidane.si/docs/reference/extensions.md#ExtensionsConfigSync) target's `apply`.
- `options?` (`ApplyConfigReportOptions`, default `{}`): Classify, allowlist, import bound, sink and compile cache.

**Returns** `Promise<ReloadChangedResult>`: What loaded, reloaded and unloaded; `needsRebuild` when the registry holds no runtime to load into.

Source: [src/extensions/declarative/host-sync.ts:511](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L511)

### `artifactBadgeTarget`

Function.

The target for an artifact row (Artifacts panel / rail): its kind's
badge kind (commit, pull request, file; `artifact` for the rest), the
row's title and link, and what "Add to prompt" inserts: a commit's SHA,
a file's path, the link, else the label.

```ts
function artifactBadgeTarget(
  artifact: { kind: string; label: string; meta?: unknown; sessionId?: string; uri: string },
  row: { href?: string; title: string },
): BadgeTarget
```

**Parameters**

- `artifact` (`{ kind: string; label: string; meta?: unknown; sessionId?: string; uri: string }`): Artifact the row shows.
- `row` (`{ href?: string; title: string }`): Title and link of the row.

**Returns** `BadgeTarget`

Source: [src/extensions/badge-actions.ts:372](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L372)

### `artifactKindLabel`

Function.

Human label for a kind (`Pull request`), falling back to the raw kind string.

```ts
function artifactKindLabel(
  kind: string,
  registry?: Pick<ExtensionRegistry, 'artifactKinds'>,
): string
```

**Parameters**

- `kind` (`string`): Artifact kind string.
- `registry?` (`Pick<ExtensionRegistry, 'artifactKinds'>`): Active registry, consulted before the built-ins.

**Returns** `string`

Source: [src/extensions/builtin-artifact-kinds.ts:861](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L861)

### `badgeMenu`

Function.

The full menu: built-ins then extension items, ordered by group (stable
within a group). An extension shortcut that collides with an earlier one
is dropped, never the item.

```ts
function badgeMenu(
  target: BadgeTarget,
  registry?: Pick<ExtensionRegistry, 'badgeActions'>,
): BadgeMenuItem[]
```

**Parameters**

- `target` (`BadgeTarget`): Badge the menu is for.
- `registry?` (`Pick<ExtensionRegistry, 'badgeActions'>`): Registry holding the extension registrations. Omitted: built-ins only.

**Returns** `BadgeMenuItem[]`

Source: [src/extensions/badge-actions.ts:276](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L276)

### `badgePromptText`

Function.

What "Add to prompt" inserts for a target.

```ts
function badgePromptText(target: BadgeTarget): string
```

**Parameters**

- `target` (`BadgeTarget`): Badge to build the text for.

**Returns** `string`

Source: [src/extensions/badge-actions.ts:149](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L149)

### `buildExtensionPreset`

Function.

Collapse the extension registry's agent-side surface into a single
[`Preset`](https://zidane.si/docs/reference/presets.md#Preset) ready to spread into `createAgent()`. Hooks bucket
per-event (every handler fires, copied into fresh arrays), tools
shallow-merge (last extension wins on canonical-name collision),
mcpServers concat with name-dedup (latest wins — mirrors
`composePresets`), skills concat. Extension instructions don't land
here: the agent reads them from the runtime (`ctx.instructions`).

```ts
function buildExtensionPreset(registry: ExtensionRegistry): Preset
```

**Parameters**

- `registry` (`ExtensionRegistry`): Registry to collapse.

**Returns** `Preset`

Source: [src/extensions/compose-preset.ts:81](https://github.com/Tahul/zidane/blob/main/src/extensions/compose-preset.ts#L81)

### `buildExtensionRegistry`

Function.

Load the extensions and return the live registry over them.
`loaded` typically comes from `discoverExtensions()` plus any inline
ones via `inlineLoadedExtension`.

Disabled extensions stay in `inactive` (alongside any load errors)
so the Settings panel shows the full picture.

```ts
function buildExtensionRegistry(
  loaded: readonly LoadedExtension[],
  options?: BuildExtensionRegistryOptions,
): Promise<ExtensionRegistry>
```

**Parameters**

- `loaded` (`readonly LoadedExtension[]`): Discovered and inline extensions.
- `options?` (`BuildExtensionRegistryOptions`, default `{}`): Logging, bridges, storage paths, setup limits and the runtime's ports.

**Returns** `Promise<ExtensionRegistry>`

**Example**

```ts
import { buildExtensionRegistry, discoverExtensions } from 'zidane/extensions'

const loaded = await discoverExtensions({ cwd: process.cwd() })
const registry = await buildExtensionRegistry(loaded, { cwd: process.cwd() })
console.log(Object.keys(registry.tools))
```

Source: [src/extensions/register.ts:124](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L124)

### `builtinBadgeActions`

Function.

The built-in actions for a target (host-implemented; see [`builtinBadgeEffect`](https://zidane.si/docs/reference/extensions.md#builtinBadgeEffect)).

```ts
function builtinBadgeActions(target: BadgeTarget): BadgeMenuItem[]
```

**Parameters**

- `target` (`BadgeTarget`): Badge the menu is for.

**Returns** `BadgeMenuItem[]`

Source: [src/extensions/badge-actions.ts:164](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L164)

### `builtinBadgeEffect`

Function.

The effect of a built-in action; `undefined` for an id that isn't one (or doesn't apply).

```ts
function builtinBadgeEffect(
  actionId: string,
  target: BadgeTarget,
): BadgeActionEffect | undefined
```

**Parameters**

- `actionId` (`string`): Id of a built-in action.
- `target` (`BadgeTarget`): Badge the action was invoked on.

**Returns** `BadgeActionEffect | undefined`

Source: [src/extensions/badge-actions.ts:191](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L191)

### `builtinKeymapEntries`

Function.

The built-in key bindings (`KEYBINDING_DEFS`) as `ctx.keymap.list` reports
them, with the user's `keybindings.json` applied. What a host passes as
`CommandHostPort.keybindings`.

```ts
function builtinKeymapEntries(
  overrides: Readonly<Record<string, unknown>> | null | undefined,
): KeymapEntry[]
```

**Parameters**

- `overrides` (`Readonly<Record<string, unknown>> | null | undefined`): The raw `keybindings.json` object (`readKeybindingsRaw`).

**Returns** `KeymapEntry[]`: One entry per built-in action, in catalog order; an unbound action has no bindings.

Source: [src/extensions/commands/keymap.ts:413](https://github.com/Tahul/zidane/blob/main/src/extensions/commands/keymap.ts#L413)

### `changeExtensionOrigin`

Function.

Installs an extension again from another source, in place: the source
must hold an extension with the same name (else `name-mismatch`, with the
names found), the folder is replaced only once the new copy fetched,
installed its dependencies and validated (the install's transaction), and
`.install.json` records the new source, which later updates follow.
Works on any installed folder, with or without a recorded source.

```ts
function changeExtensionOrigin(
  opts: InstalledExtensionTargetOptions & { io?: InstallIo; onProgress?: (message: string) => void; source: string },
): Promise<ExtensionInstallResult & { origin: ExtensionInstallOrigin; previous: ExtensionInstallOrigin | null }>
```

**Parameters**

- `opts` (`InstalledExtensionTargetOptions & { io?: InstallIo; onProgress?: (message: string) => void; source: string }`): The installed extension, the new source, progress and IO overrides.

**Returns** `Promise<ExtensionInstallResult & { origin: ExtensionInstallOrigin; previous: ExtensionInstallOrigin | null }>`: The install's result, the source it had (`null` when none was recorded) and the one it has now.

Source: [src/extensions/install.ts:699](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L699)

### `clampExtensionConfigNumber`

Function.

Clamp a number to the item's `[min, max]` and snap to `step` (when set).
Used by the input-row commit paths so a user-typed value is coerced into
range before it's persisted.

```ts
function clampExtensionConfigNumber(item: ExtensionConfigNumberItem, n: number): number
```

**Parameters**

- `item` (`ExtensionConfigNumberItem`): Number item that supplies `min`, `max` and `step`.
- `n` (`number`): Value to clamp.

**Returns** `number`

Source: [src/extensions/config.ts:480](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L480)

### `classifyUiImport`

Function.

Decides one import of a `ui` entry's graph.

- Host modules ([`UI_HOST_MODULES`](https://zidane.si/docs/reference/extensions.md#UI_HOST_MODULES)) stay external.
- Other `zidane/*` entries, `@opentui/*`, `electron`, `bun:*` and Node
  built-ins are errors: the renderer has none of them.
- A relative or absolute path from the extension's own files must stay in
  the extension folder (app internals such as `../../src/chat` are refused).
  Files inside `node_modules` may import what they like within their package.
- Everything else (local files, packages) is bundled.

```ts
function classifyUiImport(
  specifier: string,
  importer: string,
  root: string,
  extra?: readonly string[],
): UiImportVerdict
```

**Parameters**

- `specifier` (`string`): The import specifier as written.
- `importer` (`string`): The real path of the importing file.
- `root` (`string`): The real path of the extension folder.
- `extra?` (`readonly string[]`, default `[]`): More host modules the caller allows.

**Returns** `UiImportVerdict`

Source: [src/extensions/bundle/policy.ts:79](https://github.com/Tahul/zidane/blob/main/src/extensions/bundle/policy.ts#L79)

### `clockTime`

Function.

`14:05`: a local wall-clock time, the same on every surface.

```ts
function clockTime(ms: number): string
```

**Parameters**

- `ms` (`number`): Epoch milliseconds.

**Returns** `string`

Source: [src/github/client.ts:168](https://github.com/Tahul/zidane/blob/main/src/github/client.ts#L168)

### `coerceExtensionConfigInput`

Function.

Coerce a raw input string (from a free number / string input row) into a
valid persisted value, or `undefined` when it can't be made valid.
Numbers are parsed + clamped; strings are taken verbatim and checked
against the pattern; enum / boolean items aren't edited via free input
(they use choice / toggle rows) so they return `undefined` here.

```ts
function coerceExtensionConfigInput(
  item: ExtensionConfigItem,
  raw: string,
): ExtensionConfigValue | undefined
```

**Parameters**

- `item` (`ExtensionConfigItem`): Item the input belongs to.
- `raw` (`string`): Text the user typed.

**Returns** `ExtensionConfigValue | undefined`

Source: [src/extensions/config.ts:508](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L508)

### `compileReferencePattern`

Function.

Compile a pattern, or `null` when its source doesn't parse.

```ts
function compileReferencePattern(pattern: ExtensionReferencePattern): RegExp | null
```

**Parameters**

- `pattern` (`ExtensionReferencePattern`): Pattern whose `regex` and `flags` are compiled. The `g` flag is always set.

**Returns** `RegExp | null`

Source: [src/extensions/references.ts:59](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L59)

### `completionProviderSummaries`

Function.

The usable providers as a composer lists them.

```ts
function completionProviderSummaries(
  providers: readonly CompletionProvider<unknown>[],
): ExtensionCompletionProviderSummary[]
```

**Parameters**

- `providers` (`readonly CompletionProvider<unknown>[]`): The registry's providers.

**Returns** `ExtensionCompletionProviderSummary[]`

Source: [src/extensions/completion-providers.ts:72](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L72)

### `composeExtensionPreset`

Function.

Compose extension agent-loop contributions under a host/profile preset and
apply extension subagent additions/overrides to the winning spawn tool.
With a runtime (`registry.runtime`), the agents catalog's sub-agent edits
apply: registered, added and edited sub-agents join the adds, removed ones
become deleting overrides.

```ts
function composeExtensionPreset(
  registry: ExtensionRegistry,
  explicitPreset?: Preset,
): Preset
```

**Parameters**

- `registry` (`ExtensionRegistry`): Registry whose contributions are composed.
- `explicitPreset?` (`Preset`, default `{}`): Host or profile preset that wins over the extension contributions.

**Returns** `Preset`

Source: [src/extensions/compose-preset.ts:118](https://github.com/Tahul/zidane/blob/main/src/extensions/compose-preset.ts#L118)

### `configSyncFailures`

Function.

The inactive rows of a report's failures: named after the entry's source,
carrying the reason.

```ts
function configSyncFailures(report: ExtensionsConfigSyncReport): LoadedExtension[]
```

**Parameters**

- `report` (`ExtensionsConfigSyncReport`): A reconcile report.

**Returns** `LoadedExtension[]`

Source: [src/extensions/declarative/host-sync.ts:134](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L134)

### `configuredExtensions`

Function.

Reads both config files and their locks: the folders to load in place and
the ids to load disabled. Project entries count only when `trustProject`.
Never throws (a broken file reads as no entries).

```ts
function configuredExtensions(
  location: ExtensionsConfigLocation,
  options: { trustProject: boolean },
): ConfiguredExtensions
```

**Parameters**

- `location` (`ExtensionsConfigLocation`): Config dir, cwd, home and prefix.
- `options` (`{ trustProject: boolean }`): Whether the project's entries apply.

**Returns** `ConfiguredExtensions`

Source: [src/extensions/declarative/host-sync.ts:62](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L62)

### `coreExtensionHostModules`

Function.

This process's module for every entrypoint of [`hostModuleSpecifiers`](https://zidane.si/docs/reference/extensions.md#hostModuleSpecifiers),
loaded lazily. Typed as a full record, so a specifier added to the list
fails to compile until it is mapped here.

```ts
function coreExtensionHostModules(): Record<HostModuleSpecifier, HostModuleSource>
```

**Returns** `Record<HostModuleSpecifier, HostModuleSource>`: The sources, for [`registerExtensionHostModules`](https://zidane.si/docs/reference/extensions.md#registerExtensionHostModules).

Source: [src/extensions/host-modules.ts:168](https://github.com/Tahul/zidane/blob/main/src/extensions/host-modules.ts#L168)

### `createArtifactDetectHook`

Function.

`undefined` when the registration has no `detect`. The hook never
touches `result` / `isError`; a throwing detector emits nothing.
Entries default `kind` to the registration's kind; `validateMeta`
applies to entries of that kind only and drops `meta`, never the entry.

```ts
function createArtifactDetectHook(
  registration: ExtensionArtifactKindRegistration,
  options?: ArtifactDetectHookOptions,
): ((ctx: ToolHookContext & { coercions?: readonly string[]; isError: boolean; metadata: ToolResultMetadata; outputBytes: number; result: string | ToolResultContent[] }) => void) | undefined
```

**Parameters**

- `registration` (`ExtensionArtifactKindRegistration`): Artifact kind registration whose `detect` function the hook runs.
- `options?` (`ArtifactDetectHookOptions`, default `{}`): Options such as the `warn` sink for isolated failures.

**Returns** `((ctx: ToolHookContext & { coercions?: readonly string[]; isError: boolean; metadata: ToolResultMetadata; outputBytes: number; result: string | ToolResultContent[] }) => void) | undefined`

Source: [src/extensions/artifact-detect.ts:29](https://github.com/Tahul/zidane/blob/main/src/extensions/artifact-detect.ts#L29)

### `createArtifactsSurface`

Function.

Build the `ctx.artifacts` facade over a host-runtime bridge. Read-only;
every call re-resolves the scope (session switches swap it). Detached,
or a store without artifact support, answers `[]` — the same honest
degradation as `ctx.sessions`.

```ts
function createArtifactsSurface(
  resolve: () => ExtensionArtifactScope | null | undefined,
): ExtensionArtifactsSurface
```

**Parameters**

- `resolve` (`() => ExtensionArtifactScope | null | undefined`): Returns the current artifact scope, or `null`/`undefined` when detached. Called on every query.

**Returns** `ExtensionArtifactsSurface`

Source: [src/extensions/host-runtime.ts:573](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L573)

### `createCompletionRunner`

Function.

Creates a [`CompletionRunner`](https://zidane.si/docs/reference/extensions.md#CompletionRunner). A provider that ignores its signal can't
hold the answer past `timeoutMs`.

```ts
function createCompletionRunner(timeoutMs?: number): CompletionRunner
```

**Parameters**

- `timeoutMs?` (`number`, default `COMPLETION_TIMEOUT_MS`): The bound of each call. Default [`COMPLETION_TIMEOUT_MS`](https://zidane.si/docs/reference/extensions.md#COMPLETION_TIMEOUT_MS).

**Returns** `CompletionRunner`

Source: [src/extensions/completion-providers.ts:158](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L158)

### `createConfigSettingsLayer`

Function.

Builds the layer. Pass the user source first and the project source
after: a later source wins per key and for `enabled`.

```ts
function createConfigSettingsLayer(
  sources: readonly ConfigSettingsSource[],
): ConfigSettingsLayer
```

**Parameters**

- `sources` (`readonly ConfigSettingsSource[]`): Config entries with their locks, lowest precedence first.

**Returns** `ConfigSettingsLayer`

Source: [src/extensions/declarative/settings-layer.ts:71](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/settings-layer.ts#L71)

### `createCredentialsAuthStore`

Function.

An `AuthStorePort` over `<dataDir>/credentials.json`.

```ts
function createCredentialsAuthStore(dataDir: string): AuthStorePort
```

**Parameters**

- `dataDir` (`string`): Directory holding `credentials.json` (the host's `config.paths.dir`).

**Returns** `AuthStorePort`

Source: [src/extensions/integrations/auth-store-port.ts:55](https://github.com/Tahul/zidane/blob/main/src/extensions/integrations/auth-store-port.ts#L55)

### `createExtensionHostRuntimeBridge`

Function.

Creates a bridge that hosts attach their runtime implementation to.

```ts
function createExtensionHostRuntimeBridge(): ExtensionHostRuntimeBridge
```

**Returns** `ExtensionHostRuntimeBridge`

Source: [src/extensions/host-runtime.ts:461](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L461)

### `createExtensionPromptBridge`

Function.

Creates a bridge with no handler attached. `submit` returns `false` until a host attaches one.

```ts
function createExtensionPromptBridge(): ExtensionPromptBridge
```

**Returns** `ExtensionPromptBridge`

Source: [src/extensions/prompt-bridge.ts:31](https://github.com/Tahul/zidane/blob/main/src/extensions/prompt-bridge.ts#L31)

### `createExtensionsConfigSync`

Function.

Creates the coordinator. One per process: scopes are keyed by config file,
so every registry of the same user (and project) shares one run.

```ts
function createExtensionsConfigSync(
  options: ExtensionsConfigSyncOptions,
): ExtensionsConfigSync
```

**Parameters**

- `options` (`ExtensionsConfigSyncOptions`): Config dir, prefix, home, and the port, log and watch seams.

**Returns** `ExtensionsConfigSync`: The coordinator.

Source: [src/extensions/declarative/host-sync.ts:312](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L312)

### `createFacetRegistry`

Function.

Creates an empty facet registry.

```ts
function createFacetRegistry(
  options?: { attachHost?: (registry: FacetRegistry) => void; order?: (extensionId: string) => number },
): FacetsRuntime
```

**Parameters**

- `options?` (`{ attachHost?: (registry: FacetRegistry) => void; order?: (extensionId: string) => number }`, default `{}`): `order`: an extension's load-order rank (lower first); `attachHost`: called with the registry when an extension registers or refreshes a facet.

**Returns** `FacetsRuntime`

Source: [src/extensions/runtime/facets.ts:141](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L141)

### `createFileStoragePort`

Function.

Makes the default file-backed storage port.

```ts
function createFileStoragePort(options: FileStoragePortOptions): FileStoragePort
```

**Parameters**

- `options` (`FileStoragePortOptions`): Where the files go and whether to watch them.

**Returns** `FileStoragePort`

Source: [src/extensions/storage/file-port.ts:120](https://github.com/Tahul/zidane/blob/main/src/extensions/storage/file-port.ts#L120)

### `createMemorySettingsPort`

Function.

An in-memory settings port.

```ts
function createMemorySettingsPort(
  initial?: Readonly<Record<string, Readonly<Record<string, unknown>>>>,
): MemorySettingsPort
```

**Parameters**

- `initial?` (`Readonly<Record<string, Readonly<Record<string, unknown>>>>`, default `{}`): Starting values: `{ [extensionId]: { [key]: value } }`, put in the `user` layer.

**Returns** `MemorySettingsPort`: The port.

Source: [src/extensions/runtime/memory-ports.ts:90](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L90)

### `createMemoryStoragePort`

Function.

An in-memory storage port. Every save and delete is announced to every
subscriber of the location, so two caches in one process stay in sync
(the domain drops echoes of its own writes).

```ts
function createMemoryStoragePort(): MemoryStoragePort
```

**Returns** `MemoryStoragePort`: The port.

Source: [src/extensions/runtime/memory-ports.ts:31](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L31)

### `createRecordingUiClientPort`

Function.

A client port that records each call. Panel, navigate, composer and
keymap dispatch calls resolve `true`; `panelState` resolves the panels
opened so far.

```ts
function createRecordingUiClientPort(): RecordingUiClientPort
```

**Returns** `RecordingUiClientPort`: The port.

Source: [src/extensions/runtime/memory-ports.ts:214](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L214)

### `createReferenceResolver`

Function.

A cached resolver over the registry's providers.

```ts
function createReferenceResolver(
  registry: Pick<ExtensionRegistry, 'references'>,
  options?: ReferenceResolverOptions,
): ReferenceResolver
```

**Parameters**

- `registry` (`Pick<ExtensionRegistry, 'references'>`): Registry holding the extensions' providers.
- `options?` (`ReferenceResolverOptions`, default `{}`): Cache and timeout settings.

**Returns** `ReferenceResolver`

Source: [src/extensions/references.ts:295](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L295)

### `createRegistryView`

Function.

A live [`ExtensionRegistry`](https://zidane.si/docs/reference/extensions.md#ExtensionRegistry) over `source`, narrowed by `filter`.

```ts
function createRegistryView(
  source: RegistryViewSource,
  filter?: RegistryViewFilter,
): ExtensionRegistry
```

**Parameters**

- `source` (`RegistryViewSource`): The runtime and change feed (`createRegistryViewSource`).
- `filter?` (`RegistryViewFilter`, default `{}`): Allowlist and dropped plugins.

**Returns** `ExtensionRegistry`: The view.

Source: [src/extensions/runtime/registry-view.ts:665](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/registry-view.ts#L665)

### `createRegistryViewSource`

Function.

The change feed and disposal of one runtime, shared by every view of it.

```ts
function createRegistryViewSource(
  input: { cwd: string; dispose: () => Promise<void>; refused: readonly LoadedExtension[]; runtime?: ExtensionRuntime },
): RegistryViewSource & { changed: () => void }
```

**Parameters**

- `input` (`{ cwd: string; dispose: () => Promise<void>; refused: readonly LoadedExtension[]; runtime?: ExtensionRuntime }`): The runtime (absent: nothing ever changes), the host cwd, refused entries and the dispose.

**Returns** `RegistryViewSource & { changed: () => void }`: The source.

Source: [src/extensions/runtime/registry-view.ts:345](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/registry-view.ts#L345)

### `createScriptedDialogPort`

Function.

A dialog port with one client that answers from queued answers.

```ts
function createScriptedDialogPort(client?: UiClientInfo): ScriptedDialogPort
```

**Parameters**

- `client?` (`UiClientInfo`): The client it reports. Default: one client viewing nothing.

**Returns** `ScriptedDialogPort`: The port.

Source: [src/extensions/runtime/memory-ports.ts:163](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L163)

### `createSharedWatches`

Function.

Creates an empty set of shared watches.

```ts
function createSharedWatches<Owner>(): SharedWatches<Owner>
```

**Type parameters**

- `Owner`

**Returns** `SharedWatches<Owner>`

Source: [src/extensions/shared-watches.ts:28](https://github.com/Tahul/zidane/blob/main/src/extensions/shared-watches.ts#L28)

### `createWorkspaceSurface`

Function.

Build the `ctx.workspace` facade over a host-runtime bridge. Every call
re-resolves the live pair (see [`ExtensionWorkspacePair`](https://zidane.si/docs/reference/extensions.md#ExtensionWorkspacePair)); detached
calls reject with a message naming the guard.

`isAvailable` is the host's side-effect-free availability signal,
tri-state by design: `true`/`false` answer directly, `undefined` means
"no light signal wired" and falls back to `resolve()` — accepting its
side effects (a container spawn, on heavy hosts). Wire it wherever
spawning is non-trivial.

```ts
function createWorkspaceSurface(
  resolve: () => ExtensionWorkspacePair | ExtensionWorkspaceOps | Promise<ExtensionWorkspacePair | ExtensionWorkspaceOps | null> | null,
  isAvailable?: () => boolean | undefined,
): ExtensionWorkspaceSurface
```

**Parameters**

- `resolve` (`() => ExtensionWorkspacePair | ExtensionWorkspaceOps | Promise<ExtensionWorkspacePair | ExtensionWorkspaceOps | null> | null`): Returns the live execution pair, or `null` when detached. Called on every operation.
- `isAvailable?` (`() => boolean | undefined`): Side-effect-free availability signal. When omitted, availability falls back to `resolve`.

**Returns** `ExtensionWorkspaceSurface`

Source: [src/extensions/host-runtime.ts:655](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L655)

### `defaultExtensionScanPaths`

Function.

Default scan roots for extension discovery. Mirrors
`defaultSkillScanPaths` / `defaultMcpsConfigPaths`; the
subPath is `'extensions'` so each root expands to
`<scope>/.<convention>/extensions/`.

```ts
function defaultExtensionScanPaths(
  opts?: { cwd?: string; home?: string; prefix?: string },
): ExtensionScanRoot[]
```

**Parameters**

- `opts?` (`{ cwd?: string; home?: string; prefix?: string }`, default `{}`): Overrides for the working directory (`cwd`), home directory (`home`) and storage prefix (`prefix`).

**Returns** `ExtensionScanRoot[]`

Source: [src/extensions/discovery.ts:113](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L113)

### `defineExtension`

Function.

Returns `definition` unchanged. It anchors type inference for `ctx`.

```ts
function defineExtension<S extends SettingsSchema = SettingsSchema>(
  definition: ExtensionDefinition<S>,
): ExtensionDefinition<S>
```

**Type parameters**

- `S` (`extends SettingsSchema`, default `SettingsSchema`)

**Parameters**

- `definition` (`ExtensionDefinition<S>`): The extension.

**Returns** `ExtensionDefinition<S>`: The same `definition`.

Source: [src/extensions/api/define.ts:62](https://github.com/Tahul/zidane/blob/main/src/extensions/api/define.ts#L62)

### `discoverAndBuildExtensionRegistry`

Function.

Discover disk extensions, fold in the inline ones, compute the
allowlist-driven `disabled` set, and build the merged
[`ExtensionRegistry`](https://zidane.si/docs/reference/extensions.md#ExtensionRegistry).

The `disabled` set honors the allowlist for inline extensions too:
the TUI treats inline as toggleable everywhere else (Settings tab,
live filtering), so both ride the same inactive-classification path.

```ts
function discoverAndBuildExtensionRegistry(
  opts?: DiscoverAndBuildExtensionRegistryOptions,
): Promise<ExtensionRegistry>
```

**Parameters**

- `opts?` (`DiscoverAndBuildExtensionRegistryOptions`, default `{}`): Discovery, trust, allowlist and bridge options.

**Returns** `Promise<ExtensionRegistry>`

Source: [src/extensions/discover-and-build.ts:91](https://github.com/Tahul/zidane/blob/main/src/extensions/discover-and-build.ts#L91)

### `discoverExtensions`

Function.

Discover + load every trusted extension reachable from the default
scan paths — including ones the user's enable allowlist has toggled
OFF. Disabled extensions still import (and later run `setup()`) so
their config schema is browsable in Settings before enabling; the
allowlist gates their CONTRIBUTIONS at registry level, not their code.
The trust boundary stays with `trustProjectExtensions`. Returns one [`LoadedExtension`](https://zidane.si/docs/reference/extensions.md#LoadedExtension) per scan entry:
skipped entries have no definition, failed entries carry `error`.
Loaders never throw — the host can decide what to do with load errors
(typically: ship them to the Settings panel).

Imports run in parallel: a slow extension can't block the rest. The
returned array preserves the original scan order (project-first,
then user) so first-found-wins precedence stays intact.

`signal` is honored opportunistically — if the abort fires BEFORE
we dispatch imports, the whole set is skipped. Once `Promise.all` is
in flight, individual imports can't be cancelled (the module system
has no abort affordance).

Project-scoped extensions execute arbitrary local code, so they're
skipped unless `trustProjectExtensions` resolves to `true` — either
via the option or the `ZIDANE_TRUST_PROJECT_EXTENSIONS=1` env var
fallback. User-scoped extensions always load.

Each extension's module graph is evicted from the runtime cache
before import, so calling this again (e.g. `/reload`) re-evaluates
the current on-disk code — edits, overwrites, and updates apply
without a restart.

```ts
function discoverExtensions(
  opts?: { compileCache?: string; cwd?: string; extensionScanPaths?: readonly string[]; home?: string; importTimeoutMs?: number; linkedExtensionDirs?: readonly LinkedExtensionDir[]; prefix?: string; signal?: AbortSignal; sink?: LogSink; trustProjectExtensions?: boolean },
): Promise<LoadedExtension[]>
```

**Parameters**

- `opts?` (`{ compileCache?: string; cwd?: string; extensionScanPaths?: readonly string[]; home?: string; importTimeoutMs?: number; linkedExtensionDirs?: readonly LinkedExtensionDir[]; prefix?: string; signal?: AbortSignal; sink?: LogSink; trustProjectExtensions?: boolean }`, default `{}`): Scan overrides (`cwd`, `home`, `prefix`, `extensionScanPaths`), an abort `signal`, `trustProjectExtensions`, `importTimeoutMs` (default 10000) as the per-extension import limit, and the `sink` non-blocking load warnings go to (default: `warn`+ to the console, like `buildExtensionRegistry`).

**Returns** `Promise<LoadedExtension[]>`

Source: [src/extensions/discovery.ts:308](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L308)

### `disposeExtensionRegistry`

Function.

Dispose resources owned by an extension registry. Idempotent per registry.

```ts
function disposeExtensionRegistry(registry: ExtensionRegistry): Promise<void>
```

**Parameters**

- `registry` (`ExtensionRegistry`): Registry to dispose.

**Returns** `Promise<void>`

Source: [src/extensions/register.ts:287](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L287)

### `extensionBadgeActions`

Function.

Extension items for a target, in registration order, after validation:
ids and labels must be non-empty strings, ids unique per source, at most
eight per source. A throwing `actions` contributes nothing.

```ts
function extensionBadgeActions(
  target: BadgeTarget,
  registry: Pick<ExtensionRegistry, 'badgeActions'>,
): BadgeMenuItem[]
```

**Parameters**

- `target` (`BadgeTarget`): Badge the menu is for.
- `registry` (`Pick<ExtensionRegistry, 'badgeActions'>`): Registry holding the extension registrations.

**Returns** `BadgeMenuItem[]`

Source: [src/extensions/badge-actions.ts:236](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L236)

### `extensionConfigSettingsPort`

Function.

A settings port over the host's settings bag (`Settings.extensionConfig`),
which today's Settings UIs write: it is the `user` layer, and the
source of `secret` strings too. Writes are left to the host, which
persists what its Settings UI and action results give it.

```ts
function extensionConfigSettingsPort(
  readSettings: (() => Partial<Settings> | undefined) | undefined,
): SettingsPort
```

**Parameters**

- `readSettings` (`(() => Partial<Settings> | undefined) | undefined`): The host's live settings getter.

**Returns** `SettingsPort`: The port.

Source: [src/extensions/runtime/registry-view.ts:57](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/registry-view.ts#L57)

### `extensionRuntimeOf`

Function.

The runtime behind `registry.runtime` (load, unload, reload, settings), or
`undefined` when the registry loaded no extension.

```ts
function extensionRuntimeOf(
  registry: Pick<ExtensionRegistry, 'runtime'>,
): ExtensionRuntime | undefined
```

**Parameters**

- `registry` (`Pick<ExtensionRegistry, 'runtime'>`): A registry from [`buildExtensionRegistry`](https://zidane.si/docs/reference/extensions.md#buildExtensionRegistry) (or filtered from one).

**Returns** `ExtensionRuntime | undefined`

Source: [src/extensions/register.ts:101](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L101)

### `extensionSettingsWire`

Function.

One extension's settings wire with its settings pages, or `undefined`
when it has no definition (failed validation) and no page.

```ts
function extensionSettingsWire(
  r: Pick<RuntimeExtension, 'id' | 'definition' | 'info' | 'settings'>,
  ui: Pick<UiRegistry, 'list'>,
  opts?: { sessionId?: string },
): WireSettings | undefined
```

**Parameters**

- `r` (`Pick<RuntimeExtension, 'id' | 'definition' | 'info' | 'settings'>`): The extension (`runtime.get(id)`).
- `ui` (`Pick<UiRegistry, 'list'>`): The runtime's UI registry (`runtime.outputs.ui`).
- `opts?` (`{ sessionId?: string }`, default `{}`): `sessionId` adds that session's layer to live values.

**Returns** `WireSettings | undefined`

Source: [src/extensions/runtime/settings-wire.ts:30](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/settings-wire.ts#L30)

### `extensionSourceLabel`

Function.

A short name of an install spec: `owner/repo` with `@ref` when one is
pinned (the folder in the repository left out), an npm package with
`@version` when one is pinned. A spec that does not parse is returned as is.

```ts
function extensionSourceLabel(spec: string): string
```

**Parameters**

- `spec` (`string`): An install spec (`Tahul/zidane#v9.0.4:extensions/goal`, `@scope/pkg`).

**Returns** `string`

**Example**

```ts
extensionSourceLabel('Tahul/zidane#v9.0.4:extensions/goal') // 'Tahul/zidane@v9.0.4'
extensionSourceLabel('@scope/pkg') // '@scope/pkg'
```

Source: [src/extensions/install.ts:487](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L487)

### `fetchExtensionSource`

Function.

Materialize the source into `destDir` (created by the caller, assumed
empty). Returns the provenance string plus, for git clones, the exact
commit SHA. See `fetchInstallSource` for transport details and caps.

```ts
function fetchExtensionSource(
  source: InstallSource,
  destDir: string,
  io?: InstallIo,
  onProgress?: (message: string) => void,
): Promise<FetchSourceResult>
```

**Parameters**

- `source` (`InstallSource`): Parsed install source.
- `destDir` (`string`): Empty directory to fetch into.
- `io?` (`InstallIo`, default `{}`): Overrides for fetch, process execution and executable lookup.
- `onProgress?` (`(message: string) => void`): Called with a short status message as the fetch runs.

**Returns** `Promise<FetchSourceResult>`

Source: [src/extensions/install.ts:241](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L241)

### `fetchGithubPullRequest`

Function.

Read one PR. Path segments are validated to the shape a real repo has
(callers pass untrusted strings: artifact meta, matched text), so a
crafted owner can't steer the token-bearing request elsewhere. 4 s
deadline per request, or `signal`.

```ts
function fetchGithubPullRequest(
  owner: string,
  repo: string,
  number: number,
  opts?: { signal?: AbortSignal },
): Promise<GithubPull | undefined>
```

**Parameters**

- `owner` (`string`): Repository owner.
- `repo` (`string`): Repository name.
- `number` (`number`): Pull request number.
- `opts?` (`{ signal?: AbortSignal }`, default `{}`): Request options. `opts.signal` aborts the request.

**Returns** `Promise<GithubPull | undefined>`

Source: [src/extensions/github-pulls.ts:50](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L50)

### `filterExtensionRegistry`

Function.

Filter the extension registry by the user's enable allowlist. Returns
the original registry by reference when `enabled` is `undefined` (the
fresh-install default — every loaded extension is active) or when it
keeps every active extension; otherwise a live view over the same
runtime with the others listed as inactive.

The identity check is intentional — callers can compare the result
against the input registry to skip recomposing the preset when
nothing has changed.

```ts
function filterExtensionRegistry(
  registry: ExtensionRegistry,
  enabled: readonly string[] | undefined,
): ExtensionRegistry
```

**Parameters**

- `registry` (`ExtensionRegistry`): Registry to filter.
- `enabled` (`readonly string[] | undefined`): Names of the enabled extensions. `undefined` keeps every extension.

**Returns** `ExtensionRegistry`

Source: [src/extensions/register.ts:223](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L223)

### `filterRegistryPlugins`

Function.

Drop the contributions of Agent Plugins the user has disabled.

`filterExtensionRegistry` keys on EXTENSION names, so it can't express
"this extension runs, but the plugin it loaded does not". Plugin skills and
MCP servers are fanned into the loading extension's contributions by
`ctx.plugins.load`, which means without this pass `enabledPlugins` would
render a checkbox that changes nothing for extension-loaded plugins.

Skills are matched by `metadata['zidane.plugin']` (stamped by the loader);
MCP servers carry no such marker, so they're matched by identity against
the server list on each [`LoadedPluginRecord`](https://zidane.si/docs/reference/extensions.md#LoadedPluginRecord).

Returns the input registry unchanged when nothing is disabled, so callers
can compare identity to skip recomposing.

```ts
function filterRegistryPlugins(
  registry: ExtensionRegistry,
  enabledPlugins: readonly string[] | undefined,
  shadowed?: ReadonlySet<string>,
): ExtensionRegistry
```

**Parameters**

- `registry` (`ExtensionRegistry`): Registry to filter.
- `enabledPlugins` (`readonly string[] | undefined`): Names of the enabled plugins. `undefined` keeps every plugin.
- `shadowed?` (`ReadonlySet<string>`): Plugin names already provided by another source (in
  practice: disk discovery), pruned regardless of the allowlist. The
  settings list dedupes such a plugin to ONE row preferring the disk copy;
  contributions have to agree, or that single checkbox governs two live
  copies.

**Returns** `ExtensionRegistry`

Source: [src/extensions/register.ts:263](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L263)

### `findReferences`

Function.

Every reference in `text` for the providers that scan `surface`, sorted,
without overlaps: the earliest start wins, then the longest, then the
earlier provider. Zero-length matches are skipped.

```ts
function findReferences(
  text: string,
  providers: readonly ReferenceProviderWire[],
  surface?: ExtensionReferenceSurface,
): ReferenceMatch[]
```

**Parameters**

- `text` (`string`): Text to scan.
- `providers` (`readonly ReferenceProviderWire[]`): Providers to match with.
- `surface?` (`ExtensionReferenceSurface`): Surface the text belongs to. Providers that do not scan it are skipped. Omitted: every provider.

**Returns** `ReferenceMatch[]`

Source: [src/extensions/references.ts:97](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L97)

### `githubIssueView`

Function.

An issue as a reference view: its state icon and color, its number, a hover card.

```ts
function githubIssueView(issue: GithubIssue): ExtensionReferenceView
```

**Parameters**

- `issue` (`GithubIssue`): Issue to draw.

**Returns** `ExtensionReferenceView`

Source: [src/extensions/github-pulls.ts:254](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L254)

### `githubPullUrl`

Function.

The PR's canonical URL: the uri its `pull_request` artifact is stored under.

```ts
function githubPullUrl(owner: string, repo: string, number: number): string
```

**Parameters**

- `owner` (`string`): Repository owner.
- `repo` (`string`): Repository name.
- `number` (`number`): Pull request number.

**Returns** `string`

Source: [src/extensions/github-pulls.ts:361](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L361)

### `githubPullView`

Function.

A PR as a reference view: GitHub's state icon and color, its number, a hover card.

```ts
function githubPullView(
  pull: GithubPull,
  opts?: { rateLimited?: { anonymous?: boolean; retryAt?: number } },
): ExtensionReferenceView
```

**Parameters**

- `pull` (`GithubPull`): PR to draw.
- `opts?` (`{ rateLimited?: { anonymous?: boolean; retryAt?: number } }`, default `{}`): Display options. `opts.rateLimited` marks the data as stale because of a rate limit.

**Returns** `ExtensionReferenceView`

Source: [src/extensions/github-pulls.ts:117](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L117)

### `githubRateLimitText`

Function.

Why GitHub data is stale, in a few words: a pause until a time, or the anonymous limit.

```ts
function githubRateLimitText(limit: { anonymous?: boolean; retryAt?: number }): string
```

**Parameters**

- `limit` (`{ anonymous?: boolean; retryAt?: number }`): Rate limit state: when requests resume, or whether the anonymous limit was hit.

**Returns** `string`

Source: [src/extensions/github-pulls.ts:65](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L65)

### `githubRefKey`

Function.

The key an issue or PR number is resolved by: `owner/repo#123`.

```ts
function githubRefKey(owner: string, repo: string, number: string | number): string
```

**Parameters**

- `owner` (`string`): Repository owner.
- `repo` (`string`): Repository name.
- `number` (`string | number`): Issue or pull request number.

**Returns** `string`

Source: [src/extensions/github-pulls.ts:167](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L167)

### `hostModuleSpecifiers`

Function.

The specifiers a host must map for installed extensions at runtime, for
[`registerExtensionHostModules`](https://zidane.si/docs/reference/extensions.md#registerExtensionHostModules). UI modules (`react`, OpenTUI) are
the renderer host's own business and not listed.

```ts
function hostModuleSpecifiers(): ('zidane' | 'zidane/extensions' | 'zidane/extensions/testing' | 'zidane/providers' | 'zidane/providers/google' | 'zidane/oauth')[]
```

**Returns** `('zidane' | 'zidane/extensions' | 'zidane/extensions/testing' | 'zidane/providers' | 'zidane/providers/google' | 'zidane/oauth')[]`: A fresh list of [`HOST_MODULE_SPECIFIERS`](https://zidane.si/docs/reference/extensions.md#HOST_MODULE_SPECIFIERS).

Source: [src/extensions/host-modules.ts:78](https://github.com/Tahul/zidane/blob/main/src/extensions/host-modules.ts#L78)

### `inlineLoadedExtension`

Function.

Tag an inline (host-passed) extension into the same shape disk-
loaded ones produce, so host-bundled extensions (e.g. those passed
via `RunTuiOptions.extensions`) flow through `buildExtensionRegistry`
identically to disk-discovered ones. The runtime validates the
definition and lists it inactive with what is wrong.

```ts
function inlineLoadedExtension(
  definition: object | Pick<ExtensionDefinition<SettingsSchema>, 'apiVersion'>,
): LoadedExtension
```

**Parameters**

- `definition` (`object | Pick<ExtensionDefinition<SettingsSchema>, 'apiVersion'>`): Extension definition the host built in code.

**Returns** `LoadedExtension`

Source: [src/extensions/discovery.ts:583](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L583)

### `installExtensionFromSpec`

Function.

The full fetch → enumerate → deps → validate → copy pipeline. See the
module doc for invariants. Throws [`ExtensionInstallError`](https://zidane.si/docs/reference/extensions.md#ExtensionInstallError); a throw
means nothing was written to the target roots.

```ts
function installExtensionFromSpec(
  opts: InstallExtensionFromSpecOptions,
): Promise<ExtensionInstallResult>
```

**Parameters**

- `opts` (`InstallExtensionFromSpecOptions`): Source, scope and install options.

**Returns** `Promise<ExtensionInstallResult>`

Source: [src/extensions/install.ts:313](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L313)

### `integrationMethodFromOAuthProvider`

Function.

Adapts a `zidane/oauth` provider flow to an integration method of type
`custom`. `connect` runs `provider.login` with the host's flow UI
(links, device codes, prompts and choices go through [`IntegrationFlowIO`](https://zidane.si/docs/reference/extensions.md#IntegrationFlowIO));
the credential's `accessToken` is `provider.getApiKey(grant)`, the
refresh token is kept by the store, and other grant fields ride in
`credential.extra`. `refresh` runs `provider.refreshToken`. The account
is the grant's `email`, `account` or `label` when it has one.

```ts
function integrationMethodFromOAuthProvider(
  provider: OAuthProviderInterface,
  opts?: { help?: string; id?: string; label?: string },
): IntegrationCustomMethod
```

**Parameters**

- `provider` (`OAuthProviderInterface`): The flow (`OAuthProviderInterface` from `zidane/oauth`).
- `opts?` (`{ help?: string; id?: string; label?: string }`, default `{}`): Method id (default `provider.id`), label (default `Sign in with <name>`) and help.

**Returns** `IntegrationCustomMethod`

Source: [src/extensions/integrations/oauth-provider-method.ts:80](https://github.com/Tahul/zidane/blob/main/src/extensions/integrations/oauth-provider-method.ts#L80)

### `isBadgeColor`

Function.

Whether `value` is a color hosts accept (`#rgb` / `#rrggbb`).

```ts
function isBadgeColor(value: unknown): value is string
```

**Parameters**

- `value` (`unknown`): Value to test.

**Returns** `value is string`: `true` when `value` is a `#rgb` or `#rrggbb` string.

Source: [src/extensions/types.ts:246](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L246)

### `isExtensionPanelScope`

Function.

Whether `v` is a valid [`ExtensionPanelScope`](https://zidane.si/docs/reference/extensions.md#ExtensionPanelScope).

```ts
function isExtensionPanelScope(v: unknown): v is ExtensionPanelScope
```

**Parameters**

- `v` (`unknown`): Value to test.

**Returns** `v is ExtensionPanelScope`

Source: [src/extensions/panels.ts:613](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L613)

### `isJson`

Function.

Whether `value` is plain JSON: finite numbers, plain objects with safe
keys (see `isSafeRecordKey`), arrays, strings, booleans and null.

```ts
function isJson(value: unknown, depth?: number): value is Json
```

**Parameters**

- `value` (`unknown`): Candidate value.
- `depth?` (`number`, default `0`): Current nesting level. Callers leave it at 0.

**Returns** `value is Json`

Source: [src/extensions/storage/json.ts:20](https://github.com/Tahul/zidane/blob/main/src/extensions/storage/json.ts#L20)

### `isPanelSurface`

Function.

Whether `v` is a valid [`PanelSurface`](https://zidane.si/docs/reference/extensions.md#PanelSurface).

```ts
function isPanelSurface(v: unknown): v is PanelSurface
```

**Parameters**

- `v` (`unknown`): Value to test.

**Returns** `v is PanelSurface`

Source: [src/extensions/panels.ts:568](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L568)

### `isPullFresh`

Function.

Whether a stored PR is current: fresh, or in a state that never changes.

```ts
function isPullFresh(
  pull: { resolvedAt?: number; state: string },
  now?: number,
): boolean
```

**Parameters**

- `pull` (`{ resolvedAt?: number; state: string }`): Stored PR with its state and read time.
- `now?` (`number`): Current time in epoch ms. Default: `Date.now()`.

**Returns** `boolean`

Source: [src/extensions/github-pulls.ts:441](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L441)

### `isRuntimeLoadedExtension`

Function.

Whether a loaded entry carries a module for the runtime (as opposed to a
load error).

```ts
function isRuntimeLoadedExtension(
  entry: LoadedExtension,
): entry is RuntimeLoadedExtension
```

**Parameters**

- `entry` (`LoadedExtension`): An entry from discovery or `inlineLoadedExtension`.

**Returns** `entry is RuntimeLoadedExtension`

Source: [src/extensions/runtime/loaded-entry.ts:28](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/loaded-entry.ts#L28)

### `isUiHostModule`

Function.

Whether `specifier` names a module the renderer provides.

```ts
function isUiHostModule(specifier: string, extra?: readonly string[]): boolean
```

**Parameters**

- `specifier` (`string`): The import specifier as written.
- `extra?` (`readonly string[]`, default `[]`): More host modules the caller allows.

**Returns** `boolean`

Source: [src/extensions/bundle/policy.ts:48](https://github.com/Tahul/zidane/blob/main/src/extensions/bundle/policy.ts#L48)

### `isValidExtensionConfigItem`

Function.

Whether an authored item is well-formed for its declared `type` — used
by `ctx.registerConfigItem` to drop malformed declarations (wrong /
missing `default`, an `enum` without `options`) before they reach the
registry. Cheaper than letting a broken item ride to render time.

```ts
function isValidExtensionConfigItem(item: ExtensionConfigItem): boolean
```

**Parameters**

- `item` (`ExtensionConfigItem`): Item declared by an extension.

**Returns** `boolean`

Source: [src/extensions/config.ts:322](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L322)

### `isValidExtensionConfigValue`

Function.

Whether `value` is a valid concrete value for `item` — type match plus
the item's constraints (number range, enum membership, string pattern)
and the optional author `validate`. `step` is intentionally NOT enforced
here (it's a UI affordance, not a hard constraint — a persisted value or
default that doesn't align to the step is still honored).

```ts
function isValidExtensionConfigValue(
  item: ExtensionConfigItem,
  value: unknown,
): value is ExtensionConfigValue
```

**Parameters**

- `item` (`ExtensionConfigItem`): Item that defines the type and constraints.
- `value` (`unknown`): Candidate value.

**Returns** `value is ExtensionConfigValue`

Source: [src/extensions/config.ts:390](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L390)

### `listActionSummaries`

Function.

The action rows: the counterpart of `toWireConfigSchema`, which strips them.

```ts
function listActionSummaries(
  categories: Readonly<Record<string, ExtensionConfigCategory>>,
  items: StoredItems,
): ExtensionActionSummary[]
```

**Parameters**

- `categories` (`Readonly<Record<string, ExtensionConfigCategory>>`): The registry's config categories.
- `items` (`StoredItems`): The registry's config items, per extension.

**Returns** `ExtensionActionSummary[]`

Source: [src/extensions/config-actions.ts:44](https://github.com/Tahul/zidane/blob/main/src/extensions/config-actions.ts#L44)

### `listExtensionCandidates`

Function.

List the installable extensions inside a fetched tree. `fallbackName`
seeds the single-extension case when no manifest names it (repo or
unscoped package basename).

```ts
function listExtensionCandidates(
  dir: string,
  fallbackName: string,
): ExtensionInstallCandidate[]
```

**Parameters**

- `dir` (`string`): Root of the fetched tree.
- `fallbackName` (`string`): Name to use when no manifest names the extension.

**Returns** `ExtensionInstallCandidate[]`

Source: [src/extensions/install.ts:267](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L267)

### `listExtensionPaletteItems`

Function.

Every provider's items for `cwd`, normalised and stamped with the provider
id. A provider that throws or hangs contributes one disabled row naming the
failure, so the user sees why an expected command is missing.

```ts
function listExtensionPaletteItems(
  providers: readonly ExtensionPaletteProviderEntry[],
  cwd: string,
  ctx: PaletteContext,
): Promise<PaletteItem[]>
```

**Parameters**

- `providers` (`readonly ExtensionPaletteProviderEntry[]`): The registry's palette providers.
- `cwd` (`string`): The folder.
- `ctx` (`PaletteContext`): The client's palette context.

**Returns** `Promise<PaletteItem[]>`

Source: [src/extensions/panel-host.ts:240](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L240)

### `loadableExtensionDirs`

Function.

The folders [`discoverExtensions`](https://zidane.si/docs/reference/extensions.md#discoverExtensions) would import for the same options:
a trusted extension's, never an untrusted project's. What a host compiles
ahead of a load (`precompileExtension`).

```ts
function loadableExtensionDirs(
  opts?: { cwd?: string; extensionScanPaths?: readonly string[]; home?: string; linkedExtensionDirs?: readonly LinkedExtensionDir[]; prefix?: string; trustProjectExtensions?: boolean },
): string[]
```

**Parameters**

- `opts?` (`{ cwd?: string; extensionScanPaths?: readonly string[]; home?: string; linkedExtensionDirs?: readonly LinkedExtensionDir[]; prefix?: string; trustProjectExtensions?: boolean }`, default `{}`): Scan overrides and `trustProjectExtensions`, as for [`discoverExtensions`](https://zidane.si/docs/reference/extensions.md#discoverExtensions).

**Returns** `string[]`

Source: [src/extensions/discovery.ts:339](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L339)

### `loadExtensionFolder`

Function.

Imports one extension folder fresh from disk, as discovery would (version
check, manifest, module graph evicted first). Never rejects: a folder with
no entry file or a module that fails to import comes back with `error`.
The caller decides whether the folder may load at all (trust, precedence):
[`loadableExtensionDirs`](https://zidane.si/docs/reference/extensions.md#loadableExtensionDirs) answers that.

```ts
function loadExtensionFolder(
  dir: string,
  opts: { compileCache?: string; importTimeoutMs?: number; sink?: LogSink; source: LoadedExtensionSource },
): Promise<LoadedExtension>
```

**Parameters**

- `dir` (`string`): The extension folder.
- `opts` (`{ compileCache?: string; importTimeoutMs?: number; sink?: LogSink; source: LoadedExtensionSource }`): Its source, the import bound (default 10 s), the warning sink and Node's compile cache.

**Returns** `Promise<LoadedExtension>`: The loaded entry, or one carrying the error.

Source: [src/extensions/discovery.ts:546](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L546)

### `loadExtensionPanel`

Function.

Runs a panel's `load()` for a context from across the boundary (known
string fields only, bound to `cwd`). A missing, throwing or hanging panel
yields an empty content naming why.

```ts
function loadExtensionPanel(
  panel: ExtensionPanelEntry | undefined,
  rawCtx: unknown,
  cwd: string,
  deps: PanelHostDeps,
): Promise<PanelContent>
```

**Parameters**

- `panel` (`ExtensionPanelEntry | undefined`): The panel, `undefined` when the folder no longer has it.
- `rawCtx` (`unknown`): The client's context.
- `cwd` (`string`): The folder.
- `deps` (`PanelHostDeps`): Where it runs.

**Returns** `Promise<PanelContent>`

Source: [src/extensions/panel-host.ts:160](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L160)

### `loadExtensionsConfig`

Function.

Reads and parses both config files and their locks. Feed `[user,
project]` to `createConfigSettingsLayer`.

```ts
function loadExtensionsConfig(
  location: ExtensionsConfigLocation,
): LoadedExtensionsConfig
```

**Parameters**

- `location` (`ExtensionsConfigLocation`): Config dir, cwd, home and prefix.

**Returns** `LoadedExtensionsConfig`

Source: [src/extensions/declarative/node.ts:113](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/node.ts#L113)

### `mergeBadgeMenu`

Function.

Order items the way [`badgeMenu`](https://zidane.si/docs/reference/extensions.md#badgeMenu) does: by group, stable within one,
later colliding shortcuts dropped. For hosts that get the built-ins and the
extension items separately (the GUI renderer asks main for the latter).

```ts
function mergeBadgeMenu(all: readonly BadgeMenuItem[]): BadgeMenuItem[]
```

**Parameters**

- `all` (`readonly BadgeMenuItem[]`): Built-in and extension items to order.

**Returns** `BadgeMenuItem[]`

Source: [src/extensions/badge-actions.ts:287](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L287)

### `mergeWireSettings`

Function.

Joins the wire settings of several extensions into the one list the
Settings UI reads.

```ts
function mergeWireSettings(parts: readonly WireSettings[]): WireSettings
```

**Parameters**

- `parts` (`readonly WireSettings[]`): One [`WireSettings`](https://zidane.si/docs/reference/extensions.md#WireSettings) per extension.

**Returns** `WireSettings`: The merged wire settings.

Source: [src/extensions/settings/wire.ts:413](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/wire.ts#L413)

### `missingHostModuleSpecifiers`

Function.

Every specifier of [`hostModuleSpecifiers`](https://zidane.si/docs/reference/extensions.md#hostModuleSpecifiers) that is not mapped yet.
Hosts check it after their registration (a test, a debug log).

```ts
function missingHostModuleSpecifiers(): ('zidane' | 'zidane/extensions' | 'zidane/extensions/testing' | 'zidane/providers' | 'zidane/providers/google' | 'zidane/oauth')[]
```

**Returns** `('zidane' | 'zidane/extensions' | 'zidane/extensions/testing' | 'zidane/providers' | 'zidane/providers/google' | 'zidane/oauth')[]`: The unmapped specifiers, in list order.

Source: [src/extensions/host-modules.ts:88](https://github.com/Tahul/zidane/blob/main/src/extensions/host-modules.ts#L88)

### `normalizeBadgeEffect`

Function.

An effect from extension code, reduced to known, bounded string fields.

```ts
function normalizeBadgeEffect(raw: unknown): BadgeActionEffect
```

**Parameters**

- `raw` (`unknown`): Untrusted value returned by extension code.

**Returns** `BadgeActionEffect`

Source: [src/extensions/badge-actions.ts:311](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L311)

### `normalizeBadgeTarget`

Function.

A target from across a boundary (the GUI renderer), reduced to its known, bounded fields; `null` when unusable.

```ts
function normalizeBadgeTarget(raw: unknown): BadgeTarget | null
```

**Parameters**

- `raw` (`unknown`): Untrusted value from the renderer.

**Returns** `BadgeTarget | null`

Source: [src/extensions/badge-actions.ts:115](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L115)

### `normalizePanelContent`

Function.

Coerce whatever `load()` returned into a well-formed `PanelContent`:
unknown item kinds and malformed entries are dropped, strings are
trimmed to the caps, and the whole thing is size-bounded. Never throws.

```ts
function normalizePanelContent(input: unknown): PanelContent
```

**Parameters**

- `input` (`unknown`): Value returned by a panel's `load`.

**Returns** `PanelContent`

Source: [src/extensions/panels.ts:709](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L709)

### `normalizePanelHomeLayout`

Function.

A home layout from a registration or across a boundary, kept only when well-formed.

```ts
function normalizePanelHomeLayout(raw: unknown): PanelHomeLayout | undefined
```

**Parameters**

- `raw` (`unknown`): Untrusted input.

**Returns** `PanelHomeLayout | undefined`

Source: [src/extensions/panels.ts:598](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L598)

### `normalizePanelLoadContext`

Function.

A load context from across a boundary (the GUI renderer), reduced to its
known string fields. Hosts run it before handing the context to `load` /
`onAction`.

```ts
function normalizePanelLoadContext(raw: unknown): PanelLoadContextInput
```

**Parameters**

- `raw` (`unknown`): Untrusted input. Non-string fields and values over their length caps are dropped.

**Returns** `PanelLoadContextInput`

Source: [src/extensions/panels.ts:464](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L464)

### `onSettingsPagesChanged`

Function.

Calls `listener` each time a settings page of `ui` is added, replaced or
removed: the settings wire changed, read it again. Protocol clients
follow the same `extensions:ui` changes (`ExtensionsClient.settings.onChange`).

```ts
function onSettingsPagesChanged(
  ui: Pick<UiRegistry, 'subscribe'>,
  listener: () => void,
): () => void
```

**Parameters**

- `ui` (`Pick<UiRegistry, 'subscribe'>`): The registry (`runtime.outputs.ui`).
- `listener` (`() => void`): Called once per change.

**Returns** `() => void`: The unsubscribe.

Source: [src/extensions/runtime/settings-wire.ts:89](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/settings-wire.ts#L89)

### `panelBadgeText`

Function.

Tab badge as shown next to the label; `undefined` when nothing to show.

```ts
function panelBadgeText(badge: string | number | undefined): string | undefined
```

**Parameters**

- `badge` (`string | number | undefined`): Badge from [`PanelContent`](https://zidane.si/docs/reference/extensions.md#PanelContent).

**Returns** `string | undefined`

Source: [src/extensions/panels.ts:1129](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L1129)

### `panelHostRuntime`

Function.

The host runtime a panel's `load` / `onAction` (or a badge action) runs in,
read-only: the folder's project (`projectRootOf(cwd)`), plus the session
when one is bound. `ctx.artifacts.list()` answers that session's artifacts
(`[]` unbound), `list({ scope: 'project' })` every session's under the
project root. Store-wide queries (`scope: 'all'`, `find`) answer `[]`;
`record` needs a session, so it answers `undefined` unbound. Everything
else reads as detached, as it does for any extension code outside a run.

```ts
function panelHostRuntime(
  ctx: PanelLoadContextInput,
  deps: PanelScopeDeps,
): ExtensionHostRuntimeImpl
```

**Parameters**

- `ctx` (`PanelLoadContextInput`): The bound load context.
- `deps` (`PanelScopeDeps`): The scope's reads.

**Returns** `ExtensionHostRuntimeImpl`

Source: [src/extensions/panel-host.ts:111](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L111)

### `panelOnSurface`

Function.

Whether a panel shows on `surface`.

```ts
function panelOnSurface(
  panel: { surfaces?: readonly PanelSurface[] },
  surface: PanelSurface,
): boolean
```

**Parameters**

- `panel` (`{ surfaces?: readonly PanelSurface[] }`): The panel, or its summary.
- `surface` (`PanelSurface`): The surface.

**Returns** `boolean`

Source: [src/extensions/panels.ts:589](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L589)

### `panelShowsIn`

Function.

Whether a panel registered with `scope` shows in a context bound to `bound` (absent `scope` = `'session'`).

```ts
function panelShowsIn(
  scope: ExtensionPanelScope | undefined,
  bound: PanelLoadScope,
): boolean
```

**Parameters**

- `scope` (`ExtensionPanelScope | undefined`): Scope the panel registered with.
- `bound` (`PanelLoadScope`): Scope the load context is bound to.

**Returns** `boolean`

Source: [src/extensions/panels.ts:623](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L623)

### `panelSummaries`

Function.

Summaries of a folder's panels.

```ts
function panelSummaries(panels: readonly ExtensionPanelEntry[]): PanelSummary[]
```

**Parameters**

- `panels` (`readonly ExtensionPanelEntry[]`): The registry's panels.

**Returns** `PanelSummary[]`

Source: [src/extensions/panel-host.ts:85](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L85)

### `panelSurfaces`

Function.

The surfaces a panel registered for (absent or empty: `['side']`).

```ts
function panelSurfaces(
  panel: { surfaces?: readonly PanelSurface[] },
): readonly PanelSurface[]
```

**Parameters**

- `panel` (`{ surfaces?: readonly PanelSurface[] }`): The panel, or its summary.

**Returns** `readonly PanelSurface[]`

Source: [src/extensions/panels.ts:578](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L578)

### `panelViewValue`

Function.

A control's value in a view: the picked option id (`segmented`, `select`), or `fallback` when the user
picked none or the value is a list.

```ts
function panelViewValue(
  view: Readonly<Record<string, string | readonly string[]>> | undefined,
  id: string,
  fallback: string,
): string
```

**Parameters**

- `view` (`Readonly<Record<string, string | readonly string[]>> | undefined`): The panel's view state.
- `id` (`string`): The control id.
- `fallback` (`string`): The default.

**Returns** `string`

Source: [src/extensions/panels.ts:527](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L527)

### `panelViewValues`

Function.

A `multi` control's picked options in a view: `fallback` when the user never touched it.

```ts
function panelViewValues(
  view: Readonly<Record<string, string | readonly string[]>> | undefined,
  id: string,
  fallback?: readonly string[],
): readonly string[]
```

**Parameters**

- `view` (`Readonly<Record<string, string | readonly string[]>> | undefined`): The panel's view state.
- `id` (`string`): The control id.
- `fallback?` (`readonly string[]`, default `[]`): The default.

**Returns** `readonly string[]`

Source: [src/extensions/panels.ts:539](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L539)

### `parseExtensionInstallSource`

Function.

Classify a raw source string. See `parseInstallSource` for the grammar.

```ts
function parseExtensionInstallSource(raw: string): InstallSource
```

**Parameters**

- `raw` (`string`): Source spec such as `owner/repo`, `npm:pkg` or a git URL.

**Returns** `InstallSource`

Source: [src/extensions/install.ts:219](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L219)

### `parseExtensionScanPathEnv`

Function.

Parse a platform-delimited list of additional extension scan roots.
Useful for local dogfooding / host-provided packages:

ZIDANE_EXTENSION_DIRS=/repo/extensions bun run tui

Each path is a scan ROOT whose children are extension dirs/packages
(`<root>/<name>/index.ts`), not a single extension directory.

```ts
function parseExtensionScanPathEnv(value?: string | undefined): string[]
```

**Parameters**

- `value?` (`string | undefined`, default `process.env.ZIDANE_EXTENSION_DIRS`): Delimited list of scan roots. Default: `ZIDANE_EXTENSION_DIRS`.

**Returns** `string[]`

Source: [src/extensions/discovery.ts:132](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L132)

### `parseGithubRefKey`

Function.

Parses a key built by [`githubRefKey`](https://zidane.si/docs/reference/extensions.md#githubRefKey). Returns `undefined` when `key` does not have the `owner/repo#number` shape.

```ts
function parseGithubRefKey(
  key: string,
): { number: number; owner: string; repo: string } | undefined
```

**Parameters**

- `key` (`string`): Key to parse.

**Returns** `{ number: number; owner: string; repo: string } | undefined`

Source: [src/extensions/github-pulls.ts:176](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L176)

### `parseShortstat`

Function.

`git show --shortstat --format=` → `{ additions, deletions, changedFiles }`
(` 4 files changed, 120 insertions(+), 8 deletions(-)`). Any missing
clause is 0; an empty stat (empty commit) is `undefined`.

```ts
function parseShortstat(
  out: string,
): { additions: number; changedFiles: number; deletions: number } | undefined
```

**Parameters**

- `out` (`string`): Output of `git show --shortstat --format=`.

**Returns** `{ additions: number; changedFiles: number; deletions: number } | undefined`

Source: [src/extensions/builtin-artifact-kinds.ts:424](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L424)

### `partitionExtensionCatalog`

Function.

Partition a registry's `loaded` + `inactive` lists into the shape the
Settings toggle UIs render. Pure; shared by the TUI's standalone
extensions modal and the Settings-modal tab so the rules (and the
allowlist-GC key set) stay in one place.

```ts
function partitionExtensionCatalog(
  loaded: readonly LoadedExtension[],
  inactive: readonly LoadedExtension[],
): ExtensionCatalogPartition
```

**Parameters**

- `loaded` (`readonly LoadedExtension[]`): Active extensions.
- `inactive` (`readonly LoadedExtension[]`): Disabled or failed extensions.

**Returns** `ExtensionCatalogPartition`

Source: [src/extensions/register.ts:319](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L319)

### `precompileExtension`

Function.

Compiles an extension folder's TypeScript into the cache, as a load would.
Files whose entry is current are only checked. A file that does not compile
is skipped (the load reports it).

```ts
function precompileExtension(dir: string, compileCache: string): Promise<number>
```

**Parameters**

- `dir` (`string`): The extension folder.
- `compileCache` (`string`): The cache folder.

**Returns** `Promise<number>`: The files checked or compiled.

Source: [src/extensions/compile-cache.ts:97](https://github.com/Tahul/zidane/blob/main/src/extensions/compile-cache.ts#L97)

### `probeActionStatuses`

Function.

Every action's passive `status()`, keyed `extension:key`. A probe that
throws, times out or answers no message is left out.

```ts
function probeActionStatuses(
  items: StoredItems,
): Promise<Record<string, ExtensionConfigActionStatus>>
```

**Parameters**

- `items` (`StoredItems`): The registry's config items, per extension.

**Returns** `Promise<Record<string, ExtensionConfigActionStatus>>`

Source: [src/extensions/config-actions.ts:76](https://github.com/Tahul/zidane/blob/main/src/extensions/config-actions.ts#L76)

### `projectStorageFolder`

Function.

The folder that holds one project's extension storage, after moving what
an earlier build left in the project (once per process and project).

```ts
function projectStorageFolder(options: ProjectStorageFolderOptions): string
```

**Parameters**

- `options` (`ProjectStorageFolderOptions`): The data folder, the project and where to report the move.

**Returns** `string`

Source: [src/extensions/storage/project-folder.ts:60](https://github.com/Tahul/zidane/blob/main/src/extensions/storage/project-folder.ts#L60)

### `pruneExtensionCompileCache`

Function.

Drops the entries not rewritten in `maxAgeMs`.

```ts
function pruneExtensionCompileCache(
  compileCache: string,
  maxAgeMs?: number,
  now?: number,
): number
```

**Parameters**

- `compileCache` (`string`): The cache folder.
- `maxAgeMs?` (`number`, default `COMPILE_CACHE_MAX_AGE_MS`): The age past which an entry goes.
- `now?` (`number`): The current time.

**Returns** `number`: The entries dropped.

Source: [src/extensions/compile-cache.ts:130](https://github.com/Tahul/zidane/blob/main/src/extensions/compile-cache.ts#L130)

### `pullChecks`

Function.

A PR's checks line, when it says something (open PRs only).

```ts
function pullChecks(
  pull: { mergeable?: string; state: string },
): { text: string; tone: ExtensionBadgeTone } | undefined
```

**Parameters**

- `pull` (`{ mergeable?: string; state: string }`): PR with its state and mergeability.

**Returns** `{ text: string; tone: ExtensionBadgeTone } | undefined`

Source: [src/extensions/github-pulls.ts:450](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L450)

### `pullFromMeta`

Function.

A PR back from artifact meta, when the meta says enough to draw it (a
refresh has filled the title and state); `undefined` otherwise. Untrusted
input: every field is type-checked.

```ts
function pullFromMeta(meta: unknown): (GithubPull & { resolvedAt?: number }) | undefined
```

**Parameters**

- `meta` (`unknown`): Artifact meta of unknown shape.

**Returns** `(GithubPull & { resolvedAt?: number }) | undefined`

Source: [src/extensions/github-pulls.ts:402](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L402)

### `pullMeta`

Function.

A fetched PR as `pull_request` artifact meta (merged over what was there):
the one stored copy the session badge, the Artifacts row and the hover
card all read.

```ts
function pullMeta(pull: GithubPull, now?: number): Record<string, string | number>
```

**Parameters**

- `pull` (`GithubPull`): Fetched PR.
- `now?` (`number`): Timestamp recorded as the read time. Default: `Date.now()`.

**Returns** `Record<string, string | number>`

Source: [src/extensions/github-pulls.ts:373](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L373)

### `pullStateLook`

Function.

How a PR state reads, GitHub's way. Unknown (not read yet): the plain PR icon, muted.

```ts
function pullStateLook(
  state: string | undefined,
  draft?: boolean,
): { color?: string; icon: ExtensionBadgeIcon; label?: string; tone: ExtensionBadgeTone }
```

**Parameters**

- `state` (`string | undefined`): GitHub PR state (`open`, `closed`, `merged`), when known.
- `draft?` (`boolean`): Whether the PR is a draft.

**Returns** `{ color?: string; icon: ExtensionBadgeIcon; label?: string; tone: ExtensionBadgeTone }`

Source: [src/extensions/github-pulls.ts:87](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L87)

### `readExtensionInstallOrigin`

Function.

Where an installed extension came from (its `.install.json`), or `null`
for one not installed from a source (hand-written, linked, built in).

```ts
function readExtensionInstallOrigin(dir: string): ExtensionInstallOrigin | null
```

**Parameters**

- `dir` (`string`): Installed extension directory.

**Returns** `ExtensionInstallOrigin | null`

Source: [src/extensions/install.ts:505](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L505)

### `readExtensionInstallProvenance`

Function.

Read `.install.json` provenance from an installed extension dir, or null.

```ts
function readExtensionInstallProvenance(dir: string): ExtensionInstallProvenance | null
```

**Parameters**

- `dir` (`string`): Installed extension directory.

**Returns** `ExtensionInstallProvenance | null`

Source: [src/extensions/install.ts:461](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L461)

### `referenceProviders`

Function.

The providers a host offers for a registry: the extensions', then the
built-in ones (`BUILTIN_REFERENCE_PROVIDERS`: GitHub pull requests) whose
id no extension took. `builtins: false` leaves those out.

```ts
function referenceProviders(
  registry: Pick<ExtensionRegistry, 'references'>,
  opts?: { builtins?: boolean },
): ExtensionReferenceProvider[]
```

**Parameters**

- `registry` (`Pick<ExtensionRegistry, 'references'>`): Registry holding the extensions' providers.
- `opts?` (`{ builtins?: boolean }`, default `{}`): Options. `opts.builtins` set to `false` leaves out the built-in providers.

**Returns** `ExtensionReferenceProvider[]`

Source: [src/extensions/references.ts:154](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L154)

### `referenceProviderWires`

Function.

The host's providers (see [`referenceProviders`](https://zidane.si/docs/reference/extensions.md#referenceProviders)) as wire data, in order.

```ts
function referenceProviderWires(
  registry: Pick<ExtensionRegistry, 'references'>,
  opts?: { builtins?: boolean },
): ReferenceProviderWire[]
```

**Parameters**

- `registry` (`Pick<ExtensionRegistry, 'references'>`): Registry holding the extensions' providers.
- `opts?` (`{ builtins?: boolean }`, default `{}`): Options. `opts.builtins` set to `false` leaves out the built-in providers.

**Returns** `ReferenceProviderWire[]`

Source: [src/extensions/references.ts:179](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L179)

### `refreshArtifact`

Function.

Lazy refresh: run the kind's `resolve()` and return the artifact with
the patch applied (`updatedAt` bumped), or `undefined` when the kind has
no resolver, the resolver declined, or it threw. Callers persist the
result through their store / RPC — this never writes.

```ts
function refreshArtifact(
  artifact: SessionArtifact,
  registry?: Pick<ExtensionRegistry, 'artifactKinds'>,
  opts?: ArtifactResolveOptions,
): Promise<SessionArtifact | undefined>
```

**Parameters**

- `artifact` (`SessionArtifact`): Stored artifact to refresh.
- `registry?` (`Pick<ExtensionRegistry, 'artifactKinds'>`): Active registry, consulted before the built-ins.
- `opts?` (`ArtifactResolveOptions`): Resolve options, such as `force`.

**Returns** `Promise<SessionArtifact | undefined>`

Source: [src/extensions/builtin-artifact-kinds.ts:659](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L659)

### `registerExtensionApiHostModules`

Function.

Maps every zidane entrypoint of [`hostModuleSpecifiers`](https://zidane.si/docs/reference/extensions.md#hostModuleSpecifiers) (`zidane`,
`zidane/extensions`, `zidane/extensions/testing`,
`zidane/providers*`, `zidane/oauth`) to this process's live modules, so an
extension installed outside the repo (no `node_modules/zidane` beside
it) can import their runtime values, such as `Panel` or
`createTestHost`. Lazy, so registering costs nothing until an
extension imports one. Every host calls it before its first extension
import; idempotent.

```ts
function registerExtensionApiHostModules(): void
```

**Example**

```ts
registerExtensionApiHostModules()
const registry = await discoverAndBuildExtensionRegistry({ cwd })
```

Source: [src/extensions/host-modules.ts:157](https://github.com/Tahul/zidane/blob/main/src/extensions/host-modules.ts#L157)

### `registerExtensionHostModules`

Function.

Map bare import specifiers to the host's live module objects for every
subsequently-imported module (extensions included). No-op outside Bun
and for already-registered specifiers. Call BEFORE the first extension
import (the TUI does, at startup).

```ts
function registerExtensionHostModules(
  modules: Partial<Record<'zidane' | 'zidane/extensions' | 'zidane/extensions/testing' | 'zidane/providers' | 'zidane/providers/google' | 'zidane/oauth', HostModuleSource>> & Record<string, HostModuleSource>,
): void
```

**Parameters**

- `modules` (`Partial<Record<'zidane' | 'zidane/extensions' | 'zidane/extensions/testing' | 'zidane/providers' | 'zidane/providers/google' | 'zidane/oauth', HostModuleSource>> & Record<string, HostModuleSource>`): Bare import specifiers mapped to a module object, or to a function that resolves one. Any specifier is accepted; the zidane entrypoints every host must map are [`hostModuleSpecifiers`](https://zidane.si/docs/reference/extensions.md#hostModuleSpecifiers).

**Example**

```ts
import * as React from 'react'
import { registerExtensionHostModules } from 'zidane/extensions'

registerExtensionHostModules({ react: React })
```

Source: [src/extensions/host-modules.ts:118](https://github.com/Tahul/zidane/blob/main/src/extensions/host-modules.ts#L118)

### `reloadChangedExtensions`

Function.

Applies folder changes to a runtime: a held folder that changed is
imported fresh and reloaded in place; one whose folder or entry file is
gone is unloaded (its `ctx.storage.memory` cleared); a new folder loads
when `options.classify` allows it. Given a registry, a folder it refused
at build time (its import failed, an untrusted project folder) counts as
new, and leaves the refused list once it loads or is deleted. Folders are
handled one at a time, in the order given (duplicates once). Never rejects
for an extension's fault: a module that fails to import is listed
`failed` with the error.

```ts
function reloadChangedExtensions(
  target: ExtensionRegistry | ExtensionRuntime,
  changedDirs: readonly string[],
  options?: ReloadChangedOptions,
): Promise<ReloadChangedResult>
```

**Parameters**

- `target` (`ExtensionRegistry | ExtensionRuntime`): A registry from `buildExtensionRegistry` (or a view of one), or its runtime.
- `changedDirs` (`readonly string[]`): Extension folders that changed (absolute).
- `options?` (`ReloadChangedOptions`, default `{}`): How new folders load, import bound, sink and compile cache.

**Returns** `Promise<ReloadChangedResult>`: The ids loaded, reloaded and unloaded, and whether a rebuild is needed.

**Example**

```ts
await reloadChangedExtensions(registry, ['/home/me/.zidane/extensions/notes'], {
  classify: dir => (loadableExtensionDirs({ cwd }).includes(dir) ? { source: 'user' } : undefined),
})
```

Source: [src/extensions/runtime/reload.ts:86](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/reload.ts#L86)

### `removeInstalledExtension`

Function.

Delete an installed extension's directory. Works on any on-disk
extension (hand-authored ones too — no provenance required); the
containment guard is the safety boundary. The caller owns follow-up
(allowlist cleanup, registry reload).

```ts
function removeInstalledExtension(
  opts: InstalledExtensionTargetOptions,
): { dir: string }
```

**Parameters**

- `opts` (`InstalledExtensionTargetOptions`): The installed extension to remove.

**Returns** `{ dir: string }`

Source: [src/extensions/install.ts:571](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L571)

### `renderArtifactRow`

Function.

Row presentation with the guaranteed fallback. A `render` that throws
or returns nothing degrades to `label` + `uri` — a stored artifact is
never invisible because its kind's extension is gone or buggy.

```ts
function renderArtifactRow(
  artifact: SessionArtifact,
  registry?: Pick<ExtensionRegistry, 'artifactKinds'>,
): ExtensionArtifactRow
```

**Parameters**

- `artifact` (`SessionArtifact`): Stored artifact.
- `registry?` (`Pick<ExtensionRegistry, 'artifactKinds'>`): Active registry, consulted before the built-ins.

**Returns** `ExtensionArtifactRow`

Source: [src/extensions/builtin-artifact-kinds.ts:621](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L621)

### `resolveArtifactKind`

Function.

Resolve the registration for a stored artifact's kind: the active
registry wins (an extension may refine a built-in's presentation), then
built-ins, then `undefined` — callers fall back to `label` + `uri`.

```ts
function resolveArtifactKind(
  kind: string,
  registry?: Pick<ExtensionRegistry, 'artifactKinds'>,
): ExtensionArtifactKindRegistration | undefined
```

**Parameters**

- `kind` (`string`): Artifact kind string.
- `registry?` (`Pick<ExtensionRegistry, 'artifactKinds'>`): Active registry, consulted before the built-ins.

**Returns** `ExtensionArtifactKindRegistration | undefined`

Source: [src/extensions/builtin-artifact-kinds.ts:603](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L603)

### `resolveExtensionCompletionSubmit`

Function.

Runs the submit hooks of the usable providers that declare one, with the
same reference collection as the terminal app (`resolveCompletionSubmit`).

```ts
function resolveExtensionCompletionSubmit(
  providers: readonly CompletionProvider<unknown>[],
  text: string,
  cursor: number,
  signal: AbortSignal,
): Promise<void>
```

**Parameters**

- `providers` (`readonly CompletionProvider<unknown>[]`): The registry's providers.
- `text` (`string`): The submitted text.
- `cursor` (`number`): The cursor at submit.
- `signal` (`AbortSignal`): Aborts the hooks.

**Returns** `Promise<void>`

Source: [src/extensions/completion-providers.ts:128](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L128)

### `resolveExtensionConfig`

Function.

Convenience read against a merged [`ExtensionRegistry`](https://zidane.si/docs/reference/extensions.md#ExtensionRegistry) + the user's
`Settings`. Looks up the item schema (`extName → key`), reads the
persisted value out of `settings.extensionConfig`, and runs it through
[`resolveExtensionConfigValue`](https://zidane.si/docs/reference/extensions.md#resolveExtensionConfigValue). Returns `undefined` only when the
`(extName, key)` pair names no registered item.

```ts
function resolveExtensionConfig(
  registry: Pick<ExtensionRegistry, 'configItems'>,
  settings: Pick<Settings, 'extensionConfig'> | undefined,
  extName: string,
  key: string,
): ExtensionConfigValue | undefined
```

**Parameters**

- `registry` (`Pick<ExtensionRegistry, 'configItems'>`): Merged registry holding the declared items.
- `settings` (`Pick<Settings, 'extensionConfig'> | undefined`): User settings holding the persisted values.
- `extName` (`string`): Name of the declaring extension.
- `key` (`string`): Item key.

**Returns** `ExtensionConfigValue | undefined`

Source: [src/extensions/config.ts:544](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L544)

### `resolveExtensionConfigValue`

Function.

Resolve the effective value of a config item from its persisted value.
THE single place graceful degradation lives: a `persisted` that's
`undefined` (never set) OR fails [`isValidExtensionConfigValue`](https://zidane.si/docs/reference/extensions.md#isValidExtensionConfigValue)
collapses to `item.default`. Action items hold no value and resolve to
`undefined` — the overloads keep value-item call sites exact.

```ts
function resolveExtensionConfigValue(
  item: ExtensionConfigValueItem,
  persisted: unknown,
): ExtensionConfigValue
```

Resolve the effective value of a config item from its persisted value.
THE single place graceful degradation lives: a `persisted` that's
`undefined` (never set) OR fails [`isValidExtensionConfigValue`](https://zidane.si/docs/reference/extensions.md#isValidExtensionConfigValue)
collapses to `item.default`. Action items hold no value and resolve to
`undefined` — the overloads keep value-item call sites exact.

**Parameters**

- `item` (`ExtensionConfigValueItem`): Item that defines the type and constraints.
- `persisted` (`unknown`): Stored value, if any.

**Returns** `ExtensionConfigValue`

```ts
function resolveExtensionConfigValue(
  item: ExtensionConfigItem,
  persisted: unknown,
): ExtensionConfigValue | undefined
```

Resolve the effective value of a config item from its persisted value.
THE single place graceful degradation lives: a `persisted` that's
`undefined` (never set) OR fails [`isValidExtensionConfigValue`](https://zidane.si/docs/reference/extensions.md#isValidExtensionConfigValue)
collapses to `item.default`. Action items hold no value and resolve to
`undefined` — the overloads keep value-item call sites exact.

**Parameters**

- `item` (`ExtensionConfigItem`): Item that defines the type and constraints.
- `persisted` (`unknown`): Stored value, if any.

**Returns** `ExtensionConfigValue | undefined`

Source: [src/extensions/config.ts:451](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L451)

### `resolvePanelLoadContext`

Function.

Normalise `raw` and bind it to the host's `cwd` (which wins over any
`cwd` in `raw`): the context `load` / `onAction` receive. `scope` follows
`sessionId`.

```ts
function resolvePanelLoadContext(raw: unknown, cwd: string): PanelLoadContext
```

**Parameters**

- `raw` (`unknown`): Context from the renderer or host UI state.
- `cwd` (`string`): Folder the host binds the context to.

**Returns** `PanelLoadContext`

Source: [src/extensions/panels.ts:552](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L552)

### `resolveUiEntries`

Function.

The UI entries of an extension in `dir`.

A named entry (`definition.ui`, `definition.tui`) is resolved against
`dir`; it must stay inside it and exist, otherwise it is reported in
`errors` and left out (the default files are not tried then). Without a
named entry the first existing default file is used.

```ts
function resolveUiEntries(
  dir: string,
  definition?: UiEntryFields,
  options?: ResolveUiEntriesOptions,
): UiEntries
```

**Parameters**

- `dir` (`string`): The extension folder (where its index lives).
- `definition?` (`UiEntryFields`, default `{}`): The extension definition's `ui` and `tui` fields.
- `options?` (`ResolveUiEntriesOptions`, default `{}`): `exists`, to check files without the disk.

**Returns** `UiEntries`: The entries found and the errors.

**Example**

```ts
const { ui, tui, errors } = resolveUiEntries('/ext/notes', { ui: 'web/ui.tsx' })
```

Source: [src/extensions/bundle/entries.ts:57](https://github.com/Tahul/zidane/blob/main/src/extensions/bundle/entries.ts#L57)

### `runBadgeAction`

Function.

Run one menu item: a built-in resolves locally, an extension item runs its
registration's `run` (8 s deadline). Never throws: failures come back as a
`notice`.

```ts
function runBadgeAction(
  source: string,
  actionId: string,
  target: BadgeTarget,
  registry: Pick<ExtensionRegistry, 'badgeActions'> | undefined,
  ctx?: { cwd?: string; sessionId?: string },
): Promise<BadgeActionEffect>
```

**Parameters**

- `source` (`string`): `builtin`, or the id of the extension registration.
- `actionId` (`string`): Id of the action to run.
- `target` (`BadgeTarget`): Badge the action was invoked on.
- `registry` (`Pick<ExtensionRegistry, 'badgeActions'> | undefined`): Registry holding the extension registrations.
- `ctx?` (`{ cwd?: string; sessionId?: string }`, default `{}`): Session and working directory handed to the extension's `run`.

**Returns** `Promise<BadgeActionEffect>`

Source: [src/extensions/badge-actions.ts:338](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L338)

### `runExtensionAction`

Function.

Runs one action. The config patch it returns is sanitized (unknown keys and
values failing the schema are dropped) and returned, not written: the app
persists it through its settings writer.

```ts
function runExtensionAction(
  items: StoredItems,
  extensionName: string,
  actionId: string,
): Promise<ExtensionActionRunResult>
```

**Parameters**

- `items` (`StoredItems`): The registry's config items, per extension.
- `extensionName` (`string`): The declaring extension.
- `actionId` (`string`): The action's key.

**Returns** `Promise<ExtensionActionRunResult>`

Source: [src/extensions/config-actions.ts:118](https://github.com/Tahul/zidane/blob/main/src/extensions/config-actions.ts#L118)

### `runExtensionPaletteItem`

Function.

Runs `itemId` on its provider `source`.

```ts
function runExtensionPaletteItem(
  providers: readonly ExtensionPaletteProviderEntry[],
  source: string,
  itemId: string,
  cwd: string,
  ctx: PaletteContext,
): Promise<{ ok: true; result: PaletteRunResult } | PanelHostFailure>
```

**Parameters**

- `providers` (`readonly ExtensionPaletteProviderEntry[]`): The registry's palette providers.
- `source` (`string`): The provider's id (`PaletteItem.source`).
- `itemId` (`string`): The item.
- `cwd` (`string`): The folder.
- `ctx` (`PaletteContext`): The client's palette context.

**Returns** `Promise<{ ok: true; result: PaletteRunResult } | PanelHostFailure>`

Source: [src/extensions/panel-host.ts:269](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L269)

### `runExtensionPanelAction`

Function.

Runs a panel's `onAction` as [`loadExtensionPanel`](https://zidane.si/docs/reference/extensions.md#loadExtensionPanel) runs its `load`.

```ts
function runExtensionPanelAction(
  panel: ExtensionPanelEntry | undefined,
  actionId: string,
  payload: unknown,
  rawCtx: unknown,
  cwd: string,
  deps: PanelHostDeps,
): Promise<PanelHostFailure | { ok: true }>
```

**Parameters**

- `panel` (`ExtensionPanelEntry | undefined`): The panel, `undefined` when the folder no longer has it.
- `actionId` (`string`): The action.
- `payload` (`unknown`): Its payload, as the panel's content declared it.
- `rawCtx` (`unknown`): The client's context.
- `cwd` (`string`): The folder.
- `deps` (`PanelHostDeps`): Where it runs.

**Returns** `Promise<PanelHostFailure | { ok: true }>`

Source: [src/extensions/panel-host.ts:182](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L182)

### `runtimeEntryOf`

Function.

A discovered entry as the runtime loads it: its module, or its import
error (`RuntimeEntry.error`).

```ts
function runtimeEntryOf(loaded: LoadedExtension, enabled?: boolean): RuntimeEntry
```

**Parameters**

- `loaded` (`LoadedExtension`): An entry from discovery or [`loadExtensionFolder`](https://zidane.si/docs/reference/extensions.md#loadExtensionFolder).
- `enabled?` (`boolean`): Whether it may run (`false`: listed disabled).

**Returns** `RuntimeEntry`: The runtime entry.

Source: [src/extensions/runtime/loaded-entry.ts:70](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/loaded-entry.ts#L70)

### `runtimeLoadedExtension`

Function.

Wraps a definition as a `LoadedExtension` entry for the runtime.

```ts
function runtimeLoadedExtension(
  definition: unknown,
  where: { dir?: string; manifest?: ExtensionManifest; name?: string; source: LoadedExtensionSource },
): RuntimeLoadedExtension
```

**Parameters**

- `definition` (`unknown`): The module's default export (`apiVersion: 1`).
- `where` (`{ dir?: string; manifest?: ExtensionManifest; name?: string; source: LoadedExtensionSource }`): Folder name, folder, source and manifest.

**Returns** `RuntimeLoadedExtension`: The entry.

Source: [src/extensions/runtime/loaded-entry.ts:43](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/loaded-entry.ts#L43)

### `runtimeSettingsWire`

Function.

Every extension's settings wire of a runtime, merged in load order.

```ts
function runtimeSettingsWire(
  runtime: { extensions: () => readonly { id: string }[]; get: (id: string) => Pick<RuntimeExtension, 'id' | 'info' | 'definition' | 'settings'> | undefined; outputs: { ui: Pick<UiRegistry, 'list'> } },
  opts?: { sessionId?: string },
): WireSettings
```

**Parameters**

- `runtime` (`{ extensions: () => readonly { id: string }[]; get: (id: string) => Pick<RuntimeExtension, 'id' | 'info' | 'definition' | 'settings'> | undefined; outputs: { ui: Pick<UiRegistry, 'list'> } }`): The runtime: its extensions and UI registry.
- `opts?` (`{ sessionId?: string }`, default `{}`): `sessionId` adds that session's layer to live values.

**Returns** `WireSettings`

Source: [src/extensions/runtime/settings-wire.ts:55](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/settings-wire.ts#L55)

### `sanitizeExtensionConfigActionPatch`

Function.

Gate the `config` patch an action returned before the host persists it.
Per-entry, an item is accepted only when it names a registered VALUE
item of the declaring extension and passes that item's schema
([`isValidExtensionConfigValue`](https://zidane.si/docs/reference/extensions.md#isValidExtensionConfigValue)); everything else lands in
`rejected` for logging. Pure — the host applies `accepted` through its
own settings write path.

```ts
function sanitizeExtensionConfigActionPatch(
  items: Readonly<Record<string, StoredExtensionConfigItem>> | undefined,
  patch: Readonly<Record<string, ExtensionConfigValue>> | undefined,
): { accepted: Record<string, ExtensionConfigValue>; rejected: string[] }
```

**Parameters**

- `items` (`Readonly<Record<string, StoredExtensionConfigItem>> | undefined`): Declared items of the extension, keyed by item key.
- `patch` (`Readonly<Record<string, ExtensionConfigValue>> | undefined`): Values the action returned.

**Returns** `{ accepted: Record<string, ExtensionConfigValue>; rejected: string[] }`

Source: [src/extensions/config.ts:567](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L567)

### `scanExtensionDirectories`

Function.

Walk every scan root, collecting one [`ExtensionScanEntry`](https://zidane.si/docs/reference/extensions.md#ExtensionScanEntry) per
`<root>/<name>/index.*` hit. First-found per `name` wins (matches the
project-user precedence used elsewhere — see `projectUserPaths` JSDoc).

Non-existent roots are skipped silently. Stat errors inside a present
root are surfaced under `ZIDANE_DEBUG` only — they shouldn't bring
boot to a halt.

```ts
function scanExtensionDirectories(
  opts?: { cwd?: string; extensionScanPaths?: readonly string[]; home?: string; linkedExtensionDirs?: readonly LinkedExtensionDir[]; prefix?: string },
): ExtensionScanEntry[]
```

**Parameters**

- `opts?` (`{ cwd?: string; extensionScanPaths?: readonly string[]; home?: string; linkedExtensionDirs?: readonly LinkedExtensionDir[]; prefix?: string }`, default `{}`): Overrides for `cwd`, `home` and `prefix`, extra scan roots in `extensionScanPaths`, and config-linked folders in `linkedExtensionDirs` (scanned first).

**Returns** `ExtensionScanEntry[]`

Source: [src/extensions/discovery.ts:149](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L149)

### `sessionBadges`

Function.

A session's badges: its artifacts grouped by kind (newest first within
each), each kind's `badge()` (registry first, then built-ins), ordered by
`badge.order` then kind. A kind without `badge`, or whose `badge` throws
or answers nothing, contributes none.

`badge.panel` comes back as a full panel id: a bare one is prefixed with
the kind's extension, and, when `registry` lists its panels, one that no
active extension registered is dropped (hosts open Artifacts then).

```ts
function sessionBadges(
  artifacts: readonly SessionArtifact[],
  registry?: Pick<ExtensionRegistry, 'artifactKinds'> & Partial<Pick<ExtensionRegistry, 'panels'>>,
): SessionBadgeEntry[]
```

**Parameters**

- `artifacts` (`readonly SessionArtifact[]`): Artifacts of one session.
- `registry?` (`Pick<ExtensionRegistry, 'artifactKinds'> & Partial<Pick<ExtensionRegistry, 'panels'>>`): Active registry and, optionally, its panels.

**Returns** `SessionBadgeEntry[]`

Source: [src/extensions/builtin-artifact-kinds.ts:805](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L805)

### `sessionBadgeTarget`

Function.

The target for a session badge (or one row of its card): GUI sidebar, TUI sessions list.

```ts
function sessionBadgeTarget(
  sessionId: string,
  entry: SessionBadgeEntry,
  row?: ExtensionSessionBadgeCardRow,
): BadgeTarget
```

**Parameters**

- `sessionId` (`string`): Session the badge belongs to.
- `entry` (`SessionBadgeEntry`): Session badge entry.
- `row?` (`ExtensionSessionBadgeCardRow`): Card row the target stands for. Omitted: the badge itself.

**Returns** `BadgeTarget`

Source: [src/extensions/badge-actions.ts:399](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L399)

### `sessionsBadges`

Function.

Several sessions' badges at once (the sidebar rows). One badge per kind, so
one registry per session: the one of the project its newest artifact
landed in.

```ts
function sessionsBadges(
  lists: Readonly<Record<string, readonly SessionArtifact[]>>,
  registryOf: (projectRoot: string) => (Pick<ExtensionRegistry, 'artifactKinds'> & Partial<Pick<ExtensionRegistry, 'panels'>>) | undefined,
): Record<string, SessionBadgeEntry[]>
```

**Parameters**

- `lists` (`Readonly<Record<string, readonly SessionArtifact[]>>`): Each session's artifacts, by session id.
- `registryOf` (`(projectRoot: string) => (Pick<ExtensionRegistry, 'artifactKinds'> & Partial<Pick<ExtensionRegistry, 'panels'>>) | undefined`): The registry of a project root (`''`: untagged); `undefined`: the built-in kinds.

**Returns** `Record<string, SessionBadgeEntry[]>`

Source: [src/extensions/builtin-artifact-kinds.ts:845](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L845)

### `settingsSearchIndex`

Function.

Every settings row of the given extensions, with the page and section it
is on, for the settings search box. Rows of `ui` pages with a schema are
included, on that page; component-only pages have none. Order: the
extensions as given, then page and row order.

```ts
function settingsSearchIndex(
  extensions: readonly SettingsSidebarExtension[],
): SettingsSearchEntry[]
```

**Parameters**

- `extensions` (`readonly SettingsSidebarExtension[]`): The extensions, with their wires.

**Returns** `SettingsSearchEntry[]`: One entry per row.

Source: [src/extensions/settings/sidebar.ts:159](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/sidebar.ts#L159)

### `settingsSidebar`

Function.

Builds the settings sidebar from each extension's wire. An extension
without pages (no settings, no settings-page items) is left out. Works
for disabled extensions too: their wire comes from the definition.

```ts
function settingsSidebar(
  extensions: readonly SettingsSidebarExtension[],
): SettingsSidebar
```

**Parameters**

- `extensions` (`readonly SettingsSidebarExtension[]`): The extensions, with their wires.

**Returns** `SettingsSidebar`: The "Extensions" group and the extensions' own groups.

Source: [src/extensions/settings/sidebar.ts:75](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/sidebar.ts#L75)

### `subscribeExtensionPalette`

Function.

Keeps every provider's `subscribe` on, their emits debounced into one `onChange`.

```ts
function subscribeExtensionPalette(
  providers: readonly ExtensionPaletteProviderEntry[],
  onChange: () => void,
): (() => void) | null
```

**Parameters**

- `providers` (`readonly ExtensionPaletteProviderEntry[]`): The registry's palette providers.
- `onChange` (`() => void`): Called when items may have changed.

**Returns** `(() => void) | null`: The stop, or `null` when no provider has live updates.

Source: [src/extensions/panel-host.ts:289](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L289)

### `subscribeExtensionPanel`

Function.

Keeps a panel's `subscribe` on, its emits debounced into `onChange`.

```ts
function subscribeExtensionPanel(
  panel: ExtensionPanelEntry | undefined,
  onChange: () => void,
): (() => void) | null
```

**Parameters**

- `panel` (`ExtensionPanelEntry | undefined`): The panel.
- `onChange` (`() => void`): Called when its content changed.

**Returns** `(() => void) | null`: The stop, or `null` when the panel has no live updates.

Source: [src/extensions/panel-host.ts:220](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L220)

### `suggestCompletionItems`

Function.

Runs one provider's `suggest` and keeps the well-formed items, at most
[`MAX_COMPLETION_ITEMS`](https://zidane.si/docs/reference/extensions.md#MAX_COMPLETION_ITEMS). A throwing provider or a non-array result
answers `[]`; `insertText` falls back to the item id.

```ts
function suggestCompletionItems(
  provider: CompletionProvider,
  query: string,
  context: { cursor: number; text: string },
  signal: AbortSignal,
): Promise<ExtensionCompletionItemSummary[]>
```

**Parameters**

- `provider` (`CompletionProvider`): The provider.
- `query` (`string`): The text after the trigger.
- `context` (`{ cursor: number; text: string }`): The composer's state.
- `signal` (`AbortSignal`): Aborted when the query moves on.

**Returns** `Promise<ExtensionCompletionItemSummary[]>`

Source: [src/extensions/completion-providers.ts:92](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L92)

### `touchesSettingsPages`

Function.

Whether a UI change adds, replaces or removes a settings page (`reset`:
every item may have gone).

```ts
function touchesSettingsPages(change: UiChange | { type: 'reset' }): boolean
```

**Parameters**

- `change` (`UiChange | { type: 'reset' }`): A UI registry change, or a protocol `reset`.

**Returns** `boolean`

Source: [src/extensions/runtime/settings-wire.ts:72](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/settings-wire.ts#L72)

### `toWireConfigSchema`

Function.

Project the merged registry's config schema into a wire-safe shape:
categories as a flat array, items flattened to a single list carrying
their `extension` + `category`, with the non-serializable `validate`
callback stripped. Action items are omitted entirely — their `run`
callback only exists in the main process, so a remote renderer (the
GUI) has nothing it could do with the row. Pure — factored out so its
serialization is unit testable without an Electron / IPC harness.

```ts
function toWireConfigSchema(
  registry: Pick<ExtensionRegistry, 'configCategories' | 'configItems'>,
): WireExtensionConfigSchema
```

**Parameters**

- `registry` (`Pick<ExtensionRegistry, 'configCategories' | 'configItems'>`): Merged registry holding the declared categories and items.

**Returns** `WireExtensionConfigSchema`

Source: [src/extensions/config.ts:623](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L623)

### `updateInstalledExtension`

Function.

Re-run the recorded install for an extension: re-resolves the original
spec (so `owner/repo` follows the branch and `pkg` follows `latest`,
while pinned refs/versions stay pinned) and replaces the install
IN PLACE (same root the extension currently lives in, even a
`.agents/extensions` one). Requires `.install.json` provenance —
hand-authored extensions have nothing to update from.

When the remote is provably unchanged (recorded commit matches
`git ls-remote`, or the npm version re-resolves identically), the
reinstall is skipped entirely and the result carries `upToDate: true`.

```ts
function updateInstalledExtension(
  opts: InstalledExtensionTargetOptions & { io?: InstallIo; onProgress?: (message: string) => void },
): Promise<ExtensionInstallResult & { previous: ExtensionInstallProvenance; upToDate: boolean }>
```

**Parameters**

- `opts` (`InstalledExtensionTargetOptions & { io?: InstallIo; onProgress?: (message: string) => void }`): The installed extension to update, plus progress and IO overrides.

**Returns** `Promise<ExtensionInstallResult & { previous: ExtensionInstallProvenance; upToDate: boolean }>`

Source: [src/extensions/install.ts:638](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L638)

### `usableCompletionProviders`

Function.

The providers a composer can render: drops invalid ids / triggers / suggest
functions and the reserved triggers, first wins on both id and trigger.

```ts
function usableCompletionProviders(
  providers: readonly CompletionProvider<unknown>[],
): CompletionProvider<unknown>[]
```

**Parameters**

- `providers` (`readonly CompletionProvider<unknown>[]`): The registry's providers.

**Returns** `CompletionProvider<unknown>[]`

Source: [src/extensions/completion-providers.ts:44](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L44)

### `viewForIssueRead`

Function.

The view for a `#N` read that found no PR: the issue, or while a rate limit
holds a neutral `#N` that says so (it may be either), or nothing.

```ts
function viewForIssueRead(
  ref: { number: number; owner: string; repo: string },
  read: { issue: GithubIssue; kind: 'issue' } | { anonymous: boolean; kind: 'rateLimited'; retryAt?: number } | { kind: 'unavailable' },
): ExtensionReferenceView | undefined
```

**Parameters**

- `ref` (`{ number: number; owner: string; repo: string }`): The number that was read.
- `read` (`{ issue: GithubIssue; kind: 'issue' } | { anonymous: boolean; kind: 'rateLimited'; retryAt?: number } | { kind: 'unavailable' }`): Outcome of the read.

**Returns** `ExtensionReferenceView | undefined`

Source: [src/extensions/github-pulls.ts:287](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L287)

### `viewForRead`

Function.

The view for a background read: the PR when GitHub answered; when a rate
limit stopped it, the newest copy this process holds with the reason, or a
muted `#N` that says it; nothing when the PR can't be read.

```ts
function viewForRead(
  ref: { number: number; owner: string; repo: string },
  read: GithubPullRead,
  stored?: GithubPull,
): ExtensionReferenceView | undefined
```

**Parameters**

- `ref` (`{ number: number; owner: string; repo: string }`): Pull request that was read.
- `read` (`GithubPullRead`): Outcome of the read.
- `stored?` (`GithubPull`): Copy of the PR already held, used when a rate limit stopped the read.

**Returns** `ExtensionReferenceView | undefined`

Source: [src/extensions/github-pulls.ts:321](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L321)

### `wireWithSettingsPages`

Function.

An extension's wire with its `SettingsPage` items appended to its pages
(after the schema's pages, by `order`). Hosts call it where they build
an extension's settings wire and hold its UI registry.

```ts
function wireWithSettingsPages(
  wire: WireSettings,
  extensionId: string,
  ui: Pick<UiRegistry, 'list'>,
): WireSettings
```

**Parameters**

- `wire` (`WireSettings`): The extension's wire (the domain's `wire()`, or `toWireSettings` from the definition).
- `extensionId` (`string`): The extension.
- `ui` (`Pick<UiRegistry, 'list'>`): The registry holding its settings-page items.

**Returns** `WireSettings`

Source: [src/extensions/ui/settings-form.ts:81](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/settings-form.ts#L81)

### `withSettingsPages`

Function.

Adds an extension's `SettingsPage` items to its wire, after the schema's
pages, by `order` (default 100; ties keep the given order). Items of
other extensions (their id does not start with `<extensionId>/`) are
ignored. Pure.

```ts
function withSettingsPages(
  wire: WireSettings,
  extensionId: string,
  pages: readonly SettingsPageInput[],
): WireSettings
```

**Parameters**

- `wire` (`WireSettings`): One extension's wire (`toWireSettings` or the domain's `wire()`).
- `extensionId` (`string`): The extension.
- `pages` (`readonly SettingsPageInput[]`): Its settings-page items, as the UI registry serializes them.

**Returns** `WireSettings`: A new wire with the pages appended.

Source: [src/extensions/settings/wire.ts:383](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/wire.ts#L383)

## Classes

### `DialogTimeoutError`

Class.

Thrown by a dialog that got no answer within its `timeoutMs`.

```ts
class DialogTimeoutError extends Error
```

**Constructor**

```ts
new DialogTimeoutError(what: string, timeoutMs: number)
```

**Parameters**

- `what` (`string`): The dialog that timed out.
- `timeoutMs` (`number`): The time it waited.

**Returns** `DialogTimeoutError`

**Properties**

- `timeoutMs` (`number`, readonly): The time it waited.

Source: [src/extensions/api/ui.ts:473](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L473)

### `DisposedError`

Class.

Thrown by a ctx call made through a disposed owner.

```ts
class DisposedError extends Error
```

**Constructor**

```ts
new DisposedError(what: string)
```

**Parameters**

- `what` (`string`): The call that was refused.

**Returns** `DisposedError`

Source: [src/extensions/api/core.ts:139](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L139)

### `ExtensionInstallError`

Class.

Error thrown by the extension installer. `code` says which step failed.

```ts
class ExtensionInstallError extends InstallSourceError
```

**Constructor**

```ts
new ExtensionInstallError(
  code: ExtensionInstallErrorCode,
  message: string,
  candidates?: readonly string[],
)
```

Creates an install error.

**Parameters**

- `code` (`ExtensionInstallErrorCode`): Reason for the failure.
- `message` (`string`): Human-readable description.
- `candidates?` (`readonly string[]`): Extension names found in the source, set for `multiple-candidates`, `no-extension` and `name-mismatch`.

**Returns** `ExtensionInstallError`

**Properties**

- `candidates?` (`readonly string[]`, readonly, from `InstallSourceError`): Set for candidate-selection errors — the names the caller can pick from.
- `code` (`ExtensionInstallErrorCode`, readonly): Machine-readable reason for the failure.

Source: [src/extensions/install.ts:73](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L73)

### `NoUiError`

Class.

Thrown by a dialog when no client can show it.

```ts
class NoUiError extends Error
```

**Constructor**

```ts
new NoUiError(what: string)
```

**Parameters**

- `what` (`string`): The dialog that could not be shown.

**Returns** `NoUiError`

Source: [src/extensions/api/ui.ts:464](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L464)

### `RpcCallError`

Class.

The error a client call rejects with. `type` is a declared error name or one of the reserved `rpc.*` names.

```ts
class RpcCallError<Data = unknown> extends Error
```

**Constructor**

```ts
new RpcCallError<Data = unknown>(type: string, message: string, data?: Data)
```

**Type parameters**

- `Data` (default `unknown`)

**Parameters**

- `type` (`string`): Declared error name, or `rpc.invalid-input`, `rpc.invalid-output`, `rpc.unavailable`, `rpc.aborted`, `rpc.internal`, `rpc.forbidden`.
- `message` (`string`): Text for people.
- `data?` (`Data`): The error data.

**Returns** `RpcCallError<Data>`

**Type parameters**

- `Data` (default `unknown`)

**Properties**

- `data?` (`Data`, readonly): The error data.
- `type` (`string`, readonly): Declared error name, or `rpc.invalid-input`, `rpc.invalid-output`, `rpc.unavailable`, `rpc.aborted`, `rpc.internal`, `rpc.forbidden`.

Source: [src/extensions/api/rpc.ts:115](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L115)

## Constants

### `ARTIFACT_BADGES_MAX`

Constant.

The most sessions one read of badges answers (`artifacts.badges`).

```ts
const ARTIFACT_BADGES_MAX = 100
```

Source: [src/extensions/types.ts:329](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L329)

### `BadgeAction`

Constant.

Context-menu actions on badges, links, files and artifacts.

```ts
const BadgeAction: UiToken<ExtensionBadgeActions, 'badge-action'>
```

Source: [src/extensions/api/ui.ts:445](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L445)

### `branchKind`

Constant.

Built-in `branch` kind. Detects branches the model created, such as with `git switch -c`.

```ts
const branchKind: ExtensionArtifactKindRegistration
```

Source: [src/extensions/builtin-artifact-kinds.ts:474](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L474)

### `BUILTIN_ARTIFACT_KINDS`

Constant.

The built-in artifact kinds: pull request, branch, commit and file.

```ts
const BUILTIN_ARTIFACT_KINDS: readonly ExtensionArtifactKindRegistration[]
```

Source: [src/extensions/builtin-artifact-kinds.ts:581](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L581)

### `BUILTIN_REFERENCE_PROVIDERS`

Constant.

Reference providers hosts offer next to the extensions' (an extension's provider wins on id).

```ts
const BUILTIN_REFERENCE_PROVIDERS: readonly ExtensionReferenceProvider[]
```

Source: [src/extensions/github-pulls.ts:352](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L352)

### `commitKind`

Constant.

Built-in `commit` kind. Detects commits from `git commit` runs and shows their change size.

```ts
const commitKind: ExtensionArtifactKindRegistration
```

Source: [src/extensions/builtin-artifact-kinds.ts:248](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L248)

### `COMPILE_CACHE_MAX_AGE_MS`

Constant.

How old an entry may grow without being rewritten before [`pruneExtensionCompileCache`](https://zidane.si/docs/reference/extensions.md#pruneExtensionCompileCache) drops it.

```ts
const COMPILE_CACHE_MAX_AGE_MS: number
```

Source: [src/extensions/compile-cache.ts:24](https://github.com/Tahul/zidane/blob/main/src/extensions/compile-cache.ts#L24)

### `COMPLETION_TIMEOUT_MS`

Constant.

How long a provider's `suggest`, or the submit hooks, may run before the answer is given up.

```ts
const COMPLETION_TIMEOUT_MS = 5_000
```

Source: [src/extensions/completion-providers.ts:142](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L142)

### `ContextSection`

Constant.

A context breakdown or context panel section.

```ts
const ContextSection: UiToken<ContextSectionItem, 'context-section'>
```

Source: [src/extensions/api/ui.ts:449](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L449)

### `Contract`

Constant.

Helpers to declare contract tokens.

```ts
const Contract: { define: <T>(id: string) => ContractToken<T> }
```

Source: [src/extensions/api/contracts.ts:64](https://github.com/Tahul/zidane/blob/main/src/extensions/api/contracts.ts#L64)

### `EMPTY_EXTENSION_REGISTRY`

Constant.

Empty registry — useful as a zero-value when no extensions are
loaded. Frozen (shallow + nested) so a consumer can't accidentally
mutate the shared sentinel and poison every other reader.

```ts
const EMPTY_EXTENSION_REGISTRY: ExtensionRegistry
```

Source: [src/extensions/types.ts:882](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L882)

### `EMPTY_MCP_PORT`

Constant.

An MCP port with no servers. Calls reject.

```ts
const EMPTY_MCP_PORT: McpCatalogPort
```

Source: [src/extensions/runtime/memory-ports.ts:259](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L259)

### `ENTRY_CANDIDATES`

Constant.

Entry-point filenames probed inside each `<name>/` directory, in
preference order. Bun loads `.ts` / `.tsx` natively; `.mjs` / `.js`
are accepted so pre-compiled extensions (or vibe-coded JS-only ones)
work too. `index.js` is last because most authors will reach for
`.ts` first.

```ts
const ENTRY_CANDIDATES: readonly ['index.ts', 'index.tsx', 'index.mjs', 'index.js']
```

Source: [src/extensions/discovery.ts:68](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L68)

### `EXTENSION_API_VERSION`

Constant.

The API version this runtime supports.

```ts
const EXTENSION_API_VERSION = 1
```

Source: [src/extensions/api/define.ts:10](https://github.com/Tahul/zidane/blob/main/src/extensions/api/define.ts#L10)

### `FACET_COMPUTE_TIMEOUT_MS`

Constant.

Bound of one facet's `compute`, in ms.

```ts
const FACET_COMPUTE_TIMEOUT_MS = 5_000
```

Source: [src/extensions/runtime/facets.ts:19](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L19)

### `fileKind`

Constant.

`file` has NO automatic detector for plain writes on purpose. Every
`write_file` becoming an artifact is noise — a refactor would produce
dozens of rows that are really just the diff and go stale on the next
rename. A file is an artifact only when something deliberately says so:
the model via `record_artifact` (a generated report, an export), an
extension via `ctx.artifacts.record` (a build output), or a tool whose
whole output is the file (`generate_image`, `generatedImageKind`).
The kind keeps its rendering and `file:` URI canonicalization for those
paths.

```ts
const fileKind: ExtensionArtifactKindRegistration
```

Source: [src/extensions/builtin-artifact-kinds.ts:525](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L525)

### `GITHUB_ISSUE_PROVIDER_ID`

Constant.

Id of the built-in reference provider for a bare `#123`: an issue or a pull request.

```ts
const GITHUB_ISSUE_PROVIDER_ID = 'github.issue'
```

Source: [src/extensions/github-pulls.ts:207](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L207)

### `GITHUB_PULL_COLORS`

Constant.

GitHub's state colors (Primer). Draft stays the theme's gray.

```ts
const GITHUB_PULL_COLORS: { readonly closed: '#f85149'; readonly merged: '#a371f7'; readonly open: '#3fb950' }
```

Source: [src/extensions/github-pulls.ts:72](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L72)

### `GITHUB_PULL_PROVIDER_ID`

Constant.

Id of the built-in reference provider for GitHub pull requests.

```ts
const GITHUB_PULL_PROVIDER_ID = 'github.pull'
```

Source: [src/extensions/github-pulls.ts:182](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L182)

### `githubIssueReferenceProvider`

Constant.

`#12` in a chat whose repo is on GitHub, keyed like a PR
(`githubRefKey(owner, repo, 12)`). No patterns: only the host knows the
repo. GitHub's issues endpoint says whether the number is an issue (drawn
here) or a PR (read and drawn as `github.pull` draws it).

```ts
const githubIssueReferenceProvider: ExtensionReferenceProvider
```

Source: [src/extensions/github-pulls.ts:215](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L215)

### `githubPullReferenceProvider`

Constant.

PR links (`https://github.com/o/r/pull/12`, with or without a tail)
paint as `#12` at once and gain their state when GitHub answers. `#12`
alone needs the chat's repo, which only the host knows: hosts resolve it
through this provider with the key `githubRefKey(owner, repo, 12)`.

```ts
const githubPullReferenceProvider: ExtensionReferenceProvider
```

Source: [src/extensions/github-pulls.ts:190](https://github.com/Tahul/zidane/blob/main/src/extensions/github-pulls.ts#L190)

### `githubTokenSource`

Constant.

Indirection so tests (and hosts with their own credential store) can swap
the token source without touching the environment or the `gh` binary.
`resolveWithSource` is consulted only while `resolve` is the default.

```ts
const githubTokenSource: { resolve: (host?: string) => Promise<string | null>; resolveWithSource: (host?: string) => Promise<{ source: string; token: string } | null> }
```

Source: [src/github/client.ts:262](https://github.com/Tahul/zidane/blob/main/src/github/client.ts#L262)

### `HOST_MODULE_SPECIFIERS`

Constant.

The zidane entrypoints an installed extension may import at runtime. A
host maps every one to its own live module before it imports an
extension (`registerCoreExtensionHostModules` in `discover-and-build.ts`
does it from [`hostModuleSpecifiers`](https://zidane.si/docs/reference/extensions.md#hostModuleSpecifiers)); unmapped, an installed copy
or a compiled binary resolves them from the extension's folder and finds
nothing.

```ts
const HOST_MODULE_SPECIFIERS: readonly ['zidane', 'zidane/extensions', 'zidane/extensions/testing', 'zidane/providers', 'zidane/providers/google', 'zidane/oauth']
```

Source: [src/extensions/host-modules.ts:59](https://github.com/Tahul/zidane/blob/main/src/extensions/host-modules.ts#L59)

### `LINK_SOURCES`

Constant.

Every [`LinkSource`](https://zidane.si/docs/reference/extensions.md#LinkSource).

```ts
const LINK_SOURCES: readonly LinkSource[]
```

Source: [src/extensions/ui/callbacks.ts:99](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/callbacks.ts#L99)

### `LinkHandler`

Constant.

Opens matching links.

```ts
const LinkHandler: UiToken<LinkHandlerItem, 'link-handler'>
```

Source: [src/extensions/api/ui.ts:447](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L447)

### `MAX_COMPLETION_ITEMS`

Constant.

Most items a provider's popup lists.

```ts
const MAX_COMPLETION_ITEMS = 8
```

Source: [src/extensions/completion-providers.ts:33](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L33)

### `MAX_COMPOSER_BADGES`

Constant.

How many `composer.badges` items one extension may show in one session, and `app.titlebar` items in the app.

```ts
const MAX_COMPOSER_BADGES = MAX_SLOT_BADGES
```

Source: [src/extensions/ui/registry.ts:36](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/registry.ts#L36)

### `MAX_FACET_BYTES`

Constant.

The most JSON one facet value may take, in bytes of its JSON text.

```ts
const MAX_FACET_BYTES: number
```

Source: [src/extensions/runtime/facets.ts:21](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L21)

### `MAX_FACETS_PER_EXTENSION`

Constant.

How many facets one extension may hold.

```ts
const MAX_FACETS_PER_EXTENSION = 32
```

Source: [src/extensions/runtime/facets.ts:23](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L23)

### `MAX_LINK_URL_LENGTH`

Constant.

Longest URL a link handler is offered.

```ts
const MAX_LINK_URL_LENGTH = 8192
```

Source: [src/extensions/ui/callbacks.ts:102](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/callbacks.ts#L102)

### `MAX_SIDEBAR_ROWS`

Constant.

How many sidebar rows one extension may show.

```ts
const MAX_SIDEBAR_ROWS = 500
```

Source: [src/extensions/ui/registry.ts:39](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/registry.ts#L39)

### `MAX_SLOT_BADGES`

Constant.

How many items one extension may show in a badge slot (`isBadgeSlot`); per session for `composer.badges`.

```ts
const MAX_SLOT_BADGES = 8
```

Source: [src/extensions/ui/wire.ts:519](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L519)

### `MEMORY_CLIENT_ID`

Constant.

The client id [`createScriptedDialogPort`](https://zidane.si/docs/reference/extensions.md#createScriptedDialogPort) and [`createRecordingUiClientPort`](https://zidane.si/docs/reference/extensions.md#createRecordingUiClientPort) report.

```ts
const MEMORY_CLIENT_ID = 'memory'
```

Source: [src/extensions/runtime/memory-ports.ts:155](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L155)

### `Menu`

Constant.

A native menu entry.

```ts
const Menu: UiToken<MenuItem, 'menu'>
```

Source: [src/extensions/api/ui.ts:439](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L439)

### `NO_CLIENT_DIALOG_PORT`

Constant.

A dialog port with no client: every dialog rejects with `NoUiError`, toasts resolve `undefined`.

```ts
const NO_CLIENT_DIALOG_PORT: DialogPort
```

Source: [src/extensions/runtime/memory-ports.ts:186](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L186)

### `NO_INTEGRATION_FLOWS`

Constant.

An integration flow port for hosts that cannot show a sign-in flow.

```ts
const NO_INTEGRATION_FLOWS: IntegrationFlowPort
```

Source: [src/extensions/runtime/memory-ports.ts:266](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L266)

### `NO_UI_CLIENT_PORT`

Constant.

A client port for hosts without clients. Never called: the router finds no client first.

```ts
const NO_UI_CLIENT_PORT: UiClientPort
```

Source: [src/extensions/runtime/memory-ports.ts:250](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L250)

### `Panel`

Constant.

Every UI token.

```ts
const Panel: UiToken<PanelItem, 'panel'>
```

Source: [src/extensions/api/ui.ts:427](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L427)

### `PANEL_CONTENT_LIMITS`

Constant.

Caps applied before content crosses IPC or reaches a renderer.

```ts
const PANEL_CONTENT_LIMITS: { readonly actions: 8; readonly barsPoints: 400; readonly barsSeries: 8; readonly bytes: number; readonly controlOptions: 50; readonly controls: 6; readonly heatmapDays: 400; readonly itemsPerSection: 200; readonly rowActions: 4; readonly sections: 32; readonly stats: 16; readonly textChars: 20000 }
```

Source: [src/extensions/panels.ts:680](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L680)

### `pullRequestKind`

Constant.

Built-in `pull_request` kind. Detects GitHub PRs and GitLab MRs from `gh pr create`, `glab mr create` and `*create_pull_request` / `*create_merge_request` tools. Refreshes GitHub PR state.

```ts
const pullRequestKind: ExtensionArtifactKindRegistration
```

Source: [src/extensions/builtin-artifact-kinds.ts:78](https://github.com/Tahul/zidane/blob/main/src/extensions/builtin-artifact-kinds.ts#L78)

### `Reference`

Constant.

Inline reference chips (ticket ids, URLs).

```ts
const Reference: UiToken<ExtensionReferenceProvider, 'reference'>
```

Source: [src/extensions/api/ui.ts:443](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L443)

### `Registry`

Constant.

Helpers to declare registry tokens.

```ts
const Registry: { define: <T>(id: string) => RegistryToken<T> }
```

Source: [src/extensions/api/contracts.ts:66](https://github.com/Tahul/zidane/blob/main/src/extensions/api/contracts.ts#L66)

### `Renderer`

Constant.

A renderer for blocks, code languages, tools or artifacts.

```ts
const Renderer: UiToken<RendererItem, 'renderer'>
```

Source: [src/extensions/api/ui.ts:433](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L433)

### `Rpc`

Constant.

Helpers to declare RPC contracts.

```ts
const Rpc: { define: <M extends Readonly<Record<string, RpcMethodSpec>>, E extends Readonly<Record<string, RpcEventSpec>> = Record<never, never>>(spec: { events?: E; id: string; methods: M }) => RpcContract<M, E> }
```

Source: [src/extensions/api/rpc.ts:140](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L140)

### `Screen`

Constant.

A full-screen view or modal.

```ts
const Screen: UiToken<ScreenItem, 'screen'>
```

Source: [src/extensions/api/ui.ts:431](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L431)

### `SESSION_FACET_TRIGGERS`

Constant.

Every trigger, in a fixed order: what a facet without `on` runs on.

```ts
const SESSION_FACET_TRIGGERS: readonly SessionFacetTrigger[]
```

Source: [src/extensions/runtime/facets.ts:25](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L25)

### `SettingsPage`

Constant.

A Settings page.

```ts
const SettingsPage: UiToken<SettingsPageItem, 'settings-page'>
```

Source: [src/extensions/api/ui.ts:435](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L435)

### `SidebarDecoration`

Constant.

Extra data on the sidebar rows of matching sessions.

```ts
const SidebarDecoration: UiToken<SidebarDecorationItem, 'sidebar-decoration'>
```

Source: [src/extensions/api/ui.ts:459](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L459)

### `SidebarFilter`

Constant.

A filter the user turns on in the sidebar.

```ts
const SidebarFilter: UiToken<SidebarFilterItem, 'sidebar-filter'>
```

Source: [src/extensions/api/ui.ts:453](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L453)

### `SidebarGroup`

Constant.

A grouping the user can pick in the sidebar.

```ts
const SidebarGroup: UiToken<SidebarGroupItem, 'sidebar-group'>
```

Source: [src/extensions/api/ui.ts:457](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L457)

### `SidebarRow`

Constant.

A row an extension adds to a space, beside its sessions.

```ts
const SidebarRow: UiToken<SidebarRowItem, 'sidebar-row'>
```

Source: [src/extensions/api/ui.ts:461](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L461)

### `SidebarSort`

Constant.

A sort order the user can pick in the sidebar.

```ts
const SidebarSort: UiToken<SidebarSortItem, 'sidebar-sort'>
```

Source: [src/extensions/api/ui.ts:455](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L455)

### `Slot`

Constant.

A small item in a named slot.

```ts
const Slot: UiToken<SlotItem, 'slot'>
```

Source: [src/extensions/api/ui.ts:429](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L429)

### `Space`

Constant.

A space: a named, query-defined view of sessions in the sidebar.

```ts
const Space: UiToken<SpaceItem, 'space'>
```

Source: [src/extensions/api/ui.ts:451](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L451)

### `ThemeToken`

Constant.

A color theme.

```ts
const ThemeToken: UiToken<Theme, 'theme'>
```

Source: [src/extensions/api/ui.ts:441](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L441)

### `UI_HOST_MODULES`

Constant.

Bare specifiers kept external in a bundled `ui` entry: the renderer's
shared modules. `zidane` and `zidane/extensions` are usually imported
for types only (erased); a value import of them stays external and the
renderer must map it.

```ts
const UI_HOST_MODULES: readonly string[]
```

Source: [src/extensions/bundle/policy.ts:22](https://github.com/Tahul/zidane/blob/main/src/extensions/bundle/policy.ts#L22)

### `UI_TOKEN_NAMES`

Constant.

The token names, in a fixed order.

```ts
const UI_TOKEN_NAMES: readonly UiTokenName[]
```

Source: [src/extensions/ui/wire.ts:387](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L387)

### `Webview`

Constant.

A webview panel or screen.

```ts
const Webview: UiToken<WebviewItem, 'webview'>
```

Source: [src/extensions/api/ui.ts:437](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L437)

## Interfaces

### `ActionSetting`

Interface.

A button that runs code. `status` draws a live state next to it.

```ts
interface ActionSetting extends SettingBase
```

**Properties**

- `apply?` (`SettingApply`, from `SettingBase`): Default `'live'`.
- `button` (`string`): Button label.
- `description?` (`string`, from `SettingBase`): Help text under the label.
- `label` (`string`, from `SettingBase`): Label in Settings.
- `page?` (`string`, from `SettingBase`): Page id (see `SettingsSchema.pages`). When omitted: its section's page, else the first page. A page other than its section's is refused.
- `run` (`(ctx: ActionSettingContext) => void | ActionSettingResult | Promise<void | ActionSettingResult>`): Runs when the user clicks the button. May return a result to show.
- `scope?` (`AccessScope`): The least token scope a remote client needs to run it. Default `'admin'`. Apps disable the button below it.
- `scopes?` (`readonly SettingScope[]`, from `SettingBase`): Scopes the user may set it at. Default `['user', 'project']`.
- `section?` (`string`, from `SettingBase`): Section id (see `SettingsSchema.sections`). Ungrouped when omitted.
- `status?` (`(ctx: ActionSettingStatusContext) => ActionSettingStatus | Promise<ActionSettingStatus>`): Reads the live state drawn next to the button.
- `type` (`'action'`): Marks an action.

Source: [src/extensions/api/settings.ts:109](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L109)

### `ActionSettingContext`

Interface.

What an action's `run` receives.

```ts
interface ActionSettingContext extends ActionSettingStatusContext
```

**Properties**

- `get` (`(key: string) => ActionSettingValue | undefined`, from `ActionSettingStatusContext`): The effective value of a setting of this extension (as `ctx.settings.get`), `undefined` for an unknown or action key.
- `set` (`(key: string, value: ActionSettingValue | undefined) => Promise<void>`): Writes a setting of this extension, as an edit in Settings would: the
  value is checked, then stored at the first of the setting's scopes among
  `user` and `project` (a secret goes to the auth store). `undefined`
  clears it. Rejects with the reason for an unknown, action or locked key,
  a setting without a user or project scope, or a refused value.
- `signal` (`AbortSignal`): Aborts when the run is cancelled or the extension unloads.

Source: [src/extensions/api/settings.ts:95](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L95)

### `ActionSettingResult`

Interface.

What an action may return.

```ts
interface ActionSettingResult
```

**Properties**

- `message?` (`string`): Line shown after the run.
- `patch?` (`Readonly<Record<string, ActionSettingValue>>`): Values to write into other settings of this extension.
- `tone?` (`'error' | 'info' | 'success' | 'warn'`): Tone of `message`.

Source: [src/extensions/api/settings.ts:123](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L123)

### `ActionSettingStatus`

Interface.

A live state drawn next to an action.

```ts
interface ActionSettingStatus
```

**Properties**

- `text` (`string`): The state to show.
- `tone?` (`'error' | 'success' | 'warn' | 'muted'`): Tone of `text`.

Source: [src/extensions/api/settings.ts:133](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L133)

### `ActionSettingStatusContext`

Interface.

What an action's `status` receives: the extension's own settings, read-only.

```ts
interface ActionSettingStatusContext
```

**Properties**

- `get` (`(key: string) => ActionSettingValue | undefined`): The effective value of a setting of this extension (as `ctx.settings.get`), `undefined` for an unknown or action key.

Source: [src/extensions/api/settings.ts:89](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L89)

### `AgentEditor`

Interface.

Editor of agent profiles and sub-agents.

```ts
interface AgentEditor extends CatalogEditor<AgentProfile>
```

**Properties**

- `add` (`(item: AgentProfile) => void`, from `CatalogEditor`): Adds an item, or replaces the one with the same id.
- `default` (`{ get: () => string | undefined; set: (id: string) => void }`): The default profile id.
- `get` (`(id: string) => AgentProfile | undefined`, from `CatalogEditor`): The item with this id, or `undefined`.
- `list` (`() => readonly AgentProfile[]`, from `CatalogEditor`): The items as edited so far.
- `origin` (`(id: string) => ItemOrigin | undefined`, from `CatalogEditor`): Who put the item in the catalog.
- `remove` (`(id: string) => void`, from `CatalogEditor`): Removes the item with this id.
- `subagents` (`CatalogEditor<ExtensionSubagentDef> & { override: (name: string, override: SubagentOverride) => void }`): Editor of sub-agents. `override` replaces or deletes the sub-agent called `name`.
- `update` (`(id: string, edit: (item: AgentProfile) => void) => void`, from `CatalogEditor`): Edits a copy of the item.

Source: [src/extensions/api/catalogs.ts:92](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L92)

### `AgentsDomain`

Interface.

`ctx.agents`.

```ts
interface AgentsDomain extends CatalogDomain<AgentProfile, AgentEditor>
```

**Properties**

- `list` (`() => readonly AgentProfile[]`, from `CatalogDomain`): The catalog after every transform.
- `register` (`(profile: AgentProfile) => Disposable`): Adds an agent profile.
- `reload` (`() => Promise<void>`, from `CatalogDomain`): Replays every transform of this catalog.
- `subagents` (`{ register: (def: ExtensionSubagentDef) => Disposable }`): Sub-agents the model can spawn.
- `transform` (`(fn: Transform<AgentEditor>) => Disposable`, from `CatalogDomain`): Adds a transform that replays on every change. Dispose it to remove the transform.

Source: [src/extensions/api/catalogs.ts:100](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L100)

### `AppInfo`

Interface.

What `ctx.app` tells about the running app.

```ts
interface AppInfo
```

**Properties**

- `host` (`ExtensionHostKind`, readonly): The host process running the extension.
- `name` (`'zidane'`, readonly): Always `'zidane'`.
- `platform` (`string`, readonly): `process.platform`.
- `version` (`string`, readonly): zidane version, semver.

Source: [src/extensions/api/core.ts:111](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L111)

### `ApplyConfigReportOptions`

Interface.

Options of [`applyExtensionsConfigReport`](https://zidane.si/docs/reference/extensions.md#applyExtensionsConfigReport).

```ts
interface ApplyConfigReportOptions
```

**Properties**

- `allowed?` (`(id: string) => boolean`, readonly): Whether the host lets `id` run (its allowlist). Default: every id.
- `classify?` (`(dir: string) => NewExtensionFolder | undefined`, readonly): How a new folder under a scan root loads (the host's watcher rule). Linked folders load without it.
- `compileCache?` (`string`, readonly): Node hosts: the folder compiled extension code is kept in.
- `importTimeoutMs?` (`number`, readonly): How long one extension import may take. Default 10 s.
- `sink?` (`LogSink`, readonly): Where load warnings go.

Source: [src/extensions/declarative/host-sync.ts:484](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L484)

### `ArtifactDetectHookOptions`

Interface.

Options for [`createArtifactDetectHook`](https://zidane.si/docs/reference/extensions.md#createArtifactDetectHook).

```ts
interface ArtifactDetectHookOptions
```

**Properties**

- `warn?` (`(message: string, fields: Record<string, unknown>) => void`): Where isolation failures go (a throwing detector, a rejected meta).

Source: [src/extensions/artifact-detect.ts:15](https://github.com/Tahul/zidane/blob/main/src/extensions/artifact-detect.ts#L15)

### `ArtifactResolveOptions`

Interface.

Passed to a kind's `resolve`.

```ts
interface ArtifactResolveOptions
```

**Properties**

- `force?` (`boolean`): The user explicitly asked for fresh data (opened the artifacts panel):
  ignore any freshness cache and re-check states that usually stop
  refreshing (a closed PR can be reopened). Hover-driven refreshes leave
  this unset and stay cache-gated.

Source: [src/extensions/types.ts:526](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L526)

### `ArtifactsDomain`

Interface.

`ctx.artifacts`.

```ts
interface ArtifactsDomain
```

**Properties**

- `find` (`(kind: string, uri: string) => Promise<SessionArtifact | undefined>`): The most recently updated artifact with this kind and URI, or `undefined`.
- `kinds` (`{ register: (kind: ExtensionArtifactKindRegistration) => Disposable }`): Artifact kinds. `register` adds a kind: its label, detection and rendering.
- `list` (`(query?: ExtensionArtifactQuery) => Promise<readonly SessionArtifact[]>`): Lists artifacts in the scope of `query`. Default: the active session.
- `record` (`(input: SessionArtifactInput) => Promise<SessionArtifact | undefined>`): Records an artifact on the active session. Resolves the stored artifact, or `undefined` when it is refused.

Source: [src/extensions/api/sessions.ts:291](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L291)

### `BadgeActionEffect`

Interface.

What running an action asks the host to do. Every field is optional; several may combine.

```ts
interface BadgeActionEffect
```

**Properties**

- `copy?` (`string`): Put this text on the clipboard.
- `insert?` (`string`): Insert this text into the composer at the caret (and focus it).
- `notice?` (`string`): A one-line confirmation or error the host shows briefly.
- `open?` (`string`): Open this URL (browser) or absolute path (editor / file manager).
- `reveal?` (`string`): Show this absolute path in the OS file manager (a file selected in its folder, a folder opened).

Source: [src/extensions/badge-actions.ts:51](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L51)

### `BadgeActionsMatch`

Interface.

Which badges a registration acts on. Omitted axes match everything; given axes must all match.

```ts
interface BadgeActionsMatch
```

**Properties**

- `artifactKinds?` (`readonly string[]`): Artifact kinds (`target.artifact.kind`).
- `kinds?` (`readonly BadgeTargetKind[]`): Badge target kinds (`target.kind`).
- `references?` (`readonly string[]`): Reference provider ids (`target.reference.providerId`, as registered: `linear.issue`).

Source: [src/extensions/badge-actions.ts:65](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L65)

### `BadgeActionSpec`

Interface.

One menu item. `group` places it: copy, prompt, open, then the extension's own.

```ts
interface BadgeActionSpec
```

**Properties**

- `group?` (`'open' | 'prompt' | 'copy' | 'more'`): Menu group the item belongs to.
- `id` (`string`): Action id passed back to `run`.
- `label` (`string`): Menu text.
- `shortcut?` (`string`): Single-key accelerator shown in the menu.

Source: [src/extensions/badge-actions.ts:39](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L39)

### `BadgeActionWire`

Interface.

Badge actions on the wire: which badges they apply to. The menu itself is asked for per target.

```ts
interface BadgeActionWire
```

**Properties**

- `id` (`string`): The registration's id.
- `match?` (`BadgeActionsMatch`): Badges the actions apply to. Absent: every badge.

Source: [src/extensions/ui/wire.ts:197](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L197)

### `BadgeMenuItem`

Interface.

A host's resolved menu item: a built-in, or an extension's (`source` names the registration).

```ts
interface BadgeMenuItem extends BadgeAction
```

**Properties**

- `group?` (`'open' | 'prompt' | 'copy' | 'more'`, from `BadgeAction`): Menu group the item belongs to.
- `id` (`string`, from `BadgeAction`): Action id passed back to `run`.
- `label` (`string`, from `BadgeAction`): Menu text.
- `shortcut?` (`string`, from `BadgeAction`): Single-key accelerator shown in the menu.
- `source` (`string`): `builtin`, or the id of the extension registration that provided the item.

Source: [src/extensions/badge-actions.ts:88](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L88)

### `BadgeTarget`

Interface.

What a badge stands for. Every badge surface builds one so the same menu logic applies everywhere.

```ts
interface BadgeTarget
```

**Properties**

- `artifact?` (`{ kind: string; uri: string }`): The artifact behind the badge (session badges, card rows, artifact rows).
- `href?` (`string`): A URL, or an absolute path for files.
- `kind` (`BadgeTargetKind`): What kind of thing the badge stands for.
- `prompt?` (`string`): What "Add to prompt" inserts. Default: `href` for a `link`, `@<path>` for a `file`, else `text`.
- `reference?` (`{ key: string; providerId: string }`): The reference behind the badge (`ctx.registerReferences`).
- `sessionId?` (`string`): The chat the badge is in.
- `text` (`string`): What the badge shows (`e32789e`, `BOA-123`, `sessions.db`).

Source: [src/extensions/badge-actions.ts:21](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L21)

### `BooleanSetting`

Interface.

An on/off setting.

```ts
interface BooleanSetting extends SettingBase
```

**Properties**

- `apply?` (`SettingApply`, from `SettingBase`): Default `'live'`.
- `default?` (`boolean`): Used when no scope or config sets a value.
- `description?` (`string`, from `SettingBase`): Help text under the label.
- `label` (`string`, from `SettingBase`): Label in Settings.
- `page?` (`string`, from `SettingBase`): Page id (see `SettingsSchema.pages`). When omitted: its section's page, else the first page. A page other than its section's is refused.
- `scopes?` (`readonly SettingScope[]`, from `SettingBase`): Scopes the user may set it at. Default `['user', 'project']`.
- `section?` (`string`, from `SettingBase`): Section id (see `SettingsSchema.sections`). Ungrouped when omitted.
- `type` (`'boolean'`): Marks a boolean setting.

Source: [src/extensions/api/settings.ts:31](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L31)

### `BuildExtensionRegistryOptions`

Interface.

Options for [`buildExtensionRegistry`](https://zidane.si/docs/reference/extensions.md#buildExtensionRegistry).

```ts
interface BuildExtensionRegistryOptions
```

**Properties**

- `cwd?` (`string`): Runtime cwd used for `ctx.paths`.
- `disabled?` (`ReadonlySet<string>`): Names the user has explicitly disabled. Loaded but not run (their
  settings stay readable); listed in `inactive` so the Settings panel
  can show them.
- `hostRuntime?` (`ExtensionHostRuntimeBridge`): Host runtime bridge backing `ctx.sessions`, `ctx.workspace` and
  `ctx.artifacts` when `runtime.ports.host` is not given. Late-bound: the
  host attaches its implementation post-mount.
- `prefix?` (`string`): Storage prefix used to resolve the storage directories. Default: `ZIDANE_PREFIX`, else `.zidane`.
- `projectRoot?` (`string`): Project root exposed as `ctx.paths.projectRoot`.
- `promptBridge?` (`ExtensionPromptBridge`): Prompt bridge backing `ctx.sessions.submit` without a session id.
  Hosts with a submit pipeline attach their handler post-mount.
- `readSettings?` (`() => Partial<Settings> | undefined`): Live settings getter: the `user` settings layer (`Settings.extensionConfig`)
  when `runtime.ports.settings` is not given.
- `runtime?` (`BuildRuntimeOptions`): Host kind, ports and guard options of the runtime.
- `setupTimeoutMs?` (`number`): Maximum time one extension's setup may take before it is marked inactive. Default: the runtime's.
- `sink?` (`LogSink`): Override the log sink. Defaults to a `consoleSink` writing to
  stderr (which the TUI suppresses to keep the renderer clean —
  only `ZIDANE_DEBUG=1` surfaces the lines).
- `storageDirs?` (`{ cacheDir: string; configDir?: string; dataDir: string; stateDir?: string }`): Storage directories exposed through `ctx.paths`. Default: resolved from `prefix` and the platform conventions.

Source: [src/extensions/register.ts:29](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L29)

### `BuildRuntimeOptions`

Interface.

How [`buildExtensionRegistry`](https://zidane.si/docs/reference/extensions.md#buildExtensionRegistry) builds the runtime.

```ts
interface BuildRuntimeOptions
```

**Properties**

- `host?` (`ExtensionHostKind`): The host process. Default `'sdk'`.
- `ports?` (`RuntimePorts`): Host ports. Defaults: settings read from `readSettings` (the
  `extensionConfig` bag), storage in files under
  `<dataDir>/extension-storage` (project and session scope in its `_projects` folder),
  the rest in memory.
- `runtime?` (`Pick<ExtensionRuntimeOptions, 'platform' | 'onChange' | 'budget' | 'callbackTimeoutMs' | 'onStall' | 'memory'>`): Guard and status options passed through to the runtime.

Source: [src/extensions/register.ts:78](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L78)

### `CatalogDomain`

Interface.

Shared members of every catalog domain.

```ts
interface CatalogDomain<T, E>
```

**Type parameters**

- `T`
- `E`

**Properties**

- `list` (`() => readonly T[]`): The catalog after every transform.
- `reload` (`() => Promise<void>`): Replays every transform of this catalog.
- `transform` (`(fn: Transform<E>) => Disposable`): Adds a transform that replays on every change. Dispose it to remove the transform.

Source: [src/extensions/api/catalogs.ts:50](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L50)

### `CatalogEditor`

Interface.

A generic editor over a catalog keyed by id.

```ts
interface CatalogEditor<T>
```

**Type parameters**

- `T`

**Properties**

- `add` (`(item: T) => void`): Adds an item, or replaces the one with the same id.
- `get` (`(id: string) => T | undefined`): The item with this id, or `undefined`.
- `list` (`() => readonly T[]`): The items as edited so far.
- `origin` (`(id: string) => ItemOrigin | undefined`): Who put the item in the catalog.
- `remove` (`(id: string) => void`): Removes the item with this id.
- `update` (`(id: string, edit: (item: T) => void) => void`): Edits a copy of the item.

Source: [src/extensions/api/catalogs.ts:31](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L31)

### `CommandListing`

Interface.

A command as `CommandsDomain.list` reports it.

```ts
interface CommandListing
```

**Properties**

- `bind?` (`readonly string[]`): Effective chords.
- `id` (`string`): Published id.
- `slash?` (`string`): Slash name, without the `/`.
- `title` (`string`): Current title.

Source: [src/extensions/commands/registry.ts:65](https://github.com/Tahul/zidane/blob/main/src/extensions/commands/registry.ts#L65)

### `CommandsDomain`

Interface.

`ctx.commands`.

```ts
interface CommandsDomain
```

**Properties**

- `list` (`() => readonly { bind?: readonly string[]; id: string; slash?: string; title: string }[]`): Every command the host offers, built-in ones included.
- `provider` (`(spec: PaletteProviderSpec) => Disposable`): Registers a dynamic palette provider.
- `register` (`(spec: CommandSpec) => Disposable`): Registers a command.
- `run` (`(id: string, opts?: { args?: string; sessionId?: string }) => Promise<boolean>`): Runs any command by its published id (`<extension>.<id>` or a built-in).

Source: [src/extensions/api/commands.ts:88](https://github.com/Tahul/zidane/blob/main/src/extensions/api/commands.ts#L88)

### `CommandSpec`

Interface.

A command.

```ts
interface CommandSpec
```

**Properties**

- `bind?` (`string | readonly string[]`): Default keybinding(s), for example `'mod+shift+t'`. Users can rebind. Esc and ctrl+c are refused.
- `description?` (`Bindable<string>`): One line of help shown under the title.
- `editable?` (`boolean`): The binding also fires while a text field has focus.
- `enabled?` (`Bindable<boolean>`): `false` hides it from the palette and turns its keybinding off.
- `group?` (`string`): Palette category.
- `hint?` (`boolean`): Shows the binding in the footer and statusbar hints.
- `icon?` (`{ gui?: string; tui?: string }`): Icon of the palette entry: an icon name for the desktop app (`gui`) and a short glyph for the terminal (`tui`).
- `id` (`string`): Unique within the extension. Published as `<extension id>.<id>`.
- `keywords?` (`string`): Extra words the palette matches.
- `mode?` (`string`): The binding only fires while this keymap mode is active.
- `palette?` (`boolean | { featured?: boolean; suggested?: boolean }`): `false` keeps it out of the palette. `featured` lists it when the palette opens; `suggested` lists it under Suggested.
- `run?` (`(invocation: CommandInvocation) => false | void | Promise<false | void>`): Runs the command. From a keybinding, returning `false` passes the key on.
- `scope?` (`KeyScope`): Where focus must be for the binding to fire. Default `'global'`.
- `slash?` (`{ aliases?: readonly string[]; argumentHint?: string; complete?: (prefix: string) => readonly CommandArgSuggestion[] | Promise<readonly CommandArgSuggestion[]>; name: string }`): Also a `/` command.
- `steps?` (`readonly CommandStep[]`): Multi-step pipeline (slash only); the same steps as chat commands (`ChatCommand['steps']`). Use instead of `run`.
- `title` (`Bindable<string>`): Name shown in the palette.
- `when?` (`'session' | 'idle' | 'always'`): When the command is offered: always, only with a session, only while no run is going. Default `'always'`.

Source: [src/extensions/api/commands.ts:29](https://github.com/Tahul/zidane/blob/main/src/extensions/api/commands.ts#L29)

### `CompletionRunner`

Interface.

Runs completion work for a composer: each bounded in time, a newer suggest for the same key aborting the older one.

```ts
interface CompletionRunner
```

**Properties**

- `submit` (`(providers: readonly CompletionProvider<unknown>[], text: string, cursor: number) => Promise<void>`): The submit hooks ([`resolveExtensionCompletionSubmit`](https://zidane.si/docs/reference/extensions.md#resolveExtensionCompletionSubmit)); resolves once they ran or the time is up.
- `suggest` (`(key: string, provider: CompletionProvider, query: string, context: { cursor: number; text: string }) => Promise<ExtensionCompletionItemSummary[]>`): The items of `provider` for `query`; `[]` once a newer suggest for `key` started or the time is up.

Source: [src/extensions/completion-providers.ts:145](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L145)

### `ComponentRef`

Interface.

A reference to a component the extension exports from its `ui` entry
(desktop and web) or its `tui` entry (terminal). A host without the
named component draws the item's data, or its `fallback`.

```ts
interface ComponentRef
```

**Properties**

- `component` (`string`): Name of the export in the extension's `ui` / `tui` entry.
- `props?` (`Readonly<Record<string, unknown>>`): JSON props passed to the component.

Source: [src/extensions/api/core.ts:90](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L90)

### `ComponentWire`

Interface.

A component reference on the wire: the export name and JSON props.

```ts
interface ComponentWire
```

**Properties**

- `component` (`string`): Export name in the extension's `ui` / `tui` entry.
- `props?` (`Readonly<Record<string, unknown>>`): JSON props handed to the component.

Source: [src/extensions/ui/wire.ts:59](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L59)

### `ComposerDomain`

Interface.

`ctx.composer`.

```ts
interface ComposerDomain
```

**Properties**

- `attach` (`(files: readonly { path: string }[] | readonly { data: Uint8Array; mimeType: string; name: string }[], opts?: { sessionId?: string }) => Promise<boolean>`): Attaches files, by path or as bytes with a name and MIME type. Resolves whether a client did it.
- `autocomplete` (`{ register: (provider: InlineAutocompleteProvider) => Disposable }`): Registers a source of inline ghost-text suggestions.
- `completions` (`{ register: (provider: CompletionProvider) => Disposable }`): Registers a source of composer completions.
- `insert` (`(text: string, opts?: { sessionId?: string }) => Promise<boolean>`): Inserts text into the composer. Resolves whether a client did it.
- `setText` (`(text: string, opts?: { sessionId?: string }) => Promise<boolean>`): Replaces the composer text. Resolves whether a client did it.

Source: [src/extensions/api/ui.ts:548](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L548)

### `ConfigSyncItem`

Interface.

One entry's outcome, as hosts log and show it.

```ts
interface ConfigSyncItem
```

**Properties**

- `error?` (`string`, readonly): For `failed`: why.
- `id?` (`string`, readonly): The extension id, when known.
- `source` (`string`, readonly): The config `source` (or the lock's, for a dropped entry).
- `status` (`ConfigSyncStatus`, readonly): What the reconcile did with the entry.
- `warnings` (`readonly string[]`, readonly): Non-fatal notices (host-version warnings, a moved GitHub pin).

Source: [src/extensions/declarative/host-sync.ts:89](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L89)

### `ConfiguredExtensions`

Interface.

What config entries change in a registry build: linked folders and disabled ids.

```ts
interface ConfiguredExtensions
```

**Properties**

- `disabled` (`readonly string[]`, readonly): Ids of entries with `enabled: false` (the lock's id, or a local folder's name).
- `links` (`readonly LinkedExtensionDir[]`, readonly): Folders local entries link in place, once a reconcile recorded them in the lock.

Source: [src/extensions/declarative/host-sync.ts:46](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L46)

### `Connection`

Interface.

A stored connection. An integration holds several, one per account; one is the default.

```ts
interface Connection
```

**Properties**

- `account` (`string`): Stable id of the account (`'default'` when the integration names none).
- `connectedAt` (`number`): When the connection was made, in ms since the epoch.
- `integrationId` (`string`): Id of the integration.
- `isDefault?` (`boolean`): This is the integration's default connection.
- `label?` (`string`): Label shown in Settings. Default: `account`.
- `methodId` (`string`): Id of the method that made the connection.

Source: [src/extensions/api/sessions.ts:415](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L415)

### `ContextServices`

Interface.

The shared registries and host ports every extension's context draws on. One set per runtime.

```ts
interface ContextServices
```

**Properties**

- `app` (`AppInfo`, readonly): Host and version data behind `ctx.app`.
- `catalogs` (`{ readonly agents: AgentsCatalog; readonly mcp: McpCatalog; readonly models: ModelsCatalog; readonly providers: ProvidersCatalog; readonly skills: SkillsCatalog; readonly tools: ToolsCatalog }`, readonly): The catalogs behind `ctx.tools`, `ctx.agents`, `ctx.models`, `ctx.providers`, `ctx.mcp` and `ctx.skills`.
- `commands` (`CommandRegistry`, readonly): The registry behind `ctx.commands` and `ctx.keymap`.
- `contracts` (`ContractRegistry`, readonly): The registry behind `ctx.contracts`.
- `desktop?` (`DesktopPort`, readonly): The desktop app's handle behind `ctx.desktop`. Absent on other hosts.
- `dialogs` (`DialogRouter`, readonly): Routes `ctx.ui` dialogs to a client.
- `extensions` (`{ get: (id: string) => ExtensionInfo | undefined; list: () => readonly ExtensionInfo[] }`, readonly): `ctx.extensions`.
- `facets` (`FacetsRuntime`, readonly): The facet registry behind `ctx.sessions.facets`.
- `host` (`HostRuntimePorts`, readonly): Session, generate, workspace, artifacts and plugins ports. A missing port makes that domain reject.
- `instructions` (`InstructionsRuntime`, readonly): System prompt text behind `ctx.instructions`.
- `integrationFlows` (`IntegrationFlowPort`, readonly): How integration sign-in flows show their UI.
- `integrations` (`IntegrationRegistry`, readonly): The registry behind `ctx.integrations`.
- `interceptors` (`InterceptorRegistry`, readonly): Interceptors extensions add with `ctx.hooks`.
- `platform?` (`string`, readonly): Platform for keymap `mod` resolution. Default `process.platform`.
- `rpc` (`RpcRouter`, readonly): The router behind `ctx.rpc`.
- `ui` (`UiRegistry`, readonly): The registry behind `ctx.add`.
- `uiClient` (`UiClientPort`, readonly): Panels, navigation and composer calls on a client.

Source: [src/extensions/runtime/context.ts:66](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/context.ts#L66)

### `ContractsDomain`

Interface.

`ctx.contracts`.

```ts
interface ContractsDomain
```

**Properties**

- `add` (`<T>(registry: RegistryToken<T>, item: T) => Disposable`): Adds an item to a registry another extension (or this one) owns.
- `list` (`<T>(registry: RegistryToken<T>) => Readable<readonly T[]>`): Every item added to a registry this extension owns, in load order.
- `provide` (`<T>(token: ContractToken<T>, impl: T) => Disposable`): Provides `token`. Its id must be the extension id or start with `<id>.`.
- `use` (`<T>(token: ContractToken<T>) => LiveAccessor<T>`): Follows a contract another extension provides. The same accessor for every call with the token.

Source: [src/extensions/api/contracts.ts:32](https://github.com/Tahul/zidane/blob/main/src/extensions/api/contracts.ts#L32)

### `ContractToken`

Interface.

Token of an API an extension provides.

```ts
interface ContractToken<T>
```

**Type parameters**

- `T`

**Properties**

- `__type?` (`T`, readonly): Type-level only.
- `id` (`string`, readonly): `<extension id>.<name>`.
- `kind` (`'contract'`, readonly): Always `'contract'`.

Source: [src/extensions/api/contracts.ts:12](https://github.com/Tahul/zidane/blob/main/src/extensions/api/contracts.ts#L12)

### `DesktopDomain`

Interface.

`ctx.desktop`: present only in the desktop app's main process.

```ts
interface DesktopDomain
```

**Properties**

- `electron` (`<T = unknown>() => T`): The `electron` module. Type it yourself: `ctx.desktop.electron<typeof import('electron')>()`.
- `windows` (`{ list: () => readonly { focused: boolean; id: number }[]; on: (event: 'open' | 'close' | 'focus', listener: (window: { id: number }) => void) => Disposable }`): The open windows and their events.

Source: [src/extensions/api/ui.ts:562](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L562)

### `DesktopPort`

Interface.

The desktop app's main-process handle behind `ctx.desktop`. Only the
desktop host gives one; elsewhere `ctx.desktop` is undefined.

```ts
interface DesktopPort
```

**Properties**

- `electron` (`() => unknown`): The `electron` module.
- `windows` (`{ list: () => readonly { focused: boolean; id: number }[]; on: (event: 'open' | 'close' | 'focus', listener: (window: { id: number }) => void) => () => void }`): Window list and window events. `on` returns the unsubscribe.

Source: [src/extensions/runtime/context.ts:52](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/context.ts#L52)

### `DialogOptions`

Interface.

Options every dialog takes.

```ts
interface DialogOptions
```

**Properties**

- `sessionId?` (`string`): Routes to the client viewing this session. Without it: the last active client.
- `signal?` (`AbortSignal`): Cancels the dialog when it aborts.
- `timeoutMs?` (`number`): Rejects with a timeout after this many ms.

Source: [src/extensions/api/ui.ts:485](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L485)

### `DiscoverAndBuildExtensionRegistryOptions`

Interface.

Options for [`discoverAndBuildExtensionRegistry`](https://zidane.si/docs/reference/extensions.md#discoverAndBuildExtensionRegistry).

```ts
interface DiscoverAndBuildExtensionRegistryOptions
```

**Properties**

- `compileCache?` (`string`): Node hosts: the folder compiled extension code is kept in, so only a changed file compiles again (`./compile-cache`).
- `configDisabled?` (`readonly string[]`): Ids a config entry keeps installed but off (`enabled: false`): they load disabled, like ones the allowlist leaves out.
- `cwd?` (`string`): Discovery cwd — project roots are walked up from here. Defaults to `process.cwd()`.
- `enabledAllowlist?` (`readonly string[]`): User enable allowlist (`Settings.enabledExtensions`). `undefined`
  means "fresh install — everything enabled". When set it gates BOTH
  disk and inline candidates: a name absent from the list lands in the
  build's `disabled` set, so it classifies as `inactive` and its
  contributions never reach the registry's active surface. Its
  `setup()` does not run; its settings stay browsable in Settings
  before enabling.
- `extensionScanPaths?` (`readonly string[]`): Extra extension scan roots, prepended ahead of the default project/user
  roots. Each root contains extension package dirs (`<root>/<name>/index.ts`).
  Treated as user-scoped/trusted because the host/user opted into them
  explicitly.
- `home?` (`string`): User home directory. Defaults to `os.homedir()`. Mainly a test seam.
- `hostRuntime?` (`ExtensionHostRuntimeBridge`): Host runtime bridge for `ctx.sessions` / `ctx.workspace` / `ctx.artifacts`.
- `inlineExtensions?` (`readonly LoadedExtension[]`): Host-supplied inline extensions, already `inlineLoadedExtension()`-wrapped.
- `linkedExtensionDirs?` (`readonly LinkedExtensionDir[]`): Extension folders a config entry links in place (`configuredExtensions`,
  `./declarative/host-sync`). Each is one extension, ahead of every scan root.
- `prefix?` (`string`): Storage prefix (e.g. `.zidane`). Defaults to `.zidane` inside discovery.
- `promptBridge?` (`ExtensionPromptBridge`): Prompt bridge for `ctx.sessions.submit` (hosts with a submit pipeline).
- `readSettings?` (`() => Partial<Settings> | undefined`): Live settings getter: the `user` settings layer, threaded verbatim to
  `BuildExtensionRegistryOptions.readSettings`. Hosts pass a getter
  returning their current `Settings` (TUI: a live mirror; GUI: the DB
  reader) so extension settings reads are live.
- `runtime?` (`BuildRuntimeOptions`): Host kind and ports of the runtime (`registry.runtime`).
- `signal?` (`AbortSignal`): Abort discovery before its imports dispatch.
- `sink?` (`LogSink`): Log sink for the runtime. Defaults to stderr inside `buildExtensionRegistry`.
- `trustProjectExtensions?` (`boolean`): Whether project-scoped extensions are trusted (allowed to run their code).

Source: [src/extensions/discover-and-build.ts:24](https://github.com/Tahul/zidane/blob/main/src/extensions/discover-and-build.ts#L24)

### `Disposable`

Interface.

Something that can be withdrawn. Calling `dispose` twice is a no-op.

```ts
interface Disposable
```

**Properties**

- `dispose` (`() => void`): Withdraws the registration. Safe to call more than once.

Source: [src/extensions/api/core.ts:13](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L13)

### `EnumSetting`

Interface.

A choice among fixed values.

```ts
interface EnumSetting extends SettingBase
```

**Properties**

- `apply?` (`SettingApply`, from `SettingBase`): Default `'live'`.
- `default?` (`string`): Used when no scope or config sets a value. A `value` of `options`.
- `description?` (`string`, from `SettingBase`): Help text under the label.
- `label` (`string`, from `SettingBase`): Label in Settings.
- `options` (`readonly { description?: string; label: string; value: string }[]`): The values the user may pick.
- `page?` (`string`, from `SettingBase`): Page id (see `SettingsSchema.pages`). When omitted: its section's page, else the first page. A page other than its section's is refused.
- `scopes?` (`readonly SettingScope[]`, from `SettingBase`): Scopes the user may set it at. Default `['user', 'project']`.
- `section?` (`string`, from `SettingBase`): Section id (see `SettingsSchema.sections`). Ungrouped when omitted.
- `type` (`'enum'`): Marks a choice setting.

Source: [src/extensions/api/settings.ts:68](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L68)

### `ExtensionActionRunResult`

Interface.

What running an action did.

```ts
interface ExtensionActionRunResult
```

**Properties**

- `config?` (`Record<string, ExtensionConfigValue>`): The accepted config patch (sanitized against the extension's schema); the app persists it.
- `message` (`string`): `result.message`, else `updated <keys>`, else `done`, with `(ignored invalid: …)` when keys were dropped.

Source: [src/extensions/config-actions.ts:31](https://github.com/Tahul/zidane/blob/main/src/extensions/config-actions.ts#L31)

### `ExtensionActionSummary`

Interface.

An action row, without its callbacks.

```ts
interface ExtensionActionSummary
```

**Properties**

- `category` (`string`): The config category it sits in.
- `categoryLabel` (`string`): That category's name.
- `description?` (`string`): What it does.
- `extension` (`string`): The declaring extension.
- `hasStatus` (`boolean`): The action declares a passive `status()` probe.
- `key` (`string`): The action's key, unique in its extension.
- `label` (`string`): The row's name.

Source: [src/extensions/config-actions.ts:13](https://github.com/Tahul/zidane/blob/main/src/extensions/config-actions.ts#L13)

### `ExtensionArtifactDetection`

Interface.

One artifact a `detect` hook emits; `kind` defaults to the registering kind.

```ts
interface ExtensionArtifactDetection extends Omit<SessionArtifactInput, 'kind'>
```

**Properties**

- `kind?` (`string`): Artifact kind. Defaults to the kind of the registration whose `detect` returned it.
- `label` (`string`, from `Omit`): Human-readable line shown for the artifact.
- `meta?` (`JsonValue`, from `Omit`): Kind-specific payload, at most `ARTIFACT_META_MAX_BYTES`.
- `projectRoot?` (`string`, from `Omit`): Project the artifact landed in. Default: the session project.
- `uri` (`string`, from `Omit`): Canonical locator of the artifact.

Source: [src/extensions/types.ts:537](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L537)

### `ExtensionArtifactKindRegistration`

Interface.

Give meaning to an artifact `kind` (see `session/artifacts.ts`). Core
owns storage and treats `kind` as an open string; this registration
contributes behavior keyed on it: detection from tool results, a row
presentation, `meta` validation, and lazy refresh. Built-in kinds
(`pull_request`, `branch`, `commit`, `file`) go through the same API.

Kinds are global; first registration wins on collision (logged).
Sessions outlive extensions, so a stored artifact whose kind has no
registration MUST still render — core guarantees the `label` + `uri`
fallback, never drops rows.

```ts
interface ExtensionArtifactKindRegistration
```

**Properties**

- `badge?` (`(artifacts: readonly SessionArtifact[]) => ExtensionSessionBadge | undefined`): The badge this kind contributes under a session's title (GUI sidebar,
  TUI sessions list), given that session's artifacts of the kind, newest
  first (never empty). `undefined`: no badge. Synchronous and pure; a
  throw drops the badge. See [`ExtensionSessionBadge`](https://zidane.si/docs/reference/extensions.md#ExtensionSessionBadge).
- `detect?` (`(outcome: { input: Readonly<Record<string, unknown>>; isError: boolean; result: string | ToolResultContent[]; tool: string }) => ExtensionArtifactDetection | readonly ExtensionArtifactDetection[] | Promise<ExtensionArtifactDetection | readonly ExtensionArtifactDetection[] | undefined> | undefined`): Inspect a finished tool result and emit artifacts. Sugar over
  `registerToolResultTransform` that only appends to the reserved
  `metadata.artifacts` namespace — it can never mutate the result the
  model sees. Entries default `kind` to this registration's kind.
  Throwing is isolated (logged, nothing emitted).
- `kind` (`string`): Open kind string; `[\w.:-]+`. Namespace by convention: `<ext>.<kind>`.
- `label` (`string`): Human name of the kind ("Pull request", "Deployment").
- `render?` (`(artifact: SessionArtifact) => ExtensionArtifactRow | undefined`): Row presentation; see [`ExtensionArtifactRow`](https://zidane.si/docs/reference/extensions.md#ExtensionArtifactRow). Synchronous.
- `resolve?` (`(artifact: SessionArtifact, opts?: ArtifactResolveOptions) => Promise<{ label?: string; meta?: JsonValue } | undefined>`): Lazy refresh ("is the PR merged?"). Called by UIs on view, never
  polled by core; the returned patch is merged into `meta` and
  re-persisted via `upsertArtifact`.
- `validateMeta?` (`(meta: JsonValue) => boolean`): Validate `meta` on artifacts THIS registration's `detect` emits. A
  failing check drops `meta` (never the artifact). Artifacts of this
  kind emitted by other producers are not validated here.

Source: [src/extensions/types.ts:353](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L353)

### `ExtensionArtifactQuery`

Interface.

Scope selector for `ctx.artifacts.list`.

```ts
interface ExtensionArtifactQuery
```

**Properties**

- `kind?` (`string`): Only artifacts of this kind.
- `limit?` (`number`): Maximum number of artifacts to return.
- `scope?` (`'session' | 'project' | 'all'`): `session` (default): the active session only. `project`: every session
  whose artifacts landed in the active session's project root. `all`:
  the whole store.
- `since?` (`number`): Only artifacts updated at/after this epoch-ms.

Source: [src/extensions/types.ts:543](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L543)

### `ExtensionArtifactRow`

Interface.

Renderer-agnostic one-line presentation of an artifact. Core lists
(sessions badge, artifacts rail, context panel, GUI panels) call the
kind's `render` per row and fall back to `label` + `uri` when the kind
is unregistered or `render` throws.

```ts
interface ExtensionArtifactRow
```

**Properties**

- `badges?` (`readonly { text: string; title?: string; tone?: 'success' | 'warn' | 'diff' | 'neutral' }[]`): Small facts shown after the title (`+120 −8`, `3 reviews`, `ready to
  merge`). `tone` hints the renderer: `diff` colors additions/deletions,
  `success` / `warn` tint, `neutral` is a quiet chip. Optional `title` is a
  hover detail.
- `color?` (`string`): Exact color for the icon and status word (`#rgb` / `#rrggbb`), over `tone`.
- `diff?` (`{ added: number; files?: number; href?: string; removed: number }`): A change size, painted in the diff colors; `href` links it (a PR's files).
- `facts?` (`readonly ExtensionArtifactRowFact[]`): Quiet facts after the diff (`2 reviews`, `main`, `Ready to merge`). At most 8.
- `href?` (`string`): Where "open" goes: a URL or an absolute path.
- `icon?` (`ExtensionBadgeIcon`): The shared row layout (hosts that paint it: GUI Artifacts panel, TUI
  rail). Line 1: `icon` (state), `title`, `status` in the state's color.
  Line 2, one muted line: `lead` (a short id), `diff`, then `facts`. A row
  with any of these fields drops `subtitle` / `badges` from its second
  line; older rows keep them.
- `lead?` (`{ href?: string; mono?: boolean; text: string }`): A short id (`e32789e`, `stackblitz/bolt#8183`); `mono` for hashes.
- `status?` (`string`): Short state tag (`open`, `merged`, `deployed`, …).
- `subtitle?` (`string`): Secondary line under the title.
- `title` (`string`): Row title.
- `tone?` (`ExtensionBadgeTone`): Tints the icon and the status word.

Source: [src/extensions/types.ts:190](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L190)

### `ExtensionArtifactRowFact`

Interface.

One fact chip of an artifact row: text, an optional link, and its own look.

```ts
interface ExtensionArtifactRowFact
```

**Properties**

- `color?` (`string`): Exact color for the chip's icon and text, over `tone`.
- `href?` (`string`): Link target for the chip.
- `icon?` (`ExtensionBadgeIcon`): A leading icon (a project cube, a branch).
- `text` (`string`): Chip label.
- `title?` (`string`): Hover detail.
- `tone?` (`ExtensionBadgeTone`): Tints the chip (theme tone).

Source: [src/extensions/types.ts:169](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L169)

### `ExtensionArtifactScope`

Interface.

What `ctx.artifacts` resolves queries against: the host's artifacts (its
session store, or a client's view of a host's) plus the active session's
identity, so `scope: 'session'` / `'project'` can be answered without the
extension knowing either id.

```ts
interface ExtensionArtifactScope
```

**Properties**

- `projectRoot?` (`string`): Project root of the active session. Needed to answer `scope: 'project'` queries.
- `record?` (`(artifact: SessionArtifact) => Promise<SessionArtifact | null>`): Host-owned write path for `ctx.artifacts.record`. Defaults to
  `store.upsertArtifact`; hosts override to route through a daemon RPC or
  to fan out a change signal after the write.
- `runId?` (`string`): Active run id, when a run is in flight — stamped on `record`ed artifacts.
- `sessionId?` (`string`): Active session id. Needed to answer `scope: 'session'` queries.
- `store` (`Pick<SessionStore, 'listArtifacts' | 'upsertArtifact'>`): Store the artifacts are read from and written to.

Source: [src/extensions/host-runtime.ts:295](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L295)

### `ExtensionBadgeActions`

Interface.

Right-click actions an extension adds to matching badges. Registered with `ctx.registerBadgeActions`.

```ts
interface ExtensionBadgeActions
```

**Properties**

- `actions` (`(target: BadgeTarget) => readonly BadgeAction[] | undefined`): The items for one badge (synchronous, cheap). Nothing or `[]`: none.
- `id` (`string`): Unique per registry (`<ext>.<what>`); first registration wins.
- `match?` (`BadgeActionsMatch`): Badges the actions apply to. Omitted: every badge.
- `run` (`(actionId: string, target: BadgeTarget, ctx: { cwd?: string; sessionId?: string; signal: AbortSignal }) => void | BadgeActionEffect | Promise<void | BadgeActionEffect>`): Run one of them. Throws become a `notice` with the message.

Source: [src/extensions/badge-actions.ts:75](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L75)

### `ExtensionBadgeIcon`

Interface.

An icon in both renderers' vocabularies: `gui` is an icon class
(`i-ph-git-commit`), `tui` one or two terminal cells (`⎇`). Either may be
omitted; the host then draws none.

```ts
interface ExtensionBadgeIcon
```

**Properties**

- `gui?` (`string`): Icon class for the GUI host.
- `tui?` (`string`): One or two terminal cells for the TUI host.

Source: [src/extensions/types.ts:255](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L255)

### `ExtensionCatalogPartition`

Interface.

Shape returned by [`partitionExtensionCatalog`](https://zidane.si/docs/reference/extensions.md#partitionExtensionCatalog).

```ts
interface ExtensionCatalogPartition
```

**Properties**

- `allNames` (`readonly string[]`): Every known extension name — toggleable AND errored. Use this as
  the GC key set for the persisted `enabledExtensions` allowlist so
  an untrusted / temporarily-broken extension isn't permanently
  dropped from the allowlist by an unrelated toggle.
- `errored` (`readonly LoadedExtension[]`): Entries whose import or `setup()` failed — read-only diagnostics.
- `toggleable` (`readonly LoadedExtension[]`): Rows the user can toggle: active extensions plus disabled-but-
  loadable ones, sorted by name so the list order is stable across
  boots regardless of where each entry landed in the registry.

Source: [src/extensions/register.ts:292](https://github.com/Tahul/zidane/blob/main/src/extensions/register.ts#L292)

### `ExtensionCatalogs`

Interface.

The catalogs extensions register into and transform.

```ts
interface ExtensionCatalogs
```

**Properties**

- `agents` (`AgentsCatalog`, readonly): Agent catalog.
- `mcp` (`McpCatalog`, readonly): MCP server catalog.
- `models` (`ModelsCatalog`, readonly): Model catalog.
- `providers` (`ProvidersCatalog`, readonly): Provider catalog.
- `skills` (`SkillsCatalog`, readonly): Skill catalog.
- `tools` (`ToolsCatalog`, readonly): Tool catalog.

Source: [src/extensions/runtime/outputs.ts:18](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/outputs.ts#L18)

### `ExtensionCompletionItemSummary`

Interface.

One item of a provider's popup.

```ts
interface ExtensionCompletionItemSummary
```

**Properties**

- `description?` (`string`): Short text under the label.
- `id` (`string`): The item's id.
- `insertText` (`string`): What picking it inserts (the id when the provider gives none).
- `label` (`string`): What the row shows.

Source: [src/extensions/completion-providers.ts:21](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L21)

### `ExtensionCompletionProviderSummary`

Interface.

A provider as an app's composer lists it: its trigger opens its popup.

```ts
interface ExtensionCompletionProviderSummary
```

**Properties**

- `id` (`string`): The provider's id (`completions.suggest` names it).
- `label` (`string`): The popup's section title (the id when the provider names none).
- `trigger` (`string`): One character.

Source: [src/extensions/completion-providers.ts:11](https://github.com/Tahul/zidane/blob/main/src/extensions/completion-providers.ts#L11)

### `ExtensionConfigActionItem`

Interface.

An imperative config item — rendered as a "press ↵ to run" row instead
of a value editor. `run` executes in the extension's own process (it is
never serialized — [`toWireConfigSchema`](https://zidane.si/docs/reference/extensions.md#toWireConfigSchema) omits action items
entirely), so it can close over the extension's `setup(ctx)` scope.

Contract for `run`:

- Resolve with an [`ExtensionConfigActionResult`](https://zidane.si/docs/reference/extensions.md#ExtensionConfigActionResult) (or `void`) on
  success — `message` becomes the row's feedback line, `config`
  values are persisted by the host.
- Throw / reject on failure — the error message is shown on the row.
- Bound your own runtime: the host serializes actions (one in flight
  per modal) but imposes no timeout, so a hanging `run` holds the
  "running…" state until it settles.

Actions hold no persisted value: `ctx.config.get(key)` returns
`undefined` for an action key and the resolver never yields a value.

```ts
interface ExtensionConfigActionItem extends Pick<ExtensionConfigItemBase, 'key' | 'label' | 'description'>
```

**Properties**

- `description?` (`string`, from `Pick`): Longer one-line gloss shown under the label.
- `key` (`string`, from `Pick`): Stable key, unique within the declaring extension. Used as the
  persistence key (`extensionConfig[extName][key]`) and the
  `ctx.config.get(key)` lookup — pick a stable identifier.
- `label` (`string`, from `Pick`): Short display label rendered in the Settings UIs.
- `run` (`() => void | ExtensionConfigActionResult | Promise<void | ExtensionConfigActionResult>`): Runs the action. May return values to persist. Throwing shows the error on the row.
- `status?` (`() => ExtensionConfigActionStatus | Promise<ExtensionConfigActionStatus | undefined> | undefined`): Optional passive probe — called by the host when the settings panel
  surfaces the row (and re-called after any action of the panel
  settles), so the row can show live state ("running at …") WITHOUT
  the user pressing ↵. Contract:

  - Resolve an [`ExtensionConfigActionStatus`](https://zidane.si/docs/reference/extensions.md#ExtensionConfigActionStatus) to show it, or
    `undefined` for "no status" (e.g. the probed tool isn't
    installed — stay quiet rather than nag).
  - Throwing is treated as `undefined` — probes must be safe to call
    at any time and MUST NOT mutate anything.
  - Be fast: the TUI caps each probe at 3 seconds and discards
    late results.
- `type` (`'action'`): Discriminant for an action item.

Source: [src/extensions/config.ts:207](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L207)

### `ExtensionConfigActionResult`

Interface.

What a config ACTION reports back to the host after running. Actions
cannot write settings directly — there is deliberately no `config.set`
surface for extensions — so a successful run RETURNS the values it wants
persisted and the host writes them through its own validated settings
path ([`sanitizeExtensionConfigActionPatch`](https://zidane.si/docs/reference/extensions.md#sanitizeExtensionConfigActionPatch) gates the patch).

```ts
interface ExtensionConfigActionResult
```

**Properties**

- `config?` (`Record<string, ExtensionConfigValue>`): Config values of the DECLARING extension to persist on success, keyed
  by item key. Entries naming unknown keys, action items, or values that
  fail the item's schema are dropped (not errors) — a buggy action can
  degrade but never corrupt the settings bag.
- `message?` (`string`): One-line feedback shown in the Settings UI (e.g. "proxy running at …").

Source: [src/extensions/config.ts:177](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L177)

### `ExtensionConfigActionStatus`

Interface.

Result of an action's passive `status` probe. `state` drives the row
color (`ok` accent / `off` mute / `error` error); `message` is the
one-line text rendered in the row's value slot.

```ts
interface ExtensionConfigActionStatus
```

**Properties**

- `message` (`string`): One-line text shown in the row's value slot.
- `state` (`'error' | 'off' | 'ok'`): Row state: `ok`, `off` or `error`.

Source: [src/extensions/config.ts:234](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L234)

### `ExtensionConfigBooleanItem`

Interface.

A boolean config item — rendered as a toggle.

```ts
interface ExtensionConfigBooleanItem extends ExtensionConfigItemBase
```

**Properties**

- `default` (`boolean`): Value used until the user sets one.
- `description?` (`string`, from `ExtensionConfigItemBase`): Longer one-line gloss shown under the label.
- `key` (`string`, from `ExtensionConfigItemBase`): Stable key, unique within the declaring extension. Used as the
  persistence key (`extensionConfig[extName][key]`) and the
  `ctx.config.get(key)` lookup — pick a stable identifier.
- `label` (`string`, from `ExtensionConfigItemBase`): Short display label rendered in the Settings UIs.
- `onChange?` (`ExtensionConfigChangeBehavior`, from `ExtensionConfigItemBase`): How hosts should apply a changed value. Defaults to live reads through `ctx.config.get`.
- `requiresRestart?` (`boolean`, from `ExtensionConfigItemBase`): Whether changing this value requires rebuilding runtime objects.
- `scope?` (`ExtensionConfigScope`, from `ExtensionConfigItemBase`): Desired persistence scope. Current stores still persist through the
  existing per-extension settings bag unless a host implements scoped writes;
  this metadata lets UIs and future stores present the right ownership.
- `type` (`'boolean'`): Discriminant for a boolean item.
- `validate?` (`(v: unknown) => boolean`, from `ExtensionConfigItemBase`): Optional main-side validator, run at READ time AFTER the built-in
  type / range / enum / pattern checks (both must pass). Throwing is
  treated as "invalid" — the read degrades to the item's `default`. It
  is **never invoked at registration** (declaring an item has no side
  effects) and is **never serialized over IPC** ([`toWireConfigSchema`](https://zidane.si/docs/reference/extensions.md#toWireConfigSchema)
  strips it), so it only runs in-process (TUI host + extension reads);
  the GUI renderer is optimistic and relies on the authoritative core read.

Source: [src/extensions/config.ts:80](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L80)

### `ExtensionConfigCategory`

Interface.

A config category — a labelled grouping the Settings UIs render as a
sub-header. Declared via `ctx.registerConfigCategory`. An item that
names no category lands in its extension's implicit category (id =
extension name); register a category with that id to give the implicit
grouping a friendlier label.

```ts
interface ExtensionConfigCategory
```

**Properties**

- `description?` (`string`): One-line gloss shown under the label.
- `id` (`string`): Category id.
- `label` (`string`): Sub-header text.

Source: [src/extensions/config.ts:267](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L267)

### `ExtensionConfigEnumItem`

Interface.

An enum config item — rendered as a cycling choice row. The `default` must be
one of the `options` values or the item is rejected at registration.

```ts
interface ExtensionConfigEnumItem extends ExtensionConfigItemBase
```

**Properties**

- `default` (`string`): Value used until the user picks one. Must be one of `options`.
- `description?` (`string`, from `ExtensionConfigItemBase`): Longer one-line gloss shown under the label.
- `key` (`string`, from `ExtensionConfigItemBase`): Stable key, unique within the declaring extension. Used as the
  persistence key (`extensionConfig[extName][key]`) and the
  `ctx.config.get(key)` lookup — pick a stable identifier.
- `label` (`string`, from `ExtensionConfigItemBase`): Short display label rendered in the Settings UIs.
- `onChange?` (`ExtensionConfigChangeBehavior`, from `ExtensionConfigItemBase`): How hosts should apply a changed value. Defaults to live reads through `ctx.config.get`.
- `options` (`readonly { label: string; value: string }[]`): Choices the user can pick from.
- `requiresRestart?` (`boolean`, from `ExtensionConfigItemBase`): Whether changing this value requires rebuilding runtime objects.
- `scope?` (`ExtensionConfigScope`, from `ExtensionConfigItemBase`): Desired persistence scope. Current stores still persist through the
  existing per-extension settings bag unless a host implements scoped writes;
  this metadata lets UIs and future stores present the right ownership.
- `type` (`'enum'`): Discriminant for an enum item.
- `validate?` (`(v: unknown) => boolean`, from `ExtensionConfigItemBase`): Optional main-side validator, run at READ time AFTER the built-in
  type / range / enum / pattern checks (both must pass). Throwing is
  treated as "invalid" — the read degrades to the item's `default`. It
  is **never invoked at registration** (declaring an item has no side
  effects) and is **never serialized over IPC** ([`toWireConfigSchema`](https://zidane.si/docs/reference/extensions.md#toWireConfigSchema)
  strips it), so it only runs in-process (TUI host + extension reads);
  the GUI renderer is optimistic and relies on the authoritative core read.

Source: [src/extensions/config.ts:138](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L138)

### `ExtensionConfigItemBase`

Interface.

Fields shared by every config-item variant.

```ts
interface ExtensionConfigItemBase
```

**Properties**

- `description?` (`string`): Longer one-line gloss shown under the label.
- `key` (`string`): Stable key, unique within the declaring extension. Used as the
  persistence key (`extensionConfig[extName][key]`) and the
  `ctx.config.get(key)` lookup — pick a stable identifier.
- `label` (`string`): Short display label rendered in the Settings UIs.
- `onChange?` (`ExtensionConfigChangeBehavior`): How hosts should apply a changed value. Defaults to live reads through `ctx.config.get`.
- `requiresRestart?` (`boolean`): Whether changing this value requires rebuilding runtime objects.
- `scope?` (`ExtensionConfigScope`): Desired persistence scope. Current stores still persist through the
  existing per-extension settings bag unless a host implements scoped writes;
  this metadata lets UIs and future stores present the right ownership.
- `validate?` (`(v: unknown) => boolean`): Optional main-side validator, run at READ time AFTER the built-in
  type / range / enum / pattern checks (both must pass). Throwing is
  treated as "invalid" — the read degrades to the item's `default`. It
  is **never invoked at registration** (declaring an item has no side
  effects) and is **never serialized over IPC** ([`toWireConfigSchema`](https://zidane.si/docs/reference/extensions.md#toWireConfigSchema)
  strips it), so it only runs in-process (TUI host + extension reads);
  the GUI renderer is optimistic and relies on the authoritative core read.

Source: [src/extensions/config.ts:46](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L46)

### `ExtensionConfigModelItem`

Interface.

A model-id config item — rendered as an inline searchable picker over the
host's credentialed model catalog (the same interaction grammar as the
ctrl+m cross-provider picker: type to filter, `↵` picks — or toggles, in
`multi` mode, where `esc` applies the selection).

The persisted value is a plain model id, or a comma-separated id list
when `multi` — a string either way, so [`ExtensionConfigValue`](https://zidane.si/docs/reference/extensions.md#ExtensionConfigValue) and
every settings store stay unchanged, and hosts without a catalog
(headless, no authed providers) degrade to the free string input.
Deliberately catalog-UNvalidated at read time: a stored id whose
provider is temporarily unauthed must survive, not silently reset to
the default — catalog validation is the consuming extension's call.

```ts
interface ExtensionConfigModelItem extends ExtensionConfigItemBase
```

**Properties**

- `default` (`string`): Value used until the user picks one: a model id, or a comma-separated list when `multi`.
- `description?` (`string`, from `ExtensionConfigItemBase`): Longer one-line gloss shown under the label.
- `key` (`string`, from `ExtensionConfigItemBase`): Stable key, unique within the declaring extension. Used as the
  persistence key (`extensionConfig[extName][key]`) and the
  `ctx.config.get(key)` lookup — pick a stable identifier.
- `label` (`string`, from `ExtensionConfigItemBase`): Short display label rendered in the Settings UIs.
- `multi?` (`boolean`): Allow picking MORE than one model (comma-separated persisted value).
- `onChange?` (`ExtensionConfigChangeBehavior`, from `ExtensionConfigItemBase`): How hosts should apply a changed value. Defaults to live reads through `ctx.config.get`.
- `requiresRestart?` (`boolean`, from `ExtensionConfigItemBase`): Whether changing this value requires rebuilding runtime objects.
- `scope?` (`ExtensionConfigScope`, from `ExtensionConfigItemBase`): Desired persistence scope. Current stores still persist through the
  existing per-extension settings bag unless a host implements scoped writes;
  this metadata lets UIs and future stores present the right ownership.
- `type` (`'model'`): Discriminant for a model item.
- `validate?` (`(v: unknown) => boolean`, from `ExtensionConfigItemBase`): Optional main-side validator, run at READ time AFTER the built-in
  type / range / enum / pattern checks (both must pass). Throwing is
  treated as "invalid" — the read degrades to the item's `default`. It
  is **never invoked at registration** (declaring an item has no side
  effects) and is **never serialized over IPC** ([`toWireConfigSchema`](https://zidane.si/docs/reference/extensions.md#toWireConfigSchema)
  strips it), so it only runs in-process (TUI host + extension reads);
  the GUI renderer is optimistic and relies on the authoritative core read.

Source: [src/extensions/config.ts:161](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L161)

### `ExtensionConfigNumberItem`

Interface.

A numeric config item — rendered as a free input row, clamped to `[min, max]`
and snapped to `step`. The `default` must itself lie within `[min, max]` or
the item is rejected at registration.

```ts
interface ExtensionConfigNumberItem extends ExtensionConfigItemBase
```

**Properties**

- `default` (`number`): Value used until the user sets one. Must lie within `[min, max]`.
- `description?` (`string`, from `ExtensionConfigItemBase`): Longer one-line gloss shown under the label.
- `key` (`string`, from `ExtensionConfigItemBase`): Stable key, unique within the declaring extension. Used as the
  persistence key (`extensionConfig[extName][key]`) and the
  `ctx.config.get(key)` lookup — pick a stable identifier.
- `label` (`string`, from `ExtensionConfigItemBase`): Short display label rendered in the Settings UIs.
- `max?` (`number`): Largest accepted value.
- `min?` (`number`): Smallest accepted value.
- `onChange?` (`ExtensionConfigChangeBehavior`, from `ExtensionConfigItemBase`): How hosts should apply a changed value. Defaults to live reads through `ctx.config.get`.
- `requiresRestart?` (`boolean`, from `ExtensionConfigItemBase`): Whether changing this value requires rebuilding runtime objects.
- `scope?` (`ExtensionConfigScope`, from `ExtensionConfigItemBase`): Desired persistence scope. Current stores still persist through the
  existing per-extension settings bag unless a host implements scoped writes;
  this metadata lets UIs and future stores present the right ownership.
- `step?` (`number`): Increment values snap to.
- `type` (`'number'`): Discriminant for a number item.
- `validate?` (`(v: unknown) => boolean`, from `ExtensionConfigItemBase`): Optional main-side validator, run at READ time AFTER the built-in
  type / range / enum / pattern checks (both must pass). Throwing is
  treated as "invalid" — the read degrades to the item's `default`. It
  is **never invoked at registration** (declaring an item has no side
  effects) and is **never serialized over IPC** ([`toWireConfigSchema`](https://zidane.si/docs/reference/extensions.md#toWireConfigSchema)
  strips it), so it only runs in-process (TUI host + extension reads);
  the GUI renderer is optimistic and relies on the authoritative core read.

Source: [src/extensions/config.ts:92](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L92)

### `ExtensionConfigStringItem`

Interface.

A string config item — rendered as a free input row (optionally `multiline`), validated against `pattern`.

```ts
interface ExtensionConfigStringItem extends ExtensionConfigItemBase
```

**Properties**

- `default` (`string`): Value used until the user sets one.
- `description?` (`string`, from `ExtensionConfigItemBase`): Longer one-line gloss shown under the label.
- `key` (`string`, from `ExtensionConfigItemBase`): Stable key, unique within the declaring extension. Used as the
  persistence key (`extensionConfig[extName][key]`) and the
  `ctx.config.get(key)` lookup — pick a stable identifier.
- `label` (`string`, from `ExtensionConfigItemBase`): Short display label rendered in the Settings UIs.
- `multiline?` (`boolean`): Renders a multi-line editor instead of a single-line input.
- `onChange?` (`ExtensionConfigChangeBehavior`, from `ExtensionConfigItemBase`): How hosts should apply a changed value. Defaults to live reads through `ctx.config.get`.
- `pattern?` (`string`): Anchored or unanchored JS-regex source gating user-entered values at read
  time. An invalid pattern is ignored (treated as "no constraint"). The
  pattern is intentionally NOT applied to the `default`, so an empty / unset
  default (`default: ''`) for an optional patterned field is valid.
- `requiresRestart?` (`boolean`, from `ExtensionConfigItemBase`): Whether changing this value requires rebuilding runtime objects.
- `scope?` (`ExtensionConfigScope`, from `ExtensionConfigItemBase`): Desired persistence scope. Current stores still persist through the
  existing per-extension settings bag unless a host implements scoped writes;
  this metadata lets UIs and future stores present the right ownership.
- `secret?` (`boolean`): Treat the value as a credential: Settings UIs render it masked
  (`••••••••`, last 4 characters kept for recognition when the value is
  longer than 8) and seed the editor
  EMPTY rather than with the stored value, so the secret never appears on
  screen or in a screen share.

  Presentation only — the value still lives in the plain settings bag, so
  this is for "don't shoulder-surf my service token", not for secrets that
  warrant the credential store. Ignored for `multiline` items.
- `type` (`'string'`): Discriminant for a string item.
- `validate?` (`(v: unknown) => boolean`, from `ExtensionConfigItemBase`): Optional main-side validator, run at READ time AFTER the built-in
  type / range / enum / pattern checks (both must pass). Throwing is
  treated as "invalid" — the read degrades to the item's `default`. It
  is **never invoked at registration** (declaring an item has no side
  effects) and is **never serialized over IPC** ([`toWireConfigSchema`](https://zidane.si/docs/reference/extensions.md#toWireConfigSchema)
  strips it), so it only runs in-process (TUI host + extension reads);
  the GUI renderer is optimistic and relies on the authoritative core read.

Source: [src/extensions/config.ts:106](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L106)

### `ExtensionContext`

Interface.

Everything an extension can do. Registrations return a Disposable and work
until the extension (or the scope they were made through) is disposed.

`plugins`, `artifacts`, `sessions`, `generate` and `workspace` need host
support. On a host without it the domain is still there, but its members
fail with an error naming the member and the host: synchronous ones
(`artifacts.kinds.register`) throw, async ones reject.

```ts
interface ExtensionContext<S extends SettingsSchema = SettingsSchema>
```

**Type parameters**

- `S` (`extends SettingsSchema`, default `SettingsSchema`)

**Properties**

- `add` (`AddFn`): Adds a UI contribution.
- `agents` (`AgentsDomain`): Registers and edits agents.
- `app` (`AppInfo`, readonly): The running app: version, host process and platform.
- `artifacts` (`ArtifactsDomain`): Records and reads session artifacts, and registers artifact kinds.
- `commands` (`CommandsDomain`): Registers commands and palette providers, and runs commands.
- `composer` (`ComposerDomain`): Reads and edits the composer.
- `contracts` (`ContractsDomain`): Provides and uses contracts, and owns registries, between extensions.
- `desktop?` (`DesktopDomain`): Present only in the desktop app's main process.
- `dir?` (`string`, readonly): The extension's folder, when it has one. Use it instead of `import.meta.dirname`.
- `extensions` (`{ get: (id: string) => ExtensionInfo | undefined; list: () => readonly ExtensionInfo[] }`): Lists the loaded extensions and looks one up by id.
- `generate` (`GenerateDomain`): Asks a model for text or structured output.
- `hooks` (`HooksDomain`): Observes events and takes part in decisions.
- `id` (`string`, readonly): The extension id.
- `instructions` (`InstructionsDomain`): Adds text to the system prompt.
- `integrations` (`IntegrationsDomain`): Registers integrations and reads their connections.
- `keymap` (`KeymapDomain`): Reads keybindings and pushes keymap modes.
- `logger` (`Logger`, readonly): Logs attributed to the extension.
- `mcp` (`McpDomain`): Lists, registers and calls MCP servers.
- `models` (`ModelsDomain`): Lists and edits the model catalog.
- `onCleanup` (`(cleanup: Cleanup) => Disposable`): Runs `cleanup` when this context's owner is disposed.
- `paths` (`ExtensionPaths`, readonly): Folders the host gives the extension.
- `plugins` (`PluginsDomain`): Loads Agent Plugins (skills and MCP bundles).
- `providers` (`ProvidersDomain`): Registers and edits model providers.
- `rpc` (`RpcDomain`): Implements and calls typed RPC contracts.
- `schedules` (`SchedulesDomain`): Prompts and handlers that run at a set time (reminders). Rejects while Reminders is off.
- `scope` (`() => ExtensionContext<S> & Disposable`): A child context with its own lifetime. Disposing it withdraws what was registered through it.
- `sessions` (`SessionsDomain`): Reads and drives sessions.
- `settings` (`SettingsDomain<S>`): Declares the extension's settings and reads their values.
- `signal` (`AbortSignal`, readonly): Aborts when this context's owner is disposed.
- `skills` (`SkillsDomain`): Registers and edits skills.
- `source` (`ExtensionSource`, readonly): Where the extension was found.
- `storage` (`StorageDomain`): Durable data: key/value, typed stores and folders.
- `tools` (`ToolsDomain`): Registers and edits the agent's tools.
- `ui` (`UiDomain`): Asks the user questions through dialogs and opens panels.
- `version?` (`string`, readonly): The extension's version, when it declares one.
- `workspace` (`ExtensionWorkspaceSurface`): Runs commands and reads files in the session's execution context.

Source: [src/extensions/api/context.ts:45](https://github.com/Tahul/zidane/blob/main/src/extensions/api/context.ts#L45)

### `ExtensionContextInput`

Interface.

What is specific to one extension.

```ts
interface ExtensionContextInput<S extends SettingsSchema = SettingsSchema>
```

**Type parameters**

- `S` (`extends SettingsSchema`, default `SettingsSchema`)

**Properties**

- `definition` (`ExtensionDefinition<S>`, readonly): The extension's validated definition.
- `dir?` (`string`, readonly): The extension's folder.
- `directory?` (`string`, readonly): The extension's project directory for RPC routing. Default `paths.projectRoot ?? paths.cwd`.
- `guard` (`Guard`, readonly): Bounds the extension's callbacks with timeouts and an error budget.
- `hooks` (`HooksPort`, readonly): The extension's hooks port (its own agent-hook bus and host events).
- `logger` (`Logger`, readonly): The extension's logger.
- `paths` (`ExtensionPaths`, readonly): Paths handed to the extension as `ctx.paths`.
- `settings` (`SettingsDomainInstance<S>`, readonly): The extension's settings domain, built on its root owner.
- `source` (`ExtensionSource`, readonly): Where the extension was found.
- `storage` (`StorageRuntime`, readonly): The extension's storage runtime, built on its root owner.

Source: [src/extensions/runtime/context.ts:111](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/context.ts#L111)

### `ExtensionContextPanelSection`

Interface.

Section an extension adds to the context panel. Supply static or computed `rows`, a `load` function, or both.

```ts
interface ExtensionContextPanelSection
```

**Properties**

- `accentColor?` (`string`): Accent color for the section.
- `actions?` (`readonly { id: string; label: string }[]`): Actions offered on the section.
- `id` (`string`): Stable section id. Must be a safe record key.
- `load?` (`(ctx: ContextBreakdownContributionContext) => ContextExtensionSection | readonly ContextExtensionSection[] | readonly ContextExtensionRow[] | Promise<ContextExtensionSection | readonly ContextExtensionSection[] | readonly ContextExtensionRow[] | null | undefined> | null | undefined`): Builds rows or whole sections asynchronously from the breakdown context. Return nothing to add no extra content.
- `rows?` (`readonly ContextExtensionRow[] | ((ctx: ContextBreakdownContributionContext) => readonly ContextExtensionRow[])`): Rows to show, or a function that builds them from the breakdown context.
- `title` (`string`): Section heading.

Source: [src/extensions/types.ts:131](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L131)

### `ExtensionContributions`

Interface.

One extension's contributions, in the shapes hosts read.

```ts
interface ExtensionContributions
```

**Properties**

- `agents` (`Readonly<Record<string, AgentProfile>>`): Agent profiles, keyed by profile id.
- `artifactKinds` (`readonly ExtensionOrderedContribution<ExtensionArtifactKindRegistration>[]`): Artifact kinds (`ctx.artifacts.kinds.register`).
- `badgeActions` (`readonly ExtensionOrderedContribution<ExtensionBadgeActions>[]`): `BadgeAction` items.
- `commands` (`readonly Command[]`): `/` commands.
- `completionProviders` (`readonly CompletionProvider<unknown>[]`): Composer completion providers.
- `configCategories` (`Readonly<Record<string, ExtensionConfigCategory>>`): The extension's settings categories, keyed by category id.
- `configItems` (`Readonly<Record<string, StoredExtensionConfigItem>>`): The extension's settings rows (values and actions), keyed by key.
- `contextBreakdownSections` (`readonly ContextBreakdownContributor[]`): `ContextSection` items placed in the context breakdown.
- `contextPanelSections` (`readonly ContextBreakdownContributor[]`): `ContextSection` items placed in the context panel.
- `hooks` (`{ readonly 'agent:abort'?: readonly ((ctx: { reason?: string; runId?: string }) => void)[]; readonly 'agent:done'?: readonly ((ctx: AgentStats) => void)[]; readonly 'agent:start'?: readonly ((ctx: { agentName?: string; depth: number; parentRunId?: string; providerName?: string; runId: string; startedAt: number; tracingContext?: Readonly<Record<string, string>> }) => void)[]; readonly 'artifact:recorded'?: readonly ((ctx: { artifact: SessionArtifact; callId: string; name: string; runId: string; turnId: string }) => void)[]; readonly 'background:adopt'?: readonly ((ctx: { command: string; cwd: string; outputPath: string; pid: number; startedAt: number; taskId: string }) => void)[]; readonly 'background:exit'?: readonly ((ctx: { command: string; durationMs: number; exitCode: number; outputPath: string; signal?: Signals; status: 'exited' | 'killed'; taskId: string }) => void)[]; readonly 'background:reassign'?: readonly ((ctx: { childId?: string; command: string; fromHandleId: string; outputPath: string; pid: number; startedAt: number; taskId: string; toHandleId: string }) => void)[]; readonly 'background:reconcile'?: readonly ((ctx: { exits: TaskExitInfo[] }) => void)[]; readonly 'background:stall'?: readonly ((ctx: { bytesWritten: number; command: string; outputPath: string; stalledForMs: number; taskId: string }) => void)[]; readonly 'background:start'?: readonly ((ctx: { command: string; cwd: string; outputPath: string; pid: number; startedAt: number; taskId: string }) => void)[]; readonly 'budget:exceeded'?: readonly ((ctx: { budget: number; bytes: number; turn: number; turnId: string }) => void)[]; readonly 'cache:break'?: readonly ((info: CacheBreakInfo) => void | Promise<void>)[]; readonly 'cache:drift'?: readonly ((info: CacheDriftInfo) => void | Promise<void>)[]; readonly 'child:artifact:recorded'?: readonly ((ctx: { artifact: SessionArtifact; callId: string; childId: string; depth: number; name: string; runId: string; turnId: string }) => void)[]; readonly 'child:background:exit'?: readonly ((ctx: { childId: string; command: string; depth: number; durationMs: number; exitCode: number; outputPath: string; signal?: Signals; status: 'exited' | 'killed'; taskId: string }) => void)[]; readonly 'child:background:reassign'?: readonly ((ctx: { childId: string; command: string; depth: number; fromHandleId: string; outputPath: string; pid: number; startedAt: number; taskId: string; toHandleId: string }) => void)[]; readonly 'child:background:start'?: readonly ((ctx: { childId: string; command: string; cwd: string; depth: number; outputPath: string; pid: number; startedAt: number; taskId: string }) => void)[]; readonly 'child:mcp:tool:gate'?: readonly ((ctx: McpToolHookContext & { block: boolean; childId: string; depth: number; reason: string; result?: string | ToolResultContent[] }) => void)[]; readonly 'child:repeat-guard:exceeded'?: readonly ((ctx: { action: 'steer' | 'block' | 'abort'; childId: string; count: number; depth: number; threshold: number; tool: string; turnId: string }) => void)[]; readonly 'child:spawn:before'?: readonly ((ctx: ChildSpawnHookContext) => void)[]; readonly 'child:spawn:complete'?: readonly ((ctx: ChildRunStats & ChildSpawnIdentity) => void)[]; readonly 'child:spawn:error'?: readonly ((ctx: Omit<SpawnHookContext, 'tracingContext'> & ChildSpawnIdentity & { error: Error }) => void)[]; readonly 'child:stream:end'?: readonly ((ctx: StreamHookContext & { childId: string; depth: number; text: string }) => void)[]; readonly 'child:stream:error'?: readonly ((ctx: StreamHookContext & { childId: string; depth: number; err: unknown }) => void)[]; readonly 'child:stream:retry'?: readonly ((ctx: StreamHookContext & { attempt: number; childId: string; delayMs: number; depth: number; discardedText?: true; discardedThinking?: true; err: unknown; maxAttempts: number; nextAttempt: number; requestId?: string; statusCode?: number }) => void)[]; readonly 'child:stream:server_tool_result'?: readonly ((ctx: StreamHookContext & { childId: string; content: unknown; depth: number; toolName: string; toolUseId: string }) => void)[]; readonly 'child:stream:server_tool_use'?: readonly ((ctx: StreamHookContext & { childId: string; depth: number; id: string; input: Record<string, unknown>; name: string }) => void)[]; readonly 'child:stream:text'?: readonly ((ctx: StreamHookContext & { childId: string; delta: string; depth: number; text: string }) => void)[]; readonly 'child:stream:thinking'?: readonly ((ctx: StreamHookContext & { childId: string; delta: string; depth: number; thinking: string }) => void)[]; readonly 'child:tool:after'?: readonly ((ctx: ToolHookContext & { childId: string; coercions?: readonly string[]; depth: number; isError?: boolean; outcome?: ToolOutcome; outputBytes: number; result: string | ToolResultContent[]; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:before'?: readonly ((ctx: ToolHookContext & { childId: string; coercions?: readonly string[]; depth: number; priorContent?: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:cancelled'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; reason: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:dispatched'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; outcome: 'execute' | 'gate-substitute' | 'gate-block' | 'unknown' | 'invalid-input'; reason?: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:error'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; error: Error }) => void)[]; readonly 'child:tool:gate'?: readonly ((ctx: ToolHookContext & ToolGateResumeFields & { block: boolean; childId: string; depth: number; metadata: ToolResultMetadata; reason: string; result?: string | ToolResultContent[]; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:progress'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; progress: ToolProgress }) => void)[]; readonly 'child:tool:transform'?: readonly ((ctx: ToolHookContext & { childId: string; coercions?: readonly string[]; depth: number; isError: boolean; metadata: ToolResultMetadata; outputBytes: number; result: string | ToolResultContent[] }) => void)[]; readonly 'child:turn:after'?: readonly ((ctx: { aborted?: boolean; childId: string; depth: number; message: SessionTurn; toolCounts: { run: Readonly<Record<string, number>>; turn: Readonly<Record<string, number>> }; turn: number; turnId: string; usage: TurnUsage }) => void)[]; readonly 'child:validation:reject'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; reason: string; schema: Record<string, unknown> }) => void)[]; readonly 'compact:end'?: readonly ((ctx: CompactEndHookContext) => void)[]; readonly 'compact:progress'?: readonly ((ctx: CompactProgressHookContext) => void)[]; readonly 'compact:restore'?: readonly ((ctx: { add: (call: { input: Record<string, unknown>; name: string; output: string }) => void; session?: Session }) => void | Promise<void>)[]; readonly 'compact:start'?: readonly ((ctx: CompactStartHookContext) => void)[]; readonly 'content-ref:resolve'?: readonly ((ctx: { block: ResolveContentRefBlock; childId?: string; data?: string; depth?: number }) => void)[]; readonly 'context:overflow'?: readonly ((ctx: StreamHookContext & { attempt: number; err: unknown }) => void)[]; readonly 'context:transform'?: readonly ((ctx: { messages: SessionMessage[] }) => void)[]; readonly 'decision:end'?: readonly ((ctx: DecisionEndHookContext) => void)[]; readonly 'decision:start'?: readonly ((ctx: DecisionStartHookContext) => void)[]; readonly 'execution:ready'?: readonly ((ctx: { handle: ExecutionHandle; spawned: boolean }) => void)[]; readonly 'history:repair'?: readonly ((ctx: HistoryRepairHookContext) => void)[]; readonly 'mcp:auth:error'?: readonly ((ctx: { error: Error; name: string }) => void)[]; readonly 'mcp:auth:required'?: readonly ((ctx: { name: string; reason: 'no-tokens' | 'auto-promoted'; transport: 'sse' | 'stdio' | 'streamable-http' }) => void)[]; readonly 'mcp:auth:success'?: readonly ((ctx: { name: string }) => void)[]; readonly 'mcp:auth:url'?: readonly ((ctx: { name: string; url: string }) => void)[]; readonly 'mcp:bootstrap:end'?: readonly ((ctx: { durationMs: number; name: string; transport: string } & ({ cached?: boolean; lazy?: boolean; ok: true; toolCount: number; warnings?: string[] } | { error: Error; ok: false })) => void)[]; readonly 'mcp:bootstrap:settled'?: readonly ((ctx: { results: readonly ({ durationMs: number; name: string; transport: string } & ({ lazy?: boolean; ok: true; toolCount: number } | { error?: Error; ok: false; skipped?: boolean }))[] }) => void)[]; readonly 'mcp:bootstrap:start'?: readonly ((ctx: { name: string; transport: string }) => void)[]; readonly 'mcp:close'?: readonly ((ctx: { name: string }) => void)[]; readonly 'mcp:connect'?: readonly ((ctx: { lazy?: boolean; name: string; tools: string[]; transport: string }) => void)[]; readonly 'mcp:error'?: readonly ((ctx: { error: Error; name: string }) => void)[]; readonly 'mcp:tool:after'?: readonly ((ctx: McpToolHookContext & { outputBytes: number; result: string | ToolResultContent[] }) => void)[]; readonly 'mcp:tool:before'?: readonly ((ctx: McpToolHookContext) => void)[]; readonly 'mcp:tool:error'?: readonly ((ctx: McpToolHookContext & { error: Error }) => void)[]; readonly 'mcp:tool:gate'?: readonly ((ctx: McpToolHookContext & { block: boolean; reason: string; result?: string | ToolResultContent[] }) => void)[]; readonly 'mcp:tool:transform'?: readonly ((ctx: McpToolHookContext & { outputBytes: number; result: string | ToolResultContent[] }) => void)[]; readonly 'mcp:tools:filter'?: readonly ((ctx: { server: string; tools: { description?: string | null; inputSchema?: unknown; name: string }[]; transport: 'sse' | 'stdio' | 'streamable-http' }) => void)[]; readonly 'mcp:tools:list'?: readonly ((ctx: { name: string; tools: readonly McpToolSchema[]; transport: 'sse' | 'stdio' | 'streamable-http' }) => void)[]; readonly 'mcp:warn'?: readonly ((ctx: { message: string; name: string }) => void)[]; readonly 'model:fallback'?: readonly ((ctx: StreamHookContext & { discardedThinking?: true; err: Error; from: { model: string; provider: string }; targetIndex: number; to: { model: string; provider: string } }) => void)[]; readonly 'oauth:refresh'?: readonly ((ctx: OAuthRefreshHookContext) => void)[]; readonly output?: readonly ((ctx: { output: Record<string, unknown>; schema: Record<string, unknown> }) => void)[]; readonly 'pairing:repair'?: readonly ((ctx: PairingRepair & { turnId?: string }) => void)[]; readonly 'provider:diagnostic'?: readonly ((ctx: ProviderDiagnostic & { runId: string; turnId: string }) => void)[]; readonly 'provider:input-transformations'?: readonly ((ctx: InputTransformationsHookContext) => void)[]; readonly 'repeat-guard:exceeded'?: readonly ((ctx: { action: 'steer' | 'block' | 'abort'; count: number; threshold: number; tool: string; turnId: string }) => void)[]; readonly 'replay:done'?: readonly ((ctx: Record<string, never>) => void)[]; readonly 'resume:mismatch'?: readonly ((ctx: { reason: string; resumeTurn: number; runId: string; sessionId: string; storedTurns: readonly number[] }) => void)[]; readonly 'run:beforeEnd'?: readonly ((ctx: { followUp: (message: string) => void; runId: string; session?: Session; turn: number }) => void | Promise<void>)[]; readonly 'session:end'?: readonly ((ctx: SessionHookContext & { runId: string; session?: Session; status: SessionEndStatus; turnRange: [number, number] }) => void)[]; readonly 'session:meta'?: readonly ((ctx: SessionHookContext & { key: string; value: unknown }) => void)[]; readonly 'session:save'?: readonly ((ctx: SessionHookContext) => void)[]; readonly 'session:start'?: readonly ((ctx: SessionHookContext & { prompt: string; runId: string }) => void)[]; readonly 'session:turns'?: readonly ((ctx: SessionHookContext & { count: number; turns: SessionTurn[] }) => void)[]; readonly 'skills:activate'?: readonly ((ctx: { skill: SkillConfig; via: ActivationVia }) => void)[]; readonly 'skills:catalog'?: readonly ((ctx: { catalog: string; skills: SkillConfig[] }) => void)[]; readonly 'skills:deactivate'?: readonly ((ctx: { reason: DeactivationReason; skill: SkillConfig }) => void)[]; readonly 'skills:resolve'?: readonly ((ctx: { skills: SkillConfig[] }) => void)[]; readonly 'spawn:before'?: readonly ((ctx: SpawnHookContext) => void)[]; readonly 'spawn:complete'?: readonly ((ctx: ChildRunStats) => void)[]; readonly 'spawn:error'?: readonly ((ctx: SpawnHookContext & { error: Error }) => void)[]; readonly 'spawn:queued'?: readonly ((ctx: SpawnQueuedContext) => void)[]; readonly 'steer:inject'?: readonly ((ctx: { content: readonly PromptPart[]; id?: string; text: string }) => void)[]; readonly 'stream:end'?: readonly ((ctx: StreamHookContext & { text: string }) => void)[]; readonly 'stream:error'?: readonly ((ctx: StreamHookContext & { err: unknown; requestId?: string; statusCode?: number }) => void)[]; readonly 'stream:progress'?: readonly ((ctx: StreamProgressHookContext) => void)[]; readonly 'stream:retry'?: readonly ((ctx: StreamHookContext & { attempt: number; delayMs: number; discardedText?: true; discardedThinking?: true; err: unknown; maxAttempts: number; nextAttempt: number; requestId?: string; statusCode?: number }) => void)[]; readonly 'stream:server_tool_result'?: readonly ((ctx: StreamHookContext & { content: unknown; toolName: string; toolUseId: string }) => void)[]; readonly 'stream:server_tool_use'?: readonly ((ctx: StreamHookContext & { id: string; input: Record<string, unknown>; name: string }) => void)[]; readonly 'stream:start'?: readonly ((ctx: StreamHookContext & { startedAt: number }) => void)[]; readonly 'stream:text'?: readonly ((ctx: StreamHookContext & { delta: string; text: string }) => void)[]; readonly 'stream:thinking'?: readonly ((ctx: StreamHookContext & { delta: string; thinking: string }) => void)[]; readonly 'system:before'?: readonly ((ctx: { system: string }) => void)[]; readonly 'system:transform'?: readonly ((ctx: { messages: readonly SessionMessage[]; session?: Session; system: string; turn: number; turnId: string }) => void)[]; readonly 'tool-batch:resumed'?: readonly ((ctx: { done: readonly string[]; resuming: readonly string[]; runId: string; turn: number; turnId: string }) => void)[]; readonly 'tool-budget:exceeded'?: readonly ((ctx: { count: number; max: number; mode: 'steer' | 'block'; tool: string; turnId: string }) => void)[]; readonly 'tool-results:after'?: readonly ((ctx: { message: SessionTurn; results: readonly ToolResult[]; turn: number; turnId: string }) => void)[]; readonly 'tool-state:commit-failed'?: readonly ((ctx: { callId: string; error: Error; handled?: boolean; ops: readonly ToolStateOp[]; runId: string; toolName: string }) => void)[]; readonly 'tool:after'?: readonly ((ctx: ToolHookContext & { coercions?: readonly string[]; isError: boolean; outcome?: ToolOutcome; outputBytes: number; result: string | ToolResultContent[]; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'tool:before'?: readonly ((ctx: ToolHookContext & { coercions?: readonly string[]; priorContent?: string; runToolCounts: Readonly<Record<string, number>>; unknown?: boolean }) => void)[]; readonly 'tool:cancelled'?: readonly ((ctx: ToolHookContext & { reason: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'tool:dispatched'?: readonly ((ctx: ToolHookContext & { outcome: 'execute' | 'gate-substitute' | 'gate-block' | 'unknown' | 'invalid-input'; reason?: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'tool:error'?: readonly ((ctx: ToolHookContext & { error: Error; result?: string | ToolResultContent[] }) => void)[]; readonly 'tool:gate'?: readonly ((ctx: ToolHookContext & ToolGateResumeFields & { block: boolean; metadata: ToolResultMetadata; reason: string; result?: string | ToolResultContent[]; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'tool:progress'?: readonly ((ctx: ToolHookContext & { progress: ToolProgress }) => void)[]; readonly 'tool:transform'?: readonly ((ctx: ToolHookContext & { coercions?: readonly string[]; isError: boolean; metadata: ToolResultMetadata; outputBytes: number; result: string | ToolResultContent[] }) => void)[]; readonly 'tool:unknown'?: readonly ((ctx: ToolHookContext & { result?: string | ToolResultContent[]; suppressError: boolean }) => void)[]; readonly 'tracing:redact'?: readonly ((ctx: { kind: 'system' | 'prompt' | 'tool-input' | 'tool-result' | 'mcp-tool-input' | 'mcp-tool-result' | 'stream-text' | 'stream-thinking' | 'decision-answers'; meta?: Readonly<Record<string, unknown>>; redacted: string; value: string }) => void)[]; readonly 'turn:after'?: readonly ((ctx: { aborted?: boolean; cumulativeUsage: Readonly<{ cacheCreation: number; cacheRead: number; cost?: number; input: number; output: number; turns: number }>; message: SessionTurn; toolCounts: { run: Readonly<Record<string, number>>; turn: Readonly<Record<string, number>> }; turn: number; turnId: string; usage: TurnUsage }) => void)[]; readonly 'turn:before'?: readonly ((ctx: { options: StreamOptions; turn: number; turnId: string }) => void)[]; readonly usage?: readonly ((ctx: { totalIn: number; totalOut: number; turn: number; turnId: string; usage: TurnUsage }) => void)[]; readonly 'validation:coerce'?: readonly ((ctx: ToolHookContext & { coercions: readonly string[]; schema: Record<string, unknown> }) => void)[]; readonly 'validation:reject'?: readonly ((ctx: ToolHookContext & { reason: string; schema: Record<string, unknown> }) => void)[] }`): Agent-hook observers, bucketed per event (only when the host wired no agent hooks of its own).
- `inlineAutocompleteProviders` (`readonly InlineAutocompleteProvider[]`): Inline ghost-text autocomplete providers.
- `mcpServers` (`readonly McpServerConfig[]`): MCP servers the extension added.
- `palette` (`readonly ExtensionPaletteProviderEntry[]`): Command palette providers.
- `panels` (`readonly ExtensionPanelEntry[]`): `Panel` items, ids namespaced `<extension>/<id>`.
- `plugins` (`readonly LoadedPluginRecord[]`): Agent Plugins loaded via `ctx.plugins.load`, in load order.
- `providers` (`Readonly<Record<string, ProviderDescriptor>>`): Provider descriptors, keyed by descriptor key.
- `references` (`readonly ExtensionOrderedContribution<ExtensionReferenceProvider>[]`): `Reference` items.
- `runSettled` (`readonly ExtensionRunSettledHandler[]`): `run:settled` observers (only when the host emits no host events of its own).
- `sessionEvents` (`readonly ExtensionSessionEventHandler[]`): `session:event` observers (only when the host emits no host events of its own).
- `skills` (`readonly SkillConfig[]`): Skills the extension added.
- `subagents` (`Readonly<Record<string, SubagentDef>>`): Spawnable subagents, keyed by name.
- `themes` (`Readonly<Record<string, Theme>>`): `Theme` items, keyed by theme id.
- `toolResultMetadata` (`readonly ExtensionOrderedContribution<ExtensionToolResultMetadataRegistration>[]`): Tool-result metadata namespaces the extension claimed (`ctx.tools.metadata`).
- `tools` (`Readonly<Record<string, ToolDef>>`): Tools the extension added to the catalog, keyed by name.
- `tui` (`TuiContributions`): TUI keybindings and footer hints of the extension's commands.

Source: [src/extensions/types.ts:712](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L712)

### `ExtensionCreateSessionParams`

Interface.

What `ctx.sessions.create()` takes.

```ts
interface ExtensionCreateSessionParams
```

**Properties**

- `agentId?` (`string`): Agent profile id.
- `cwd` (`string`): Folder the session runs in; `''` for none.
- `modelId?` (`string`): Model id.
- `prompt?` (`string`): First prompt, sent at once. Omit to create a session that waits (an orchestrator waiting for events).
- `providerKey?` (`string`): Provider registry key, with `modelId`.
- `subscribe?` (`ExtensionSessionScope`): Sessions whose events it receives as `<session-event>` turns. `{}` = every session.
- `title?` (`string`): Its title.
- `tools?` (`readonly ExtensionOrchestrationTool[]`): Orchestration tools it holds: `sessions` (drive sessions), `interactions` (answer their prompts).

Source: [src/extensions/host-runtime.ts:105](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L105)

### `ExtensionDefinition`

Interface.

An extension. Export it as the module's default export, either through
`defineExtension` or as a plain object (no import needed).

```ts
interface ExtensionDefinition<S extends SettingsSchema = SettingsSchema>
```

**Type parameters**

- `S` (`extends SettingsSchema`, default `SettingsSchema`): The settings schema, so `ctx.settings.get` is typed.

**Properties**

- `apiVersion` (`1`): Must be `1`.
- `dependencies?` (`Readonly<Record<string, string>>`): Other extensions this one builds on: `{ id: semver range }`. Sets the load
  order and gives install hints. A missing dependency never fails a load;
  `ctx.use` reports it as inactive.
- `description?` (`string`): One line shown in Settings.
- `displayName?` (`string`): Name shown in Settings. Defaults to `id`.
- `icon?` (`{ gui?: string; tui?: string }`): The extension's icon in each app's vocabulary: `gui` an icon class for
  the desktop and web apps (a Phosphor class such as `'i-ph-git-branch'`),
  `tui` a short glyph for the terminal app. The settings sidebar draws it
  on the extension's entry. Absent: a letter badge of the display name.
- `id` (`string`): Lowercase id, words joined by `-`. Equals the folder name for discovered extensions. Prefixes every id the extension contributes.
- `settings?` (`S`): Settings the extension reads. Shown in Settings even when the extension is off.
- `setup` (`(ctx: ExtensionContext<S>) => void | Cleanup | Promise<void | Cleanup>`): Runs once per load. Register what the extension adds. May return a
  cleanup that runs when the extension unloads. Registrations made later
  (after an await, from a handler) work until the extension unloads.
- `tui?` (`string`): Entry exporting OpenTUI React components for the terminal app. Default `tui.tsx` when present.
- `ui?` (`string`): Entry exporting React components for the desktop and web apps. Default `ui.tsx` when present.
- `version?` (`string`): Semver of the extension.

Source: [src/extensions/api/define.ts:18](https://github.com/Tahul/zidane/blob/main/src/extensions/api/define.ts#L18)

### `ExtensionEventQuery`

Interface.

What `ctx.sessions.events()` searches for. Every field narrows.

```ts
interface ExtensionEventQuery
```

**Properties**

- `limit?` (`number`): How many, newest first (default 20, at most 100).
- `sessionId?` (`string`): Only this session's events.
- `since?` (`number`): Only events after this `seq`.
- `status?` (`'error' | 'done' | 'needs-attention' | 'cancelled'`): Only events of this status.
- `text?` (`string`): Text in the title, summary, goal, detail or folder.

Source: [src/extensions/host-runtime.ts:147](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L147)

### `ExtensionFooterHint`

Interface.

Footer hint entry contributed by an extension.

Hints whose `key` parses as a real chord (`ctrl+j`, `^J`, `⌘+k`, `f6`,
…) are CLICKABLE in the TUI: a click synthesizes that exact keypress
through the input pipeline, so pair the hint with a
`registerKeybinding` handler for the same chord and the button works
by mouse and keyboard alike. Decorative keys that don't parse render
as inert text.

```ts
interface ExtensionFooterHint
```

**Properties**

- `key` (`string`): Display string for the chord (e.g. `'^J'`, `'⌘+k'`).
- `label` (`string`): Short label rendered next to the chord.

Source: [src/extensions/types.ts:641](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L641)

### `ExtensionHookHandlers`

Interface.

Handlers an extension put on its own agent-hook bus and host events (when the host gave no agent hooks).

```ts
interface ExtensionHookHandlers
```

**Properties**

- `agent` (`ReadonlyMap<string, ReadonlySet<(...args: unknown[]) => unknown>>`, readonly): Agent-hook handlers, by hook name.
- `host` (`ReadonlyMap<HostEventName, ReadonlySet<(event: never) => void>>`, readonly): Host-event handlers, by event name.

Source: [src/extensions/runtime/host.ts:226](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/host.ts#L226)

### `ExtensionHostRuntimeBridge`

Interface.

Connects a host to the runtime surfaces extensions see as `ctx.runtime`, `ctx.sessions`, `ctx.workspace` and `ctx.artifacts`.

```ts
interface ExtensionHostRuntimeBridge
```

**Properties**

- `attach` (`(impl: ExtensionHostRuntimeImpl) => () => void`): Process-wide attachment — a single-session host (the TUI) attaches the
  active session's impl once and swaps it on session change.
- `attachSessionControl` (`(control: ExtensionSessionControl) => () => void`): Attach the chat host's session control (one per bridge; the newest wins). Returns a detach.
- `current` (`() => ExtensionHostRuntimeImpl | null`): Returns the implementation in effect: the innermost `runWith` scope, else the attached one, else `null`.
- `runWith` (`<T>(impl: ExtensionHostRuntimeImpl, fn: () => Promise<T>) => Promise<T>`): Async-scoped attachment — a multi-session host (daemon, GUI) runs a
  command for session X inside `runWith(implForX, …)`; every
  `ctx.runtime` / `ctx.sessions` / `ctx.workspace` call made anywhere in
  that async tree resolves to X, even while another session's command
  runs concurrently. Takes precedence over `attach` inside the scope.
- `scheduleHandlers` (`ExtensionScheduleHandlers`): The extensions' `ctx.schedules.onFire` handlers; the host's scheduler reads them.
- `sessionControl` (`() => ExtensionSessionControl | null`): The attached session control, or `null`.

Source: [src/extensions/host-runtime.ts:410](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L410)

### `ExtensionHostRuntimeImpl`

Interface.

What a host attaches to power the runtime surfaces.

```ts
interface ExtensionHostRuntimeImpl
```

**Properties**

- `appendNote` (`(blocks: readonly CommandOutputBlock[]) => boolean`): Appends output blocks to the active transcript. Returns whether the host accepted them.
- `artifacts?` (`() => ExtensionArtifactScope | null`): Backing for `ctx.artifacts`. Optional so pre-artifact host impls keep
  typechecking; the facade treats absence (or a store without artifact
  methods) as an empty store.
- `createSession` (`() => Promise<boolean>`): Opens a new, empty session in this window (`ctx.ui.newSession`). Resolves to whether one was opened.
- `model` (`() => string | null`): Returns the active model id, or `null` when none is selected.
- `models?` (`() => readonly ExtensionModelEntry[]`): Model catalog across every provider the user has credentials for.
  Optional so pre-catalog host impls keep typechecking; the facade
  treats absence as an empty catalog.
- `setThinking` (`(level: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive') => boolean`): Sets the thinking level. Returns whether the host accepted it.
- `switchSession` (`(id: string) => Promise<boolean>`): Shows session `id` in this window (`ctx.ui.openSession`). Resolves to whether it did.
- `thinking` (`() => 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive' | null`): Returns the active thinking level, or `null` when none applies.
- `workspace?` (`() => Promise<ExtensionWorkspacePair | ExtensionWorkspaceOps | null>`): Resolve the ACTIVE session's execution pair, spawning the handle if
  no run has created it yet (`agent.ensureExecution()`). `null` when
  no agent/session is live; REJECT when a live agent's spawn fails
  (daemon down, spawn timeout) so the facade surfaces the real error
  instead of a generic "detached". Optional so pre-workspace host
  impls keep typechecking; the facade treats absence as detached.
  A host whose execution lives in another process returns session-bound
  [`ExtensionWorkspaceOps`](https://zidane.si/docs/reference/extensions.md#ExtensionWorkspaceOps) instead of a pair.
- `workspaceAvailable?` (`() => boolean`): Side-effect-free availability signal ("is there a live agent?").
  MUST NOT spawn: `workspace()` may boot a container on first call,
  and `ctx.workspace.available()` — a guard extensions call casually,
  even at setup — must never pay that price to answer a boolean.
  Optional; when absent the facade falls back to `workspace()` (with
  its side effects — implement this on any host with heavy spawns).

Source: [src/extensions/host-runtime.ts:313](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L313)

### `ExtensionInfo`

Interface.

An extension as `ctx.extensions` reports it.

```ts
interface ExtensionInfo
```

**Properties**

- `displayName` (`string`): The name shown in the UI.
- `error?` (`string`): Why the extension failed, for `'failed'`.
- `icon?` (`{ gui?: string; tui?: string }`): The extension's icon (`ExtensionDefinition.icon`), when it declares one.
- `id` (`string`): The extension id.
- `source` (`ExtensionSource`): Where the extension was found.
- `status` (`'failed' | 'disabled' | 'active'`): `'active'` is running, `'disabled'` is turned off, `'failed'` did not load.
- `version?` (`string`): The extension's version, when it declares one.

Source: [src/extensions/api/context.ts:19](https://github.com/Tahul/zidane/blob/main/src/extensions/api/context.ts#L19)

### `ExtensionInstallCandidate`

Interface.

One installable extension found inside a fetched tree.

```ts
interface ExtensionInstallCandidate
```

**Properties**

- `dir` (`string`): Absolute directory inside the fetched tree.
- `name` (`string`): Proposed name (manifest name, else collection dirname, else repo/pkg basename).

Source: [src/extensions/install.ts:134](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L134)

### `ExtensionInstallOrigin`

Interface.

Where an installed extension came from, from its `.install.json`: what Settings shows ("Update from <label>").

```ts
interface ExtensionInstallOrigin
```

**Properties**

- `commit?` (`string`): The exact commit, when the install cloned it.
- `installedAt?` (`string`): When it was installed (ISO 8601), when recorded.
- `label` (`string`): A short name of the source: `Tahul/zidane`, `Tahul/zidane@v9.0.4`, `@scope/pkg`.
- `source` (`string`): The resolved provenance (`github:Tahul/zidane@v9.0.4:extensions/goal`, `npm:pkg@1.2.3`).
- `spec` (`string`): The spec it was installed from, what an update re-resolves (`Tahul/zidane#v9.0.4:extensions/goal`).

Source: [src/extensions/install.ts:120](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L120)

### `ExtensionInstallProvenance`

Interface.

What `.install.json` records — enough to replay the install for updates.

```ts
interface ExtensionInstallProvenance
```

**Properties**

- `commit?` (`string`): Exact commit SHA (GitHub via git clone) — anchors the update no-op check.
- `extension?` (`string`): Candidate selected from a multi-extension source, when one was.
- `installedAt` (`string`): ISO 8601 timestamp of the install.
- `scope` (`InstallScope`): Scope the extension was installed into.
- `source` (`string`): Resolved provenance, e.g. `npm:foo@1.2.3` / `github:owner/repo@main`.
- `spec` (`string`): The raw spec the user passed — what an update re-resolves.

Source: [src/extensions/install.ts:104](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L104)

### `ExtensionInstallResult`

Interface.

Outcome of an install or update.

```ts
interface ExtensionInstallResult
```

**Properties**

- `commit?` (`string`): Exact commit SHA when known (GitHub via git clone).
- `dir` (`string`): Absolute installed directory.
- `name` (`string`): Final name — the validated `definition.name`.
- `provenance` (`string`): Human-readable provenance, e.g. `npm:foo@1.2.3` / `github:owner/repo@main`.
- `scope` (`InstallScope`): Scope the extension was installed into.
- `warnings` (`readonly string[]`): Non-fatal problems met during the install, such as dependency install notices.

Source: [src/extensions/install.ts:142](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L142)

### `ExtensionKeybinding`

Interface.

A TUI keybinding contributed by an extension. The `id` is namespaced
by convention (`<ext-name>.<action>`) so two extensions registering
the same logical action don't collide. `onTrigger` runs synchronously
inside the TUI keyboard dispatcher — heavy work should hop to its
own microtask.

`default` is a spec string in the same grammar as `keybindings.json`
(e.g. `'ctrl+shift+j'`); pass `''` to leave the action unbound by
default while still registering the id so users can rebind it via
their personal `keybindings.json`.

```ts
interface ExtensionKeybinding
```

**Properties**

- `default` (`string`): Default chord spec. Empty string = unbound by default.
- `description` (`string`): Longer description rendered in the keybindings panel.
- `id` (`string`): Globally-unique id, namespaced by extension.
- `label` (`string`): Short label used in shortcut hint rows.
- `onTrigger` (`(ctx: ExtensionKeybindingDispatchContext) => void | Promise<void>`): Fires when the chord matches. The dispatcher passes a minimal env.

Source: [src/extensions/types.ts:607](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L607)

### `ExtensionKeybindingDispatchContext`

Interface.

Argument the TUI dispatcher hands to `ExtensionKeybinding.onTrigger`.
Intentionally tiny — the extension can capture whatever it needs from
`setup`'s closure. Extra fields may be added in minor releases; treat
unknown ones as forward-compat noise.

```ts
interface ExtensionKeybindingDispatchContext
```

**Properties**

- `extensionName` (`string`): Id of the extension that owns the binding.

Source: [src/extensions/types.ts:626](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L626)

### `ExtensionManifest`

Interface.

Static metadata an extension declares in `extension.json` or the `zidane` key of `package.json`.
Discovery reads it before the module runs, so a bad `apiVersion` or `name` fails the load early.

```ts
interface ExtensionManifest
```

**Properties**

- `apiVersion?` (`number`): Extension API version the module targets. Must be `1`; anything else fails the load.
- `description?` (`string`): One-line description for settings UIs.
- `displayName?` (`string`): Human-readable name for settings UIs.
- `icon?` (`{ gui?: string; tui?: string }`): Icon for settings UIs: `gui` an icon class (`'i-ph-git-branch'`), `tui` a short glyph. Same shape as the definition's `icon`.
- `name?` (`string`): Extension name. Must match the folder name when set.

Source: [src/extensions/types.ts:53](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L53)

### `ExtensionMcpHost`

Interface.

The host side of `ctx.mcp`, shared by every extension of a registry build.

```ts
interface ExtensionMcpHost
```

**Properties**

- `callTool` (`(cwd: string, server: string, tool: string, args: Record<string, unknown>, opts: { signal?: AbortSignal; timeout?: number }) => Promise<ExtensionMcpToolResult>`): Call one of `server`'s tools by its own (un-namespaced) name.
- `dispose?` (`() => Promise<void>`): Close every connection this host opened.
- `servers` (`(cwd: string) => Promise<readonly ExtensionMcpServerInfo[]>`): Enabled servers for `cwd` (discovered `mcps.json` entries through the allowlist).

Source: [src/extensions/mcp-host.ts:13](https://github.com/Tahul/zidane/blob/main/src/extensions/mcp-host.ts#L13)

### `ExtensionMcpServerInfo`

Interface.

One server `ctx.mcp.servers()` reports.

```ts
interface ExtensionMcpServerInfo
```

**Properties**

- `command?` (`string`): Launch command, for stdio transports.
- `name` (`string`): Server name as configured.
- `toolPrefix` (`string`): The prefix the agent gives this server's tools (`mcp_<name>_`): match tool names in hooks and `detect` against it.
- `transport` (`'sse' | 'stdio' | 'streamable-http'`): Transport the server uses.
- `url?` (`string`): Server URL, for URL-based transports.

Source: [src/extensions/types.ts:504](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L504)

### `ExtensionMcpToolResult`

Interface.

What an MCP tool call answered. In-band tool errors resolve with `isError: true`.

```ts
interface ExtensionMcpToolResult
```

**Properties**

- `isError` (`boolean`): `true` when the tool reported an error in its answer.
- `text` (`string`): Text content of the answer.

Source: [src/extensions/types.ts:518](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L518)

### `ExtensionModelEntry`

Interface.

One row of `ctx.runtime.models()` — a model offered by a provider the
user has credentials for. `provider.key` is the registry key (stable id,
e.g. `anthropic`); `provider.name` is the display name. `model` mirrors
the host's [`ModelInfo`](https://zidane.si/docs/reference/chat.md#ModelInfo) (id, context window, cost, …).

```ts
interface ExtensionModelEntry
```

**Properties**

- `model` (`ModelInfo`): Catalog entry for the model.
- `provider` (`{ key: string; name: string }`): Provider offering the model: registry `key` and display `name`.

Source: [src/extensions/host-runtime.ts:47](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L47)

### `ExtensionOrderedContribution`

Interface.

A contribution tagged with the extension that made it, kept in registration order.

```ts
interface ExtensionOrderedContribution<T>
```

**Type parameters**

- `T`

**Properties**

- `extensionName` (`string`): Name of the contributing extension.
- `source` (`LoadedExtensionSource`): Where the contributing extension was loaded from.
- `value` (`T`): The contributed value.

Source: [src/extensions/types.ts:586](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L586)

### `ExtensionPaletteProviderEntry`

Interface.

Registry entry: a host-facing [`PaletteProvider`](https://zidane.si/docs/reference/chat-pure.md#PaletteProvider) plus its owner and default group.

```ts
interface ExtensionPaletteProviderEntry extends PaletteProvider
```

**Properties**

- `group` (`string`): Section header used for items that set no group of their own.
- `id` (`string`, from `PaletteProvider`): Provider id, stamped on its items as `source`.
- `items` (`(ctx: PaletteContext) => readonly PaletteItem[] | Promise<readonly PaletteItem[]>`, from `PaletteProvider`): Items for the current context. Called on open, on `subscribe` emits, and on explicit refresh.
- `owner` (`string`): Name of the registering extension.
- `run` (`(itemId: string, ctx: PaletteContext) => PaletteRunResult | Promise<PaletteRunResult>`, from `PaletteProvider`): Runs the item with the given id. May return a follow-up result.
- `subscribe?` (`(emit: () => void) => () => void`, from `PaletteProvider`): Live updates while the palette is open, same contract as panels.

Source: [src/extensions/types.ts:657](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L657)

### `ExtensionPanel`

Interface.

A side-panel tab an extension registers with `ctx.registerPanel`.

```ts
interface ExtensionPanel
```

**Properties**

- `home?` (`PanelHomeLayout`): Its default place on the project home (`'home'` surface only).
- `icon?` (`PanelIcon`): Tab icon. Absent: apps draw the extension's own mark (its icon, else its logo, else its first letter).
- `id` (`string`): Stable id; namespaced `<extension>/<id>` at registration.
- `label` (`string`): Tab label.
- `load` (`(ctx: PanelLoadContext) => PanelContent | Promise<PanelContent>`): Produce the current content. Called on open, on `subscribe` emits, and on explicit refresh.
- `onAction?` (`(actionId: string, payload: JsonValue | undefined, ctx: PanelLoadContext) => void | Promise<void>`): Row / button callbacks. Runs where the extension runs.
- `scope?` (`ExtensionPanelScope`): Where the side tab shows. Default `'session'`: only beside a session.
  Opt in with `'project'` / `'both'` to also show where only a folder is
  open (the GUI's new-chat screen); `load` then gets `scope: 'project'`
  and no `sessionId`, and must work from `cwd` alone. Home blocks always
  load that way, whatever `scope` says.
- `subscribe?` (`(emit: (change?: { sessionId?: string }) => void) => () => void`): Live updates: call `emit()` whenever `load()` would return something
  new; `emit({ sessionId })` when only that session's content changed.
  Return an unsubscribe. Hosts debounce emits and only reload while the
  panel is visible.
- `surfaces?` (`readonly PanelSurface[]`): The surfaces it shows on. Default `['side']`. Add `'home'` for a block
  on the project home (`ctx.surface === 'home'` in `load`); `['home']`
  alone keeps it out of the side panel.

Source: [src/extensions/panels.ts:629](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L629)

### `ExtensionPanelEntry`

Interface.

Registry entry: the definition plus its owning extension.

```ts
interface ExtensionPanelEntry extends ExtensionPanel
```

**Properties**

- `home?` (`PanelHomeLayout`, from `ExtensionPanel`): Its default place on the project home (`'home'` surface only).
- `icon?` (`PanelIcon`, from `ExtensionPanel`): Tab icon. Absent: apps draw the extension's own mark (its icon, else its logo, else its first letter).
- `id` (`string`, from `ExtensionPanel`): Stable id; namespaced `<extension>/<id>` at registration.
- `label` (`string`, from `ExtensionPanel`): Tab label.
- `load` (`(ctx: PanelLoadContext) => PanelContent | Promise<PanelContent>`, from `ExtensionPanel`): Produce the current content. Called on open, on `subscribe` emits, and on explicit refresh.
- `onAction?` (`(actionId: string, payload: JsonValue | undefined, ctx: PanelLoadContext) => void | Promise<void>`, from `ExtensionPanel`): Row / button callbacks. Runs where the extension runs.
- `owner` (`string`): Name of the registering extension.
- `ownerIcon?` (`PanelIcon`): The registering extension's own icon. Apps draw its mark when the panel has no `icon`.
- `ownerName?` (`string`): The registering extension's display name: with `ownerIcon`, what apps draw its mark from (`extensionMark`).
- `scope?` (`ExtensionPanelScope`, from `ExtensionPanel`): Where the side tab shows. Default `'session'`: only beside a session.
  Opt in with `'project'` / `'both'` to also show where only a folder is
  open (the GUI's new-chat screen); `load` then gets `scope: 'project'`
  and no `sessionId`, and must work from `cwd` alone. Home blocks always
  load that way, whatever `scope` says.
- `subscribe?` (`(emit: (change?: { sessionId?: string }) => void) => () => void`, from `ExtensionPanel`): Live updates: call `emit()` whenever `load()` would return something
  new; `emit({ sessionId })` when only that session's content changed.
  Return an unsubscribe. Hosts debounce emits and only reload while the
  panel is visible.
- `surfaces?` (`readonly PanelSurface[]`, from `ExtensionPanel`): The surfaces it shows on. Default `['side']`. Add `'home'` for a block
  on the project home (`ctx.surface === 'home'` in `load`); `['home']`
  alone keeps it out of the side panel.

Source: [src/extensions/panels.ts:666](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L666)

### `ExtensionPaths`

Interface.

Filesystem locations given to an extension.

```ts
interface ExtensionPaths
```

**Properties**

- `cacheDir` (`string`, readonly): Directory for disposable cached files.
- `configDir?` (`string`, readonly): Directory for user configuration.
- `cwd` (`string`, readonly): Working directory of the host.
- `dataDir` (`string`, readonly): Directory for persistent application data.
- `projectRoot?` (`string`, readonly): Project root, when the host resolved one.
- `stateDir?` (`string`, readonly): Directory for runtime state.

Source: [src/extensions/api/core.ts:123](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L123)

### `ExtensionPendingRequest`

Interface.

One prompt waiting for an answer, from `ctx.sessions.pending()`.

```ts
interface ExtensionPendingRequest
```

**Properties**

- `kind` (`'plan' | 'question' | 'approval'`): `question` (ask_user), `plan` (present_plan), `approval` (a tool call).
- `payload` (`unknown`): The questions and choices, the plan, or the tool and its input.
- `requestId` (`string`): The id to answer with.
- `sessionId` (`string`): The session waiting.
- `summary` (`string`): One line: what is asked.

Source: [src/extensions/host-runtime.ts:133](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L133)

### `ExtensionPromptBridge`

Interface.

Connects `ctx.submitPrompt` to the host's prompt pipeline. Hosts attach their handler after the UI mounts.

```ts
interface ExtensionPromptBridge
```

**Properties**

- `attach` (`(handler: (text: string, opts?: ExtensionPromptDelivery) => void) => () => void`): Attach the host handler (last attach wins). Returns a detach fn.
- `submit` (`(text: string, opts?: ExtensionPromptDelivery) => boolean`): Route a prompt to the host. `false` when no host handler is attached, the text is blank, or the handler throws.

Source: [src/extensions/prompt-bridge.ts:23](https://github.com/Tahul/zidane/blob/main/src/extensions/prompt-bridge.ts#L23)

### `ExtensionPromptDelivery`

Interface.

Prompt bridge — the host hand-off behind `ctx.submitPrompt`.

Extensions submit prompts at any point in their lifetime; the host (the
TUI, post-mount) attaches the single handler that routes them into its
real submit machinery (run-or-queue gate, `Agent.steer`, `Agent.followUp`).
Same holder idiom as the host runtime bridge. Prompts are deliberately NOT
buffered pre-attach: silently replaying stale prompts after mount would
be surprising — `submit` returns `false` so callers can react.

```ts
interface ExtensionPromptDelivery
```

**Properties**

- `delivery?` (`'auto' | 'steer' | 'followUp'`): `'auto'` (default) — run now when idle, join the follow-up queue when a
  run is active. `'steer'` — inject into the CURRENT run between turns
  (falls back to `auto` when idle). `'followUp'` — queue until the current
  run finishes (falls back to `auto` when idle).

Source: [src/extensions/prompt-bridge.ts:12](https://github.com/Tahul/zidane/blob/main/src/extensions/prompt-bridge.ts#L12)

### `ExtensionReferenceCard`

Interface.

A reference's hover card: what the host shows over the badge. JSON-safe, bounded.

```ts
interface ExtensionReferenceCard
```

**Properties**

- `body?` (`string`): A description, as Markdown. The host keeps at most 600 chars of it and
  renders headings, lists, emphasis, code and links; images and raw HTML
  are dropped.
- `facts?` (`readonly ExtensionReferenceCardFact[]`): Short facts (`Assignee: Ada`). At most 6.
- `subtitle?` (`string`): A line under the title (`Backend, Documentation`).
- `subtitleHref?` (`string`): Makes the subtitle a link. http(s) only.

Source: [src/extensions/types.ts:433](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L433)

### `ExtensionReferenceCardFact`

Interface.

One fact of a reference card.

```ts
interface ExtensionReferenceCardFact
```

**Properties**

- `diff?` (`{ added: number; files?: number; removed: number }`): A change size: hosts paint `+added −removed` in the diff colors, then `files`.
- `href?` (`string`): Makes the value a link (a profile, a repo; with `diff`, the diff itself). http(s) only.
- `label` (`string`): Fact name (`Assignee`).
- `value` (`string`): The text (also the fallback for hosts that don't paint `diff`).

Source: [src/extensions/types.ts:421](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L421)

### `ExtensionReferencePattern`

Interface.

A pattern a reference provider finds in text. Declarative so every host
matches the same way, in any process (the GUI renderer has no extension
runtime): `regex` is JavaScript RegExp source, run with the `g` flag plus
`flags` (`i`, `u`, `m`, `s`; others are ignored). `key` builds the key
handed to `resolve` from the match: `$0` is the whole match, `$1`… its
groups (default `$0`). A match whose key comes out empty is skipped.

```ts
interface ExtensionReferencePattern
```

**Properties**

- `flags?` (`string`): Extra RegExp flags (`i`, `u`, `m`, `s`). The `g` flag is always set.
- `key?` (`string`, default `'$0'`): Template that builds the key passed to `resolve`.
- `placeholder?` (`string`): For matches that are certainly a reference (an issue URL, not a bare id
  that may be `UTF-8`): a label template (`$0`, `$1`…, like `key`) the
  host paints as a badge at once, before `resolve` answers. Omitted: the
  text stays plain until the view is known.
- `placeholderIcon?` (`ExtensionBadgeIcon`): The icon the placeholder badge shows (the state icon arrives with the view).
- `regex` (`string`): JavaScript RegExp source to search for.

Source: [src/extensions/types.ts:402](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L402)

### `ExtensionReferenceProvider`

Interface.

Text references without a trigger character: ticket ids, issue URLs,
anything a pattern can find in prompts, assistant replies, and session
titles. Hosts match `patterns`, then ask `resolve` for each key; only a
key that resolves to a view paints as a badge, so a false positive
(`UTF-8` for a `[A-Z]+-\d+` pattern) stays plain text. Views are cached
by the host per `(provider, key)`.

Overlaps: the earliest match wins, then the longest; across providers,
registration order breaks ties.

```ts
interface ExtensionReferenceProvider
```

**Properties**

- `id` (`string`): Unique per registry (`<ext>.<what>`); first registration wins.
- `patterns` (`readonly ExtensionReferencePattern[]`): Patterns that find candidate references in text.
- `resolve` (`(key: string, ctx: { signal: AbortSignal }) => Promise<ExtensionReferenceView | undefined>`): The view for a key, or `undefined` when the key names nothing (no
  badge). Throws are treated as `undefined` and not cached.
- `surfaces?` (`readonly ExtensionReferenceSurface[]`): Surfaces to scan. Default: all.

Source: [src/extensions/types.ts:489](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L489)

### `ExtensionReferenceView`

Interface.

How a resolved reference paints: a badge in place of the matched text.

```ts
interface ExtensionReferenceView
```

**Properties**

- `card?` (`ExtensionReferenceCard`): Shown in a hover card over the badge, under `title` (hosts without one use `title` as a tooltip).
- `color?` (`string`): Exact icon color, over `tone`; see [`ExtensionBadgeColor`](https://zidane.si/docs/reference/extensions.md#ExtensionBadgeColor).
- `detail?` (`string`): A toned-down second part after the label (a ticket's title): muted, cut
  with an ellipsis where the badge runs out of room.
- `href?` (`string`): Link opened by the badge.
- `icon?` (`ExtensionBadgeIcon`): Leading icon.
- `label` (`string`): Badge label shown in place of the matched text.
- `prompt?` (`string`): What "Add to prompt" inserts (default: the matched text).
- `status?` (`string`): Short state shown after the label (`In Progress`).
- `title?` (`string`): Hover detail (the ticket's title).
- `tone?` (`ExtensionBadgeTone`): Tints the icon.

Source: [src/extensions/types.ts:449](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L449)

### `ExtensionRegistry`

Interface.

Every active extension's contributions, merged, as a LIVE view of the
extension runtime: each field reads the runtime's registries (cached
until they change), so a command, panel or palette entry registered
after `setup` shows up on the next read. `ExtensionRegistry.subscribe`
says when to read again.

- **Agent-loop surface** (`tools`, `hooks`, `mcpServers`, `skills`):
  folded into a `Preset` by `buildExtensionPreset`.
- **Config-level registries** (`themes`, `agents`, `providers`,
  `subagents`): merged into `ResolvedConfig`.
- **UI-bound** (`completionProviders`, `tuiContributions`, `panels`,
  `palette`, references, badge actions): passed to the renderer.
- **Settings** (`configCategories`, `configItems`): the settings rows
  of every active and disabled extension.

```ts
interface ExtensionRegistry
```

**Properties**

- `agents` (`Readonly<Record<string, AgentProfile>>`, readonly): Agent profiles, keyed by profile id.
- `artifactKinds` (`readonly ExtensionOrderedContribution<ExtensionArtifactKindRegistration>[]`, readonly): Artifact kind registrations across every active extension, deduped by
  kind (first registration wins). UIs resolve a stored artifact's kind
  against this list for presentation; unknown kinds fall back to
  `label` + `uri`.
- `badgeActions` (`readonly ExtensionOrderedContribution<ExtensionBadgeActions>[]`, readonly): Badge right-click actions.
- `commands` (`readonly Command[]`, readonly): `/` commands, deduped by name (first registration wins).
- `completionProviders` (`readonly CompletionProvider<unknown>[]`, readonly): Completion providers (TUI/GUI shared).
- `configCategories` (`Readonly<Record<string, ExtensionConfigCategory>>`, readonly): Settings categories of every active and disabled extension, keyed by category id (first wins).
- `configItems` (`Readonly<Record<string, Readonly<Record<string, StoredExtensionConfigItem>>>>`, readonly): Settings rows, namespaced `extensionName → key → item`, for every active and disabled extension.
- `contextBreakdownSections` (`readonly ContextBreakdownContributor[]`, readonly): Context breakdown contributors.
- `contextPanelSections` (`readonly ContextBreakdownContributor[]`, readonly): Context panel contributors, normalized to the contributor shape.
- `dispose` (`() => Promise<void>`): Disposes the runtime behind the view. Idempotent.
- `hooks` (`{ readonly 'agent:abort'?: readonly ((ctx: { reason?: string; runId?: string }) => void)[]; readonly 'agent:done'?: readonly ((ctx: AgentStats) => void)[]; readonly 'agent:start'?: readonly ((ctx: { agentName?: string; depth: number; parentRunId?: string; providerName?: string; runId: string; startedAt: number; tracingContext?: Readonly<Record<string, string>> }) => void)[]; readonly 'artifact:recorded'?: readonly ((ctx: { artifact: SessionArtifact; callId: string; name: string; runId: string; turnId: string }) => void)[]; readonly 'background:adopt'?: readonly ((ctx: { command: string; cwd: string; outputPath: string; pid: number; startedAt: number; taskId: string }) => void)[]; readonly 'background:exit'?: readonly ((ctx: { command: string; durationMs: number; exitCode: number; outputPath: string; signal?: Signals; status: 'exited' | 'killed'; taskId: string }) => void)[]; readonly 'background:reassign'?: readonly ((ctx: { childId?: string; command: string; fromHandleId: string; outputPath: string; pid: number; startedAt: number; taskId: string; toHandleId: string }) => void)[]; readonly 'background:reconcile'?: readonly ((ctx: { exits: TaskExitInfo[] }) => void)[]; readonly 'background:stall'?: readonly ((ctx: { bytesWritten: number; command: string; outputPath: string; stalledForMs: number; taskId: string }) => void)[]; readonly 'background:start'?: readonly ((ctx: { command: string; cwd: string; outputPath: string; pid: number; startedAt: number; taskId: string }) => void)[]; readonly 'budget:exceeded'?: readonly ((ctx: { budget: number; bytes: number; turn: number; turnId: string }) => void)[]; readonly 'cache:break'?: readonly ((info: CacheBreakInfo) => void | Promise<void>)[]; readonly 'cache:drift'?: readonly ((info: CacheDriftInfo) => void | Promise<void>)[]; readonly 'child:artifact:recorded'?: readonly ((ctx: { artifact: SessionArtifact; callId: string; childId: string; depth: number; name: string; runId: string; turnId: string }) => void)[]; readonly 'child:background:exit'?: readonly ((ctx: { childId: string; command: string; depth: number; durationMs: number; exitCode: number; outputPath: string; signal?: Signals; status: 'exited' | 'killed'; taskId: string }) => void)[]; readonly 'child:background:reassign'?: readonly ((ctx: { childId: string; command: string; depth: number; fromHandleId: string; outputPath: string; pid: number; startedAt: number; taskId: string; toHandleId: string }) => void)[]; readonly 'child:background:start'?: readonly ((ctx: { childId: string; command: string; cwd: string; depth: number; outputPath: string; pid: number; startedAt: number; taskId: string }) => void)[]; readonly 'child:mcp:tool:gate'?: readonly ((ctx: McpToolHookContext & { block: boolean; childId: string; depth: number; reason: string; result?: string | ToolResultContent[] }) => void)[]; readonly 'child:repeat-guard:exceeded'?: readonly ((ctx: { action: 'steer' | 'block' | 'abort'; childId: string; count: number; depth: number; threshold: number; tool: string; turnId: string }) => void)[]; readonly 'child:spawn:before'?: readonly ((ctx: ChildSpawnHookContext) => void)[]; readonly 'child:spawn:complete'?: readonly ((ctx: ChildRunStats & ChildSpawnIdentity) => void)[]; readonly 'child:spawn:error'?: readonly ((ctx: Omit<SpawnHookContext, 'tracingContext'> & ChildSpawnIdentity & { error: Error }) => void)[]; readonly 'child:stream:end'?: readonly ((ctx: StreamHookContext & { childId: string; depth: number; text: string }) => void)[]; readonly 'child:stream:error'?: readonly ((ctx: StreamHookContext & { childId: string; depth: number; err: unknown }) => void)[]; readonly 'child:stream:retry'?: readonly ((ctx: StreamHookContext & { attempt: number; childId: string; delayMs: number; depth: number; discardedText?: true; discardedThinking?: true; err: unknown; maxAttempts: number; nextAttempt: number; requestId?: string; statusCode?: number }) => void)[]; readonly 'child:stream:server_tool_result'?: readonly ((ctx: StreamHookContext & { childId: string; content: unknown; depth: number; toolName: string; toolUseId: string }) => void)[]; readonly 'child:stream:server_tool_use'?: readonly ((ctx: StreamHookContext & { childId: string; depth: number; id: string; input: Record<string, unknown>; name: string }) => void)[]; readonly 'child:stream:text'?: readonly ((ctx: StreamHookContext & { childId: string; delta: string; depth: number; text: string }) => void)[]; readonly 'child:stream:thinking'?: readonly ((ctx: StreamHookContext & { childId: string; delta: string; depth: number; thinking: string }) => void)[]; readonly 'child:tool:after'?: readonly ((ctx: ToolHookContext & { childId: string; coercions?: readonly string[]; depth: number; isError?: boolean; outcome?: ToolOutcome; outputBytes: number; result: string | ToolResultContent[]; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:before'?: readonly ((ctx: ToolHookContext & { childId: string; coercions?: readonly string[]; depth: number; priorContent?: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:cancelled'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; reason: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:dispatched'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; outcome: 'execute' | 'gate-substitute' | 'gate-block' | 'unknown' | 'invalid-input'; reason?: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:error'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; error: Error }) => void)[]; readonly 'child:tool:gate'?: readonly ((ctx: ToolHookContext & ToolGateResumeFields & { block: boolean; childId: string; depth: number; metadata: ToolResultMetadata; reason: string; result?: string | ToolResultContent[]; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'child:tool:progress'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; progress: ToolProgress }) => void)[]; readonly 'child:tool:transform'?: readonly ((ctx: ToolHookContext & { childId: string; coercions?: readonly string[]; depth: number; isError: boolean; metadata: ToolResultMetadata; outputBytes: number; result: string | ToolResultContent[] }) => void)[]; readonly 'child:turn:after'?: readonly ((ctx: { aborted?: boolean; childId: string; depth: number; message: SessionTurn; toolCounts: { run: Readonly<Record<string, number>>; turn: Readonly<Record<string, number>> }; turn: number; turnId: string; usage: TurnUsage }) => void)[]; readonly 'child:validation:reject'?: readonly ((ctx: ToolHookContext & { childId: string; depth: number; reason: string; schema: Record<string, unknown> }) => void)[]; readonly 'compact:end'?: readonly ((ctx: CompactEndHookContext) => void)[]; readonly 'compact:progress'?: readonly ((ctx: CompactProgressHookContext) => void)[]; readonly 'compact:restore'?: readonly ((ctx: { add: (call: { input: Record<string, unknown>; name: string; output: string }) => void; session?: Session }) => void | Promise<void>)[]; readonly 'compact:start'?: readonly ((ctx: CompactStartHookContext) => void)[]; readonly 'content-ref:resolve'?: readonly ((ctx: { block: ResolveContentRefBlock; childId?: string; data?: string; depth?: number }) => void)[]; readonly 'context:overflow'?: readonly ((ctx: StreamHookContext & { attempt: number; err: unknown }) => void)[]; readonly 'context:transform'?: readonly ((ctx: { messages: SessionMessage[] }) => void)[]; readonly 'decision:end'?: readonly ((ctx: DecisionEndHookContext) => void)[]; readonly 'decision:start'?: readonly ((ctx: DecisionStartHookContext) => void)[]; readonly 'execution:ready'?: readonly ((ctx: { handle: ExecutionHandle; spawned: boolean }) => void)[]; readonly 'history:repair'?: readonly ((ctx: HistoryRepairHookContext) => void)[]; readonly 'mcp:auth:error'?: readonly ((ctx: { error: Error; name: string }) => void)[]; readonly 'mcp:auth:required'?: readonly ((ctx: { name: string; reason: 'no-tokens' | 'auto-promoted'; transport: 'sse' | 'stdio' | 'streamable-http' }) => void)[]; readonly 'mcp:auth:success'?: readonly ((ctx: { name: string }) => void)[]; readonly 'mcp:auth:url'?: readonly ((ctx: { name: string; url: string }) => void)[]; readonly 'mcp:bootstrap:end'?: readonly ((ctx: { durationMs: number; name: string; transport: string } & ({ cached?: boolean; lazy?: boolean; ok: true; toolCount: number; warnings?: string[] } | { error: Error; ok: false })) => void)[]; readonly 'mcp:bootstrap:settled'?: readonly ((ctx: { results: readonly ({ durationMs: number; name: string; transport: string } & ({ lazy?: boolean; ok: true; toolCount: number } | { error?: Error; ok: false; skipped?: boolean }))[] }) => void)[]; readonly 'mcp:bootstrap:start'?: readonly ((ctx: { name: string; transport: string }) => void)[]; readonly 'mcp:close'?: readonly ((ctx: { name: string }) => void)[]; readonly 'mcp:connect'?: readonly ((ctx: { lazy?: boolean; name: string; tools: string[]; transport: string }) => void)[]; readonly 'mcp:error'?: readonly ((ctx: { error: Error; name: string }) => void)[]; readonly 'mcp:tool:after'?: readonly ((ctx: McpToolHookContext & { outputBytes: number; result: string | ToolResultContent[] }) => void)[]; readonly 'mcp:tool:before'?: readonly ((ctx: McpToolHookContext) => void)[]; readonly 'mcp:tool:error'?: readonly ((ctx: McpToolHookContext & { error: Error }) => void)[]; readonly 'mcp:tool:gate'?: readonly ((ctx: McpToolHookContext & { block: boolean; reason: string; result?: string | ToolResultContent[] }) => void)[]; readonly 'mcp:tool:transform'?: readonly ((ctx: McpToolHookContext & { outputBytes: number; result: string | ToolResultContent[] }) => void)[]; readonly 'mcp:tools:filter'?: readonly ((ctx: { server: string; tools: { description?: string | null; inputSchema?: unknown; name: string }[]; transport: 'sse' | 'stdio' | 'streamable-http' }) => void)[]; readonly 'mcp:tools:list'?: readonly ((ctx: { name: string; tools: readonly McpToolSchema[]; transport: 'sse' | 'stdio' | 'streamable-http' }) => void)[]; readonly 'mcp:warn'?: readonly ((ctx: { message: string; name: string }) => void)[]; readonly 'model:fallback'?: readonly ((ctx: StreamHookContext & { discardedThinking?: true; err: Error; from: { model: string; provider: string }; targetIndex: number; to: { model: string; provider: string } }) => void)[]; readonly 'oauth:refresh'?: readonly ((ctx: OAuthRefreshHookContext) => void)[]; readonly output?: readonly ((ctx: { output: Record<string, unknown>; schema: Record<string, unknown> }) => void)[]; readonly 'pairing:repair'?: readonly ((ctx: PairingRepair & { turnId?: string }) => void)[]; readonly 'provider:diagnostic'?: readonly ((ctx: ProviderDiagnostic & { runId: string; turnId: string }) => void)[]; readonly 'provider:input-transformations'?: readonly ((ctx: InputTransformationsHookContext) => void)[]; readonly 'repeat-guard:exceeded'?: readonly ((ctx: { action: 'steer' | 'block' | 'abort'; count: number; threshold: number; tool: string; turnId: string }) => void)[]; readonly 'replay:done'?: readonly ((ctx: Record<string, never>) => void)[]; readonly 'resume:mismatch'?: readonly ((ctx: { reason: string; resumeTurn: number; runId: string; sessionId: string; storedTurns: readonly number[] }) => void)[]; readonly 'run:beforeEnd'?: readonly ((ctx: { followUp: (message: string) => void; runId: string; session?: Session; turn: number }) => void | Promise<void>)[]; readonly 'session:end'?: readonly ((ctx: SessionHookContext & { runId: string; session?: Session; status: SessionEndStatus; turnRange: [number, number] }) => void)[]; readonly 'session:meta'?: readonly ((ctx: SessionHookContext & { key: string; value: unknown }) => void)[]; readonly 'session:save'?: readonly ((ctx: SessionHookContext) => void)[]; readonly 'session:start'?: readonly ((ctx: SessionHookContext & { prompt: string; runId: string }) => void)[]; readonly 'session:turns'?: readonly ((ctx: SessionHookContext & { count: number; turns: SessionTurn[] }) => void)[]; readonly 'skills:activate'?: readonly ((ctx: { skill: SkillConfig; via: ActivationVia }) => void)[]; readonly 'skills:catalog'?: readonly ((ctx: { catalog: string; skills: SkillConfig[] }) => void)[]; readonly 'skills:deactivate'?: readonly ((ctx: { reason: DeactivationReason; skill: SkillConfig }) => void)[]; readonly 'skills:resolve'?: readonly ((ctx: { skills: SkillConfig[] }) => void)[]; readonly 'spawn:before'?: readonly ((ctx: SpawnHookContext) => void)[]; readonly 'spawn:complete'?: readonly ((ctx: ChildRunStats) => void)[]; readonly 'spawn:error'?: readonly ((ctx: SpawnHookContext & { error: Error }) => void)[]; readonly 'spawn:queued'?: readonly ((ctx: SpawnQueuedContext) => void)[]; readonly 'steer:inject'?: readonly ((ctx: { content: readonly PromptPart[]; id?: string; text: string }) => void)[]; readonly 'stream:end'?: readonly ((ctx: StreamHookContext & { text: string }) => void)[]; readonly 'stream:error'?: readonly ((ctx: StreamHookContext & { err: unknown; requestId?: string; statusCode?: number }) => void)[]; readonly 'stream:progress'?: readonly ((ctx: StreamProgressHookContext) => void)[]; readonly 'stream:retry'?: readonly ((ctx: StreamHookContext & { attempt: number; delayMs: number; discardedText?: true; discardedThinking?: true; err: unknown; maxAttempts: number; nextAttempt: number; requestId?: string; statusCode?: number }) => void)[]; readonly 'stream:server_tool_result'?: readonly ((ctx: StreamHookContext & { content: unknown; toolName: string; toolUseId: string }) => void)[]; readonly 'stream:server_tool_use'?: readonly ((ctx: StreamHookContext & { id: string; input: Record<string, unknown>; name: string }) => void)[]; readonly 'stream:start'?: readonly ((ctx: StreamHookContext & { startedAt: number }) => void)[]; readonly 'stream:text'?: readonly ((ctx: StreamHookContext & { delta: string; text: string }) => void)[]; readonly 'stream:thinking'?: readonly ((ctx: StreamHookContext & { delta: string; thinking: string }) => void)[]; readonly 'system:before'?: readonly ((ctx: { system: string }) => void)[]; readonly 'system:transform'?: readonly ((ctx: { messages: readonly SessionMessage[]; session?: Session; system: string; turn: number; turnId: string }) => void)[]; readonly 'tool-batch:resumed'?: readonly ((ctx: { done: readonly string[]; resuming: readonly string[]; runId: string; turn: number; turnId: string }) => void)[]; readonly 'tool-budget:exceeded'?: readonly ((ctx: { count: number; max: number; mode: 'steer' | 'block'; tool: string; turnId: string }) => void)[]; readonly 'tool-results:after'?: readonly ((ctx: { message: SessionTurn; results: readonly ToolResult[]; turn: number; turnId: string }) => void)[]; readonly 'tool-state:commit-failed'?: readonly ((ctx: { callId: string; error: Error; handled?: boolean; ops: readonly ToolStateOp[]; runId: string; toolName: string }) => void)[]; readonly 'tool:after'?: readonly ((ctx: ToolHookContext & { coercions?: readonly string[]; isError: boolean; outcome?: ToolOutcome; outputBytes: number; result: string | ToolResultContent[]; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'tool:before'?: readonly ((ctx: ToolHookContext & { coercions?: readonly string[]; priorContent?: string; runToolCounts: Readonly<Record<string, number>>; unknown?: boolean }) => void)[]; readonly 'tool:cancelled'?: readonly ((ctx: ToolHookContext & { reason: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'tool:dispatched'?: readonly ((ctx: ToolHookContext & { outcome: 'execute' | 'gate-substitute' | 'gate-block' | 'unknown' | 'invalid-input'; reason?: string; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'tool:error'?: readonly ((ctx: ToolHookContext & { error: Error; result?: string | ToolResultContent[] }) => void)[]; readonly 'tool:gate'?: readonly ((ctx: ToolHookContext & ToolGateResumeFields & { block: boolean; metadata: ToolResultMetadata; reason: string; result?: string | ToolResultContent[]; runToolCounts: Readonly<Record<string, number>> }) => void)[]; readonly 'tool:progress'?: readonly ((ctx: ToolHookContext & { progress: ToolProgress }) => void)[]; readonly 'tool:transform'?: readonly ((ctx: ToolHookContext & { coercions?: readonly string[]; isError: boolean; metadata: ToolResultMetadata; outputBytes: number; result: string | ToolResultContent[] }) => void)[]; readonly 'tool:unknown'?: readonly ((ctx: ToolHookContext & { result?: string | ToolResultContent[]; suppressError: boolean }) => void)[]; readonly 'tracing:redact'?: readonly ((ctx: { kind: 'system' | 'prompt' | 'tool-input' | 'tool-result' | 'mcp-tool-input' | 'mcp-tool-result' | 'stream-text' | 'stream-thinking' | 'decision-answers'; meta?: Readonly<Record<string, unknown>>; redacted: string; value: string }) => void)[]; readonly 'turn:after'?: readonly ((ctx: { aborted?: boolean; cumulativeUsage: Readonly<{ cacheCreation: number; cacheRead: number; cost?: number; input: number; output: number; turns: number }>; message: SessionTurn; toolCounts: { run: Readonly<Record<string, number>>; turn: Readonly<Record<string, number>> }; turn: number; turnId: string; usage: TurnUsage }) => void)[]; readonly 'turn:before'?: readonly ((ctx: { options: StreamOptions; turn: number; turnId: string }) => void)[]; readonly usage?: readonly ((ctx: { totalIn: number; totalOut: number; turn: number; turnId: string; usage: TurnUsage }) => void)[]; readonly 'validation:coerce'?: readonly ((ctx: ToolHookContext & { coercions: readonly string[]; schema: Record<string, unknown> }) => void)[]; readonly 'validation:reject'?: readonly ((ctx: ToolHookContext & { reason: string; schema: Record<string, unknown> }) => void)[] }`, readonly): Agent-hook observers, bucketed per event.
- `inactive` (`readonly LoadedExtension[]`, readonly): Skipped / failed extensions — kept around so the Settings modal
  can show "couldn't load: ..." next to the toggle. Includes
  disabled-but-discovered ones too (so the user can flip them on).
- `inlineAutocompleteProviders` (`readonly InlineAutocompleteProvider[]`, readonly): Inline ghost-text autocomplete providers, deduped by id (first wins).
- `loaded` (`readonly LoadedExtension[]`, readonly): Successfully loaded + enabled extensions (one entry per ext).
- `mcpServers` (`readonly McpServerConfig[]`, readonly): MCP servers extensions added.
- `palette` (`readonly ExtensionPaletteProviderEntry[]`, readonly): Command palette providers across every enabled extension, in load order.
- `panels` (`readonly ExtensionPanelEntry[]`, readonly): Side-panel tabs across every enabled extension, in load order. Ids `<extension>/<id>`.
- `plugins` (`readonly LoadedPluginRecord[]`, readonly): Agent Plugins loaded by extensions, across every active extension.

  Informational — the plugins' own skills / servers already appear in
  `skills` and `mcpServers`. This is what lets the settings list show an
  extension-loaded plugin as its own row with its origin.
- `providers` (`Readonly<Record<string, ProviderDescriptor>>`, readonly): Provider descriptors, keyed by descriptor key.
- `references` (`readonly ExtensionOrderedContribution<ExtensionReferenceProvider>[]`, readonly): Text reference providers, deduped by id (first wins).
- `runSettled` (`readonly ExtensionOrderedContribution<ExtensionRunSettledHandler>[]`, readonly): `run:settled` observers across every active extension.
- `runtime?` (`ExtensionRuntimeOutputs`, readonly): The runtime's shared registries (interceptors, catalogs, instructions,
  UI, commands, RPC, contracts, integrations). Absent when no extension
  was loaded.
- `sessionEvents` (`readonly ExtensionOrderedContribution<ExtensionSessionEventHandler>[]`, readonly): `session:event` observers across every active extension.
- `skills` (`readonly SkillConfig[]`, readonly): Skills extensions added.
- `subagents` (`Readonly<Record<string, SubagentDef>>`, readonly): Spawnable subagents across every active extension, keyed by name.
- `subscribe` (`(listener: () => void) => () => void`): Calls `listener` after anything this view shows changed (a
  registration, a dispose, an extension loaded, failed or unloaded).
  Coalesced to one call per microtask. Returns the unsubscribe.
- `themes` (`Readonly<Record<string, Theme>>`, readonly): Themes, keyed by theme id.
- `toolResultMetadata` (`readonly ExtensionOrderedContribution<ExtensionToolResultMetadataRegistration>[]`, readonly): Tool-result metadata namespaces across every active extension.
- `tools` (`Readonly<Record<string, ToolDef>>`, readonly): Tools across every active extension, keyed by canonical name.
- `tuiContributions` (`TuiContributions`, readonly): Keybindings and footer hints of extension commands.

Source: [src/extensions/types.ts:781](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L781)

### `ExtensionRunSettledEvent`

Interface.

What run-settled handlers receive (the `run:settled` host event, in the shape hosts deliver it).

```ts
interface ExtensionRunSettledEvent
```

**Properties**

- `aborted` (`boolean`): The user stopped the run (Esc / Stop). An interrupted run can still be `ok`.
- `decide` (`AgentDecide`): The session's decision model (the same `decide` hook contexts carry).
- `ok` (`boolean`): The run ended without an error.
- `runId` (`string`): The run that settled.
- `session` (`{ metadata: Readonly<Record<string, unknown>>; turns: readonly SessionTurn[] } | null`): The session as the run left it, or `null` when no live session remained.
- `sessionId` (`string`): The session whose run settled.

Source: [src/extensions/types.ts:67](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L67)

### `ExtensionRuntime`

Interface.

What `createExtensionRuntime` returns.

```ts
interface ExtensionRuntime
```

**Properties**

- `artifactKinds` (`(id: string) => readonly ArtifactKindEntry[]`): Artifact kinds an extension registered (`ctx.artifacts.kinds.register`), callbacks guarded.
- `checkStorageWrite` (`(loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined) => Promise<string | undefined>`): Checks a client's write to an extension's storage against what the
  extension holds (a store's version and schema): why it is refused, or
  `undefined` (also for an extension that is not active).
- `dispose` (`() => Promise<void>`): Unloads everything and releases the registries.
- `extensions` (`() => ExtensionInfo[]`): Every known extension, in load order.
- `get` (`(id: string) => RuntimeExtension | undefined`): One extension's state.
- `hookHandlers` (`(id: string) => ExtensionHookHandlers`): An extension's own agent-hook and host-event handlers.
- `hostWired` (`{ agentHooks: boolean; hostEvents: boolean }`, readonly): Whether the host gave its own agent hooks / emits host events (the registry view skips those parts).
- `idOfDir` (`(dir: string) => string | undefined`): The id of the extension loaded from `dir`, if any.
- `issues` (`readonly LoadOrderIssue[]`, readonly): Load-order issues of the last `load`.
- `load` (`(entries: readonly RuntimeEntry[]) => Promise<readonly ExtensionInfo[]>`): Loads entries (in dependency order, after those already loaded). Never rejects.
- `outputs` (`ExtensionRuntimeOutputs`, readonly): The shared registries.
- `plugins` (`(id: string) => readonly LoadedPluginRecord[]`): Agent Plugins an extension loaded (`ctx.plugins.load`).
- `preloadSession` (`(sessionId: string) => Promise<void>`): Loads `'session'` storage of every active extension for a run. Failures are logged.
- `reload` (`(id: string, opts?: { entry?: RuntimeEntry }) => Promise<ExtensionInfo | undefined>`): Reloads one extension in place: its owner is disposed (registrations
  withdrawn, cleanups run), its module imported again from its folder
  (`options.reimport`), and `setup` runs again at the same load-order
  position. Other extensions are untouched; `ctx.storage.memory`
  survives. `opts.entry` replaces the entry instead of re-importing.
  Resolves with the new status, or `undefined` for an unknown id.
- `rpcBridge?` (`RpcRemoteBridge`, readonly): The protocol side of RPC, when the host gave a transport.
- `settingsWire` (`() => WireSettings`): Settings of every known extension (active and disabled) in the Settings wire format.
- `subscribe` (`(listener: () => void) => () => void`): Calls `listener` after an extension's status changed (loaded, failed,
  disabled by its guard, unloaded) or it registered or released an
  artifact kind, an Agent Plugin or the first observer of an agent hook.
  The registry view re-reads on it. Returns the unsubscribe.
- `unload` (`(id: string, opts?: { forget?: boolean }) => Promise<void>`): Unloads an extension and forgets it. `forget: true` also clears its `ctx.storage.memory`.

Source: [src/extensions/runtime/host.ts:234](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/host.ts#L234)

### `ExtensionRuntimeEnv`

Interface.

Identity of the extension a transform runs on behalf of. Passed as the second argument to registered transforms.

```ts
interface ExtensionRuntimeEnv
```

**Properties**

- `extensionName` (`string`): Name of the extension that registered the transform.
- `source` (`LoadedExtensionSource`): Where that extension was loaded from.

Source: [src/extensions/types.ts:86](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L86)

### `ExtensionRuntimeOptions`

Interface.

Options of `createExtensionRuntime`.

```ts
interface ExtensionRuntimeOptions
```

**Properties**

- `budget?` (`false | Partial<ErrorBudget>`): Error budget of each guard. `false` never trips.
- `callbackTimeoutMs?` (`number`): Default bound of guarded callbacks, in ms.
- `drainTimeoutMs?` (`number`): How long an unloaded extension's teardown waits for a call in flight that
  has no bound of its own (a command run, a tool execute), in ms. Default
  `DEFAULT_DRAIN_MS` (`owner.ts`): 30 minutes.
- `host` (`ExtensionHostKind`): The host process.
- `logger?` (`Logger`): Base logger; each extension logs through `logger.with({ extension })`. Default: warnings to stderr.
- `memory?` (`MemoryRegistry`): Process-wide `ctx.storage.memory`. Default: one registry per process.
- `onChange?` (`(info: ExtensionInfo | { id: string; status: 'unloaded' }) => void`): Called after an extension's status changed (loaded, failed, disabled by its guard, unloaded).
- `onStall?` (`(report: StallReport) => void`): Receives event-loop stalls (after they are logged).
- `paths` (`ExtensionPaths`): Paths handed to every extension.
- `platform?` (`string`): Platform for `ctx.app` and keymap `mod`. Default `process.platform`.
- `ports?` (`RuntimePorts`): Host ports.
- `reimport?` (`(entry: RuntimeEntry) => Promise<RuntimeEntry>`): Imports an entry's module again for `ExtensionRuntime.reload`.
  Default: entries with a folder (`project`, `user`, `config`) are
  imported fresh from it (`loadExtensionFolder`, module graph evicted
  first); `inline` and `builtin` entries keep their definition.
- `setupTimeoutMs?` (`number`): Bound of `setup`, in ms.
- `trackCalls?` (`(pending: Promise<unknown>) => void`): Receives the promise of every async guarded callback (observers, RPC
  handlers, panel loads). A test seam: the testing kit waits on them so a
  fired event has been handled before it returns.
- `version?` (`string`): zidane version for `ctx.app`. Default: this package's.

Source: [src/extensions/runtime/host.ts:161](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/host.ts#L161)

### `ExtensionRuntimeOutputs`

Interface.

The extension runtime's outputs.

```ts
interface ExtensionRuntimeOutputs
```

**Properties**

- `catalogs` (`ExtensionCatalogs`, readonly): Catalogs extensions registered into and transformed.
- `commands` (`CommandRegistry`, readonly): Commands, palette providers and keybindings.
- `contracts` (`ContractRegistry`, readonly): Contracts extensions declared.
- `facets` (`FacetRegistry`, readonly): Facets extensions registered (`ctx.sessions.facets`): hosts compute and store them per session.
- `hostEvents` (`HostEventSink`, readonly): Where hosts emit events the runtime cannot see.
- `instructions` (`InstructionsRegistry`, readonly): System prompt text added by extensions.
- `integrations` (`IntegrationRegistry`, readonly): Integrations extensions registered.
- `interceptors` (`InterceptorRegistry`, readonly): Interceptors extensions added, run by the agent at its decision points.
- `rpc` (`RpcRouter`, readonly): Routes RPC calls to extension handlers.
- `ui` (`UiRegistry`, readonly): UI contributions in wire form.
- `withdrawals` (`() => number`, readonly): How many times registrations were withdrawn: it grows when an extension
  is unloaded, reloaded or disabled by its guard, and when the runtime is
  disposed. An agent built before it grew may hold withdrawn tools and
  hooks, and must be rebuilt before its next run.

Source: [src/extensions/runtime/outputs.ts:48](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/outputs.ts#L48)

### `ExtensionRuntimeSurface`

Interface.

`ctx.runtime` — reads/controls over the host's active model state.

```ts
interface ExtensionRuntimeSurface
```

**Properties**

- `model` (`() => string | null`): Active model id, or `null` when detached / none picked.
- `models` (`() => readonly ExtensionModelEntry[]`): Every model available across the user's credentialed providers.
  Empty when detached (headless, or before the renderer mounts).
  Use it to build model pickers (e.g. a review command letting the
  user pin subagents to specific models).
- `setThinking` (`(level: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive') => boolean`): Set the thinking level. `false` when detached or unsupported by the model.
- `thinking` (`() => 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive' | null`): Active thinking level, or `null` when detached / not applicable.

Source: [src/extensions/host-runtime.ts:488](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L488)

### `ExtensionScanEntry`

Interface.

A discovered (but not yet loaded) extension entry.

```ts
interface ExtensionScanEntry
```

**Properties**

- `dir` (`string`): Absolute path to the extension directory.
- `entry` (`string`): Absolute path to the entry file picked from `ENTRY_CANDIDATES`.
- `manifest?` (`ExtensionManifest`): Manifest read from the extension, when it has a valid one.
- `name` (`string`): Folder name — the canonical persisted extension identity.
- `source` (`LoadedExtensionSource`): Where the discovery root lives.

Source: [src/extensions/discovery.ts:71](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L71)

### `ExtensionsConfigSync`

Interface.

The process's declarative-install coordinator.

```ts
interface ExtensionsConfigSync
```

**Properties**

- `attach` (`(target: ExtensionsConfigSyncTarget) => () => void`): Follows the config for one registry. Reconciles in the background the
  scopes no run covered yet; a scope already reconciled replays its last
  report to the target. Returns the detach.
- `close` (`() => void`): Stops watching; runs in flight finish but apply nothing.
- `settled` (`() => Promise<void>`): Resolves once no scope run (and no apply it started) is in flight.

Source: [src/extensions/declarative/host-sync.ts:248](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L248)

### `ExtensionsConfigSyncOptions`

Interface.

Options of [`createExtensionsConfigSync`](https://zidane.si/docs/reference/extensions.md#createExtensionsConfigSync).

```ts
interface ExtensionsConfigSyncOptions
```

**Properties**

- `configDir` (`string`, readonly): The user config dir (`ResolvedConfig.paths.configDir`).
- `home?` (`string`, readonly): Default `os.homedir()`.
- `log?` (`ConfigSyncLog`, readonly): Where outcomes and errors go. Default: warnings and errors to the console.
- `now?` (`() => Date`, readonly): Clock for the lock's `installedAt`.
- `port?` (`(scope: ExtensionsConfigScope, cwd: string) => ExtensionsInstallPort`, readonly): The install port of a scope run from `cwd`. Default `createNodeInstallPort`. A test seam.
- `prefix?` (`string`, readonly): Default `.zidane`.
- `watch?` (`false | ((file: string, onChange: () => void) => () => void)`, readonly): Calls `onChange` after `file` changes (hosts pass `watchFileChanges`,
  which follows atomic replaces and polls). Returns the stop. Absent or
  `false`: no watching, the config applies at attach only.

Source: [src/extensions/declarative/host-sync.ts:226](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L226)

### `ExtensionsConfigSyncReport`

Interface.

The result of one scope's reconcile, handed to every attached target.

```ts
interface ExtensionsConfigSyncReport
```

**Properties**

- `changedDirs` (`readonly string[]`, readonly): Folders installed, updated, replaced or removed: reload them.
- `configPath` (`string`, readonly): The `config.json` the entries came from.
- `diagnostics` (`readonly ExtensionsConfigDiagnostic[]`, readonly): Problems found in the config file itself (bad entries, unknown keys).
- `entries` (`readonly { readonly enabled: boolean; readonly id: string }[]`, readonly): The scope's entries with a known id, and whether they may load.
- `items` (`readonly ConfigSyncItem[]`, readonly): Each entry's outcome, in config order.
- `linkedDirs` (`readonly string[]`, readonly): Folders local entries link in place.
- `replay` (`boolean`, readonly): `true`: the result of an earlier run, given to a target that attached
  after it (its registry was built from the disk the run left). Folders
  the registry already holds are not reloaded.
- `scope` (`ExtensionsConfigScope`, readonly): The config scope that was reconciled (user or project).
- `unlinkedDirs` (`readonly string[]`, readonly): Folders whose entry was dropped from the config: unload them.

Source: [src/extensions/declarative/host-sync.ts:103](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L103)

### `ExtensionsConfigSyncTarget`

Interface.

A registry a host keeps in line with the config.

```ts
interface ExtensionsConfigSyncTarget
```

**Properties**

- `apply` (`(report: ExtensionsConfigSyncReport) => void | Promise<void>`, readonly): Applies a report to the registry (usually [`applyExtensionsConfigReport`](https://zidane.si/docs/reference/extensions.md#applyExtensionsConfigReport)). Its errors are logged.
  Called without awaiting the previous apply (the scope's next run does not wait for it): a host that
  waits (for runs to end) queues the reports itself, in call order.
- `cwd` (`string`, readonly): The folder the registry was built for: picks the project config.
- `trustProject` (`() => boolean`, readonly): Whether the project's entries apply (the build's project-extensions trust).

Source: [src/extensions/declarative/host-sync.ts:209](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L209)

### `ExtensionSessionBadge`

Interface.

What a session shows under its title for one artifact kind: GUI sidebar
rows and the TUI sessions list paint the same data. Built by the kind's
`badge(artifacts)` over that session's artifacts of the kind (newest
first). JSON-safe: it crosses IPC as-is.

```ts
interface ExtensionSessionBadge
```

**Properties**

- `card?` (`{ rows: readonly ExtensionSessionBadgeCardRow[]; title: string }`): The hover / click card listing every artifact behind the badge.
- `color?` (`string`): Exact icon color, over `tone`; see [`ExtensionBadgeColor`](https://zidane.si/docs/reference/extensions.md#ExtensionBadgeColor).
- `count?` (`number`): A number in `text` that rolls when it changes (hosts that animate).
- `detail?` (`string`): A toned-down second part after `text` (a ticket's title): muted, cut
  with an ellipsis where the badge runs out of room.
- `href?` (`string`): The badge's one link (a lone ticket, a lone PR): hosts open it on a modifier-click (⌘ / ctrl).
- `icon?` (`ExtensionBadgeIcon`): Leading icon.
- `more?` (`number`): `+N` after the text: more artifacts than the text names.
- `order?` (`number`): Left-to-right position among a session's badges (lower first; default 100). Pull requests are 0, commits 10.
- `panel?` (`string`): The panel a click opens, focused on the badge (`PanelLoadContext.focus`):
  a panel this extension registered (bare id, `tickets`), a full
  `<extension>/<id>`, or `'artifacts'`, the built-in Artifacts panel, which
  is also the default. An id no active extension registered falls back to
  Artifacts.
- `prompt?` (`string`): What "Add to prompt" inserts for the badge (default: its `href`, else `text`).
- `text` (`string`): The badge text (`4 commits`, `#8147`, `BOA-123`).
- `title?` (`string`): Hover / accessible description.
- `tone?` (`ExtensionBadgeTone`): Tints the icon.

Source: [src/extensions/types.ts:290](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L290)

### `ExtensionSessionBadgeCardRow`

Interface.

One line of a session badge's card.

```ts
interface ExtensionSessionBadgeCardRow
```

**Properties**

- `color?` (`string`): Exact icon color (`#rrggbb`), over `tone`; see [`ExtensionBadgeColor`](https://zidane.si/docs/reference/extensions.md#ExtensionBadgeColor).
- `href?` (`string`): Link opened by the row.
- `icon?` (`ExtensionBadgeIcon`): Leading icon.
- `lead?` (`string`): Short leading token (`a1b2c3d`, `#12`, `BOA-123`).
- `prompt?` (`string`): What "Add to prompt" inserts for this row (default: its `href`, else `lead`, else `title`).
- `title` (`string`): Main text of the row.
- `tone?` (`ExtensionBadgeTone`): Tints the icon (or the lead when there is no icon).
- `trailing?` (`string`): Short trailing fact (a branch, a state).
- `uri?` (`string`): The artifact the row stands for: a click opens the badge's panel focused on it (`PanelLoadContext.focus.uri`).

Source: [src/extensions/types.ts:263](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L263)

### `ExtensionSessionControl`

Interface.

Host-level session control behind `ctx.sessions`: the orchestration verbs
and per-session extension state, addressing any session by id, inside a run
or not.

```ts
interface ExtensionSessionControl
```

**Properties**

- `attachFacets?` (`(registry: FacetRegistry) => void`): Starts computing a runtime's facets (`ctx.sessions.facets`): the
  runtime calls it when an extension registers or refreshes a facet.
  Idempotent. Optional: a host without it computes no facets.
- `getData` (`(sessionId: string, extension: string, key: string) => Promise<JsonValue | undefined>`): One value of `extension`'s per-session state (`ctx.session`), live or stored.
- `schedules?` (`(extension: string) => ExtensionScheduleVerbs`): The host's schedules acting as extension `extension` (`ctx.schedules`). Optional: a host without it has no schedules.
- `setData` (`(sessionId: string, extension: string, key: string, value: JsonValue | undefined) => Promise<void>`): Write one value of `extension`'s per-session state; `undefined` deletes it.
- `verbs` (`(extension: string) => ExtensionSessionVerbs & ExtensionSessionLifecycleVerbs`): The orchestration verbs acting as extension `extension`, with the lifecycle verbs the host implements.

Source: [src/extensions/host-runtime.ts:365](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L365)

### `ExtensionSessionDetail`

Interface.

What `ctx.sessions.read()` returns.

```ts
interface ExtensionSessionDetail extends ExtensionSessionRow
```

**Properties**

- `cwd` (`string`, from `ExtensionSessionRow`): Its folder; `''` for none.
- `lastMessage` (`string | null`): Its last assistant message, cut to a few hundred characters.
- `orchestrator?` (`boolean`, from `ExtensionSessionRow`): Holds the `sessions` tool.
- `running` (`boolean`, from `ExtensionSessionRow`): A run is in flight.
- `sessionId` (`string`, from `ExtensionSessionRow`): Session id.
- `state` (`'running' | 'idle' | 'blocked'`, from `ExtensionSessionRow`): `blocked`: a question, plan or tool approval waits for an answer.
- `title` (`string`, from `ExtensionSessionRow`): Session title (the id when it has none).
- `turns` (`number`, from `ExtensionSessionRow`): Turns in the session.
- `updatedAt` (`number`, from `ExtensionSessionRow`): Last change, epoch ms.
- `worker` (`boolean`, from `ExtensionSessionRow`): Created by this extension.

Source: [src/extensions/host-runtime.ts:99](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L99)

### `ExtensionSessionEvent`

Interface.

A session event (a run ended, or a session waits for an answer), as `ctx.sessions.onEvent` handlers get it.

```ts
interface ExtensionSessionEvent
```

**Properties**

- `artifacts?` (`{ changed: readonly string[]; commands: number; toolCalls: number }`): What the run touched.
- `at` (`number`): When, epoch ms.
- `costUsd?` (`number`): Cost of the run in USD.
- `cwd?` (`string`): Its folder; `''` for none.
- `detail?` (`string`): For `needs-attention`: what is asked, in one line.
- `durationMs?` (`number`): The run's duration, tokens, turns and cost, when known.
- `error?` (`string`): For `error`: the failure.
- `finishReason?` (`'length' | 'content-filter' | 'pause'`): The run ended abnormally: it hit the length limit, paused, or was filtered.
- `goal?` (`string`): The prompt that started the run.
- `request?` (`{ id: string; kind: 'plan' | 'question' | 'approval'; payload: unknown }`): For `needs-attention`: the request, to answer with `ctx.sessions.answer` / `approve`.
- `seq?` (`number`): Its place in the event log: pass it as `since` to `ctx.sessions.events`.
- `sessionId` (`string`): The session it is about.
- `status` (`'error' | 'done' | 'needs-attention' | 'cancelled'`): `done`, `error`, `cancelled`, or `needs-attention` (a question, plan or tool approval waits).
- `summary` (`string`): One line: its last message, the failure, or what it waits for.
- `title` (`string`): Its title at the time.
- `tokens?` (`number`): Tokens the run used.
- `turns?` (`number`): Turns the run took.
- `worker?` (`boolean`): Created by the caller that reads it.

Source: [src/extensions/host-runtime.ts:228](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L228)

### `ExtensionSessionRow`

Interface.

One row of the orchestration `list(limit)` (`ExtensionSessionVerbs.list`), which `ctx.sessions.list` falls back to on a host without the `query` verb.

```ts
interface ExtensionSessionRow
```

**Properties**

- `cwd` (`string`): Its folder; `''` for none.
- `orchestrator?` (`boolean`): Holds the `sessions` tool.
- `running` (`boolean`): A run is in flight.
- `sessionId` (`string`): Session id.
- `state` (`'running' | 'idle' | 'blocked'`): `blocked`: a question, plan or tool approval waits for an answer.
- `title` (`string`): Session title (the id when it has none).
- `turns` (`number`): Turns in the session.
- `updatedAt` (`number`): Last change, epoch ms.
- `worker` (`boolean`): Created by this extension.

Source: [src/extensions/host-runtime.ts:77](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L77)

### `ExtensionSessionScope`

Interface.

Which sessions a subscriber hears from. Every field narrows; `{}` is every session.

```ts
interface ExtensionSessionScope
```

**Properties**

- `machine?` (`string`): Sessions on this machine: a lent machine's name, or `local` for the host itself.
- `projectRoot?` (`string`): Sessions in this project: its root, or a folder inside it.
- `sessionIds?` (`readonly string[]`): Only these sessions.

Source: [src/extensions/host-runtime.ts:64](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L64)

### `ExtensionSessionsSurface`

Interface.

`ctx.sessions` — the orchestration verbs, acting as this extension
(docs/ORCHESTRATION.md), plus this extension's state of any session. Every
verb rejects without a chat host (a TUI-only window), and when the call is
refused (an unknown session).

```ts
interface ExtensionSessionsSurface extends ExtensionSessionVerbs
```

**Properties**

- `answer` (`(requestId: string, response: InteractionResponse) => Promise<boolean>`, from `ExtensionSessionVerbs`): Answers a question or a plan by its request id. Resolves to `false` when it was already answered.
- `approve` (`(requestId: string, decision: ExtensionApprovalDecision) => Promise<boolean>`, from `ExtensionSessionVerbs`): Decides a tool approval by its request id. Resolves to `false` when it was already decided.
- `cancel` (`(sessionId: string) => Promise<void>`, from `ExtensionSessionVerbs`): Interrupts the run.
- `create` (`(params: ExtensionCreateSessionParams) => Promise<string>`, from `ExtensionSessionVerbs`): Creates a session. Resolves to its id.
- `events` (`(query?: ExtensionEventQuery) => Promise<readonly ExtensionSessionEvent[]>`, from `ExtensionSessionVerbs`): The recent session events (runs ended, sessions blocked), newest first, without the pending request.
- `getData` (`(sessionId: string, key: string) => Promise<JsonValue | undefined>`): This extension's per-session value `key` (`ctx.session`'s store) of any session, inside a run or not. `undefined` when unset. Rejects when detached.
- `list` (`(limit?: number) => Promise<readonly ExtensionSessionRow[]>`, from `ExtensionSessionVerbs`): Other sessions, newest first. Default 30, at most 100.
- `onEvent` (`(handler: ExtensionSessionEventHandler) => void`): Hear every session event: a run ended (`done`, `error`) or a session waits
  for an answer (`needs-attention`, with the request). Register during setup;
  runs on the chat host (GUI and daemon), outside any run.
- `pending` (`(sessionId?: string) => Promise<readonly ExtensionPendingRequest[]>`, from `ExtensionSessionVerbs`): Prompts waiting for an answer, of one session or all.
- `read` (`(sessionId: string) => Promise<ExtensionSessionDetail>`, from `ExtensionSessionVerbs`): A session's state and last message.
- `send` (`(sessionId: string, prompt: string) => Promise<boolean>`, from `ExtensionSessionVerbs`): Queues a prompt as the session's next turn. Resolves to `false` when the host declined it.
- `setData` (`(sessionId: string, key: string, value: JsonValue | undefined) => Promise<void>`): Write this extension's per-session value `key` of any session; `undefined` deletes it. Rejects when detached.
- `steer` (`(sessionId: string, message: string) => Promise<void>`, from `ExtensionSessionVerbs`): Guidance into the current run, at its next turn boundary.
- `transcript` (`(sessionId: string, limit?: number) => Promise<string>`, from `ExtensionSessionVerbs`): The last turns as plain text, oldest first. Default 10, at most 50.
- `wait` (`(sessionId: string, timeoutSec?: number) => Promise<ExtensionWaitResult>`, from `ExtensionSessionVerbs`): Returns once the session is idle or blocked, or after `timeoutSec`. Default 30, at most 50.

Source: [src/extensions/host-runtime.ts:510](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L510)

### `ExtensionSessionVerbs`

Interface.

The orchestration verbs acting as one extension (docs/ORCHESTRATION.md).

```ts
interface ExtensionSessionVerbs
```

**Properties**

- `answer` (`(requestId: string, response: InteractionResponse) => Promise<boolean>`): Answers a question or a plan by its request id. Resolves to `false` when it was already answered.
- `approve` (`(requestId: string, decision: ExtensionApprovalDecision) => Promise<boolean>`): Decides a tool approval by its request id. Resolves to `false` when it was already decided.
- `cancel` (`(sessionId: string) => Promise<void>`): Interrupts the run.
- `create` (`(params: ExtensionCreateSessionParams) => Promise<string>`): Creates a session. Resolves to its id.
- `events` (`(query?: ExtensionEventQuery) => Promise<readonly ExtensionSessionEvent[]>`): The recent session events (runs ended, sessions blocked), newest first, without the pending request.
- `list` (`(limit?: number) => Promise<readonly ExtensionSessionRow[]>`): Other sessions, newest first. Default 30, at most 100.
- `pending` (`(sessionId?: string) => Promise<readonly ExtensionPendingRequest[]>`): Prompts waiting for an answer, of one session or all.
- `read` (`(sessionId: string) => Promise<ExtensionSessionDetail>`): A session's state and last message.
- `send` (`(sessionId: string, prompt: string) => Promise<boolean>`): Queues a prompt as the session's next turn. Resolves to `false` when the host declined it.
- `steer` (`(sessionId: string, message: string) => Promise<void>`): Guidance into the current run, at its next turn boundary.
- `transcript` (`(sessionId: string, limit?: number) => Promise<string>`): The last turns as plain text, oldest first. Default 10, at most 50.
- `wait` (`(sessionId: string, timeoutSec?: number) => Promise<ExtensionWaitResult>`): Returns once the session is idle or blocked, or after `timeoutSec`. Default 30, at most 50.

Source: [src/extensions/host-runtime.ts:161](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L161)

### `ExtensionsInstallPort`

Interface.

The effects declarative install needs from the host.

```ts
interface ExtensionsInstallPort
```

**Properties**

- `describe` (`(req: { readonly dir: string }) => Promise<DescribedExtension | null>`): Reads an extension directory without installing: id, version, host-version check. `null` when it is not an extension.
- `install` (`(req: InstallRequest) => Promise<InstalledExtensionRecord>`): Fetches, validates and installs. Throws on failure, leaving nothing half-installed.
- `listInstalled` (`(scope: ExtensionsConfigScope) => Promise<readonly InstalledExtensionInfo[]>`): Extension folders in the scope's install root (the one installs write to).
- `remove` (`(req: { readonly dir: string }) => Promise<void>`): Deletes an installed extension folder.
- `update` (`(req: { readonly dir: string; readonly onProgress?: (message: string) => void; readonly signal?: AbortSignal }) => Promise<InstalledExtensionRecord & { readonly upToDate: boolean }>`): Re-resolves the recorded install of `dir` (`updateInstalledExtension`).

Source: [src/extensions/declarative/port.ts:72](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/port.ts#L72)

### `ExtensionSkillPolicy`

Interface.

Rule that activates a skill automatically at the start of a run.

```ts
interface ExtensionSkillPolicy
```

**Properties**

- `autoActivate?` (`boolean`): Activates the skill when set. Policies without it do nothing.
- `name` (`string`): Name of the skill the policy applies to. Policies naming an unknown skill are ignored.
- `when?` (`(ctx: ExtensionRuntimeEnv & { run: Pick<AgentRunOptions, 'model' | 'prompt' | 'parentRunId' | 'depth'>; skills: readonly SkillConfig[] }) => boolean | Promise<boolean>`): Extra condition checked before activating. Without it the skill always activates. A thrown error skips the policy.

Source: [src/extensions/types.ts:118](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L118)

### `ExtensionToolResultMetadataRegistration`

Interface.

Declares a tool-result metadata namespace owned by an extension and how it appears in the context panel.

```ts
interface ExtensionToolResultMetadataRegistration
```

**Properties**

- `contextRows?` (`(ctx: { entries: readonly { block: unknown; turn: unknown; value: JsonValue }[]; namespace: string; turns: readonly unknown[] }) => ContextExtensionSection | readonly ContextExtensionSection[] | readonly ContextExtensionRow[] | null | undefined`): Builds context panel rows or sections from every entry stored under the namespace. Without it the panel shows an entry count.
- `namespace` (`string`): Metadata key to claim. Must be a safe record key.
- `schema?` (`unknown`): Optional schema describing the metadata value, for documentation.
- `summarize?` (`(metadata: ToolResultMetadata) => JsonValue | undefined`): Reduces one metadata value to a compact JSON summary, or `undefined` to omit it.

Source: [src/extensions/types.ts:153](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L153)

### `ExtensionUiSurface`

Interface.

`ctx.ui` — what this window shows. Per window: a daemon or a server has none, and answers `false`.

```ts
interface ExtensionUiSurface
```

**Properties**

- `newSession` (`() => Promise<boolean>`): Open a new, empty session in this window. `false` when detached.
- `openSession` (`(id: string) => Promise<boolean>`): Show session `id` in this window. `false` when detached or it could not.

Source: [src/extensions/host-runtime.ts:524](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L524)

### `ExtensionWaitResult`

Interface.

What `ctx.sessions.wait()` returns.

```ts
interface ExtensionWaitResult
```

**Properties**

- `reason` (`'idle' | 'blocked' | 'timeout' | 'ended'`): Why it returned: `idle` (was not running), `ended` (a run ended), `blocked` (a prompt waits), `timeout`.
- `session` (`ExtensionSessionDetail`): The session as it is now.

Source: [src/extensions/host-runtime.ts:125](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L125)

### `ExtensionWorkspacePair`

Interface.

The live `(execution, handle)` pair behind `ctx.workspace`. Resolved
per call — never cached by the facade — because the pair changes on
session switch, cwd change, and registry rebuilds; a captured pair
would point at a destroyed container.

```ts
interface ExtensionWorkspacePair
```

**Properties**

- `execution` (`ExecutionContext`): Execution context the commands run in.
- `handle` (`ExecutionHandle`): Handle to the live execution.

Source: [src/extensions/host-runtime.ts:275](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L275)

### `ExtensionWorkspaceSurface`

Interface.

`ctx.workspace` — shell + file operations routed through the SESSION'S
execution context, so extension work happens wherever the agent's tools
run (host process, docker, remote sandbox) with the same transport
output caps and containment. The curated "do work in the workspace"
subset — lifecycle methods (`spawn` / `destroy` / background tasks)
are deliberately absent: the pair belongs to the agent.

Unlike `ctx.runtime` / `ctx.sessions` (queries and toggles that degrade
to `null` / `false`), these are imperative operations whose silent
failure would corrupt caller logic — a no-op `writeFile` must not look
like success. Detached ⇒ every method REJECTS with a clear error.
Guard with `ExtensionWorkspaceSurface.available` or try/catch.

```ts
interface ExtensionWorkspaceSurface
```

**Properties**

- `available` (`() => Promise<boolean>`): `true` when a live session's execution pair is reachable.
- `exec` (`(command: string, options?: { cwd?: string; env?: Record<string, string>; signal?: AbortSignal; timeout?: number }) => Promise<ExecResult>`): Run a shell command in the workspace. Resolves with the full
  ExecResult (non-zero exits RESOLVE — inspect `exitCode`); rejects
  only when detached or the transport itself fails. Output is
  byte-capped by the context's transport (10MB default).
- `fileSize` (`(path: string) => Promise<number | null>`): Byte size of a file, or `null` when unknowable — same contract as `ExecutionContext.fileSize`.
- `listFiles` (`(path: string, options?: ListFilesOptions) => Promise<ListFilesEntry[]>`): List a directory in the workspace — `ListFilesOptions` semantics (`glob: true` treats `path` as a pattern).
- `readFile` (`(path: string) => Promise<string>`): Read a file from the workspace's filesystem (whole-file — probe `fileSize` first for anything potentially large).
- `writeFile` (`(path: string, content: string) => Promise<void>`): Write a file into the workspace's filesystem (parent dirs created).

Source: [src/extensions/host-runtime.ts:545](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L545)

### `FacetComputeOptions`

Interface.

Options of `FacetRegistry.compute`.

```ts
interface FacetComputeOptions
```

**Properties**

- `extension?` (`string`): Only this extension's facets.

Source: [src/extensions/runtime/facets.ts:61](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L61)

### `FacetInfo`

Interface.

A registered facet, as hosts list it.

```ts
interface FacetInfo
```

**Properties**

- `extension` (`string`, readonly): The extension that computes it.
- `id` (`string`, readonly): `<extensionId>.<key>`: its key in a row's `facets` and its query path after `facet.`.
- `key` (`string`, readonly): The extension's key.
- `on` (`readonly SessionFacetTrigger[]`, readonly): The triggers it is computed again on.

Source: [src/extensions/runtime/facets.ts:28](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L28)

### `FacetRefreshRequest`

Interface.

A `ctx.sessions.facets.refresh` call, as hosts get it.

```ts
interface FacetRefreshRequest
```

**Properties**

- `extension` (`string`, readonly): The extension whose facets to compute again.
- `sessionId?` (`string`, readonly): Only this session. Absent: every session.

Source: [src/extensions/runtime/facets.ts:40](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L40)

### `FacetRegistry`

Interface.

The facets every extension registered. Hung on `ExtensionRuntimeOutputs.facets`.

```ts
interface FacetRegistry
```

**Properties**

- `compute` (`(session: SessionSnapshot, triggers?: SessionFacetTrigger | ReadonlySet<SessionFacetTrigger>, options?: FacetComputeOptions) => Promise<Record<string, JsonValue>>`): Computes the facets that run on `triggers` (one trigger or a set; every
  facet when absent) for one session, each facet once, in parallel, each
  under its extension's guard. Each extension's facets see
  `metadata.extensions` cut down to its own slice. The result holds a key
  per facet that answered: its JSON value, or `null` to clear it. A facet
  that threw, timed out, or answered something too big or not JSON has no
  key: keep its last value.
- `disposed` (`() => boolean`): Whether the runtime that owns the registry was disposed: nothing is computed with it again.
- `list` (`() => readonly FacetInfo[]`): Every facet, in extension load order, then registration order.
- `onDispose` (`(listener: () => void) => () => void`): Calls `listener` once, when the owning runtime is disposed (at once when it already is). Returns the unsubscribe.
- `onRefresh` (`(handler: (request: FacetRefreshRequest) => void | Promise<void>) => () => void`): Handles `ctx.sessions.facets.refresh`: the host computes the facets again
  and stores them. `refresh` resolves once every handler did. Returns the
  unsubscribe. With no handler, `refresh` resolves at once.
- `subscribe` (`(listener: (change: FacetChange) => void) => () => void`): Calls `listener` after a facet is added or withdrawn, or an extension is forgotten, with what was withdrawn on purpose (`FacetChange`). Not called once the registry is disposed. Returns the unsubscribe.
- `warn` (`(extension: string, message: string) => void`): Logs a warning on `extension`'s logger (a host refusing its values). Dropped when the extension holds no facet.

Source: [src/extensions/runtime/facets.ts:67](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L67)

### `GeneratedImage`

Interface.

One generated image.

```ts
interface GeneratedImage
```

**Properties**

- `data` (`Uint8Array`): The image's bytes.
- `mimeType` (`string`): Its MIME type (`image/png`).
- `path?` (`string`): Where it was saved, with `save`.

Source: [src/extensions/api/sessions.ts:278](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L278)

### `GenerateDomain`

Interface.

`ctx.generate`: model calls outside any session. Uses the user's provider
resolution and counts usage. On a host without model access, `text` and
`object` reject, `decide.available` is `false` and `decide` answers
`unavailable`.

```ts
interface GenerateDomain
```

**Properties**

- `decide` (`AgentDecide`): Structured multi-question decisions (the decisions model).
- `image` (`(opts: GenerateImageOptions) => Promise<{ images: readonly GeneratedImage[] }>`): Generates images. The model defaults to the one the generate_image tool
  uses. With `save`, each image is also written under the session's (or
  project's) folder and recorded as an artifact; `path` is then set.
- `object` (`<S extends Schema>(opts: { model?: { modelId: string; providerId: string }; prompt: string; schema: S; signal?: AbortSignal; system?: string }) => Promise<Infer<S>>`): Generates an object that matches `schema`.
- `text` (`(opts: { model?: { modelId: string; providerId: string }; prompt: string; signal?: AbortSignal; system?: string }) => Promise<string>`): Generates text from a prompt.

Source: [src/extensions/api/sessions.ts:244](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L244)

### `GenerateImageOptions`

Interface.

What `ctx.generate.image` takes.

```ts
interface GenerateImageOptions
```

**Properties**

- `aspectRatio?` (`string`): Aspect ratio, as the image providers take it (`'16:9'`).
- `model?` (`{ modelId: string; providerId: string }`): Defaults to the generate_image tool's model.
- `n?` (`number`): How many images, 1 to 4. Default 1.
- `prompt` (`string`): What to draw.
- `references?` (`readonly ({ path: string } | { data: Uint8Array; mimeType: string })[]`): Images to start from: paths, or bytes with their type.
- `save?` (`boolean | { sessionId?: string }`): Write the files and record artifacts. Optional `sessionId` picks the session folder.
- `signal?` (`AbortSignal`): Cancels the request.

Source: [src/extensions/api/sessions.ts:260](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L260)

### `GithubPull`

Interface.

A pull request as read from GitHub.

```ts
interface GithubPull
```

**Properties**

- `additions?` (`number`): Lines added.
- `author?` (`string`): Login of the author.
- `body?` (`string`): The PR description (markdown).
- `changedFiles?` (`number`): Number of changed files.
- `comments?` (`number`): Issue + review comments.
- `deletions?` (`number`): Lines deleted.
- `mergeable?` (`string`): GitHub's `mergeable_state` (open PRs): `clean`, `unstable`, `dirty`, `blocked`…
- `number` (`number`): Pull request number.
- `owner` (`string`): Repository owner.
- `repo` (`string`): Repository name.
- `reviews?` (`number`): Submitted reviews (open PRs).
- `state` (`GithubPullState`): Display state. See [`GithubPullState`](https://zidane.si/docs/reference/extensions.md#GithubPullState).
- `title?` (`string`): Pull request title.
- `updatedAt?` (`string`): GitHub's `updated_at` (ISO): moves on any activity, so it tells a stored copy is current.
- `url` (`string`): Web URL of the pull request.

Source: [src/github/pulls.ts:31](https://github.com/Tahul/zidane/blob/main/src/github/pulls.ts#L31)

### `Handle`

Interface.

A live UI contribution. `update` patches the item and pushes it to every
host. `dispose` withdraws it.

```ts
interface Handle<T> extends Disposable
```

**Type parameters**

- `T`

**Properties**

- `current` (`Readonly<T>`, readonly): The item as the hosts see it now.
- `dispose` (`() => void`, from `Disposable`): Withdraws the registration. Safe to call more than once.
- `update` (`(patch: Partial<T> | ((current: Readonly<T>) => T)) => void`): Merges `patch` into the item, or replaces it with the function's result.

Source: [src/extensions/api/core.ts:39](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L39)

### `HooksDomain`

Interface.

`ctx.hooks`.

```ts
interface HooksDomain
```

**Properties**

- `intercept` (`<K extends keyof Interceptors>(name: K, handler: InterceptorHandler<K>, opts?: InterceptOptions) => Disposable`): Takes part in a decision.
- `on` (`<K extends keyof AgentHooks | 'run:settled' | 'session:event'>(event: K, handler: (event: Readonly<HookEvents[K]>) => void | Promise<void>, opts?: OnOptions) => Disposable`): Observes an event. The handler cannot change it.

Source: [src/extensions/api/hooks.ts:244](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L244)

### `HostEventSink`

Interface.

Host events the runtime cannot see by itself; hosts emit them.

```ts
interface HostEventSink
```

**Properties**

- `emit` (`<K extends 'run:settled' | 'session:event'>(name: K, event: HookEvents[K]) => void`): Delivers a host event to the extensions' observers.

Source: [src/extensions/runtime/outputs.ts:42](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/outputs.ts#L42)

### `HttpRequestInput`

Interface.

An HTTP request a provider is about to send.

```ts
interface HttpRequestInput
```

**Properties**

- `body?` (`unknown`): The request body, when it has one.
- `headers` (`Readonly<Record<string, string>>`): The request headers.
- `method` (`string`): The HTTP method, upper case.
- `provider` (`string`): Id of the provider sending the request.
- `url` (`string`): The request URL.

Source: [src/extensions/api/hooks.ts:157](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L157)

### `HttpResponseInput`

Interface.

An HTTP response a provider received.

```ts
interface HttpResponseInput
```

**Properties**

- `headers` (`Readonly<Record<string, string>>`): The response headers.
- `provider` (`string`): Id of the provider that got the response.
- `status` (`number`): The HTTP status code.
- `url` (`string`): The URL the request went to.

Source: [src/extensions/api/hooks.ts:171](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L171)

### `InstalledExtensionTargetOptions`

Interface.

Identifies an installed extension and where to look for extension folders. Used by [`updateInstalledExtension`](https://zidane.si/docs/reference/extensions.md#updateInstalledExtension) and [`removeInstalledExtension`](https://zidane.si/docs/reference/extensions.md#removeInstalledExtension).

```ts
interface InstalledExtensionTargetOptions
```

**Properties**

- `cwd?` (`string`, default `process.cwd()`): Working directory used to find the project root.
- `dir` (`string`): The installed extension's directory (e.g. `LoadedExtension.dir`).
- `extensionScanPaths?` (`readonly string[]`): Extra trusted roots (`ZIDANE_EXTENSION_DIRS` / host scan paths).
- `home?` (`string`, default `os.homedir()`): User home directory.
- `prefix?` (`string`, default `'.zidane'`): Storage prefix.

Source: [src/extensions/install.ts:524](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L524)

### `InstallExtensionFromSpecOptions`

Interface.

Options for [`installExtensionFromSpec`](https://zidane.si/docs/reference/extensions.md#installExtensionFromSpec).

```ts
interface InstallExtensionFromSpecOptions
```

**Properties**

- `cwd?` (`string`, default `process.cwd()`): Working directory used to find the project root.
- `expectName?` (`string`): The name the install must have: the candidate of that name, else the
  only candidate, and its definition's id must equal it. Anything else
  fails with `name-mismatch` (listing the names found) before the target
  is touched. Used by [`changeExtensionOrigin`](https://zidane.si/docs/reference/extensions.md#changeExtensionOrigin).
- `extension?` (`string`): Candidate name to install when the source contains several extensions.
- `fallbackExtension?` (`string`): Candidate to pick when the source contains several and `extension` is unset: an update of an
  install recorded without one (older hosts did not record it). Unlike `extension`, a source
  with one candidate, or none of that name, is not an error. The pick is recorded.
- `home?` (`string`, default `os.homedir()`): User home directory.
- `importTimeoutMs?` (`number`): Timeout for the validation import. Default 10s (matches discovery).
- `installRoot?` (`string`): Advanced: exact extensions root to install into, bypassing the
  scope → `.{prefix}/extensions` resolution. Used by
  [`updateInstalledExtension`](https://zidane.si/docs/reference/extensions.md#updateInstalledExtension) to replace an install in place
  (e.g. one living under `.agents/extensions`).
- `io?` (`InstallIo`): Overrides for fetch, process execution and executable lookup. Mainly for tests.
- `onProgress?` (`(message: string) => void`): Called with a short status message as each step runs.
- `overwrite?` (`boolean`): Replace an existing install of the same name. Default false → `exists` error.
- `prefix?` (`string`): Storage prefix (e.g. `.zidane`). Matches discovery's default.
- `scope` (`InstallScope`): Scope to install into.
- `source` (`string`): Raw source spec — see [`parseExtensionInstallSource`](https://zidane.si/docs/reference/extensions.md#parseExtensionInstallSource).

Source: [src/extensions/install.ts:164](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L164)

### `InstructionsDomain`

Interface.

`ctx.instructions`: text added to the system prompt.

```ts
interface InstructionsDomain
```

**Properties**

- `add` (`(text: string, opts?: { key?: string; sessionId?: string }) => Disposable`): Adds `text`. Without `sessionId` it applies to every session. A `key` replaces an earlier entry with the same key.

Source: [src/extensions/api/catalogs.ts:220](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L220)

### `InstructionsRegistry`

Interface.

System prompt text added by extensions (`ctx.instructions`).

```ts
interface InstructionsRegistry
```

**Properties**

- `list` (`(sessionId?: string) => readonly string[]`): Global entries, then the entries of `sessionId`, in load order.
- `subscribe` (`(listener: () => void) => () => void`): Calls `listener` after any change.

Source: [src/extensions/runtime/outputs.ts:34](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/outputs.ts#L34)

### `IntegrationCustomMethod`

Interface.

A connect method the extension runs itself (a bespoke OAuth flow, one
sending custom headers). `connect` drives the host's UI through
[`IntegrationFlowIO`](https://zidane.si/docs/reference/extensions.md#IntegrationFlowIO). An OAuth credential may carry `refreshToken`:
the store keeps it, `resolve` never hands it out, and `refresh` gets it
back when the credential expires within the refresh skew.
[`integrationMethodFromOAuthProvider`](https://zidane.si/docs/reference/extensions.md#integrationMethodFromOAuthProvider) adapts a `zidane/oauth` provider.

```ts
interface IntegrationCustomMethod
```

**Properties**

- `connect` (`(io: IntegrationFlowIO) => Promise<IntegrationCustomResult>`): Runs the sign-in flow and returns the credential.
- `help?` (`string`): Help text for the method.
- `id` (`string`): Method id, unique in the integration.
- `label` (`string`): Name of the method in Settings.
- `refresh?` (`(credential: Credential) => Promise<Credential>`): Renews an expiring credential. Without it, an expired custom credential asks the user to connect again.
- `type` (`'custom'`): Marks a custom method.

Source: [src/extensions/api/sessions.ts:341](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L341)

### `IntegrationCustomResult`

Interface.

What a `custom` method's `connect` returns.

```ts
interface IntegrationCustomResult
```

**Properties**

- `account?` (`string`): Stable id of the account (an email, a user id). Connecting the same account again replaces it. Default: the spec's `account`, else `'default'`.
- `credential` (`Credential`): The credential the flow produced.
- `label?` (`string`): Label shown for it. Default: `account`.

Source: [src/extensions/api/sessions.ts:324](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L324)

### `IntegrationFlowIO`

Interface.

What a `custom` method's `connect` drives the host's sign-in UI with.
The host shows each step the way it shows an OAuth flow's (a link, a code,
a question), in the TUI, the desktop app or a browser on another machine.

```ts
interface IntegrationFlowIO
```

**Properties**

- `log` (`(message: string) => void`): Shows a progress line.
- `openUrl` (`(url: string) => void`): Shows a link for the user to open (a browser sign-in page).
- `prompt` (`(opts: { allowEmpty?: boolean; message: string; options?: readonly { id: string; label: string }[]; placeholder?: string }) => Promise<string | undefined>`): Asks the user through a dialog. With `options`, a choice (resolves to the
  picked option's `id`). Resolves to `undefined` when the user cancels.
- `showCode` (`(code: string, url?: string) => void`): Shows a code to enter, and where (device flows).
- `signal` (`AbortSignal`): Aborts when the user cancels or the extension is disposed.

Source: [src/extensions/api/sessions.ts:307](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L307)

### `IntegrationHandle`

Interface.

A registration. `update` changes the spec in place; Settings redraws.

```ts
interface IntegrationHandle extends Disposable
```

**Properties**

- `dispose` (`() => void`, from `Disposable`): Withdraws the registration. Safe to call more than once.
- `update` (`(patch: IntegrationSpecPatch) => void`): Replaces these fields. Throws a `TypeError` when the result is invalid (the spec stays as it was). A no-op once disposed or when the registration was refused.

Source: [src/extensions/api/sessions.ts:409](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L409)

### `IntegrationsDomain`

Interface.

`ctx.integrations`.

```ts
interface IntegrationsDomain
```

**Properties**

- `connect` (`{ key: (integrationId: string, key: string) => Promise<Connection>; start: (integrationId: string, methodId: string, opts?: { signal?: AbortSignal }) => Promise<Connection> }`): Each adds a connection; one for an account already connected replaces it. The first becomes the default.
- `connection` (`(integrationId: string, opts?: { account?: string }) => Connection | undefined`): The default connection, or the one of `account`.
- `connections` (`(integrationId: string) => readonly Connection[]`): Every connection of an integration, any extension's: the default first.
- `disconnect` (`(integrationId: string, opts?: { account?: string }) => Promise<void>`): Removes the connection of `account`, or every connection when omitted.
- `onChange` (`(integrationId: string, listener: (connection: Connection | undefined) => void) => Disposable`): Called with the default connection whenever any connection of the integration changes.
- `register` (`(spec: IntegrationSpec) => IntegrationHandle`): Offers an integration. Dispose the handle to withdraw it.
- `resolve` (`(connection: Connection) => Promise<Credential>`): The credential of a connection, refreshed when needed.
- `setDefault` (`(integrationId: string, account: string) => Promise<void>`): Makes the connection of `account` the default. Rejects when there is none.

Source: [src/extensions/api/sessions.ts:443](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L443)

### `IntegrationSpec`

Interface.

An integration an extension offers. Settings draws Connect / Disconnect for it.

```ts
interface IntegrationSpec
```

**Properties**

- `account?` (`(credential: Credential) => Promise<string | undefined>`): The account a credential belongs to (an email, a user name), read once after connecting: its stable id and the label shown.
- `beforeConnect?` (`(method: IntegrationMethod) => string | Promise<string | undefined> | undefined`): Runs before any connect (a key, a flow) with the method the user picked.
  Return a message to refuse: it is shown to the user and nothing is
  contacted. A throw refuses with its message.
- `description?` (`string`): Text under the name.
- `icon?` (`{ gui?: string; tui?: string }`): Icon per host: the desktop app (`gui`) and the terminal app (`tui`).
- `id` (`string`): Integration id.
- `legacyCredentialKey?` (`string`): A legacy provider sign-in to adopt: the `credentials.json` key it lived under
  (e.g. `'antigravity'`). On first access, when the integration has no
  connection, an entry under this key becomes one (tokens kept; account
  from the entry's `account` or `email`, else `'default'`; the first
  `oauth` or `custom` method refreshes it). The old entry stays, so a
  downgrade still works; it is marked so a later disconnect sticks.
- `methods` (`readonly IntegrationMethod[]`): The ways to connect.
- `name` (`string`): Name shown in Settings.
- `parseCommandOutput?` (`(stdout: string) => Credential`): Reads the credential a `command` method produced (its stdout).
- `verify?` (`(credential: Credential) => Promise<string | undefined>`): Checks a credential; return an error message to refuse it.

Source: [src/extensions/api/sessions.ts:371](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L371)

### `InterceptOptions`

Interface.

Options of `hooks.intercept`.

```ts
interface InterceptOptions
```

**Properties**

- `match?` (`readonly string[]`): Only for these tools (`tool.call`, `tool.result`), providers (`http.*`, `provider`) or MCP servers (`mcp.tools`). Ignored by other interceptors.
- `priority?` (`number`): Higher runs first among extensions loaded at the same position. Default 0.

Source: [src/extensions/api/hooks.ts:236](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L236)

### `Interceptors`

Interface.

Every interceptor: `[input, result]`. The handler returns a new result or `undefined`.

```ts
interface Interceptors
```

**Properties**

- `behavior` (`[AgentBehavior, AgentBehavior]`): Edits the resolved behavior of a run. Explicit run-level behavior keys still win.
- `compaction` (`[{ messages: readonly SessionMessage[]; reason: 'auto' | 'overflow' | 'manual'; sessionId?: string }, { summary: string } | undefined]`): Returns `{ summary }` to supply the compaction summary, or `undefined` to let the model write it. Runs when a session is compacted.
- `content-ref.resolve` (`[Omit<{ block: ResolveContentRefBlock; childId?: string; data?: string; depth?: number }, 'data'>, string | undefined]`): Returns the data a content reference points to, or `undefined` when it cannot. Runs when a reference is resolved.
- `context` (`[{ messages: readonly SessionMessage[]; sessionId?: string }, readonly SessionMessage[]]`): Returns the wire messages for a turn. Runs before each provider call.
- `http.request` (`[HttpRequestInput, Partial<Pick<HttpRequestInput, 'url' | 'headers' | 'body'>>]`): Edits the URL, headers or body of a provider request. Runs before the request is sent.
- `http.response` (`[HttpResponseInput, Partial<Pick<HttpResponseInput, 'status' | 'headers'>>]`): Edits the status or headers of a provider response. Runs after the response arrives, before the provider reads it.
- `mcp.tools` (`[{ server: string; tools: { description?: string | null; inputSchema?: unknown; name: string }[]; transport: 'sse' | 'stdio' | 'streamable-http' }, readonly { description?: string | null; inputSchema?: unknown; name: string }[]]`): Returns the tools an MCP server exposes to the agent. Runs when the host lists the server's tools.
- `prompt` (`[PromptInput, PromptInput | { handled: true }]`): Edits a submitted prompt, or returns `{ handled: true }` to consume it. Runs after `/` commands, before skills.
- `provider` (`[{ descriptor: ProviderDescriptor; provider: Provider }, Provider]`): Returns the provider that serves the run, to wrap or replace it. Runs when the provider is first used.
- `retry` (`[{ attempt: number; error: string; model: string; provider: string }, { delayMs?: number; retry: boolean }]`): Decides whether to retry a failed provider stream and after how long (`delayMs`). Runs before each retry.
- `run` (`[AgentRunOptions, AgentRunOptions]`): Edits a run's options before it starts.
- `shell.env` (`[{ command: string; cwd: string; sessionId?: string }, Readonly<Record<string, string>>]`): Returns environment variables to add to a shell command. Runs before the command starts.
- `skills.activate` (`[{ run: Pick<AgentRunOptions, 'model' | 'prompt' | 'parentRunId' | 'depth'>; skills: readonly SkillConfig[] }, readonly string[]]`): Returns the names of skills to activate. Runs once at the start of each run.
- `system` (`[{ messages: readonly SessionMessage[]; sessionId?: string; system: string; turn: number; turnId: string }, string]`): Returns the system prompt for a turn. Runs before each provider call.
- `title` (`[{ messages: readonly SessionMessage[]; sessionId: string }, string | undefined]`): Returns a title for a session, or `undefined` to keep the generated one. Runs when the host titles a session.
- `tool.call` (`[ToolCall, ToolCallDecision]`): Rules on a tool call: allow, ask, block, patch the input, or answer it. Runs before the tool executes.
- `tool.result` (`[ToolCallResult, ToolResultDecision]`): Replaces a tool's result, error flag and added metadata. Runs after the tool finishes.
- `tracing.redact` (`[Omit<{ kind: 'system' | 'prompt' | 'tool-input' | 'tool-result' | 'mcp-tool-input' | 'mcp-tool-result' | 'stream-text' | 'stream-thinking' | 'decision-answers'; meta?: Readonly<Record<string, unknown>>; redacted: string; value: string }, 'redacted'>, string]`): Returns the redacted form of a value bound for a trace. Runs synchronously.
- `validation` (`[ToolHookContext & { coercions: readonly string[]; schema: Record<string, unknown> } & { sessionId?: string }, Readonly<Record<string, unknown>>]`): Returns the input of a tool call after auto-coercion, which is validated again. Runs only when a coercion changed a field.

Source: [src/extensions/api/hooks.ts:183](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L183)

### `KeymapDomain`

Interface.

`ctx.keymap`.

```ts
interface KeymapDomain
```

**Properties**

- `active` (`(opts?: { sessionId?: string }) => readonly string[]`): The active mode stack, top last. With `sessionId`, that session's stack.
- `bindings` (`(commandId: string) => readonly string[]`): The effective bindings of a command after user overrides.
- `dispatch` (`(chord: string, opts?: { sessionId?: string }) => Promise<boolean>`): Presses `chord` (`'mod+k'`) in the client viewing `sessionId` (else the
  last active client), as if the user typed it. Resolves `true` when a
  binding took it. Rejects with `NoUiError` when no client can.
- `list` (`() => readonly KeymapEntry[]`): Every command the host offers, built-in and extension, with its effective bindings, scope and mode.
- `mode` (`{ current: () => string | undefined; push: (name: string, opts?: { priority?: number; sessionId?: string }) => Disposable }`): Activates a mode. Bindings with `mode` set fire only while it is on top.

Source: [src/extensions/api/commands.ts:100](https://github.com/Tahul/zidane/blob/main/src/extensions/api/commands.ts#L100)

### `KeymapEntry`

Interface.

One command as `ctx.keymap.list` reports it.

```ts
interface KeymapEntry
```

**Properties**

- `bindings` (`readonly string[]`): Effective bindings after user overrides.
- `editable` (`boolean`): Fires while a text field has focus.
- `extensionId?` (`string`): The extension that registered it; absent for built-ins.
- `id` (`string`): Published id (`<extension>.<id>` or a built-in id).
- `mode?` (`string`): The mode the bindings need, when any.
- `scope` (`KeyScope`): Where focus must be.
- `title` (`string`): Palette title.

Source: [src/extensions/api/commands.ts:121](https://github.com/Tahul/zidane/blob/main/src/extensions/api/commands.ts#L121)

### `KeyValue`

Interface.

Durable key/value data. Reads are synchronous, from a cache: the host
loads `user` and `project` before setup and the run's session before each
run. The first `kv()` call for any other scope or session starts loading
it, and reads return `undefined` until the load ends; await `ready()`
before reading when that matters (a session's data after a restart).

```ts
interface KeyValue
```

**Properties**

- `delete` (`(key: string) => Promise<void>`): Removes `key`. Resolves once the change is saved.
- `get` (`<T extends Json = Json>(key: string) => T | undefined`): The value of `key`, or `undefined` when it is not set or not loaded yet.
- `ready` (`() => Promise<void>`): Resolves once the scope's data is loaded (at once when it is). Rejects when the host fails to load it.
- `scan` (`(prefix?: string) => readonly { key: string; value: Json }[]`): Entries whose key starts with `prefix`, sorted by key.
- `set` (`(key: string, value: Json) => Promise<void>`): Stores `value` under `key`. Resolves once it is saved.
- `subscribe` (`(listener: (change: { key: string; value: Json | undefined }) => void) => Disposable`): Calls `listener` after a change from any window or client.

Source: [src/extensions/api/storage.ts:23](https://github.com/Tahul/zidane/blob/main/src/extensions/api/storage.ts#L23)

### `LinkedExtensionDir`

Interface.

One extension folder a config entry links in place (a local `source` in
`config.json`), scanned ahead of every root. Its scope gates it like a
scan root's: a `project` link loads only in a trusted project.

```ts
interface LinkedExtensionDir
```

**Properties**

- `dir` (`string`, readonly): Absolute extension folder.
- `source` (`'user' | 'project'`, readonly): The config file that links it.

Source: [src/extensions/discovery.ts:94](https://github.com/Tahul/zidane/blob/main/src/extensions/discovery.ts#L94)

### `LinkHandlerItem`

Interface.

Opens links the extension understands, before the app's own behavior.
Every link the apps open goes through it: transcript links, file and
reference chips, panel rows, badge menus, terminal links. Holding Alt
opens a link the default way.

```ts
interface LinkHandlerItem
```

**Properties**

- `id` (`string`): Handler id, unique in the extension.
- `match` (`string | RegExp | ((url: string) => boolean)`): A URL prefix, a pattern, or a test. Runs where the extension runs.
- `open` (`(url: string, ctx: { sessionId?: string; source: LinkSource }) => boolean | void | Promise<boolean | void>`): Opens the link. Return `false` to let the next handler (or the app) open it.
- `priority?` (`number`): Higher first among extensions. Default 0.

Source: [src/extensions/api/ui.ts:412](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L412)

### `LinkHandlerWire`

Interface.

A link handler on the wire: which handlers exist and their order. `match`
and `open` stay in the backend; hosts open a link through the resolver
(`UiRegistry.openLink`, `extensions.links.open`).

```ts
interface LinkHandlerWire
```

**Properties**

- `extensionId` (`string`): The registering extension.
- `id` (`string`): `<extension>/<id>`.
- `priority` (`number`): Higher first among extensions.

Source: [src/extensions/ui/wire.ts:330](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L330)

### `LinkOpenRequest`

Interface.

A link to open, as hosts pass it to `UiCallbacks.openLink`.

```ts
interface LinkOpenRequest
```

**Properties**

- `sessionId?` (`string`): The session it was clicked in.
- `source?` (`LinkSource`): Where it was clicked. Default `'other'`.
- `url` (`string`): The link as clicked.

Source: [src/extensions/ui/callbacks.ts:89](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/callbacks.ts#L89)

### `LiveAccessor`

Interface.

A [`Live`](https://zidane.si/docs/reference/extensions.md#Live) value you can read and watch.

```ts
interface LiveAccessor<T> extends Readable<Live<T>>
```

**Type parameters**

- `T`

**Properties**

- `get` (`() => Live`, from `Readable`): The current value.
- `subscribe` (`(listener: (value: Live) => void) => () => void`, from `Readable`): Calls `listener` after each change. Returns the unsubscribe.
- `value` (`() => T | undefined`): The value when active, else `undefined`.

Source: [src/extensions/api/core.ts:71](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L71)

### `LoadedExtension`

Interface.

Result of attempting to load one extension. Active and disabled entries
carry their live `contributions`; failed ones carry `error`.

```ts
interface LoadedExtension
```

**Properties**

- `contributions?` (`ExtensionContributions`): What the extension contributes right now, read live from the runtime:
  everything when active, settings only when disabled. Absent on failed
  entries.
- `definition?` (`ExtensionDefinition<SettingsSchema>`): The validated definition. Absent when loading or validation failed.
- `dir?` (`string`): Absolute path to the extension's directory. Absent for inline extensions.
- `error?` (`string`): Loader / setup error, when one occurred. Absent on success.
- `manifest?` (`ExtensionManifest`): Optional manifest metadata read before import/setup.
- `name` (`string`): Stable name used for toggle persistence: the folder name, else the definition's `id`.
- `setupRan?` (`boolean`): True once `setup()` was invoked, even if it later failed or timed out.
- `source` (`LoadedExtensionSource`): Where it came from.

Source: [src/extensions/types.ts:668](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L668)

### `LoadedPluginRecord`

Interface.

One Agent Plugin an extension loaded through `ctx.plugins.load`.

The plugin's skills and MCP servers are already folded into the
surrounding [`ExtensionContributions`](https://zidane.si/docs/reference/extensions.md#ExtensionContributions); this record exists so hosts can
still see that a PLUGIN was involved. Without it a plugin's contributions
are indistinguishable from ones the extension author wrote by hand, and the
settings UI has nothing to show a row or a toggle for.

```ts
interface LoadedPluginRecord
```

**Properties**

- `dir` (`string`): Plugin root as requested by the extension.
- `extensionName` (`string`): Name of the extension that loaded it.
- `name` (`string`): Manifest name, or the plugin root's basename when it was rejected.
- `plugin` (`LoadedPlugin`): Load result, including `manifest`, `components` and `diagnostics`.

Source: [src/extensions/types.ts:700](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L700)

### `McpDomain`

Interface.

`ctx.mcp`.

```ts
interface McpDomain
```

**Properties**

- `call` (`(server: string, tool: string, args?: Record<string, unknown>, opts?: { signal?: AbortSignal; timeoutMs?: number }) => Promise<{ content: unknown; isError: boolean }>`): Calls a tool of a connected server outside a run.
- `list` (`() => readonly McpServerStatus[]`): The servers and their connection state.
- `register` (`(server: McpServerConfig) => Disposable`): Adds an MCP server.
- `reload` (`() => Promise<void>`): Replays every transform.
- `transform` (`(fn: Transform<CatalogEditor<McpServerConfig>>) => Disposable`): Adds a transform of the server configs that replays on every change. Dispose it to remove the transform.

Source: [src/extensions/api/catalogs.ts:194](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L194)

### `McpServerStatus`

Interface.

A connected MCP server, as `ctx.mcp.list` reports it.

```ts
interface McpServerStatus
```

**Properties**

- `command?` (`string`): The launch command, for `stdio`.
- `error?` (`string`): Why the connection failed.
- `name` (`string`): The server name.
- `status` (`'idle' | 'connecting' | 'connected' | 'failed' | 'disabled'`): The connection state. `'idle'`: enabled, but no connection is open yet (a remote server no chat in the
  folder has used since the host started): `ctx.mcp.call` connects it. `'disabled'`: configured, not enabled.
- `toolPrefix` (`string`): The prefix of this server's tools in the agent (`mcp_<name>_`): the
  canonical tool names `tool.call` / `tool.result` interceptors and
  `ToolCall.tool` see are `<toolPrefix><tool>`.
- `tools` (`readonly string[]`): The server's own tool names (not namespaced).
- `url?` (`string`): The server URL, for URL transports (`sse`, `streamable-http`).

Source: [src/extensions/api/catalogs.ts:169](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L169)

### `MemorySettingsPort`

Interface.

An in-memory `SettingsPort` whose layers can be set from outside.

```ts
interface MemorySettingsPort extends SettingsPort
```

**Properties**

- `put` (`(extensionId: string, layer: SettingsLayer, values: Readonly<Record<string, unknown>>, sessionId?: string) => void`): Replaces one layer of an extension (a config edit, another window) and notifies its listeners.
- `read` (`(extensionId: string, layer: SettingsLayer, sessionId?: string) => Readonly<Record<string, unknown>> | undefined`, from `SettingsPort`): The values stored in one layer for the extension, by key. Synchronous:
  hosts read from a cache. `sessionId` is set for the `session` layer.
  Values are raw; the domain checks them.
- `secrets` (`SettingsSecretPort`, from `SettingsPort`): Where secret strings live.
- `subscribe?` (`(extensionId: string, listener: () => void) => () => void`, from `SettingsPort`): Calls `listener` after any layer of the extension changed. Returns the unsubscribe. Optional: without it only writes made through the domain notify.
- `write` (`(extensionId: string, scope: SettingScope, key: string, value: StoredSettingValue | undefined, sessionId?: string) => void | Promise<void>`, from `SettingsPort`): Stores a value in a user-writable scope, or clears it when `value` is `undefined`.

Source: [src/extensions/runtime/memory-ports.ts:79](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L79)

### `MemoryStoragePort`

Interface.

An in-memory `StoragePort` with a way to simulate another client's write.

```ts
interface MemoryStoragePort extends StoragePort
```

**Properties**

- `delete` (`(loc: StorageLocation, area: StorageArea, key: string) => Promise<void>`, from `StoragePort`): Removes one entry. Removing a missing entry is a no-op.
- `folderOf?` (`(extensionId: string, scope: 'user' | 'project') => string`, from `StoragePort`): The folder this port keeps one extension's data of `scope` in
  (`project` covers sessions). `storage.path` puts the extension's files
  under it. Absent (a port with no folders): `<dataDir>/extension-storage`
  and the project's folder in it (`./project-folder`).
- `load` (`(loc: StorageLocation) => Promise<StorageSnapshot>`, from `StoragePort`): Reads everything at `loc`. A missing location is an empty snapshot.
- `remote` (`(loc: StorageLocation, change: StorageChange) => void`): Another client wrote: stores the change and tells every subscriber of `loc`.
- `save` (`(loc: StorageLocation, area: StorageArea, key: string, value: Json) => Promise<void>`, from `StoragePort`): Writes one entry.
- `snapshot` (`(loc: StorageLocation) => StorageSnapshot`): What is stored at `loc` now (a copy).
- `subscribe` (`(loc: StorageLocation, listener: (change: StorageChange) => void) => Disposable`, from `StoragePort`): Calls `listener` for changes made by others (not through this port's own
  `save` / `delete`). Echoes are harmless: the domain drops a change that
  matches what it already holds.

Source: [src/extensions/runtime/memory-ports.ts:17](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L17)

### `MenuItem`

Interface.

A native menu entry (desktop). It runs a command.

```ts
interface MenuItem
```

**Properties**

- `accelerator?` (`string`): Keyboard shortcut, as an Electron accelerator string.
- `command` (`string`): Id of the command it runs.
- `enabled?` (`Bindable<boolean>`): Greys the entry out when `false`. Default `true`.
- `label` (`Bindable<string>`): Text of the entry.
- `menu` (`'session' | 'app' | 'tray'`): The menu that holds the entry.

Source: [src/extensions/api/ui.ts:174](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L174)

### `MenuWire`

Interface.

A native menu entry on the wire.

```ts
interface MenuWire
```

**Properties**

- `accelerator?` (`string`): Keyboard shortcut.
- `command` (`string`): The command it runs.
- `enabled` (`boolean`): Whether it can be chosen. Default `true`.
- `label` (`string`): Entry text.
- `menu` (`'session' | 'app' | 'tray'`): Which native menu holds it.

Source: [src/extensions/ui/wire.ts:183](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L183)

### `ModelEditor`

Interface.

Editor of the model catalog (active providers only).

```ts
interface ModelEditor
```

**Properties**

- `default` (`{ get: () => { modelId: string; providerId: string } | undefined; set: (providerId: string, modelId: string) => void }`): The default selection. `set` throws when the model does not exist.
- `get` (`(providerId: string, modelId: string) => ModelInfo | undefined`): The model, or `undefined`.
- `list` (`(providerId?: string) => readonly ModelInfo[]`): The models, or those of one provider.
- `remove` (`(providerId: string, modelId: string) => void`): Removes the model.
- `update` (`(providerId: string, modelId: string, edit: (model: ModelInfo) => void) => void`): Edits a copy of the model.

Source: [src/extensions/api/catalogs.ts:128](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L128)

### `ModelInfo`

Interface.

A model entry.

```ts
interface ModelInfo
```

**Properties**

- `capabilities` (`{ images: boolean; reasoning: boolean; tools: boolean }`): What the model can do.
- `contextWindow?` (`number`): Size of the context window, in tokens.
- `cost?` (`{ input: number; output: number }`): Price in USD per million tokens.
- `enabled` (`boolean`): A disabled model is left out of the chat's model list.
- `id` (`string`): Model id, unique in its provider.
- `maxOutput?` (`number`): Most tokens the model writes in one reply.
- `name` (`string`): Name shown in pickers.
- `providerId` (`string`): Id of the provider the model belongs to.

Source: [src/extensions/api/catalogs.ts:108](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L108)

### `ModelsDomain`

Interface.

`ctx.models`.

```ts
interface ModelsDomain extends CatalogDomain<ModelInfo, ModelEditor>
```

**Properties**

- `default` (`() => { modelId: string; providerId: string } | undefined`): The default selection after transforms.
- `list` (`() => readonly ModelInfo[]`, from `CatalogDomain`): The catalog after every transform.
- `reload` (`() => Promise<void>`, from `CatalogDomain`): Replays every transform of this catalog.
- `transform` (`(fn: Transform<ModelEditor>) => Disposable`, from `CatalogDomain`): Adds a transform that replays on every change. Dispose it to remove the transform.

Source: [src/extensions/api/catalogs.ts:142](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L142)

### `ModelSetting`

Interface.

A model picker. `multi` stores a list.

```ts
interface ModelSetting extends SettingBase
```

**Properties**

- `apply?` (`SettingApply`, from `SettingBase`): Default `'live'`.
- `default?` (`string | readonly string[]`): Used when no scope or config sets a value.
- `description?` (`string`, from `SettingBase`): Help text under the label.
- `label` (`string`, from `SettingBase`): Label in Settings.
- `multi?` (`boolean`): Lets the user pick several models. The value is then a list.
- `page?` (`string`, from `SettingBase`): Page id (see `SettingsSchema.pages`). When omitted: its section's page, else the first page. A page other than its section's is refused.
- `scopes?` (`readonly SettingScope[]`, from `SettingBase`): Scopes the user may set it at. Default `['user', 'project']`.
- `section?` (`string`, from `SettingBase`): Section id (see `SettingsSchema.sections`). Ungrouped when omitted.
- `type` (`'model'`): Marks a model picker.

Source: [src/extensions/api/settings.ts:77](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L77)

### `NamedTool`

Interface.

A tool with its name.

```ts
interface NamedTool
```

**Properties**

- `def` (`ToolDef`): The tool's definition.
- `name` (`string`): The name the model calls the tool by.

Source: [src/extensions/api/catalogs.ts:60](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L60)

### `NewExtensionFolder`

Interface.

How a folder the runtime does not hold may load.

```ts
interface NewExtensionFolder
```

**Properties**

- `enabled?` (`boolean`): `false`: listed disabled (not in the user's allowlist). Default `true`.
- `source` (`ExtensionSource`): Where it was found.

Source: [src/extensions/runtime/reload.ts:21](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/reload.ts#L21)

### `NumberSetting`

Interface.

A number setting.

```ts
interface NumberSetting extends SettingBase
```

**Properties**

- `apply?` (`SettingApply`, from `SettingBase`): Default `'live'`.
- `default?` (`number`): Used when no scope or config sets a value.
- `description?` (`string`, from `SettingBase`): Help text under the label.
- `label` (`string`, from `SettingBase`): Label in Settings.
- `max?` (`number`): Largest value allowed.
- `min?` (`number`): Smallest value allowed.
- `page?` (`string`, from `SettingBase`): Page id (see `SettingsSchema.pages`). When omitted: its section's page, else the first page. A page other than its section's is refused.
- `scopes?` (`readonly SettingScope[]`, from `SettingBase`): Scopes the user may set it at. Default `['user', 'project']`.
- `section?` (`string`, from `SettingBase`): Section id (see `SettingsSchema.sections`). Ungrouped when omitted.
- `step?` (`number`): Increment of the input control.
- `type` (`'number'`): Marks a number setting.

Source: [src/extensions/api/settings.ts:38](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L38)

### `OnOptions`

Interface.

Options of `hooks.on`.

```ts
interface OnOptions
```

**Properties**

- `sessionId?` (`string`): Only events of this session.

Source: [src/extensions/api/hooks.ts:57](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L57)

### `Owner`

Interface.

A group of registrations with one lifetime. The extension's root owner
lives until the extension unloads. `scope()` makes a child that can end
earlier (for example "while connected").

```ts
interface Owner extends Disposable
```

**Properties**

- `dispose` (`() => void`, from `Disposable`): Withdraws the registration. Safe to call more than once.
- `disposed` (`boolean`, readonly): `true` once the owner was disposed. Registrations through a disposed owner throw.
- `onCleanup` (`(cleanup: Cleanup) => Disposable`): Runs `cleanup` when the owner is disposed. Returns a Disposable that cancels it.
- `signal` (`AbortSignal`, readonly): Aborts when the owner is disposed.

Source: [src/extensions/api/core.ts:26](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L26)

### `PaletteProviderSpec`

Interface.

A dynamic palette source: items computed on open, drill-down results.

```ts
interface PaletteProviderSpec
```

**Properties**

- `group?` (`string`): Section header for items that set no group.
- `id` (`string`): Unique within the extension. A duplicate id is refused.
- `items` (`(ctx: { busy: boolean; query: string; sessionId?: string }) => readonly ExtensionPaletteItem[] | Promise<readonly ExtensionPaletteItem[]>`): Returns the items to show for `query`. `busy` is true while a run is going.
- `run` (`(itemId: string, ctx: { sessionId?: string }) => ExtensionPaletteRunResult | Promise<ExtensionPaletteRunResult>`): Runs the item the user picked. It can return a follow-up: more items, a prompt, text for the composer or a notice.
- `subscribe?` (`(refresh: () => void) => () => void`): Call `refresh` when items change while the palette is open.

Source: [src/extensions/api/commands.ts:74](https://github.com/Tahul/zidane/blob/main/src/extensions/api/commands.ts#L74)

### `PanelAction`

Interface.

A button an extension adds to a panel footer. Clicking it calls the extension's `onAction` with `id`.

```ts
interface PanelAction
```

**Properties**

- `id` (`string`): Action id passed back to `onAction`.
- `label` (`string`): Button text.
- `tone?` (`'danger' | 'default'`): `danger` renders in the destructive tint.

Source: [src/extensions/panels.ts:40](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L40)

### `PanelBarsItem`

Interface.

A stacked bar chart with its legend (daily tokens by model).

```ts
interface PanelBarsItem
```

**Properties**

- `empty?` (`string`): Shown instead of the chart when every value is 0.
- `kind` (`'bars'`): Discriminant for a bars item.
- `label?` (`string`): Accessible name of the chart.
- `other?` (`boolean`): The last series is the rest folded together: painted muted.
- `points` (`readonly PanelBarsPoint[]`): The bars, in axis order.
- `series` (`readonly PanelBarsSeries[]`): The series, biggest first: colors follow this order.

Source: [src/extensions/panels.ts:246](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L246)

### `PanelBarsPoint`

Interface.

One bar of a bars item.

```ts
interface PanelBarsPoint
```

**Properties**

- `label` (`string`): Axis label (`Oct 12`).
- `title?` (`string`): The bar's tooltip.
- `values` (`readonly number[]`): One value per series, in series order.

Source: [src/extensions/panels.ts:236](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L236)

### `PanelBarsSeries`

Interface.

One series of a bars item: a legend row.

```ts
interface PanelBarsSeries
```

**Properties**

- `chips?` (`readonly string[]`): Facts beside the label (`12M in`, `3M out`).
- `hint?` (`string`): Tooltip on the label (an id).
- `label` (`string`): Legend label.
- `share?` (`string`): Its share, right-aligned (`42%`).

Source: [src/extensions/panels.ts:224](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L224)

### `PanelContent`

Interface.

JSON-safe content a panel's `load` returns. The host paints it with its own components.

```ts
interface PanelContent
```

**Properties**

- `actions?` (`readonly PanelAction[]`): Buttons in the panel footer.
- `badge?` (`string | number`): Count / short tag shown on the tab. `0` and `''` hide it.
- `controls?` (`readonly PanelControl[]`): Controls in the panel's header, in order (the first starts it, the last ends it).
- `empty?` (`string`): Shown when `sections` are empty.
- `more?` (`PanelMore`): There is more after this content: a Show more button.
- `search?` (`PanelSearch`): A search field in the header.
- `sections` (`readonly PanelSection[]`): Sections to show, in order.
- `title?` (`string`): Overrides the tab label inside the panel header.

Source: [src/extensions/panels.ts:341](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L341)

### `PanelControl`

Interface.

A control in the panel's header. The host keeps what the user picked as `view[id]` and reloads the panel
with it: no `onAction` round trip.

- `'segmented'` (default): a few options side by side (Overview | Models, All | 30d | 7d). `view[id]` is
  one option id.
- `'select'`: one option from a menu (Team, Project). `view[id]` is one option id.
- `'multi'`: any options from a menu (State: Todo, In progress). `view[id]` is a list of option ids;
  none picked means no filter.

```ts
interface PanelControl
```

**Properties**

- `id` (`string`): Key in the view state.
- `kind?` (`'select' | 'multi' | 'segmented'`): How it shows. Default `'segmented'`.
- `label` (`string`): Accessible name of the control, and the menu's label.
- `neutral?` (`string`): The option that means "no filter" (`select`): picking it shows no active-filter chip. Default: the first.
- `options` (`readonly PanelControlOption[]`): Choices, in order. A `segmented` control shows at most 8; a menu up to [`PANEL_CONTENT_LIMITS`](https://zidane.si/docs/reference/extensions.md#PANEL_CONTENT_LIMITS).controlOptions.
- `role?` (`'group' | 'tabs'`): `'tabs'`: switches what the panel shows (a tablist, `segmented` only). Default `'group'`: a filter.
- `value` (`string`): The option this content was built for (`segmented`, `select`).
- `values?` (`readonly string[]`): The options this content was built for (`multi`).

Source: [src/extensions/panels.ts:291](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L291)

### `PanelControlOption`

Interface.

One choice of a segmented control.

```ts
interface PanelControlOption
```

**Properties**

- `icon?` (`PanelIcon`): Its icon (`select` and `multi` menus).
- `id` (`string`): Value stored in the view state when picked.
- `label` (`string`): Its text.

Source: [src/extensions/panels.ts:272](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L272)

### `PanelCustomItem`

Interface.

Host-specific rich view. The TUI resolves `renderer` against
`ctx.tui.registerRenderer` ids (`<extension>/<id>`, bare ids are
prefixed at registration); the GUI, and any host without the renderer,
paints `fallback` as markdown.

```ts
interface PanelCustomItem
```

**Properties**

- `data?` (`JsonValue`): JSON data passed to the renderer.
- `fallback` (`string`): Markdown shown when the host has no matching renderer.
- `kind` (`'custom'`): Discriminant for a custom item.
- `renderer` (`string`): Renderer id, namespaced `<extension>/<id>`.

Source: [src/extensions/panels.ts:166](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L166)

### `PanelFocus`

Interface.

Identifies the badge or card row that opened a panel.

```ts
interface PanelFocus
```

**Properties**

- `kind?` (`string`): Artifact kind of the badge.
- `uri?` (`string`): Artifact URI of the card row.

Source: [src/extensions/panels.ts:450](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L450)

### `PanelHeatmapDay`

Interface.

One day of a heatmap. Sparse: days left out are empty.

```ts
interface PanelHeatmapDay
```

**Properties**

- `date` (`string`): Local `YYYY-MM-DD`.
- `tip?` (`readonly string[]`): Lines of the day's tooltip, under its date (`12.3M tokens`, `40 messages`).
- `value` (`number`): The day's amount. Intensity is its quartile among the days above 0.

Source: [src/extensions/panels.ts:198](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L198)

### `PanelHeatmapItem`

Interface.

A week × weekday activity grid ending at `end`.

```ts
interface PanelHeatmapItem
```

**Properties**

- `days` (`readonly PanelHeatmapDay[]`): The days with activity.
- `end?` (`string`): The last day (local `YYYY-MM-DD`). Default: today, where the host paints it.
- `kind` (`'heatmap'`): Discriminant for a heatmap item.
- `label?` (`string`): Heading above the grid.
- `legend?` (`{ less: string; more: string }`): Legend words either side of the intensity ramp. Absent: no legend.
- `weeks?` (`number`): Weeks shown. Default 26.

Source: [src/extensions/panels.ts:208](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L208)

### `PanelHomeLayout`

Interface.

How a block sits on the project home before the user arranges it.

```ts
interface PanelHomeLayout
```

**Properties**

- `order?` (`number`): Lower first. Default 100.
- `width?` (`'full' | 'half'`): `'half'` shares a row with the next half block. Default `'full'`.

Source: [src/extensions/panels.ts:368](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L368)

### `PanelHostDeps`

Interface.

Where panels run: the scope's reads, and the bridge extension code reads its host from (absent: detached).

```ts
interface PanelHostDeps extends PanelScopeDeps
```

**Properties**

- `artifactsEnabled` (`() => boolean`, from `PanelScopeDeps`): Whether artifacts are on: off, the scope reads none.
- `hostRuntime?` (`ExtensionHostRuntimeBridge`): The bridge extension code reads its host from; absent, panels run detached.
- `listArtifacts` (`(query: { sessionId: string } | { projectRoot: string }) => Promise<SessionArtifact[]>`, from `PanelScopeDeps`): A session's artifacts, or a project's.
- `projectRootOf` (`(cwd: string) => string`, from `PanelScopeDeps`): The project a folder belongs to (its checkout's root).

Source: [src/extensions/panel-host.ts:75](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L75)

### `PanelHostFailure`

Interface.

A panel action's or a palette run's failure: the extension's own words.

```ts
interface PanelHostFailure
```

**Properties**

- `error` (`string`): What the extension said went wrong.
- `ok` (`false`): Always `false`: the call did not go through.

Source: [src/extensions/panel-host.ts:57](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L57)

### `PanelIcon`

Interface.

Per-surface icon: an iconify class for the GUI, a single glyph for the
TUI. The GUI ships Phosphor only (`i-ph-<name>`, `-fill` for a filled
weight); other collections are not registered and paint nothing.

```ts
interface PanelIcon
```

**Properties**

- `gui?` (`string`): Iconify class for the GUI, for example `i-ph-git-branch`.
- `tui?` (`string`): Single glyph for the TUI.

Source: [src/extensions/panels.ts:32](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L32)

### `PanelKeyValueItem`

Interface.

A list of label and value pairs in a panel.

```ts
interface PanelKeyValueItem
```

**Properties**

- `kind` (`'kv'`): Discriminant for a key/value item.
- `mono?` (`boolean`): Values in the code face (default: true, for paths, branches, hashes). `false`: plain text (names, states).
- `rows` (`readonly PanelKeyValueRow[]`): Pairs to show, in order.

Source: [src/extensions/panels.ts:151](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L151)

### `PanelKeyValueRow`

Interface.

One label and value pair in a key/value item.

```ts
interface PanelKeyValueRow
```

**Properties**

- `color?` (`string`): Exact icon color, over `tone`.
- `icon?` (`PanelIcon`): An icon before the value (a state).
- `label` (`string`): Row label.
- `tone?` (`ExtensionBadgeTone`): Tints the value.
- `value` (`string`): Row value.

Source: [src/extensions/panels.ts:137](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L137)

### `PanelLoadContext`

Interface.

The context hosts hand to `load` / `onAction`.

```ts
interface PanelLoadContext
```

**Properties**

- `cursor?` (`string`): The page asked for: a `PanelMore.cursor` this panel returned. Absent: the first page.
- `cwd` (`string`): The folder the panel is for. Always set: a session's cwd, or the open folder.
- `focus?` (`PanelFocus`): What opened the panel, when something pointed at it: a session badge
  (its artifact `kind`) or one row of its card (`uri` too). Absent for a
  plain tab pick. Show that item first or expanded; hosts keep sending it
  on reloads until the panel is opened for something else.
- `global?` (`true`): The project home of no project (a new chat outside any folder): `cwd`
  is the user's home folder, and a block shows what spans projects (all
  usage, every recent session). Home blocks only.
- `scope` (`PanelLoadScope`): `'session'` when `sessionId` is attached, else `'project'`.
- `search?` (`string`): The text in the panel's search field (`PanelContent.search`), trimmed. Absent: empty.
- `sessionId?` (`string`): The session the panel shows beside; absent when only a folder is open (`scope: 'project'`).
- `surface` (`PanelSurface`): Where the content shows: a side tab or a project-home block.
- `view?` (`Readonly<Record<string, string | readonly string[]>>`): The picked option of each segmented control (`PanelContent.controls`),
  by control id. A control the user never touched is absent: use its
  default. Kept by the host per panel and folder.

Source: [src/extensions/panels.ts:415](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L415)

### `PanelLoadContextInput`

Interface.

A load context as it arrives from across a boundary (the GUI renderer)
or from host UI state, before the host binds it: every field optional.
`normalizePanelLoadContext` reduces untrusted input to this shape;
`resolvePanelLoadContext` turns it into the [`PanelLoadContext`](https://zidane.si/docs/reference/extensions.md#PanelLoadContext)
`load` / `onAction` receive.

```ts
interface PanelLoadContextInput
```

**Properties**

- `cursor?` (`string`): The page asked for (`PanelMore.cursor`).
- `cwd?` (`string`): Folder the panel is for.
- `focus?` (`PanelFocus`): What opened the panel, when something pointed at it.
- `global?` (`boolean`): The home of no project (`cwd` is the user's home folder).
- `search?` (`string`): The text in its search field.
- `sessionId?` (`string`): Session the panel is shown beside.
- `surface?` (`PanelSurface`): The surface asking (`'side'` when absent).
- `view?` (`Readonly<Record<string, string | readonly string[]>>`): The values of its controls.

Source: [src/extensions/panels.ts:392](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L392)

### `PanelMarkdownItem`

Interface.

A block of Markdown text in a panel.

```ts
interface PanelMarkdownItem
```

**Properties**

- `kind` (`'markdown'`): Discriminant for a Markdown item.
- `text` (`string`): Markdown source.

Source: [src/extensions/panels.ts:129](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L129)

### `PanelMore`

Interface.

More items to load after this content: the host shows a Show more button and calls `load` again with
`cursor`, then appends what comes back (rows to the sections of the same id, new sections after). A new
view, search or a change emit loads the first page again.

```ts
interface PanelMore
```

**Properties**

- `cursor` (`string`): Handed back as `PanelLoadContext.cursor`.
- `label?` (`string`): The button's text. Default: the host's "Show more".

Source: [src/extensions/panels.ts:321](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L321)

### `PanelRowAction`

Interface.

A button on a panel row. With `start`, the app opens a new chat for it (never sent); without, it calls the
panel's `onAction(id, payload)`.

```ts
interface PanelRowAction
```

**Properties**

- `icon?` (`PanelIcon`): Its icon.
- `id` (`string`): Action id: passed to `onAction` when there is no `start`. Unique in the row.
- `label` (`string`): Its text.
- `payload?` (`JsonValue`): Extra data handed back with the action.
- `start?` (`PanelStartSession`): Opens a new chat draft for the panel's folder instead of calling `onAction`.

Source: [src/extensions/panels.ts:93](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L93)

### `PanelRowItem`

Interface.

One line in a panel, same presentation as an artifact row.

```ts
interface PanelRowItem extends ExtensionArtifactRow
```

**Properties**

- `actionId?` (`string`): Fired via `onAction` on click / Enter. `href` opens externally when no action is set.
- `actions?` (`readonly PanelRowAction[]`): Buttons on the row (at most [`PANEL_CONTENT_LIMITS`](https://zidane.si/docs/reference/extensions.md#PANEL_CONTENT_LIMITS).rowActions): shown on hover and focus, and in the
  row's right-click menu. One with `start` is run by the app (a new chat); others go to `onAction`.
- `badges?` (`readonly { text: string; title?: string; tone?: 'success' | 'warn' | 'diff' | 'neutral' }[]`, from `ExtensionArtifactRow`): Small facts shown after the title (`+120 −8`, `3 reviews`, `ready to
  merge`). `tone` hints the renderer: `diff` colors additions/deletions,
  `success` / `warn` tint, `neutral` is a quiet chip. Optional `title` is a
  hover detail.
- `color?` (`string`): Exact icon color (`#rgb` / `#rrggbb`), over `tone`.
- `details?` (`readonly PanelItem[]`): What the row unfolds into (facts, a description): hosts draw a chevron
  and toggle it on click. Not nested: rows inside `details` can't have
  their own.
- `diff?` (`{ added: number; files?: number; href?: string; removed: number }`, from `ExtensionArtifactRow`): A change size, painted in the diff colors; `href` links it (a PR's files).
- `expanded?` (`boolean`): Open at first (`details` only); the user's toggles win after that.
- `facts?` (`readonly ExtensionArtifactRowFact[]`, from `ExtensionArtifactRow`): Quiet facts after the diff (`2 reviews`, `main`, `Ready to merge`). At most 8.
- `href?` (`string`, from `ExtensionArtifactRow`): Where "open" goes: a URL or an absolute path.
- `icon?` (`PanelIcon`): A leading icon (a state, a kind). With one, hosts drop the `status` chip's slot for it.
- `id?` (`string`): Stable key for the host; defaults to the title.
- `kind` (`'row'`): Discriminant for a row item.
- `lead?` (`{ href?: string; mono?: boolean; text: string }`, from `ExtensionArtifactRow`): A short id (`e32789e`, `stackblitz/bolt#8183`); `mono` for hashes.
- `meter?` (`number`): A bar under the title, filled to this share (0-1): a part of a whole (spend per provider).
- `payload?` (`JsonValue`): Extra data handed back with the action.
- `session?` (`string`): A session of this host the row stands for: a click opens it in the app
  (before `actionId` and `href`). For hosts that show sessions.
- `status?` (`string`, from `ExtensionArtifactRow`): Short state tag (`open`, `merged`, `deployed`, …).
- `subtitle?` (`string`, from `ExtensionArtifactRow`): Secondary line under the title.
- `title` (`string`, from `ExtensionArtifactRow`): Row title.
- `tone?` (`ExtensionBadgeTone`): Tints the icon (theme tone).
- `wrap?` (`boolean`): Let the title wrap instead of truncating (a detail header).

Source: [src/extensions/panels.ts:50](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L50)

### `PanelScopeDeps`

Interface.

What a panel's scope reads from its host.

```ts
interface PanelScopeDeps
```

**Properties**

- `artifactsEnabled` (`() => boolean`): Whether artifacts are on: off, the scope reads none.
- `listArtifacts` (`(query: { sessionId: string } | { projectRoot: string }) => Promise<SessionArtifact[]>`): A session's artifacts, or a project's.
- `projectRootOf` (`(cwd: string) => string`): The project a folder belongs to (its checkout's root).

Source: [src/extensions/panel-host.ts:65](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L65)

### `PanelSearch`

Interface.

A search field in the panel's header: the host keeps its text and reloads with it (`PanelLoadContext.search`).

```ts
interface PanelSearch
```

**Properties**

- `placeholder?` (`string`): Placeholder text.

Source: [src/extensions/panels.ts:311](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L311)

### `PanelSection`

Interface.

A titled group of items in a panel.

```ts
interface PanelSection
```

**Properties**

- `collapsed?` (`boolean`): Collapsed by default when true.
- `id` (`string`): Stable section id.
- `items` (`readonly PanelItem[]`): Items in the section, in order.
- `title?` (`string`): Section heading. Omitted: no heading.

Source: [src/extensions/panels.ts:329](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L329)

### `PanelStartSession`

Interface.

A new chat a row action opens: a draft in the panel's folder, never sent. The user reviews the prompt and
sends it.

- `where: 'worktree'`: the draft runs in a new git worktree on `branch` (a pull request's head when
  `pullRequest` is set: fetched when the branch is not local).
- `where: 'here'`: the draft runs in the folder itself. With `pullRequest` or `branch`, the folder switches
  to it first (never forced: git's refusal comes back to the user); without, the branch is left alone.

```ts
interface PanelStartSession
```

**Properties**

- `branch?` (`string`): The branch to run on.
- `prompt?` (`string`): The draft's text.
- `pullRequest?` (`number`): A pull request of the folder's repository, by number: its head branch.
- `title?` (`string`): The session's title.
- `where` (`'worktree' | 'here'`): A new worktree, or the folder itself.

Source: [src/extensions/panels.ts:115](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L115)

### `PanelStat`

Interface.

One big-number tile of a stats item.

```ts
interface PanelStat
```

**Properties**

- `hint?` (`string`): Tooltip on the number (the exact figure).
- `label` (`string`): What it counts, under the number.
- `value` (`string`): The number, formatted (`72.5B`, `17 days`).

Source: [src/extensions/panels.ts:178](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L178)

### `PanelStatsItem`

Interface.

A grid of big-number tiles (totals, streaks).

```ts
interface PanelStatsItem
```

**Properties**

- `columns?` (`4 | 2 | 3`): Tiles per row on a wide surface. Default 4.
- `kind` (`'stats'`): Discriminant for a stats item.
- `stats` (`readonly PanelStat[]`): Tiles, in reading order.

Source: [src/extensions/panels.ts:188](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L188)

### `PanelSummary`

Interface.

One panel a folder offers, as an app lists it.

```ts
interface PanelSummary
```

**Properties**

- `home?` (`PanelHomeLayout`): Its default place on the project home, when it gave one.
- `icon?` (`PanelIcon`): Its tab icon, when the extension gave one.
- `id` (`string`): The panel's id, unique in the folder.
- `label` (`string`): Its tab title.
- `owner` (`string`): The extension that registered it.
- `ownerIcon?` (`PanelIcon`): Its extension's own icon: apps draw the extension's mark (`extensionMark`) when the panel has no `icon`. Additive.
- `ownerName?` (`string`): Its extension's display name. Additive.
- `scope` (`ExtensionPanelScope`): Where its side tab shows (`ExtensionPanel.scope`, `'session'` when unset).
- `surfaces` (`readonly PanelSurface[]`): The surfaces it shows on (`ExtensionPanel.surfaces`, `['side']` when unset).

Source: [src/extensions/panel-host.ts:35](https://github.com/Tahul/zidane/blob/main/src/extensions/panel-host.ts#L35)

### `PanelWire`

Interface.

A panel on the wire. Its `load` / `onAction` / `subscribe` stay backend-side.

```ts
interface PanelWire
```

**Properties**

- `actions` (`boolean`): It has `onAction`.
- `component?` (`ComponentWire`): Drawn instead of the data where the host has it.
- `home?` (`PanelHomeLayout`): Layout of the block on the project home.
- `icon?` (`PanelIcon`): Per-surface icon.
- `id` (`string`): `<extension>/<id>`.
- `label` (`string`): Tab title.
- `live` (`boolean`): It has `subscribe`: the registry pushes `panel-changed` when it would load something new.
- `ownerIcon?` (`PanelIcon`): The extension's own icon: without `icon`, apps draw the extension's mark (`extensionMark`).
- `ownerName?` (`string`): The extension's display name.
- `scope?` (`'session' | 'project' | 'both'`): Where it shows: beside a session, in a project, or both. Default `session`.
- `surfaces` (`readonly PanelSurface[]`): Where it shows. Default `['side']`.

Source: [src/extensions/ui/wire.ts:67](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L67)

### `PluginsDomain`

Interface.

`ctx.plugins`: Agent Plugins (skills + MCP bundles).

```ts
interface PluginsDomain
```

**Properties**

- `load` (`(spec: string | { dir: string; mcp?: boolean; namePrefix?: string; skills?: boolean }) => Promise<LoadedPlugin & Disposable>`): Loads an Agent Plugin folder and registers its skills and MCP servers.

Source: [src/extensions/api/catalogs.ts:214](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L214)

### `PromptInput`

Interface.

A prompt on its way in, before commands and skills.

```ts
interface PromptInput
```

**Properties**

- `attachments` (`readonly { mimeType: string; name: string; path?: string }[]`): Files sent with the prompt.
- `delivery` (`'auto' | 'steer' | 'followUp'`): How the prompt reaches a running session: `'auto'` lets the host choose, `'steer'` and `'followUp'` queue it for the running agent.
- `metadata` (`Readonly<Record<string, unknown>>`): Host data that travels with the prompt.
- `sessionId?` (`string`): The session the prompt goes to.
- `text` (`string`): The prompt text.

Source: [src/extensions/api/hooks.ts:143](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L143)

### `ProviderEditor`

Interface.

Editor of provider descriptors (including inactive ones).

```ts
interface ProviderEditor extends CatalogEditor<ProviderDescriptor>
```

**Properties**

- `add` (`(item: ProviderDescriptor) => void`, from `CatalogEditor`): Adds an item, or replaces the one with the same id.
- `get` (`(id: string) => ProviderDescriptor | undefined`, from `CatalogEditor`): The item with this id, or `undefined`.
- `list` (`() => readonly ProviderDescriptor[]`, from `CatalogEditor`): The items as edited so far.
- `models` (`{ remove: (providerId: string, modelId: string) => void; set: (providerId: string, models: readonly ModelInfo[], opts?: { account?: string }) => void; update: (providerId: string, modelId: string, edit: (model: ModelInfo) => void) => void }`): Edits the models of a provider. `set` replaces the whole list.
- `origin` (`(id: string) => ItemOrigin | undefined`, from `CatalogEditor`): Who put the item in the catalog.
- `remove` (`(id: string) => void`, from `CatalogEditor`): Removes the item with this id.
- `update` (`(id: string, edit: (item: ProviderDescriptor) => void) => void`, from `CatalogEditor`): Edits a copy of the item.

Source: [src/extensions/api/catalogs.ts:148](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L148)

### `ProvidersDomain`

Interface.

`ctx.providers`.

```ts
interface ProvidersDomain extends CatalogDomain<ProviderDescriptor, ProviderEditor>
```

**Properties**

- `list` (`() => readonly ProviderDescriptor[]`, from `CatalogDomain`): The catalog after every transform.
- `register` (`(descriptor: ProviderDescriptor) => Disposable`): Adds a provider.
- `reload` (`() => Promise<void>`, from `CatalogDomain`): Replays every transform of this catalog.
- `transform` (`(fn: Transform<ProviderEditor>) => Disposable`, from `CatalogDomain`): Adds a transform that replays on every change. Dispose it to remove the transform.

Source: [src/extensions/api/catalogs.ts:163](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L163)

### `Readable`

Interface.

A value that changes over time. Stores and selectors implement it.

```ts
interface Readable<T>
```

**Type parameters**

- `T`

**Properties**

- `get` (`() => T`): The current value.
- `subscribe` (`(listener: (value: T) => void) => () => void`): Calls `listener` after each change. Returns the unsubscribe.

Source: [src/extensions/api/core.ts:47](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L47)

### `RecordingUiClientPort`

Interface.

A `UiClientPort` that records calls and reports success.

```ts
interface RecordingUiClientPort extends UiClientPort
```

**Properties**

- `calls` (`readonly UiClientCall[]`, readonly): Every call, oldest first.
- `composer` (`(clientId: string, op: ComposerOp, opts: { sessionId?: string }) => Promise<boolean>`, from `UiClientPort`): Edits the composer of the client (the one for `sessionId` when given). Whether it did.
- `keymapDispatch?` (`(clientId: string, request: { chord: string; sessionId?: string }) => Promise<boolean>`, from `UiClientPort`): Presses a chord (`'mod+k'`, `mod` not resolved: the client resolves it
  for its platform) in the client, as if the user typed it, in the view
  of `sessionId` when given. Whether a binding took it. Absent: the host's
  clients cannot, and `ctx.keymap.dispatch` rejects with `NoUiError`.
- `navigate` (`(clientId: string, to: NavigateTarget) => Promise<boolean>`, from `UiClientPort`): Shows a screen, a session or a new session in the client. Whether it did.
- `notify` (`(clientId: string, notification: { body?: string; extensionId: string; sessionId?: string; sound?: boolean; title: string }) => void`, from `UiClientPort`): Shows an OS notification from the client, unless the app has focus.
- `panel` (`(clientId: string, request: { action: 'open' | 'toggle' | 'close'; focus?: PanelFocus; panelId: string; sessionId?: string }) => Promise<boolean>`, from `UiClientPort`): Opens, closes or toggles a panel (full id or built-in) in the client. Whether it did.
- `panelState` (`(clientId: string, opts: { sessionId?: string }) => Promise<readonly string[]>`, from `UiClientPort`): The panels open in the client (beside `sessionId` when given).

Source: [src/extensions/runtime/memory-ports.ts:202](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L202)

### `ReferenceMatch`

Interface.

One reference found in a text: `[start, end)` and the key to resolve.

```ts
interface ReferenceMatch
```

**Properties**

- `end` (`number`): Index after the last character of the match.
- `key` (`string`): Key to pass to the provider's `resolve`.
- `placeholder?` (`string`): The pattern's `placeholder`, expanded: a label to paint before the view is known.
- `placeholderIcon?` (`ExtensionBadgeIcon`): The pattern's `placeholderIcon`.
- `providerId` (`string`): Id of the provider whose pattern matched.
- `start` (`number`): Index of the first character of the match.

Source: [src/extensions/references.ts:36](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L36)

### `ReferenceProviderWire`

Interface.

What a host needs to match a provider's references: JSON-safe.

```ts
interface ReferenceProviderWire
```

**Properties**

- `id` (`string`): Provider id.
- `patterns` (`readonly ExtensionReferencePattern[]`): Patterns that find candidate references.
- `surfaces?` (`readonly ExtensionReferenceSurface[]`): Surfaces to scan. Omitted: all.

Source: [src/extensions/references.ts:26](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L26)

### `ReferenceResolver`

Interface.

Resolves reference keys to views, caching the answers.

```ts
interface ReferenceResolver
```

**Properties**

- `clear` (`() => void`): Drop every cached view.
- `resolve` (`(providerId: string, key: string) => Promise<ExtensionReferenceView | null>`): The view for `(providerId, key)`; `null` when it names nothing, the provider is unknown, or resolving failed.

Source: [src/extensions/references.ts:282](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L282)

### `ReferenceResolverOptions`

Interface.

Options for [`createReferenceResolver`](https://zidane.si/docs/reference/extensions.md#createReferenceResolver).

```ts
interface ReferenceResolverOptions
```

**Properties**

- `builtins?` (`boolean`): Include the built-in providers (GitHub pull requests). Default true.
- `missTtlMs?` (`number`): How long "names nothing" is remembered. Default 1 minute.
- `now?` (`() => number`, default `Date.now`): Clock in epoch ms.
- `timeoutMs?` (`number`): Per-resolve deadline. Default 8 s.
- `ttlMs?` (`number`): How long a view stays fresh. Default 5 minutes.

Source: [src/extensions/references.ts:268](https://github.com/Tahul/zidane/blob/main/src/extensions/references.ts#L268)

### `RegistryToken`

Interface.

Token of a list an extension owns.

```ts
interface RegistryToken<T>
```

**Type parameters**

- `T`

**Properties**

- `__type?` (`T`, readonly): Type-level only.
- `id` (`string`, readonly): `<extension id>.<name>`.
- `kind` (`'registry'`, readonly): Always `'registry'`.

Source: [src/extensions/api/contracts.ts:22](https://github.com/Tahul/zidane/blob/main/src/extensions/api/contracts.ts#L22)

### `RegistryViewFilter`

Interface.

How a view narrows its source.

```ts
interface RegistryViewFilter
```

**Properties**

- `droppedPlugins?` (`ReadonlySet<string>`, readonly): Agent Plugin names whose skills and MCP servers drop out.
- `enabled?` (`ReadonlySet<string>`, readonly): Names of the extensions to keep active; the rest show as inactive. `undefined`: all.

Source: [src/extensions/runtime/registry-view.ts:427](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/registry-view.ts#L427)

### `RegistryViewSource`

Interface.

What a registry view reads from: the runtime, the entries it refused, and the change feed.

```ts
interface RegistryViewSource
```

**Properties**

- `cwd` (`string`, readonly): The host cwd (panel loads without one).
- `dispose` (`() => Promise<void>`): Disposes the runtime. Idempotent.
- `dropRefused` (`(dir: string) => boolean`): Takes the refused entry of folder `dir` off the list (the folder was
  deleted, or it loads into the runtime now). Returns whether there was one.
- `refused` (`readonly LoadedExtension[]`, readonly): Entries refused before the runtime: load errors, modules without a definition, duplicates.
- `reportRefused` (`(group: string, entries: readonly LoadedExtension[]) => void`): Replaces the rows a host reports under `group` (config install
  failures, `config:user`), listed after `refused`. An empty list
  clears the group.
- `runtime?` (`ExtensionRuntime`, readonly): The runtime. Absent when no extension was loaded into one.
- `subscribe` (`(listener: () => void) => () => void`): Calls `listener` (coalesced per microtask) after a change.
- `version` (`() => number`): Bumped on every change; views recompute when it moved.

Source: [src/extensions/runtime/registry-view.ts:298](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/registry-view.ts#L298)

### `ReloadChangedOptions`

Interface.

Options of [`reloadChangedExtensions`](https://zidane.si/docs/reference/extensions.md#reloadChangedExtensions).

```ts
interface ReloadChangedOptions
```

**Properties**

- `classify?` (`(dir: string) => NewExtensionFolder | undefined`): Whether a folder no extension was loaded from may load now, and how.
  `undefined`: it may not (not under a scan root, an untrusted project
  folder, shadowed by a folder of the same name that wins). Without
  `classify`, new folders are ignored.
- `compileCache?` (`string`): Node hosts: the folder compiled extension code is kept in.
- `importTimeoutMs?` (`number`): How long one import may take. Default 10 s.
- `sink?` (`LogSink`): Where load warnings go. Default: warnings to stderr.

Source: [src/extensions/runtime/reload.ts:29](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/reload.ts#L29)

### `ReloadChangedResult`

Interface.

What [`reloadChangedExtensions`](https://zidane.si/docs/reference/extensions.md#reloadChangedExtensions) did, by extension id.

```ts
interface ReloadChangedResult
```

**Properties**

- `loaded` (`string[]`): New folders that loaded (active, disabled or failed).
- `needsRebuild` (`boolean`): A change could not be applied in place: the registry holds no runtime
  (it loaded no extension), so a new folder needs a full rebuild.
- `reloaded` (`string[]`): Extensions imported again and reloaded in place.
- `unloaded` (`string[]`): Extensions whose folder (or entry file) is gone.

Source: [src/extensions/runtime/reload.ts:46](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/reload.ts#L46)

### `RendererItem`

Interface.

A renderer: a component per host, with a markdown fallback.

```ts
interface RendererItem
```

**Properties**

- `component` (`ComponentRef`): The component that draws it.
- `fallthrough?` (`boolean`): `true`: the component returns null to let the next renderer (or the default) draw.
- `for` (`RendererTarget`): What the renderer draws.

Source: [src/extensions/api/ui.ts:134](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L134)

### `RendererWire`

Interface.

A renderer on the wire.

```ts
interface RendererWire
```

**Properties**

- `component` (`ComponentWire`): The component that draws it.
- `fallthrough?` (`true`): The component returns null to let the next renderer (or the default) draw.
- `for` (`RendererTarget`): What it draws: a block id, a code-block language, a tool result or an artifact kind.

Source: [src/extensions/ui/wire.ts:143](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L143)

### `RpcCallContext`

Interface.

What an implementation receives besides its input.

```ts
interface RpcCallContext<S extends RpcMethodSpec>
```

**Type parameters**

- `S` (`extends RpcMethodSpec`)

**Properties**

- `caller` (`{ id: string; kind: 'extension' } | { kind: 'ui' } | { clientId: string; kind: 'client' }`, readonly): Who called: another extension, the extension's UI, or a protocol client.
- `error` (`<N extends string>(type: N, message: string, data: Infer<ErrorsOf<S>[N]>) => RpcError<N, Infer<ErrorsOf<S>[N]>>`): Builds a declared error. Return or throw it.
- `signal` (`AbortSignal`, readonly): Aborts when the caller cancels, the call times out or the extension unloads.

Source: [src/extensions/api/rpc.ts:63](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L63)

### `RpcContract`

Interface.

An RPC contract made by `Rpc.define`. Holds no implementation, so others can import it.

```ts
interface RpcContract<M extends Readonly<Record<string, RpcMethodSpec>> = Readonly<Record<string, RpcMethodSpec>>, E extends Readonly<Record<string, RpcEventSpec>> = Readonly<Record<string, RpcEventSpec>>>
```

**Type parameters**

- `M` (`extends Readonly<Record<string, RpcMethodSpec>>`, default `Readonly<Record<string, RpcMethodSpec>>`)
- `E` (`extends Readonly<Record<string, RpcEventSpec>>`, default `Readonly<Record<string, RpcEventSpec>>`)

**Properties**

- `events` (`E`, readonly): The events by name.
- `id` (`string`, readonly): Contract id: the extension id, or `<extension id>.<name>`.
- `kind` (`'rpc'`, readonly): Always `'rpc'`.
- `methods` (`M`, readonly): The methods by name.

Source: [src/extensions/api/rpc.ts:32](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L32)

### `RpcDomain`

Interface.

`ctx.rpc`.

```ts
interface RpcDomain
```

**Properties**

- `client` (`<C extends RpcContract<Readonly<Record<string, RpcMethodSpec>>, Readonly<Record<string, RpcEventSpec>>>>(contract: C) => RpcClient<C>`): A client for any registered contract (this extension's or another's).
- `register` (`<C extends RpcContract<Readonly<Record<string, RpcMethodSpec>>, Readonly<Record<string, RpcEventSpec>>>>(contract: C, impl: RpcImplementation<C>) => RpcRegistration<C>`): Implements `contract`. Its id must be the extension id or start with `<id>.`.

Source: [src/extensions/api/rpc.ts:107](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L107)

### `RpcError`

Interface.

A declared error, returned or thrown by an implementation.

```ts
interface RpcError<Name extends string = string, Data = unknown>
```

**Type parameters**

- `Name` (`extends string`, default `string`)
- `Data` (default `unknown`)

**Properties**

- `data` (`Data`, readonly): The error data.
- `kind` (`'rpc-error'`, readonly): Always `'rpc-error'`.
- `message` (`string`, readonly): Text for people.
- `type` (`Name`, readonly): The declared error name.

Source: [src/extensions/api/rpc.ts:51](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L51)

### `RpcEvent`

Interface.

An event delivered to subscribers.

```ts
interface RpcEvent<D = unknown>
```

**Type parameters**

- `D` (default `unknown`)

**Properties**

- `data` (`D`, readonly): The event data.
- `location` (`{ directory: string }`, readonly): The project the emitting extension runs in.
- `type` (`string`, readonly): `rpc.<contract id>.<event>`.

Source: [src/extensions/api/rpc.ts:78](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L78)

### `RpcEvents`

Interface.

Event side of a client.

```ts
interface RpcEvents<E extends Readonly<Record<string, RpcEventSpec>>>
```

**Type parameters**

- `E` (`extends Readonly<Record<string, RpcEventSpec>>`)

**Properties**

- `on` (`<K extends string>(name: K, listener: (event: RpcEvent<Infer<E[K]['schema']>>) => void) => Disposable`): Calls `listener` for each event called `name`.
- `subscribe` (`<K extends string>(name: K) => AsyncIterable<RpcEvent<Infer<E[K]['schema']>>>`): The events called `name` as an async iterable.

Source: [src/extensions/api/rpc.ts:88](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L88)

### `RpcEventSpec`

Interface.

One event of an RPC contract. Event data must be an object.

```ts
interface RpcEventSpec
```

**Properties**

- `schema` (`Schema`): Schema of the event data.

Source: [src/extensions/api/rpc.ts:26](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L26)

### `RpcMethodSpec`

Interface.

One method of an RPC contract.

```ts
interface RpcMethodSpec
```

**Properties**

- `errors?` (`Readonly<Record<string, Schema>>`): Expected failures by name. Names starting with `rpc.` are reserved.
- `input?` (`Schema`): Schema of the input. Without it the method takes none.
- `output?` (`Schema`): Schema of the result. Without it the method returns nothing.
- `scope?` (`AccessScope`): The least token scope a protocol client needs to call it. Default
  `'chat'`. In-process callers, local connections and other extensions are
  not limited.

Source: [src/extensions/api/rpc.ts:10](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L10)

### `RpcRegistration`

Interface.

A registered implementation.

```ts
interface RpcRegistration<C extends RpcContract> extends Disposable
```

**Type parameters**

- `C` (`extends RpcContract`)

**Properties**

- `dispose` (`() => void`, from `Disposable`): Withdraws the registration. Safe to call more than once.
- `events` (`{ emit: <K extends string>(name: K, data: Infer<C['events'][K]['schema']>) => void }`, readonly): Emits events of the contract to its subscribers.

Source: [src/extensions/api/rpc.ts:101](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L101)

### `RunSettledEvent`

Interface.

What `run:settled` observers receive.

```ts
interface RunSettledEvent
```

**Properties**

- `aborted` (`boolean`): The user stopped the run. An interrupted run can still be `ok`.
- `ok` (`boolean`): The run ended without an error.
- `runId` (`string`): The run that ended.
- `session` (`{ metadata: Readonly<Record<string, unknown>>; turns: readonly SessionTurn[] } | null`): The session as the run left it: every turn (tool results included) and
  its metadata. `null` when no live session remained (it was deleted or
  its agent torn down before the run settled).
- `sessionId` (`string`): The session the run belonged to.

Source: [src/extensions/api/hooks.ts:31](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L31)

### `RuntimeCatalogPorts`

Interface.

Base data of the shared catalogs. Each falls back to an empty base.

```ts
interface RuntimeCatalogPorts
```

**Properties**

- `agents?` (`AgentsCatalogPort`): Base agent profiles.
- `mcp?` (`McpCatalogPort`): Base MCP servers.
- `models?` (`ModelsCatalogPort`): Base models.
- `providers?` (`ProvidersCatalogPort`): Base providers.
- `skills?` (`SkillsCatalogPort`): Base skills.
- `tools?` (`ToolsCatalogPort`): Base tools.

Source: [src/extensions/runtime/host.ts:89](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/host.ts#L89)

### `RuntimeEntry`

Interface.

One extension to load.

```ts
interface RuntimeEntry
```

**Properties**

- `definition` (`unknown`): The module's default export; validated before use.
- `dir?` (`string`): The extension's folder. Its name must equal the id.
- `enabled?` (`boolean`): `false`: discovered but turned off. Not run; settings stay readable. Default `true`.
- `error?` (`string`): Why the module could not be imported (a syntax error, no definition). The
  entry is listed as `failed` with this error and never validated, so a
  later `ExtensionRuntime.reload` of its folder can bring it up.
- `manifest?` (`ExtensionManifest`): Its manifest (`extension.json`, `package.json#zidane`): the display name and icon when the definition has none.
- `source` (`ExtensionSource`): Where the extension was found.

Source: [src/extensions/runtime/host.ts:141](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/host.ts#L141)

### `RuntimeExtension`

Interface.

The loaded state of one extension, for hosts and the registry view.

```ts
interface RuntimeExtension
```

**Properties**

- `definition?` (`ExtensionDefinition<SettingsSchema>`, readonly): The validated definition; absent when validation failed.
- `entry` (`RuntimeEntry`, readonly): The entry it was loaded from.
- `guard?` (`RuntimeGuard`, readonly): Present while active.
- `id` (`string`, readonly): The extension id.
- `info` (`ExtensionInfo`, readonly): Status and metadata, as `ctx.extensions` shows it.
- `settings?` (`SettingsDomainInstance<SettingsSchema>`, readonly): Present while active.
- `warnings` (`readonly string[]`, readonly): Validation warnings and load-order issues about this extension.

Source: [src/extensions/runtime/host.ts:208](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/host.ts#L208)

### `RuntimeHooksPorts`

Interface.

The agent-hook side of the hooks port.

```ts
interface RuntimeHooksPorts
```

**Properties**

- `agentHooks?` (`Pick<Hookable<AgentHooks, HookKeys<AgentHooks>>, 'hook'>`): The agent hook bus (`Agent['hooks']`, or a fan-out over every agent).
  Without it, observers land on a per-extension bus the registry
  view hands to the hosts as ordinary hook handlers.
- `emitsHostEvents?` (`boolean`): The host calls `outputs.hostEvents.emit` itself. When `false` (default),
  the registry view also exposes per-extension `runSettled` /
  `sessionEvents` handlers so the host delivers host events through them.
- `sessionIdOf?` (`(name: keyof AgentHooks | 'run:settled' | 'session:event', event: unknown) => string | undefined`): See `HooksPort.sessionIdOf`.

Source: [src/extensions/runtime/host.ts:71](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/host.ts#L71)

### `RuntimeLoadedExtension`

Interface.

A discovered or inline extension, carried in the `LoadedExtension` list until the runtime takes it.

```ts
interface RuntimeLoadedExtension extends LoadedExtension
```

**Properties**

- `contributions?` (`ExtensionContributions`, from `LoadedExtension`): What the extension contributes right now, read live from the runtime:
  everything when active, settings only when disabled. Absent on failed
  entries.
- `definition?` (`ExtensionDefinition<SettingsSchema>`, from `LoadedExtension`): The validated definition. Absent when loading or validation failed.
- `dir?` (`string`, from `LoadedExtension`): Absolute path to the extension's directory. Absent for inline extensions.
- `error?` (`string`, from `LoadedExtension`): Loader / setup error, when one occurred. Absent on success.
- `manifest?` (`ExtensionManifest`, from `LoadedExtension`): Optional manifest metadata read before import/setup.
- `name` (`string`, from `LoadedExtension`): Stable name used for toggle persistence: the folder name, else the definition's `id`.
- `runtime` (`{ definition: unknown }`): The module's default export (validated by the runtime).
- `setupRan?` (`boolean`, from `LoadedExtension`): True once `setup()` was invoked, even if it later failed or timed out.
- `source` (`LoadedExtensionSource`, from `LoadedExtension`): Where it came from.

Source: [src/extensions/runtime/loaded-entry.ts:17](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/loaded-entry.ts#L17)

### `RuntimePorts`

Interface.

Everything a host plugs into the runtime. Every member is optional.

```ts
interface RuntimePorts
```

**Properties**

- `authStore?` (`AuthStorePort`): Where integration connections persist. Default: in memory.
- `catalogs?` (`RuntimeCatalogPorts`): Catalog bases.
- `commands?` (`CommandHostPort`): Built-in commands, slash submission and session-bound invocation members.
- `currentSessionId?` (`() => string | undefined`): The session the current call runs for (default of `'session'` storage).
- `desktop?` (`DesktopPort`): The desktop app's main-process handle; `ctx.desktop` is undefined without it.
- `dialogs?` (`DialogPort`): Clients and dialogs. Default: no client (dialogs reject with `NoUiError`).
- `hooks?` (`RuntimeHooksPorts`): Agent hooks and host events.
- `host?` (`HostRuntimePorts`): Session, generate, workspace, artifacts and plugins ports. A missing one
  makes that domain reject, except `plugins`, which defaults to the
  runtime's own catalogs.
- `integrationFlows?` (`IntegrationFlowPort`): How integration sign-in flows show their UI. Default: refuses.
- `keymap?` (`KeymapPort`): User keybinding overrides.
- `rpcTransport?` (`RpcRemoteTransport`): Where RPC events go to remote clients. With it, the runtime exposes `rpcBridge`.
- `settings?` (`SettingsPort`): Where settings values live. Default: in memory.
- `storage?` (`StoragePort`): Where `ctx.storage` keeps data. Default: in memory.
- `uiClient?` (`UiClientPort`): Panels, navigation, composer and notifications on a client.

Source: [src/extensions/runtime/host.ts:105](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/host.ts#L105)

### `ScheduleFireEvent`

Interface.

What an `onFire` handler gets.

```ts
interface ScheduleFireEvent
```

**Properties**

- `dueAt` (`number`): The time the fire was due (epoch ms).
- `late` (`boolean`): It runs after the host was down past `dueAt`.
- `manual` (`boolean`): It runs from `runNow`, not from the clock.
- `payload?` (`JsonValue`): The action's `payload`.
- `schedule` (`Schedule`): The schedule, as it was when it fired.

Source: [src/extensions/api/schedules.ts:14](https://github.com/Tahul/zidane/blob/main/src/extensions/api/schedules.ts#L14)

### `SchedulesDomain`

Interface.

`ctx.schedules`. Every call rejects while the person has Reminders off
(Settings > Sessions > Reminders) and on a host without a chat host. What
this extension creates is tagged `createdBy: { kind: 'extension', id }`.

```ts
interface SchedulesDomain
```

**Properties**

- `create` (`(input: ScheduleInput) => Promise<Schedule>`): Create a schedule. A bad input rejects with every problem named.
- `enabled` (`() => Promise<boolean>`): Whether Reminders is on and the host keeps schedules. Never rejects.
- `fires` (`(id: string, limit?: number) => Promise<ScheduleFire[]>`): A schedule's fires, newest first (default 20, at most 50).
- `get` (`(id: string) => Promise<Schedule | null>`): One schedule, or `null`.
- `list` (`(filter?: ScheduleListFilter) => Promise<Schedule[]>`): Every schedule on the host (any creator), oldest first.
- `onFire` (`(handler: string, fn: (event: ScheduleFireEvent) => void | Promise<void>) => Disposable`): Run `fn` when a schedule with `{ kind: 'extension', extensionId: <this
  extension>, handler }` fires. Register during setup: a fire that finds no
  handler is recorded as failed and skipped, not held. Unloading the
  extension removes it.
- `remove` (`(id: string) => Promise<boolean>`): Remove a schedule and its fires. `false` when it was gone.
- `runNow` (`(id: string) => Promise<ScheduleFire>`): Run a schedule's action now. Its next fire does not move.
- `update` (`(id: string, patch: SchedulePatch) => Promise<Schedule>`): Change some fields. A new trigger, or turning it back on, counts its next fire from now.

**Example**

```ts
ctx.schedules.onFire('stretch', async ({ payload }) => {
  await ctx.sessions.note(String((payload as { sessionId: string }).sessionId), [{ text: 'Time to stretch.' }])
})
await ctx.schedules.create({
  name: 'Stretch',
  trigger: { kind: 'cron', expr: '0 15 * * 1-5', tz: 'Europe/Paris' },
  action: { kind: 'extension', extensionId: ctx.id, handler: 'stretch', payload: { sessionId } },
})
```

Source: [src/extensions/api/schedules.ts:44](https://github.com/Tahul/zidane/blob/main/src/extensions/api/schedules.ts#L44)

### `ScreenItem`

Interface.

A full-screen view, or a modal when `presentation` is `'modal'`.

```ts
interface ScreenItem
```

**Properties**

- `component` (`ComponentRef`): Required: hosts without the component draw `fallback`.
- `fallback?` (`string`): Markdown drawn where the component is missing.
- `id` (`string`): Screen id, unique in the extension. Other extensions use `<extension>/<id>`.
- `presentation?` (`'modal' | 'screen'`): `'screen'` fills the window, `'modal'` opens a dialog.
- `title` (`Bindable<string>`): Title of the screen.

Source: [src/extensions/api/ui.ts:117](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L117)

### `ScreenWire`

Interface.

A screen on the wire.

```ts
interface ScreenWire
```

**Properties**

- `component` (`ComponentWire`): Required: hosts without the component draw `fallback`.
- `fallback?` (`string`): Markdown drawn where the component is missing.
- `id` (`string`): `<extension>/<id>`.
- `presentation` (`'modal' | 'screen'`): `modal` draws a dialog, `screen` a full-screen view.
- `title` (`string`): Heading of the screen or modal.

Source: [src/extensions/ui/wire.ts:129](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L129)

### `ScriptedDialogPort`

Interface.

A `DialogPort` with one client that answers from a script.

```ts
interface ScriptedDialogPort extends DialogPort
```

**Properties**

- `answer` (`(kind: 'prompt' | 'select' | 'confirm' | 'form' | 'askUser' | 'presentPlan' | 'toast', answer: unknown) => void`): Queues an answer for the next dialog of `kind`. Unanswered dialogs resolve `undefined`.
- `clients` (`() => readonly UiClientInfo[]`, from `DialogPort`): The connected clients now.
- `onClientsChange?` (`(listener: () => void) => () => void`, from `DialogPort`): Calls `listener` after a client attached, detached or changed. Returns
  the unsubscribe. Optional: without it, buffered toasts and
  notifications go out at the next `ctx.ui` call that finds a client.
- `show` (`(clientId: string, request: DialogRequest, ctx: DialogShowContext) => Promise<unknown>`, from `DialogPort`): Shows `request` on `clientId` and resolves with the client's raw answer.
- `shown` (`readonly { extensionId: string; request: DialogRequest; sessionId?: string }[]`, readonly): Every dialog shown, oldest first.

Source: [src/extensions/runtime/memory-ports.ts:147](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L147)

### `SelectOption`

Interface.

One option of `select`.

```ts
interface SelectOption
```

**Properties**

- `description?` (`string`): Text under the label.
- `group?` (`string`): Heading the option is listed under.
- `icon?` (`ExtensionBadgeIcon`): Icon drawn with the option.
- `id` (`string`): Value returned in `ids` when picked.
- `label` (`string`): Text of the option.

Source: [src/extensions/api/ui.ts:495](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L495)

### `SessionBadgeEntry`

Interface.

A session badge with the kind it was built for and the artifacts behind it.

```ts
interface SessionBadgeEntry
```

**Properties**

- `artifactCount` (`number`): How many artifacts the badge stands for (hosts animate growth).
- `badge` (`ExtensionSessionBadge`): The badge to display.
- `kind` (`string`): Artifact kind the badge was built for.

Source: [src/extensions/types.ts:332](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L332)

### `SessionEvent`

Interface.

A session event the host reports: a run ended, or a session waits for the user.

```ts
interface SessionEvent
```

**Properties**

- `error?` (`string`): Error text for `'error'`.
- `kind` (`'error' | 'done' | 'needs-attention'`): What happened: the run finished, the run failed, or the session waits for the user.
- `requestId?` (`string`): The pending request for `'needs-attention'`.
- `sessionId` (`string`): The session the event is about.

Source: [src/extensions/api/hooks.ts:19](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L19)

### `SessionFacetsDomain`

Interface.

`ctx.sessions.facets`. Works on every host; a host without sessions never computes them.

```ts
interface SessionFacetsDomain
```

**Properties**

- `refresh` (`(sessionId?: string) => Promise<void>`): Asks the host to compute this extension's facets again, for one session,
  or without `sessionId` for the 500 most recently updated sessions.
  Resolves once it did.
- `register` (`(spec: SessionFacetSpec) => Disposable`): Adds a facet. The host also computes it for the 50 most recently
  updated existing sessions that never had it; older ones get it on their
  next trigger or on `refresh()`.

  Stored values are deleted in two cases only: you dispose the returned
  handle (or its scope ends) while the extension stays loaded, or the
  extension is uninstalled. The host then deletes them from the sessions
  computed with this runtime and the 500 newest stored, so queries stop
  matching them. Disabling, failing or reloading the extension keeps them.
  Enabled again, it computes its facets for the 50 newest sessions that
  miss one; older sessions keep their last values until a trigger or
  `refresh()`.

Source: [src/extensions/api/sessions.ts:178](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L178)

### `SessionFacetSpec`

Interface.

A facet: a JSON value the extension computes for every session, which
queries read as `facet.<extensionId>.<key>` (filters, sorts, groupings,
templates). The host stores the last value per session and computes it
again on each trigger in `on`. `undefined` or `null` clears it; a
throw or a timeout (5 s) keeps the last value and counts against the
extension's error budget. A value is at most 8 KiB of JSON, and one
extension's values on one session 16 KiB together: a value past either
keeps the last one, with a warning on the extension's logger.

```ts
interface SessionFacetSpec
```

**Properties**

- `compute` (`(session: SessionSnapshot) => JsonValue | Promise<JsonValue | undefined> | undefined`): Computes the value for one session.
- `key` (`string`): Facet key, unique in the extension: a letter or `_`, then letters, digits, `_` or `-` (64 at most).
- `on?` (`readonly SessionFacetTrigger[]`): When to compute it again. Default: every trigger.

Source: [src/extensions/api/sessions.ts:168](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L168)

### `SessionFields`

Interface.

The fields of a session a query reads, as `ctx.sessions.list` rows and facet snapshots carry them.

```ts
interface SessionFields
```

**Properties**

- `account?` (`string`): The provider account the session is pinned to.
- `agentId?` (`string`): Agent profile id.
- `archived` (`boolean`): Archived.
- `createdAt?` (`number`): Creation time, epoch ms. Absent from hosts that list through orchestration only.
- `cwd` (`string`): Working directory; `''` for none.
- `effort?` (`'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive'`): Thinking effort.
- `environment?` (`SessionQueryEnvironment`): Where the work happens, when not on this machine's folder.
- `favorite?` (`boolean`): Marked favorite.
- `hostId?` (`string`): Host serving the session.
- `id` (`string`): Session id.
- `isMain?` (`boolean`): The orchestration main session.
- `modelId?` (`string`): Model id.
- `projectName` (`string`): Folder name of `projectRoot`, or of `cwd` without one (`projectNameOf`); `''` for neither. Queries compute it from those two.
- `projectRoot` (`string | null`): Project root, or `null` for none.
- `providerKey?` (`string`): Provider registry key.
- `repoKey?` (`string`): Repository the folder is a checkout of (`github.com/owner/repo`).
- `runStartedAt?` (`number`): When the run in progress began, epoch ms. Absent when no run is in progress.
- `scheduleId?` (`string`): The schedule that created the session (a reminder's "new session" fire).
- `spaceId?` (`string`): Space id, when not the default space.
- `status` (`SessionListStatus`): Run state.
- `title` (`string`): Title (the id when it has none).
- `updatedAt` (`number`): Last change, epoch ms.
- `wakes?` (`readonly string[]`): The orchestrator sessions this session's current run (or its next,
  between runs) wakes with a `<session-event>` when it ends: its creator
  unless the run was asked for with `wake: false`, and the session that
  asked for it with wake on. Absent when it wakes none. Only in
  `ctx.sessions.list` rows, not facet snapshots. Query it with `eq`: a
  session's running workers are `{ all: [{ field: 'wakes', eq: id },
  { field: 'status', in: ['running', 'blocked'] }] }`.

Source: [src/extensions/api/sessions.ts:52](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L52)

### `SessionInfo`

Interface.

A session's live settings.

```ts
interface SessionInfo
```

**Properties**

- `agentId?` (`string`): Id of the agent profile in use.
- `cwd` (`string`): Working directory of the session.
- `id` (`string`): Session id.
- `modelId?` (`string`): Id of the model in use.
- `providerId?` (`string`): Id of the provider of the model in use.
- `status` (`SessionListStatus`): Run state, with the values of a list row's `status` ([`SessionListStatus`](https://zidane.si/docs/reference/extensions.md#SessionListStatus)).
- `thinking?` (`'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive'`): Thinking level in use.
- `title?` (`string`): Title of the session.

Source: [src/extensions/api/sessions.ts:24](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L24)

### `SessionListPage`

Interface.

One page of `ctx.sessions.list`.

```ts
interface SessionListPage
```

**Properties**

- `cursor?` (`string`): Pass it back as `cursor` for the next page. Absent on the last page.
- `rows` (`readonly SessionListRow[]`): The rows.

Source: [src/extensions/api/sessions.ts:132](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L132)

### `SessionListQuery`

Interface.

What `ctx.sessions.list` takes. Every field is optional.

```ts
interface SessionListQuery
```

**Properties**

- `archived?` (`boolean | 'all'`): `false` (default): leave archived sessions out. `true`: only archived ones. `'all'`: both.
- `cursor?` (`string`): The previous page's `cursor`. Pass the same `where`, `sort` and `archived`: a cursor made for others is refused.
- `limit?` (`number`): Rows per page, 1 to 100. Default 30.
- `sort?` (`readonly SessionSort[]`): Sort keys. Default `[{ field: 'updatedAt', dir: 'desc' }]`. Ties break by id.
- `where?` (`SessionQuery`): Only rows that match.

Source: [src/extensions/api/sessions.ts:118](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L118)

### `SessionListRow`

Interface.

One row of `ctx.sessions.list`.

```ts
interface SessionListRow extends SessionFields
```

**Properties**

- `account?` (`string`, from `SessionFields`): The provider account the session is pinned to.
- `agentId?` (`string`, from `SessionFields`): Agent profile id.
- `archived` (`boolean`, from `SessionFields`): Archived.
- `createdAt?` (`number`, from `SessionFields`): Creation time, epoch ms. Absent from hosts that list through orchestration only.
- `cwd` (`string`, from `SessionFields`): Working directory; `''` for none.
- `effort?` (`'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive'`, from `SessionFields`): Thinking effort.
- `environment?` (`SessionQueryEnvironment`, from `SessionFields`): Where the work happens, when not on this machine's folder.
- `facets` (`Readonly<Record<string, JsonValue>>`): Facet values, keyed `<extensionId>.<key>`.
- `favorite?` (`boolean`, from `SessionFields`): Marked favorite.
- `hostId?` (`string`, from `SessionFields`): Host serving the session.
- `id` (`string`, from `SessionFields`): Session id.
- `isMain?` (`boolean`, from `SessionFields`): The orchestration main session.
- `modelId?` (`string`, from `SessionFields`): Model id.
- `projectName` (`string`, from `SessionFields`): Folder name of `projectRoot`, or of `cwd` without one (`projectNameOf`); `''` for neither. Queries compute it from those two.
- `projectRoot` (`string | null`, from `SessionFields`): Project root, or `null` for none.
- `providerKey?` (`string`, from `SessionFields`): Provider registry key.
- `repoKey?` (`string`, from `SessionFields`): Repository the folder is a checkout of (`github.com/owner/repo`).
- `runStartedAt?` (`number`, from `SessionFields`): When the run in progress began, epoch ms. Absent when no run is in progress.
- `scheduleId?` (`string`, from `SessionFields`): The schedule that created the session (a reminder's "new session" fire).
- `spaceId?` (`string`, from `SessionFields`): Space id, when not the default space.
- `status` (`SessionListStatus`, from `SessionFields`): Run state.
- `title` (`string`, from `SessionFields`): Title (the id when it has none).
- `updatedAt` (`number`, from `SessionFields`): Last change, epoch ms.
- `wakes?` (`readonly string[]`, from `SessionFields`): The orchestrator sessions this session's current run (or its next,
  between runs) wakes with a `<session-event>` when it ends: its creator
  unless the run was asked for with `wake: false`, and the session that
  asked for it with wake on. Absent when it wakes none. Only in
  `ctx.sessions.list` rows, not facet snapshots. Query it with `eq`: a
  session's running workers are `{ all: [{ field: 'wakes', eq: id },
  { field: 'status', in: ['running', 'blocked'] }] }`.
- `worker` (`boolean`): Created by this extension.

Source: [src/extensions/api/sessions.ts:110](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L110)

### `SessionsDomain`

Interface.

`ctx.sessions`. Acts as the extension; what it creates is tagged with the
extension id. Rejects on hosts without a session runtime, except `facets`.

```ts
interface SessionsDomain extends Omit<ExtensionSessionsSurface, 'onEvent' | 'getData' | 'setData' | 'list'>
```

**Properties**

- `answer` (`(requestId: string, response: InteractionResponse) => Promise<boolean>`, from `Omit`): Answers a question or a plan by its request id. Resolves to `false` when it was already answered.
- `approve` (`(requestId: string, decision: ExtensionApprovalDecision) => Promise<boolean>`, from `Omit`): Decides a tool approval by its request id. Resolves to `false` when it was already decided.
- `cancel` (`(sessionId: string) => Promise<void>`, from `Omit`): Interrupts the run.
- `compact` (`(sessionId: string) => Promise<boolean>`): Compacts the session's history. Resolves whether it did.
- `create` (`(params: ExtensionCreateSessionParams) => Promise<string>`, from `Omit`): Creates a session. Resolves to its id.
- `events` (`(query?: ExtensionEventQuery) => Promise<readonly ExtensionSessionEvent[]>`, from `Omit`): The recent session events (runs ended, sessions blocked), newest first, without the pending request.
- `facets` (`SessionFacetsDomain`): Facets: values computed per session that queries read.
- `get` (`(sessionId: string) => Promise<SessionInfo | undefined>`): The session's live settings, or `undefined` when there is none.
- `list` (`(query?: SessionListQuery) => Promise<SessionListPage>`): Sessions that match `query`, one page at a time, newest first by
  default. Throws a `SessionQueryError` naming each problem of an invalid
  query. Side sessions are left out.
- `note` (`(sessionId: string, blocks: readonly CommandOutputBlock[]) => Promise<boolean>`): Adds display-only blocks to the transcript. Persisted, never sent to the model.
- `pending` (`(sessionId?: string) => Promise<readonly ExtensionPendingRequest[]>`, from `Omit`): Prompts waiting for an answer, of one session or all.
- `read` (`(sessionId: string) => Promise<ExtensionSessionDetail>`, from `Omit`): A session's state and last message.
- `remove` (`(sessionId: string) => Promise<boolean>`): Deletes the session. Resolves whether it did.
- `send` (`(sessionId: string, prompt: string) => Promise<boolean>`, from `Omit`): Queues a prompt as the session's next turn. Resolves to `false` when the host declined it.
- `setThinking` (`(sessionId: string, level: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive') => Promise<boolean>`): Changes the thinking level of the session. Resolves whether it did.
- `steer` (`(sessionId: string, message: string) => Promise<void>`, from `Omit`): Guidance into the current run, at its next turn boundary.
- `submit` (`(text: string, opts?: { delivery?: 'auto' | 'steer' | 'followUp'; sessionId?: string }) => Promise<boolean>`): Submits text as if the user typed it: commands, interceptors and skills apply. Without `sessionId`, the session in view.
- `switchAgent` (`(sessionId: string, agentId: string) => Promise<boolean>`): Changes the agent profile of the session. Resolves whether it did.
- `switchModel` (`(sessionId: string, model: { modelId: string; providerId: string }) => Promise<boolean>`): Changes the model of the session. Resolves whether it did.
- `synthetic` (`(sessionId: string, message: { role: 'user' | 'assistant'; text: string }) => Promise<boolean>`): Adds a message the model sees on the next turn, without starting a run.
- `transcript` (`(sessionId: string, limit?: number) => Promise<string>`, from `Omit`): The last turns as plain text, oldest first. Default 10, at most 50.
- `wait` (`(sessionId: string, timeoutSec?: number) => Promise<ExtensionWaitResult>`, from `Omit`): Returns once the session is idle or blocked, or after `timeoutSec`. Default 30, at most 50.

Source: [src/extensions/api/sessions.ts:206](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L206)

### `SessionSnapshot`

Interface.

What a facet is computed on: the session's fields, its metadata and its turn count. Frozen.

```ts
interface SessionSnapshot extends SessionFields
```

**Properties**

- `account?` (`string`, from `SessionFields`): The provider account the session is pinned to.
- `agentId?` (`string`, from `SessionFields`): Agent profile id.
- `archived` (`boolean`, from `SessionFields`): Archived.
- `createdAt?` (`number`, from `SessionFields`): Creation time, epoch ms. Absent from hosts that list through orchestration only.
- `cwd` (`string`, from `SessionFields`): Working directory; `''` for none.
- `effort?` (`'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive'`, from `SessionFields`): Thinking effort.
- `environment?` (`SessionQueryEnvironment`, from `SessionFields`): Where the work happens, when not on this machine's folder.
- `favorite?` (`boolean`, from `SessionFields`): Marked favorite.
- `hostId?` (`string`, from `SessionFields`): Host serving the session.
- `id` (`string`, from `SessionFields`): Session id.
- `isMain?` (`boolean`, from `SessionFields`): The orchestration main session.
- `metadata` (`Readonly<Record<string, JsonValue>>`): The session's metadata, as the host stores it, minus two things: the
  facet values themselves, and every other extension's `ctx.session`
  state. `metadata.extensions` holds only this extension's own slice
  (`{ [yourId]: { [key]: value } }`), absent when it stored none. The
  other keys are the host's own (such as `cwd`, `title`, `archived`,
  `spaceId`, `providerKey`, `modelId`, `effort`, `environment`); they
  are not a stable API, prefer the typed fields above.
- `modelId?` (`string`, from `SessionFields`): Model id.
- `projectName` (`string`, from `SessionFields`): Folder name of `projectRoot`, or of `cwd` without one (`projectNameOf`); `''` for neither. Queries compute it from those two.
- `projectRoot` (`string | null`, from `SessionFields`): Project root, or `null` for none.
- `providerKey?` (`string`, from `SessionFields`): Provider registry key.
- `repoKey?` (`string`, from `SessionFields`): Repository the folder is a checkout of (`github.com/owner/repo`).
- `runStartedAt?` (`number`, from `SessionFields`): When the run in progress began, epoch ms. Absent when no run is in progress.
- `scheduleId?` (`string`, from `SessionFields`): The schedule that created the session (a reminder's "new session" fire).
- `spaceId?` (`string`, from `SessionFields`): Space id, when not the default space.
- `status` (`SessionListStatus`, from `SessionFields`): Run state.
- `title` (`string`, from `SessionFields`): Title (the id when it has none).
- `turns` (`number`): Turns in the session.
- `updatedAt` (`number`, from `SessionFields`): Last change, epoch ms.
- `wakes?` (`readonly string[]`, from `SessionFields`): The orchestrator sessions this session's current run (or its next,
  between runs) wakes with a `<session-event>` when it ends: its creator
  unless the run was asked for with `wake: false`, and the session that
  asked for it with wake on. Absent when it wakes none. Only in
  `ctx.sessions.list` rows, not facet snapshots. Query it with `eq`: a
  session's running workers are `{ all: [{ field: 'wakes', eq: id },
  { field: 'status', in: ['running', 'blocked'] }] }`.

Source: [src/extensions/api/sessions.ts:140](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L140)

### `SettingBase`

Interface.

Fields every setting has.

```ts
interface SettingBase
```

**Properties**

- `apply?` (`SettingApply`): Default `'live'`.
- `description?` (`string`): Help text under the label.
- `label` (`string`): Label in Settings.
- `page?` (`string`): Page id (see `SettingsSchema.pages`). When omitted: its section's page, else the first page. A page other than its section's is refused.
- `scopes?` (`readonly SettingScope[]`): Scopes the user may set it at. Default `['user', 'project']`.
- `section?` (`string`): Section id (see `SettingsSchema.sections`). Ungrouped when omitted.

Source: [src/extensions/api/settings.ts:15](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L15)

### `SettingsCategory`

Interface.

An extension's own group in the settings sidebar.

```ts
interface SettingsCategory
```

**Properties**

- `icon?` (`{ gui?: string; tui?: string }`): Icon in each app's vocabulary.
- `label` (`string`): Group label.

Source: [src/extensions/api/settings.ts:144](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L144)

### `SettingsDomain`

Interface.

`ctx.settings`.

```ts
interface SettingsDomain<S extends SettingsSchema = SettingsSchema>
```

**Type parameters**

- `S` (`extends SettingsSchema`, default `SettingsSchema`)

**Properties**

- `get` (`<K extends string>(key: K, opts?: { sessionId?: string }) => SettingValue<S['items'][K]> | undefined`): The effective value: session, then project, then user, then config, then the default.
- `locked` (`(key: ValueKeys<S>) => boolean`): Whether the value comes from a declarative config entry (locked in the UI).
- `onChange` (`<K extends string>(key: K, listener: (value: SettingValue<S['items'][K]> | undefined) => void) => Disposable`): Calls `listener` when the value of `key` changes.

Source: [src/extensions/api/settings.ts:196](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L196)

### `SettingsPageItem`

Interface.

A page in Settings under the extension. Data from a settings-like schema, or a component.

```ts
interface SettingsPageItem
```

**Properties**

- `component?` (`ComponentRef`): Component the page draws.
- `icon?` (`{ gui?: string; tui?: string }`): Icon in the settings sidebar.
- `id` (`string`): Page id, unique in the extension.
- `order?` (`number`): Place among the extension's pages: after the definition's pages, lower first. Default 100.
- `schema?` (`SettingsSchema`): Settings the host draws as a form.
- `title` (`Bindable<string>`): Title of the page.

Source: [src/extensions/api/ui.ts:144](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L144)

### `SettingsPageSpec`

Interface.

One page of an extension's settings.

```ts
interface SettingsPageSpec
```

**Properties**

- `description?` (`string`): Line under the page title.
- `icon?` (`{ gui?: string; tui?: string }`): Icon in each app's vocabulary.
- `id` (`string`): Page id, unique in the extension.
- `label` (`string`): Sidebar label.

Source: [src/extensions/api/settings.ts:152](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L152)

### `SettingsPageWire`

Interface.

A settings page on the wire.

```ts
interface SettingsPageWire
```

**Properties**

- `component?` (`ComponentWire`): Drawn instead of the data where the host has it.
- `icon?` (`{ gui?: string; tui?: string }`): Icon in the settings sidebar.
- `id` (`string`): `<extension>/<id>`.
- `order?` (`number`): Place among the extension's pages, after the definition's pages; lower first. Absent: 100.
- `schema?` (`WireSettings`): The page's settings in the settings renderer's wire format.
- `title` (`string`): Page title.

Source: [src/extensions/ui/wire.ts:153](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L153)

### `SettingsSchema`

Interface.

The settings of an extension.

```ts
interface SettingsSchema
```

**Properties**

- `category?` (`SettingsCategory`): A top-level group of its own in the settings sidebar, after the
  built-in groups. Without it the extension's pages sit under the
  "Extensions" group.
- `items` (`Readonly<Record<string, Setting>>`): Settings by key. A key starts with a letter or `_`, then letters,
  digits, `_`, `.` or `-`: `baseUrl`, `record-mentions`. `__proto__`,
  `constructor` and `prototype` are refused.
- `pages?` (`readonly SettingsPageSpec[]`): Ordered pages. Without them the extension has one page, titled with its name.
- `sections?` (`readonly { description?: string; id: string; label: string; page?: string }[]`): Ordered sections. A section with `page` sits on that page, else on the first.

Source: [src/extensions/api/settings.ts:164](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L164)

### `SettingsSearchEntry`

Interface.

One searchable settings row.

```ts
interface SettingsSearchEntry
```

**Properties**

- `description?` (`string`): Help text.
- `extensionId` (`string`): Extension id.
- `key` (`string`): Setting key.
- `kind` (`'value' | 'action'`): Value row or action row.
- `label` (`string`): Row label.
- `page` (`string`): The page it is on (`WireSettingsPage.id`).
- `pageLabel` (`string`): That page's label.
- `section?` (`string`): Its section id; absent for ungrouped rows.
- `sectionLabel?` (`string`): That section's label.

Source: [src/extensions/settings/sidebar.ts:95](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/sidebar.ts#L95)

### `SettingsSidebar`

Interface.

What [`settingsSidebar`](https://zidane.si/docs/reference/extensions.md#settingsSidebar) returns.

```ts
interface SettingsSidebar
```

**Properties**

- `categories` (`SettingsSidebarCategory[]`): One group per extension with a category, by category label; drawn after the built-in groups.
- `extensionsGroup` (`SettingsSidebarEntry[]`): The "Extensions" group: one entry per extension without a category, by label.

Source: [src/extensions/settings/sidebar.ts:41](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/sidebar.ts#L41)

### `SettingsSidebarCategory`

Interface.

A top-level group an extension declared (`SettingsSchema.category`).

```ts
interface SettingsSidebarCategory
```

**Properties**

- `category` (`SettingsCategory`): Label and icon of the group.
- `extensionId` (`string`): Extension id.
- `pages` (`WireSettingsPage[]`): Its pages in order (at least one), one sidebar entry each.

Source: [src/extensions/settings/sidebar.ts:31](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/sidebar.ts#L31)

### `SettingsSidebarEntry`

Interface.

One extension's entry in the "Extensions" group.

```ts
interface SettingsSidebarEntry
```

**Properties**

- `extensionId` (`string`): Extension id.
- `label` (`string`): Display name, else the id.
- `pages` (`WireSettingsPage[]`): Its pages in order (at least one).

Source: [src/extensions/settings/sidebar.ts:21](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/sidebar.ts#L21)

### `SettingsSidebarExtension`

Interface.

One extension as [`settingsSidebar`](https://zidane.si/docs/reference/extensions.md#settingsSidebar) and [`settingsSearchIndex`](https://zidane.si/docs/reference/extensions.md#settingsSearchIndex) take it.

```ts
interface SettingsSidebarExtension
```

**Properties**

- `displayName?` (`string`): Its display name, when it has one. Labels its entry and its implicit page.
- `id` (`string`): Extension id.
- `wire` (`WireSettings`): Its settings wire, or a merged wire holding it: only its pages are read.

Source: [src/extensions/settings/sidebar.ts:11](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/sidebar.ts#L11)

### `SharedWatches`

Interface.

Subscriptions shared by the clients that asked for them (an extension
panel's or palette's live updates): started on the first request for a
key, stopped when the last owner releases it or goes away. Without the
count, one window closing a panel would stop the updates of another window
showing the same one, and a window that closed without releasing would keep
its subscription until the registry was rebuilt.

```ts
interface SharedWatches<Owner>
```

**Type parameters**

- `Owner`

**Properties**

- `owners` (`(key: string) => Owner[]`): Who watches `key` now.
- `release` (`(owner: Owner) => void`): Every share `owner` holds (it went away).
- `reset` (`() => void`): Stop everything (registry rebuilt, host shutting down).
- `unwatch` (`(key: string, owner: Owner) => void`): Drops one of `owner`'s shares of `key`; the last share stops the watch.
- `watch` (`(key: string, owner: Owner, start: () => Promise<(() => void) | null>) => Promise<void>`): `start` runs once per key; it resolves to the stop function, or `null` when there is nothing to watch.

Source: [src/extensions/shared-watches.ts:9](https://github.com/Tahul/zidane/blob/main/src/extensions/shared-watches.ts#L9)

### `SidebarBadge`

Interface.

A small label on an extension row.

```ts
interface SidebarBadge
```

**Properties**

- `icon?` (`ExtensionBadgeIcon`): Icon drawn with the text.
- `text` (`string`): Badge text.
- `tone?` (`ExtensionBadgeTone`): Tint of the badge.

Source: [src/extensions/api/ui.ts:338](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L338)

### `SidebarDecorationItem`

Interface.

Extra data on the sidebar rows of the sessions that match `where`: an
icon, a tone, a subtitle, chips, or a component. Only `{ template }`
values are read as templates; a plain string is drawn as given. Bindable
fields follow the sidebar rule ([`SpaceItem`](https://zidane.si/docs/reference/extensions.md#SpaceItem)).

```ts
interface SidebarDecorationItem
```

**Properties**

- `chips?` (`Bindable<readonly SidebarChip[]>`): Chips drawn on the row, at most 8.
- `component?` (`ComponentRef`): Drawn on the row where the host has it, with `{ sessionId }` added to its props.
- `icon?` (`Bindable<ExtensionBadgeIcon>`): Icon drawn on the row.
- `id` (`string`): Decoration id, unique in the extension.
- `subtitle?` (`Bindable<SidebarText>`): Text drawn under the title: as given, or `{ template }`.
- `tone?` (`Bindable<ExtensionBadgeTone>`): Tint of the row's icon and chips.
- `where?` (`Bindable<SessionQuery>`): The sessions it applies to. Absent: every session.

Source: [src/extensions/api/ui.ts:317](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L317)

### `SidebarDecorationWire`

Interface.

A sidebar decoration on the wire.

```ts
interface SidebarDecorationWire
```

**Properties**

- `chips?` (`readonly SidebarChip[]`): Chips, at most 8: `text` drawn as given, `template` validated (render it with `renderTemplate`), or `facet`.
- `component?` (`ComponentWire`): Drawn on the row where the host has it.
- `icon?` (`ExtensionBadgeIcon`): Icon drawn on the row.
- `id` (`string`): `<extension>/<id>`.
- `subtitle?` (`SidebarText`): Text under the title: a string drawn as given, or `{ template }` (validated; render it with `renderTemplate`).
- `tone?` (`ExtensionBadgeTone`): Tint of the row's icon and chips.
- `where?` (`SessionQuery`): The sessions it applies to. Absent: every session.

Source: [src/extensions/ui/wire.ts:270](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L270)

### `SidebarFilterItem`

Interface.

A filter the user turns on in the sidebar. `toggle` keeps the sessions
that match `query` while on; `select` keeps those of the one option
picked; `multi` keeps those that match any picked option. Bindable
fields follow the sidebar rule ([`SpaceItem`](https://zidane.si/docs/reference/extensions.md#SpaceItem)).

```ts
interface SidebarFilterItem
```

**Properties**

- `icon?` (`ExtensionBadgeIcon`): Icon drawn with the label.
- `id` (`string`): Filter id, unique in the extension.
- `kind` (`'toggle' | 'select' | 'multi'`): How the user picks: on or off, one option, or several.
- `label` (`Bindable<string>`): Text of the filter.
- `options?` (`Bindable<readonly SidebarFilterOption[]>`): `select` and `multi`: the options, 1 to 32.
- `query?` (`Bindable<SessionQuery>`): `toggle`: the sessions kept while it is on.
- `spaces?` (`readonly string[] | 'all'`): Spaces it is offered in: `'all'` (default), or space ids (`default`, own ids, `<extension>/<id>`).

Source: [src/extensions/api/ui.ts:257](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L257)

### `SidebarFilterOption`

Interface.

One choice of a `select` or `multi` sidebar filter. Bind the filter's `options` to change its labels or queries.

```ts
interface SidebarFilterOption
```

**Properties**

- `id` (`string`): Option id, unique in the filter.
- `label` (`string`): Text of the option.
- `query` (`SessionQuery`): The sessions the option keeps.

Source: [src/extensions/api/ui.ts:242](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L242)

### `SidebarFilterWire`

Interface.

A sidebar filter on the wire.

```ts
interface SidebarFilterWire
```

**Properties**

- `icon?` (`ExtensionBadgeIcon`): Icon drawn with the label.
- `id` (`string`): `<extension>/<id>`.
- `kind` (`'toggle' | 'select' | 'multi'`): How the user picks.
- `label` (`string`): Text of the filter.
- `options?` (`readonly { id: string; label: string; query: SessionQuery }[]`): `select` / `multi`: the options.
- `query?` (`SessionQuery`): `toggle`: the sessions kept while on.
- `spaces` (`readonly string[] | 'all'`): `'all'`, or full space ids (`default`, `<extension>/<id>`).

Source: [src/extensions/ui/wire.ts:232](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L232)

### `SidebarGroupItem`

Interface.

A grouping the user can pick for the sidebar. Bindable fields follow the sidebar rule ([`SpaceItem`](https://zidane.si/docs/reference/extensions.md#SpaceItem)).

```ts
interface SidebarGroupItem
```

**Properties**

- `groupBy` (`Bindable<SessionGroupBy>`): The field or facet grouped on, with group labels and order.
- `id` (`string`): Grouping id, unique in the extension.
- `label` (`Bindable<string>`): Text of the choice.

Source: [src/extensions/api/ui.ts:285](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L285)

### `SidebarGroupWire`

Interface.

A sidebar grouping on the wire.

```ts
interface SidebarGroupWire
```

**Properties**

- `groupBy` (`SessionGroupBy`): The grouping, validated.
- `id` (`string`): `<extension>/<id>`.
- `label` (`string`): Text of the choice.

Source: [src/extensions/ui/wire.ts:260](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L260)

### `SidebarRowAction`

Interface.

An action in an extension row's menu.

```ts
interface SidebarRowAction
```

**Properties**

- `command?` (`string`): The command it runs: this extension's own command by that id when it has
  one (`ack` runs `<extension>.ack`), else the id as written (another
  extension's `<extension>.<id>`, or a built-in). Its argument is the row's
  id as the extension gave it (`ticket-1`, not `<extension>/ticket-1`).
  Without one the host draws it disabled.
- `id` (`string`): Action id, unique in the row.
- `label` (`string`): Text of the action.

Source: [src/extensions/api/ui.ts:348](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L348)

### `SidebarRowActionWire`

Interface.

A sidebar row's action on the wire.

```ts
interface SidebarRowActionWire extends SidebarRowAction
```

**Properties**

- `command?` (`string`): The full command id to run as is (resolved: `<extension>.<id>` when the extension has that command, else as written), with the row's `args`.
- `id` (`string`, from `SidebarRowAction`): Action id, unique in the row.
- `label` (`string`, from `SidebarRowAction`): Text of the action.

Source: [src/extensions/ui/wire.ts:288](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L288)

### `SidebarRowItem`

Interface.

A row an extension adds to a space's list beside its sessions: a ticket, a
job, a pull request. It lists only in a space that allows items. `time`
sorts it as a session's `updatedAt`. Bindable fields follow the sidebar
rule ([`SpaceItem`](https://zidane.si/docs/reference/extensions.md#SpaceItem)).

```ts
interface SidebarRowItem
```

**Properties**

- `actions?` (`readonly SidebarRowAction[]`): Actions in the row's menu, at most 8.
- `badges?` (`Bindable<readonly SidebarBadge[]>`): Labels drawn on the row, at most 8.
- `children?` (`Bindable<SessionQuery>`): Sessions listed under the row, as its children.
- `group?` (`string`): The group (a group key of the space's grouping) it lists in. Absent: the group of rows without a value.
- `icon?` (`Bindable<ExtensionBadgeIcon>`): Icon drawn on the row.
- `id` (`string`): Row id, unique in the extension.
- `open?` (`SidebarRowOpen`): What a click does. Absent: nothing.
- `space` (`string`): The space it lists in: `default`, an own space id, or `<extension>/<id>`.
- `status?` (`Bindable<SidebarRowStatus>`): Run state drawn as a session's.
- `subtitle?` (`Bindable<string>`): Text under the title. Blank or whitespace-only: none.
- `time?` (`Bindable<number>`): Sorts as a session's `updatedAt`, epoch ms.
- `title` (`Bindable<string>`): Row title. Blank or whitespace-only: the row's `id` stands in.
- `tone?` (`Bindable<ExtensionBadgeTone>`): Tint of the row.

Source: [src/extensions/api/ui.ts:377](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L377)

### `SidebarRowWire`

Interface.

A sidebar row on the wire, its bindings read and its references resolved: hosts use them as is.

```ts
interface SidebarRowWire
```

**Properties**

- `actions?` (`readonly SidebarRowActionWire[]`): Menu actions, at most 8, their commands resolved.
- `args` (`string`): The row's id as the extension gave it: the argument its `command`s run with (actions and `open.command`).
- `badges?` (`readonly SidebarBadge[]`): Labels, at most 8.
- `children?` (`SessionQuery`): Sessions listed under it.
- `group?` (`string`): Group key it lists under.
- `icon?` (`ExtensionBadgeIcon`): Icon drawn on the row.
- `id` (`string`): `<extension>/<id>`.
- `open?` (`SidebarRowOpen`): What a click does: `command` resolved as an action's, `panel` / `screen` as full ids (`<extension>/<id>` when the extension has one by that id, else as written).
- `space` (`string`): Full space id: `default` or `<extension>/<id>`.
- `status?` (`SidebarRowStatus`): Run state.
- `subtitle?` (`string`): Text under the title.
- `time?` (`number`): Sorts as `updatedAt`, epoch ms.
- `title` (`string`): Row title.
- `tone?` (`ExtensionBadgeTone`): Tint of the row.

Source: [src/extensions/ui/wire.ts:294](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L294)

### `SidebarSortItem`

Interface.

A sort order the user can pick for the sidebar. Bindable fields follow the sidebar rule ([`SpaceItem`](https://zidane.si/docs/reference/extensions.md#SpaceItem)).

```ts
interface SidebarSortItem
```

**Properties**

- `id` (`string`): Sort id, unique in the extension.
- `label` (`Bindable<string>`): Text of the choice.
- `sortBy` (`Bindable<readonly SessionSort[]>`): The sort keys, most significant first (1 to 8).

Source: [src/extensions/api/ui.ts:275](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L275)

### `SidebarSortWire`

Interface.

A sidebar sort on the wire.

```ts
interface SidebarSortWire
```

**Properties**

- `id` (`string`): `<extension>/<id>`.
- `label` (`string`): Text of the choice.
- `sortBy` (`readonly SessionSort[]`): The sort keys, validated.

Source: [src/extensions/ui/wire.ts:250](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L250)

### `SkillsDomain`

Interface.

`ctx.skills`.

```ts
interface SkillsDomain extends CatalogDomain<SkillConfig, CatalogEditor<SkillConfig> & { autoinvoke: (name: string, on: boolean) => void }>
```

**Properties**

- `list` (`() => readonly SkillConfig[]`, from `CatalogDomain`): The catalog after every transform.
- `register` (`(skill: SkillConfig) => Disposable`): Adds a skill.
- `reload` (`() => Promise<void>`, from `CatalogDomain`): Replays every transform of this catalog.
- `transform` (`(fn: Transform<CatalogEditor<SkillConfig> & { autoinvoke: (name: string, on: boolean) => void }>) => Disposable`, from `CatalogDomain`): Adds a transform that replays on every change. Dispose it to remove the transform.

Source: [src/extensions/api/catalogs.ts:208](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L208)

### `SlotItem`

Interface.

A small item placed in a slot: a status line, a banner, a composer badge.

```ts
interface SlotItem
```

**Properties**

- `at` (`SlotName`): The slot that draws the item.
- `color?` (`string`): Accent color of the item.
- `command?` (`string`): A click runs this command.
- `component?` (`ComponentRef`): Drawn instead of the data where the host has it.
- `count?` (`Bindable<string | number>`): A number or short label shown with the item.
- `highlight?` (`Bindable<boolean>`): Raised and breathing: something waits on the user.
- `icon?` (`ExtensionBadgeIcon`): Icon drawn with the item.
- `lines?` (`Bindable<readonly string[]>`): Lines of a banner (`composer.above`).
- `loader?` (`Bindable<boolean>`): A running arc in place of the icon.
- `order?` (`number`): Lower first. Default 100.
- `panel?` (`string`): A click opens this panel (`<id>`, `<extension>/<id>`, or a built-in tab).
- `sessionId?` (`string`): Limits the item to one session. A session's items go when it is deleted.
- `text?` (`Bindable<string>`): Main text of the item.
- `timeoutMs?` (`number`): Withdraws the item after this many ms.
- `title?` (`Bindable<string>`): Hover text.
- `tone?` (`Bindable<ExtensionBadgeTone>`): Tone of the item.
- `turnId?` (`string`): `transcript.turn-end` only: the item draws right after the turn with
  this id (pair it with `sessionId`). Without it the item draws once, at
  the end of the transcript. A host whose transcript holds no turn with
  this id does not draw the item. Other slots refuse it.

Source: [src/extensions/api/ui.ts:74](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L74)

### `SlotWire`

Interface.

A slot item on the wire, its bindings read.

```ts
interface SlotWire
```

**Properties**

- `at` (`SlotName`): The slot it fills.
- `color?` (`string`): Exact color, over `tone`.
- `command?` (`string`): A click runs this command.
- `component?` (`ComponentWire`): Drawn instead of the data where the host has it.
- `count?` (`string`): A number past 999 shows `999+`.
- `highlight?` (`true`): Raised and breathing: something waits on the user.
- `icon?` (`ExtensionBadgeIcon`): Per-surface icon.
- `lines?` (`readonly string[]`): Lines of a banner (`composer.above`).
- `loader?` (`true`): A running arc in place of the icon.
- `order` (`number`): Lower first. Default 100.
- `panel?` (`string`): As the extension named it; hosts resolve it with the entry's extension.
- `sessionId?` (`string`): Limits the item to one session.
- `text?` (`string`): Item text.
- `title?` (`string`): Hover text.
- `tone?` (`ExtensionBadgeTone`): Tint of the item.
- `turnId?` (`string`): `transcript.turn-end` only: draw after this turn. Absent: once, at the end of the transcript.

Source: [src/extensions/ui/wire.ts:93](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L93)

### `SpaceItem`

Interface.

A space: a named view of sessions, listed in the sidebar beside the
built-in spaces. Its published id is `<extension>/<id>`.

The Bindable rule of every sidebar token (spaces, filters, sorts, groups,
decorations, rows): a field is Bindable when it is data that follows the
extension's state (names, labels, queries, sorts, groupings, new-session
defaults, row state, decoration content). Ids, `kind`, placement (`space`,
`spaces`, `group`, `order`, `items`), actions, `open` and components stay
fixed: change them with `handle.update`. A Bindable is read whole: bind
the list (`options`, `chips`) to change one of its elements.

```ts
interface SpaceItem
```

**Properties**

- `groupBy?` (`Bindable<SessionGroupBy>`): How the space groups its sessions until the user picks a grouping. Absent: one flat list.
- `icon?` (`ExtensionBadgeIcon`): Icon drawn with the name.
- `id` (`string`): Space id, unique in the extension. `default` is the built-in space's and is refused.
- `items?` (`boolean`): Whether [`SidebarRowItem`](https://zidane.si/docs/reference/extensions.md#SidebarRowItem)s (any extension's, this one's included) may list in the space. Default `false`.
- `name` (`Bindable<string>`): Name shown for the space.
- `newSession?` (`Bindable<SpaceNewSession>`): What a session started from the space runs with.
- `order?` (`number`): Lower first among extension spaces. Default 100.
- `query` (`Bindable<SessionQuery>`): Which sessions the space lists, besides the others: a session is in it
  when it is tagged with the space (started from it, or moved to it),
  when it is the orchestration Main session, or when it matches this query.
- `sortBy?` (`Bindable<readonly SessionSort[]>`): How the space sorts its sessions until the user picks a sort. Absent: the app's order.

Source: [src/extensions/api/ui.ts:216](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L216)

### `SpaceNewSession`

Interface.

What a session started from a space runs with. Each field left out takes the app's default.

```ts
interface SpaceNewSession
```

**Properties**

- `agentId?` (`string`): Agent profile id.
- `effort?` (`'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive'`): Thinking effort.
- `modelId?` (`string`): Model id.
- `providerKey?` (`string`): Provider registry key, with `modelId`.

Source: [src/extensions/api/ui.ts:193](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L193)

### `SpaceWire`

Interface.

A space on the wire.

```ts
interface SpaceWire
```

**Properties**

- `groupBy?` (`SessionGroupBy`): How it groups its sessions.
- `icon?` (`ExtensionBadgeIcon`): Icon drawn with the name.
- `id` (`string`): `<extension>/<id>`.
- `items` (`boolean`): Sidebar items may list in it.
- `name` (`string`): Name shown for the space.
- `newSession?` (`SpaceNewSession`): What a session started from it runs with.
- `order` (`number`): Lower first. Default 100.
- `query` (`SessionQuery`): The sessions the space lists, validated.
- `sortBy?` (`readonly SessionSort[]`): How it sorts its sessions.

Source: [src/extensions/ui/wire.ts:210](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L210)

### `StorageDomain`

Interface.

`ctx.storage`.

```ts
interface StorageDomain
```

**Properties**

- `kv` (`(scope: StorageScope, sessionId?: string) => KeyValue`): Key/value data in `scope`. For `'session'`, pass the session (defaults to the current one).
- `memory` (`<T>(key: string, init: () => T) => T`): In-memory values that survive a reload of the extension, not a restart.
- `path` (`(scope: StoragePathScope, ...segments: string[]) => string`): A path in the extension's own folder for `scope`. `..` cannot escape it.
- `store` (`<S extends Schema>(name: string, schema: S, initial: Infer<S>, opts: StoreOptions<Infer<S>>) => Store<Infer<S>>`): A typed store validated by `schema`; `initial` when nothing is stored.

Source: [src/extensions/api/storage.ts:59](https://github.com/Tahul/zidane/blob/main/src/extensions/api/storage.ts#L59)

### `Store`

Interface.

A typed, reactive value, kept on disk and synced to every window and client.

```ts
interface Store<T> extends Readable<T>
```

**Type parameters**

- `T`

**Properties**

- `get` (`() => T`, from `Readable`): The current value.
- `select` (`<U>(pick: (value: T) => U) => Readable<U>`): A readable over part of the value; use it to bind UI fields.
- `set` (`(value: T | ((current: T) => T)) => Promise<void>`): Replaces the value, or computes the next one from the current. Resolves once it is saved.
- `subscribe` (`(listener: (value: T) => void) => () => void`, from `Readable`): Calls `listener` after each change. Returns the unsubscribe.

Source: [src/extensions/api/storage.ts:51](https://github.com/Tahul/zidane/blob/main/src/extensions/api/storage.ts#L51)

### `StoreOptions`

Interface.

Options of a typed store.

```ts
interface StoreOptions<T>
```

**Type parameters**

- `T`

**Properties**

- `migrate?` (`(old: unknown, fromVersion: number) => T`): Brings a value saved at an older `version` to the current shape. A throw falls back to the initial value.
- `scope` (`StorageScope`): Where the store keeps its data.
- `sessionId?` (`string`): For `'session'` scope: which session. Defaults to the session the call runs for.
- `version?` (`number`): Bump when the shape changes; `migrate` receives the older value.

Source: [src/extensions/api/storage.ts:39](https://github.com/Tahul/zidane/blob/main/src/extensions/api/storage.ts#L39)

### `StringSetting`

Interface.

A text setting. `secret` values go to the auth store and never show in config files.

```ts
interface StringSetting extends SettingBase
```

**Properties**

- `apply?` (`SettingApply`, from `SettingBase`): Default `'live'`.
- `default?` (`string`): Used when no scope or config sets a value.
- `description?` (`string`, from `SettingBase`): Help text under the label.
- `label` (`string`, from `SettingBase`): Label in Settings.
- `multiline?` (`boolean`): Draws a multi-line input.
- `page?` (`string`, from `SettingBase`): Page id (see `SettingsSchema.pages`). When omitted: its section's page, else the first page. A page other than its section's is refused.
- `pattern?` (`string`): Regular expression the value must match.
- `placeholder?` (`string`): Hint shown in an empty input.
- `scopes?` (`readonly SettingScope[]`, from `SettingBase`): Scopes the user may set it at. Default `['user', 'project']`.
- `secret?` (`boolean`): Stores the value in the auth store, never in config files.
- `section?` (`string`, from `SettingBase`): Section id (see `SettingsSchema.sections`). Ungrouped when omitted.
- `type` (`'string'`): Marks a string setting.
- `validate?` (`(value: string) => string | undefined`): Extra check; return an error message to refuse the value.

Source: [src/extensions/api/settings.ts:51](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L51)

### `ToolCall`

Interface.

A tool call an interceptor can rule on (from `tool:gate`, which also fires for MCP tools under their `mcp_<server>_<tool>` name).

```ts
interface ToolCall
```

**Properties**

- `callId` (`string`): The model's id for this call.
- `depth?` (`number`): Subagent depth; absent at the top level.
- `displayName` (`string`): Name the model used (an alias), equal to `tool` when none.
- `input` (`Readonly<Record<string, unknown>>`): The tool's input, read-only. Return a `patch` to change it.
- `mcpServer?` (`string`): The MCP server when the tool comes from one.
- `parentRunId?` (`string`): The run that started this one, for a subagent.
- `resumed?` (`true`): The call passed the gate in a process that died. `'ask'` and `result` are ignored for it.
- `runId?` (`string`): The run making the call.
- `runToolCounts` (`Readonly<Record<string, number>>`): Calls per tool so far in this run.
- `sessionId?` (`string`): The session, when the run has one.
- `tool` (`string`): Canonical tool name.
- `turnId` (`string`): The turn the call belongs to.

Source: [src/extensions/api/hooks.ts:63](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L63)

### `ToolCallResult`

Interface.

A finished tool call (from `tool:transform`, which also fires for MCP tools).

```ts
interface ToolCallResult
```

**Properties**

- `callId` (`string`): The model's id for the call.
- `displayName` (`string`): Name the model used (an alias), equal to `tool` when none.
- `input` (`Readonly<Record<string, unknown>>`): The input the tool ran with.
- `isError` (`boolean`): The call failed.
- `metadata` (`Readonly<ToolResultMetadata>`): The result's metadata so far (what the tool and `tool:transform`
  observers wrote), read-only: writes throw. Return
  `ToolResultDecision.metadata` to add to it.
- `result` (`string | ToolResultContent[]`): What the tool returned, as the model will see it.
- `sessionId?` (`string`): The session, when the run has one.
- `tool` (`string`): Canonical tool name.
- `turnId` (`string`): The turn the call belongs to.

Source: [src/extensions/api/hooks.ts:98](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L98)

### `ToolEditor`

Interface.

Editor of the tool catalog, per run.

```ts
interface ToolEditor extends CatalogEditor<NamedTool>
```

**Properties**

- `add` (`(item: NamedTool) => void`, from `CatalogEditor`): Adds an item, or replaces the one with the same id.
- `get` (`(id: string) => NamedTool | undefined`, from `CatalogEditor`): The item with this id, or `undefined`.
- `list` (`() => readonly NamedTool[]`, from `CatalogEditor`): The items as edited so far.
- `origin` (`(id: string) => ItemOrigin | undefined`, from `CatalogEditor`): Who put the item in the catalog.
- `phase` (`'pre-run' | 'run'`, readonly): `'pre-run'` when the host lists tools before a run, `'run'` during it.
- `remove` (`(id: string) => void`, from `CatalogEditor`): Removes the item with this id.
- `sessionId?` (`string`, readonly): The session the run is for.
- `update` (`(id: string, edit: (item: NamedTool) => void) => void`, from `CatalogEditor`): Edits a copy of the item.

Source: [src/extensions/api/catalogs.ts:68](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L68)

### `ToolMetadataNamespace`

Interface.

A tool-result metadata namespace an extension owns.

```ts
interface ToolMetadataNamespace
```

**Properties**

- `contextRows?` (`(ctx: { entries: readonly { value: Json }[]; namespace: string }) => readonly { label: string; value: string }[] | undefined`): Builds context panel rows from every entry. Without it the panel shows a count.
- `summarize?` (`(metadata: ToolResultMetadata) => Json | undefined`): Reduces one value to a compact summary.

Source: [src/extensions/api/catalogs.ts:76](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L76)

### `ToolResultDecision`

Interface.

What a `tool.result` interceptor returns.

```ts
interface ToolResultDecision
```

**Properties**

- `isError` (`boolean`): Marks the call as failed. Return `current.isError` to keep it.
- `metadata?` (`Readonly<Record<string, Json>>`): Metadata to add to the stored result, by namespace (the names
  `ctx.tools.metadata` declares, such as `'headroom'`). Each namespace
  replaces the one already in the result's metadata. Namespaces an earlier
  interceptor of the chain returned stay unless this one returns them
  again; `current.metadata` holds them. Values must be JSON.
- `result` (`string | ToolResultContent[]`): The result the model sees. Return `current.result` to keep it.

Source: [src/extensions/api/hooks.ts:124](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L124)

### `ToolsDomain`

Interface.

`ctx.tools`.

```ts
interface ToolsDomain extends CatalogDomain<NamedTool, ToolEditor>
```

**Properties**

- `list` (`() => readonly NamedTool[]`, from `CatalogDomain`): The catalog after every transform.
- `metadata` (`(namespace: string, spec: ToolMetadataNamespace) => Disposable`): Claims a tool-result metadata namespace for this extension.
- `register` (`(name: string, def: ToolDef) => Disposable`): Adds a tool under `name`.
- `reload` (`() => Promise<void>`, from `CatalogDomain`): Replays every transform of this catalog.
- `transform` (`(fn: Transform<ToolEditor>) => Disposable`, from `CatalogDomain`): Adds a transform that replays on every change. Dispose it to remove the transform.

Source: [src/extensions/api/catalogs.ts:84](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L84)

### `TuiContributions`

Interface.

TUI-side merged contributions.

```ts
interface TuiContributions
```

**Properties**

- `footerHints` (`readonly ExtensionFooterHint[]`, readonly): Footer hints of extension commands with `hint: true`.
- `keybindings` (`readonly ExtensionKeybinding[]`, readonly): Keybindings of extension commands.

Source: [src/extensions/types.ts:868](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L868)

### `UiClientCall`

Interface.

One call a [`RecordingUiClientPort`](https://zidane.si/docs/reference/extensions.md#RecordingUiClientPort) received.

```ts
interface UiClientCall
```

**Properties**

- `args` (`readonly unknown[]`): The arguments after `clientId`.
- `clientId` (`string`): The client the call targeted.
- `method` (`keyof UiClientPort`): The port method called.

Source: [src/extensions/runtime/memory-ports.ts:192](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L192)

### `UiDomain`

Interface.

`ctx.ui`. Dialogs (`confirm`, `prompt`, `select`, `form`, `askUser`,
`presentPlan`) reject with [`NoUiError`](https://zidane.si/docs/reference/extensions.md#NoUiError) at once when no client can
show them. `toast` and `notify` wait for a client instead: up to 20 of
them, each for 60 s, delivered in order to the first client that attaches.

```ts
interface UiDomain
```

**Properties**

- `askUser` (`(payload: QuestionPayload, opts?: DialogOptions) => Promise<QuestionResponse>`): Asks the user the questions of `payload`.
- `confirm` (`(opts: DialogOptions & { confirmLabel?: string; danger?: boolean; message?: string; title: string }) => Promise<boolean>`): Asks a yes or no question. Resolves `true` when the user confirms.
- `form` (`<S extends SettingsSchema>(opts: DialogOptions & { schema: S; title: string; values?: Readonly<Record<string, unknown>> }) => Promise<Readonly<Record<string, unknown>> | undefined>`): Asks for the values of a settings schema. Resolves the values, or `undefined` when the user cancels.
- `navigate` (`(to: { screen: string } | { session: string } | { newSession: true }, opts?: DialogOptions) => Promise<boolean>`): Shows a screen, a session, or a new session.
- `notify` (`(opts: { body?: string; sessionId?: string; sound?: boolean; title: string }) => void`): An OS notification on the client that shows it, skipped while the app has focus. Waits for a client like `toast`.
- `panel` (`{ close: (id: string, opts?: { sessionId?: string }) => Promise<boolean>; open: (id: string, opts?: { focus?: PanelFocus; sessionId?: string }) => Promise<boolean>; state: (opts?: { sessionId?: string }) => Promise<readonly string[]>; toggle: (id: string, opts?: { sessionId?: string }) => Promise<boolean> }`): Opens, closes and toggles panels in a client. Each resolves whether the client did it.
- `presentPlan` (`(payload: PlanProposal, opts?: DialogOptions) => Promise<PlanResponse>`): Shows a plan and waits for the user's answer.
- `prompt` (`(opts: DialogOptions & { initial?: string; message?: string; placeholder?: string; secret?: boolean; title: string }) => Promise<string | undefined>`): Asks for a line of text. Resolves `undefined` when the user cancels.
- `select` (`(opts: DialogOptions & { actions?: readonly { id: string; label: string }[]; multi?: boolean; options: readonly SelectOption[]; placeholder?: string; title: string }) => Promise<{ action?: string; ids: readonly string[] } | undefined>`): Asks for one or more options. Resolves the picked ids and the clicked action, or `undefined` when the user cancels.
- `toast` (`(opts: { actions?: readonly { id: string; label: string }[]; sessionId?: string; text: string; timeoutMs?: number; tone?: 'error' | 'info' | 'success' | 'warn' }) => Promise<string | undefined>`): A toast. Resolves with the action the user clicked, or `undefined`
  (dismissed, timed out, or dropped before any client attached).
  `timeoutMs` counts from when it is shown.

Source: [src/extensions/api/ui.ts:514](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L514)

### `UiEntry`

Interface.

One contribution as the hosts see it.

```ts
interface UiEntry<N extends UiTokenName = UiTokenName>
```

**Type parameters**

- `N` (`extends UiTokenName`, default `UiTokenName`)

**Properties**

- `extension` (`string`, readonly): The contributing extension.
- `item` (`UiWireMap[N]`, readonly): The wire form, bindings read.
- `key` (`string`, readonly): Unique across the registry; stable for the item's life. Hosts address the item by it.
- `token` (`N`, readonly): The token name of the contribution.

Source: [src/extensions/ui/registry.ts:52](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/registry.ts#L52)

### `UiToken`

Interface.

A token naming a kind of UI contribution.

```ts
interface UiToken<T, K extends string = string>
```

**Type parameters**

- `T`
- `K` (`extends string`, default `string`)

**Properties**

- `__type?` (`T`, readonly): Type-level only.
- `kind` (`'ui'`, readonly): Always `'ui'`.
- `name` (`K`, readonly): The contribution kind, e.g. `'panel'`.

Source: [src/extensions/api/ui.ts:23](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L23)

### `WebviewItem`

Interface.

A web page shown in a panel or a screen, sandboxed. It talks to the extension through RPC only.

```ts
interface WebviewItem
```

**Properties**

- `id` (`string`): Webview id, unique in the extension.
- `placement` (`'screen' | 'panel'`): Shows the page in a panel or a full screen.
- `rpc?` (`readonly string[]`): RPC contract ids the page may call through the injected bridge.
- `src` (`{ url: string } | { file: string }`): A URL, or a file in the extension folder.
- `title` (`Bindable<string>`): Title of the panel or screen.

Source: [src/extensions/api/ui.ts:160](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L160)

### `WebviewWire`

Interface.

A webview on the wire. A `file` source is relative to the extension's folder; the host resolves it.

```ts
interface WebviewWire
```

**Properties**

- `id` (`string`): `<extension>/<id>`.
- `placement` (`'screen' | 'panel'`): Shown in a panel or a screen.
- `rpc?` (`readonly string[]`): RPC contract ids the page may call through the injected bridge.
- `src` (`{ url: string } | { file: string }`): A URL, or a file in the extension folder.
- `title` (`string`): Heading of the panel or screen.

Source: [src/extensions/ui/wire.ts:169](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L169)

### `WireExtensionConfigSchema`

Interface.

The full extension-config schema in IPC-safe form.

```ts
interface WireExtensionConfigSchema
```

**Properties**

- `categories` (`readonly ExtensionConfigCategory[]`): Declared categories.
- `items` (`readonly WireExtensionConfigItem[]`): Declared items, each tagged with its extension and category.

Source: [src/extensions/config.ts:605](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L605)

### `WireSettings`

Interface.

Everything a Settings UI needs to draw an extension's settings.

```ts
interface WireSettings
```

**Properties**

- `actions` (`WireSettingsAction[]`): The action rows, as `listActionSummaries` produces them, with their scope.
- `category?` (`SettingsCategory`): One extension's wire: its own sidebar group (`SettingsSchema.category`). Absent on a merged wire (see `extensionCategories`).
- `extensionCategories?` (`Record<string, SettingsCategory>`): A merged wire: each extension's category, by extension id.
- `extensions?` (`Record<string, WireSettingsExtension>`): Each extension's display name and icon, by extension id: the settings
  sidebar's labels and glyphs. Set by `toWireSettings` (its extension),
  `mergeWireSettings` (every part's) and `runtimeSettingsWire` (the
  definition's `displayName` and `icon`). Absent on older wires: apps
  fall back to the implicit page's label, else the id.
- `locked` (`string[]`): Locked settings (set by a declarative config entry), as `extension:key`.
- `pages?` (`WireSettingsPage[]`): The settings pages in sidebar order: per extension, the schema's pages,
  then its `ui` pages by `order`. Always set by `toWireSettings` and
  `mergeWireSettings`; optional so older wires (and hand-built empty ones) still type.
- `schema` (`WireExtensionConfigSchema`): The value rows, as `toWireConfigSchema` produces them.
- `values` (`Record<string, Record<string, ExtensionConfigValue>>`): Values by extension then key, the shape of `Settings.extensionConfig`. Secrets are left out.

Source: [src/extensions/settings/wire.ts:80](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/wire.ts#L80)

### `WireSettingsExtension`

Interface.

An extension as the settings wire names it (`WireSettings.extensions`).

```ts
interface WireSettingsExtension
```

**Properties**

- `description?` (`string`): What it does (`ExtensionDefinition.description`): the line under its name atop its settings.
- `icon?` (`{ gui?: string; tui?: string }`): Its icon in each app's vocabulary (`ExtensionDefinition.icon`).
- `name` (`string`): Its display name, else its id.

Source: [src/extensions/settings/wire.ts:110](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/wire.ts#L110)

### `WireSettingsPage`

Interface.

One page of an extension's settings in the sidebar. `kind: 'schema'`
pages come from the definition's schema and list keys of the wire's own
rows; `kind: 'ui'` pages are `SettingsPage` items, drawn from their own
`schema` wire or `component`.

```ts
interface WireSettingsPage
```

**Properties**

- `component?` (`ComponentWire`): `kind: 'ui'`: drawn instead of the data where the host has it.
- `description?` (`string`): Line under the page title.
- `extension` (`string`): The extension the page belongs to.
- `icon?` (`{ gui?: string; tui?: string }`): Icon in each app's vocabulary.
- `id` (`string`): Unique among the extension's pages: the schema page id, or the item's `<extension>/<id>` for a `ui` page.
- `implicit?` (`true`): The page the extension gets when its schema declares none: id `main`,
  labelled with the extension's name. `settingsSidebar` relabels it with
  the display name it is given.
- `kind` (`'schema' | 'ui'`): Where the page comes from.
- `label` (`string`): Sidebar label (the page title for `ui` pages).
- `order?` (`number`): `kind: 'ui'`: its place among the extension's `ui` pages (lower first, default 100).
- `schema?` (`WireSettings`): `kind: 'ui'`: the page's settings in this same wire format.
- `sections` (`WireSettingsPageSection[]`): `kind: 'schema'`: the rows of the page, by section. Ungrouped rows first, then sections as declared.

Source: [src/extensions/settings/wire.ts:50](https://github.com/Tahul/zidane/blob/main/src/extensions/settings/wire.ts#L50)

## Types

### `AccessScope`

Type.

The least client token scope a remote caller needs: the same scopes as
every protocol method (`chat` ⊂ `admin`). In-process callers,
local connections and other extensions are never limited by it.

```ts
type AccessScope = 'chat' | 'admin'
```

Source: [src/extensions/api/core.ts:102](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L102)

### `ActionSettingValue`

Type.

A value an action reads or writes: what a value setting holds.

```ts
type ActionSettingValue = string | number | boolean | readonly string[]
```

Source: [src/extensions/api/settings.ts:86](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L86)

### `AddFn`

Type.

The `add` signature: a token and its item.

```ts
type AddFn = <T>(token: UiToken<T>, item: T) => Handle<T>
```

Source: [src/extensions/api/ui.ts:573](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L573)

### `BadgeTargetKind`

Type.

What kind of thing a badge stands for.

```ts
type BadgeTargetKind =
  | 'link'
  | 'file'
  | 'commit'
  | 'pull_request'
  | 'branch'
  | 'reference'
  | 'artifact'
```

Source: [src/extensions/badge-actions.ts:18](https://github.com/Tahul/zidane/blob/main/src/extensions/badge-actions.ts#L18)

### `Bindable`

Type.

A field of a UI item that may be a fixed value or a [`Readable`](https://zidane.si/docs/reference/extensions.md#Readable). A
bound field re-pushes the item to the hosts when the readable changes.

```ts
type Bindable<T> = T | Readable<T>
```

**Type parameters**

- `T`

Source: [src/extensions/api/core.ts:58](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L58)

### `Cleanup`

Type.

A cleanup function returned from `setup` or passed to `ctx.onCleanup`.

```ts
type Cleanup = () => void | Promise<void>
```

Source: [src/extensions/api/core.ts:19](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L19)

### `CommandInvocation`

Type.

What `run` receives. A slash invocation carries the full step context
(`runAgent`, `emit`, `interaction`…); other sources leave the
session-bound members out when no session is active.

```ts
type CommandInvocation = Partial<CommandStepContext> & { readonly args: string; readonly sessionId?: string; readonly signal: AbortSignal; readonly source: CommandSource }
```

Source: [src/extensions/api/commands.ts:18](https://github.com/Tahul/zidane/blob/main/src/extensions/api/commands.ts#L18)

### `CommandSource`

Type.

How a command was started.

```ts
type CommandSource = 'palette' | 'slash' | 'key' | 'menu' | 'api'
```

Source: [src/extensions/api/commands.ts:11](https://github.com/Tahul/zidane/blob/main/src/extensions/api/commands.ts#L11)

### `ConfigSyncLog`

Type.

A level and a line, for the host's log.

```ts
type ConfigSyncLog = (level: 'info' | 'warn' | 'error', message: string) => void
```

Source: [src/extensions/declarative/host-sync.ts:223](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L223)

### `ConfigSyncStatus`

Type.

What happened to one config entry (or lock entry) in a reconcile.

```ts
type ConfigSyncStatus =
  | 'installed'
  | 'updated'
  | 'up-to-date'
  | 'kept'
  | 'adopted'
  | 'linked'
  | 'removed'
  | 'unlinked'
  | 'forgotten'
  | 'failed'
```

Source: [src/extensions/declarative/host-sync.ts:86](https://github.com/Tahul/zidane/blob/main/src/extensions/declarative/host-sync.ts#L86)

### `ContextSectionItem`

Type.

A section of the context breakdown or the context panel.

```ts
type ContextSectionItem =
  | { contributor: ContextBreakdownContributor; placement: 'breakdown' }
  | { placement: 'panel'; section: ExtensionContextPanelSection }
```

Source: [src/extensions/api/ui.ts:188](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L188)

### `ContextSectionWire`

Type.

A context section on the wire.

```ts
type ContextSectionWire =
  | { placement: 'breakdown' }
  | { accentColor?: string; actions?: readonly { id: string; label: string }[]; id: string; placement: 'panel'; title: string }
```

Source: [src/extensions/ui/wire.ts:205](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/wire.ts#L205)

### `Credential`

Type.

A usable credential. OAuth tokens refresh on `resolve`.

`refreshToken` is only read from what a `custom` method returns (the store
keeps it; `resolve` strips it). `extra` carries provider fields kept with
the grant (an account id) and is handed back as stored.

```ts
type Credential =
  | { key: string; type: 'apiKey' }
  | { accessToken: string; expiresAt?: number; extra?: Readonly<Record<string, unknown>>; refreshToken?: string; scopes?: readonly string[]; type: 'oauth' }
  | { token: string; type: 'token' }
```

Source: [src/extensions/api/sessions.ts:437](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L437)

### `DialogAnswer`

Type.

A scripted answer for one dialog: a value, or a function of the request.

```ts
type DialogAnswer =
  | unknown
  | ((request: DialogRequest, ctx: DialogShowContext) => unknown)
```

Source: [src/extensions/runtime/memory-ports.ts:144](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/memory-ports.ts#L144)

### `DialogRequest`

Type.

A dialog on the wire, by kind.

```ts
type DialogRequest =
  | { confirmLabel?: string; danger?: boolean; kind: 'confirm'; message?: string; title: string }
  | { initial?: string; kind: 'prompt'; message?: string; placeholder?: string; secret?: boolean; title: string }
  | { actions?: readonly { id: string; label: string }[]; kind: 'select'; multi?: boolean; options: readonly SelectOption[]; placeholder?: string; title: string }
  | { kind: 'form'; settings: WireSettings; title: string }
  | { kind: 'askUser'; payload: QuestionPayload }
  | { kind: 'presentPlan'; payload: PlanProposal }
  | { actions?: readonly { id: string; label: string }[]; kind: 'toast'; text: string; timeoutMs?: number; tone: 'info' | 'success' | 'warn' | 'error' }
```

Source: [src/extensions/ui/dialogs.ts:38](https://github.com/Tahul/zidane/blob/main/src/extensions/ui/dialogs.ts#L38)

### `ExtensionApiVersion`

Type.

The extension API version this runtime loads.

```ts
type ExtensionApiVersion = 1
```

Source: [src/extensions/types.ts:47](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L47)

### `ExtensionApprovalDecision`

Type.

A tool approval's decision.

```ts
type ExtensionApprovalDecision =
  | 'accept-once'
  | 'accept-session'
  | 'accept-safelist'
  | 'deny'
  | { kind: 'partial'; mask: readonly boolean[] }
```

Source: [src/extensions/host-runtime.ts:74](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L74)

### `ExtensionBadgeColor`

Type.

An exact icon color, `#rgb` or `#rrggbb`, for a brand's own palette (a
tracker's state colors). Hosts paint it over `tone` and ignore anything
else; keep `tone` set too, for hosts and themes that don't take colors.

```ts
type ExtensionBadgeColor = string
```

Source: [src/extensions/types.ts:238](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L238)

### `ExtensionBadgeTone`

Type.

Color hint shared by session badges and text references. Hosts map it to
their theme: `muted` is the quiet default, `subtle` quieter still,
`accent` the theme accent, the rest the status colors.

```ts
type ExtensionBadgeTone = 'muted' | 'subtle' | 'accent' | 'success' | 'warn' | 'danger'
```

Source: [src/extensions/types.ts:231](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L231)

### `ExtensionBehaviorTransform`

Type.

Rewrites the agent behavior settings before a run starts. Return a replacement, or nothing to keep it.

```ts
type ExtensionBehaviorTransform = (behavior: AgentBehavior, env: ExtensionRuntimeEnv) => AgentBehavior | void
```

Source: [src/extensions/types.ts:100](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L100)

### `ExtensionConfigChangeBehavior`

Type.

How a host applies a changed config value: read live, rebuild the agent, or restart.

```ts
type ExtensionConfigChangeBehavior = 'live' | 'agent-rebuild' | 'restart'
```

Source: [src/extensions/config.ts:43](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L43)

### `ExtensionConfigItem`

Type.

Discriminated union of the typed config items an extension can declare.
The `type` tag drives both validation ([`resolveExtensionConfigValue`](https://zidane.si/docs/reference/extensions.md#resolveExtensionConfigValue))
and rendering (toggle / choice / input / action row).

```ts
type ExtensionConfigItem = ExtensionConfigValueItem | ExtensionConfigActionItem
```

Source: [src/extensions/config.ts:258](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L258)

### `ExtensionConfigScope`

Type.

Where a config value should be persisted.

```ts
type ExtensionConfigScope = 'user' | 'project' | 'session'
```

Source: [src/extensions/config.ts:41](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L41)

### `ExtensionConfigValue`

Type.

Concrete value a config item can hold.

```ts
type ExtensionConfigValue = boolean | number | string
```

Source: [src/extensions/config.ts:38](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L38)

### `ExtensionConfigValueItem`

Type.

The value-holding config items — everything except `action`. Functions
that produce or validate persisted VALUES take this narrower union;
[`ExtensionConfigItem`](https://zidane.si/docs/reference/extensions.md#ExtensionConfigItem) is the full declarable set.

```ts
type ExtensionConfigValueItem =
  | ExtensionConfigBooleanItem
  | ExtensionConfigNumberItem
  | ExtensionConfigStringItem
  | ExtensionConfigEnumItem
  | ExtensionConfigModelItem
```

Source: [src/extensions/config.ts:246](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L246)

### `ExtensionFetchResult`

Type.

Result of [`fetchExtensionSource`](https://zidane.si/docs/reference/extensions.md#fetchExtensionSource): the provenance string and, for git clones, the commit SHA.

```ts
type ExtensionFetchResult = FetchSourceResult
```

Source: [src/extensions/install.ts:229](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L229)

### `ExtensionHostKind`

Type.

The host process the extension runs in.

```ts
type ExtensionHostKind = 'tui' | 'desktop' | 'daemon' | 'server' | 'sdk'
```

Source: [src/extensions/api/core.ts:108](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L108)

### `ExtensionInstallErrorCode`

Type.

Reason an install, update or removal failed. Matches `ExtensionInstallError.code`.

```ts
type ExtensionInstallErrorCode =
  | 'invalid-source'
  | 'fetch-failed'
  | 'no-extension'
  | 'multiple-candidates'
  | 'deps-failed'
  | 'validate-failed'
  | 'exists'
  | 'no-package-manager'
  | 'not-installed'
  | 'no-provenance'
  | 'name-mismatch'
```

Source: [src/extensions/install.ts:59](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L59)

### `ExtensionInstallIo`

Type.

Injectable side-effect seams — tests swap these to stay offline; hosts
normally omit the whole object. Shared shape with the skills installer.

```ts
type ExtensionInstallIo = InstallIo
```

Source: [src/extensions/install.ts:161](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L161)

### `ExtensionInstallScope`

Type.

Where an extension is installed: the project or the user directory.

```ts
type ExtensionInstallScope = InstallScope
```

Source: [src/extensions/install.ts:53](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L53)

### `ExtensionInstallSource`

Type.

The shared install-source shape — see `src/install/source.ts` for the grammar.

```ts
type ExtensionInstallSource = InstallSource
```

Source: [src/extensions/install.ts:56](https://github.com/Tahul/zidane/blob/main/src/extensions/install.ts#L56)

### `ExtensionMcpConfigTransform`

Type.

Rewrites the MCP server configs before they are connected. Return a replacement list, or nothing to keep it.

```ts
type ExtensionMcpConfigTransform = (servers: readonly McpServerConfig[], env: ExtensionRuntimeEnv) => readonly McpServerConfig[] | void
```

Source: [src/extensions/types.ts:112](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L112)

### `ExtensionOrchestrationTool`

Type.

An orchestration tool a session can hold: `sessions` drives sessions, `interactions` answers their prompts.

```ts
type ExtensionOrchestrationTool = 'sessions' | 'interactions'
```

Source: [src/extensions/host-runtime.ts:61](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L61)

### `ExtensionPaletteItem`

Type.

Item shape a dynamic provider returns: `source` is stamped by the host, `group` defaults to the provider's.

```ts
type ExtensionPaletteItem = Omit<PaletteItem, 'source' | 'group'> & { group?: string; source?: never }
```

Source: [src/extensions/types.ts:649](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L649)

### `ExtensionPaletteRunResult`

Type.

[`PaletteRunResult`](https://zidane.si/docs/reference/chat-pure.md#PaletteRunResult) as an extension produces it: nested items are [`ExtensionPaletteItem`](https://zidane.si/docs/reference/extensions.md#ExtensionPaletteItem)s.

```ts
type ExtensionPaletteRunResult =
  | Exclude<PaletteRunResult, { kind: 'items' }>
  | { items: readonly ExtensionPaletteItem[]; kind: 'items'; placeholder?: string; title?: string }
```

Source: [src/extensions/types.ts:652](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L652)

### `ExtensionPanelScope`

Type.

Where a panel shows (`ExtensionPanel.scope`): `'session'` (the default)
only beside a session; `'project'` only where a folder is open without a
session (the new-chat draft screen, project pages); `'both'` anywhere.

```ts
type ExtensionPanelScope = 'session' | 'project' | 'both'
```

Source: [src/extensions/panels.ts:380](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L380)

### `ExtensionReferenceSurface`

Type.

Where hosts look for references.

```ts
type ExtensionReferenceSurface = 'prompt' | 'assistant' | 'title'
```

Source: [src/extensions/types.ts:476](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L476)

### `ExtensionRunSettledHandler`

Type.

A run-settled handler; may be async.

```ts
type ExtensionRunSettledHandler = (event: ExtensionRunSettledEvent) => void | Promise<void>
```

Source: [src/extensions/types.ts:83](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L83)

### `ExtensionRunTransform`

Type.

Rewrites the options of a run before it starts. Return replacement options, or nothing to keep them.

```ts
type ExtensionRunTransform = (options: AgentRunOptions, env: ExtensionRuntimeEnv) => AgentRunOptions | void
```

Source: [src/extensions/types.ts:94](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L94)

### `ExtensionSessionEventHandler`

Type.

Handler registered with `ctx.sessions.onEvent`.

```ts
type ExtensionSessionEventHandler = (event: ExtensionSessionEvent) => void | Promise<void>
```

Source: [src/extensions/host-runtime.ts:267](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L267)

### `ExtensionSource`

Type.

Where an extension was found.

```ts
type ExtensionSource = 'project' | 'user' | 'config' | 'inline' | 'builtin'
```

Source: [src/extensions/api/core.ts:105](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L105)

### `ExtensionToolCatalogTransform`

Type.

Rewrites the tool catalog before a run. `env.phase` tells whether it is the pre-run pass or the run itself, and `env.mcpToolNames` lists the tools that came from MCP servers. Return a replacement catalog, or nothing to keep it.

```ts
type ExtensionToolCatalogTransform = (tools: Readonly<Record<string, ToolDef>>, env: ExtensionRuntimeEnv & { mcpToolNames: ReadonlySet<string>; phase: 'run' | 'pre-run' }) => Readonly<Record<string, ToolDef>> | void
```

Source: [src/extensions/types.ts:106](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L106)

### `ExtensionWorkspaceOps`

Type.

`ctx.workspace`'s operations already bound to a session, for a host whose
execution lives in another process (the TUI in daemon mode reaches the
session's workspace over IPC). Same contract as the facade's methods.

```ts
type ExtensionWorkspaceOps = Omit<ExtensionWorkspaceSurface, 'available'>
```

Source: [src/extensions/host-runtime.ts:287](https://github.com/Tahul/zidane/blob/main/src/extensions/host-runtime.ts#L287)

### `FacetsRuntime`

Type.

The registry together with its per-extension domain factory, its close
(the runtime's dispose calls it first), and `forget` (the runtime's
`unload` with `forget` calls it, after the extension's facets went).

```ts
type FacetsRuntime = FacetRegistry & { close: () => void; domain: (deps: DomainDeps) => SessionFacetsDomain; forget: (extensionId: string) => void }
```

Source: [src/extensions/runtime/facets.ts:101](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/facets.ts#L101)

### `GithubPullState`

Type.

What a PR shows: `merged` / `draft` / `closed`, or for an open one its
review decision (`approved` / `changes_requested`) else `open`.

```ts
type GithubPullState =
  | 'open'
  | 'draft'
  | 'merged'
  | 'closed'
  | 'approved'
  | 'changes_requested'
```

Source: [src/github/pulls.ts:28](https://github.com/Tahul/zidane/blob/main/src/github/pulls.ts#L28)

### `HookEvents`

Type.

Every event `hooks.on` accepts: each AgentHooks key plus host events.

```ts
type HookEvents = { [K in keyof AgentHooks]: Parameters<AgentHooks[K]>[0] } & { 'run:settled': RunSettledEvent; 'session:event': SessionEvent }
```

Source: [src/extensions/api/hooks.ts:49](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L49)

### `HostModuleSource`

Type.

A host module, eager or lazy. Lazy (`() => Promise<module>`) exists for
self-referencing hosts: `zidane/tui` maps to ITSELF, which can only be
expressed as a deferred dynamic import (the module is still evaluating
when it registers).

```ts
type HostModuleSource = object | (() => Promise<object>)
```

Source: [src/extensions/host-modules.ts:46](https://github.com/Tahul/zidane/blob/main/src/extensions/host-modules.ts#L46)

### `HostModuleSpecifier`

Type.

One of [`HOST_MODULE_SPECIFIERS`](https://zidane.si/docs/reference/extensions.md#HOST_MODULE_SPECIFIERS).

```ts
type HostModuleSpecifier = typeof HOST_MODULE_SPECIFIERS[number]
```

Source: [src/extensions/host-modules.ts:69](https://github.com/Tahul/zidane/blob/main/src/extensions/host-modules.ts#L69)

### `Infer`

Type.

The value type a [`Schema`](https://zidane.si/docs/reference/extensions.md#Schema) accepts: inferred for Standard Schema, `unknown` for JSON Schema.

```ts
type Infer<S> = S extends StandardSchemaLike<infer O> ? O : unknown
```

**Type parameters**

- `S`

Source: [src/extensions/api/core.ts:83](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L83)

### `InstructionsRuntime`

Type.

The instructions registry together with its per-extension domain factory (`createInstructionsRegistry`).

```ts
type InstructionsRuntime = InstructionsRegistry & { domain: (deps: DomainDeps) => InstructionsDomain }
```

Source: [src/extensions/runtime/context.ts:63](https://github.com/Tahul/zidane/blob/main/src/extensions/runtime/context.ts#L63)

### `IntegrationMethod`

Type.

One way to connect an integration. For `oauth`: `pkce` needs
`redirectUri` (a loopback URL with an explicit port, e.g.
`http://localhost:51121/callback`), `device` needs `deviceUrl` (the
device authorization endpoint). `clientSecret` is sent to the token
endpoint when set; `params` are extra authorize-URL parameters
(`access_type`, `prompt`). `custom`: see [`IntegrationCustomMethod`](https://zidane.si/docs/reference/extensions.md#IntegrationCustomMethod).

```ts
type IntegrationMethod =
  | { help?: string; id: string; label: string; placeholder?: string; type: 'apiKey' }
  | { authorizeUrl: string; clientId: string; clientSecret?: string; deviceUrl?: string; flow: 'pkce' | 'device'; id: string; label: string; params?: Readonly<Record<string, string>>; redirectUri?: string; scopes?: readonly string[]; tokenUrl: string; type: 'oauth' }
  | { command: readonly string[]; help?: string; id: string; label: string; type: 'command' }
  | IntegrationCustomMethod
```

Source: [src/extensions/api/sessions.ts:364](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L364)

### `IntegrationSpecPatch`

Type.

What `IntegrationHandle.update` may change.

```ts
type IntegrationSpecPatch = Partial<Pick<IntegrationSpec, 'name' | 'description' | 'icon' | 'methods' | 'beforeConnect'>>
```

Source: [src/extensions/api/sessions.ts:406](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L406)

### `InterceptorHandler`

Type.

Handler of interceptor `K`.

```ts
type InterceptorHandler<K extends keyof Interceptors> = (input: Readonly<Interceptors[K][0]>, current: Interceptors[K][1]) => K extends SyncInterceptorName ? Interceptors[K][1] | undefined : Interceptors[K][1] | undefined | Promise<Interceptors[K][1] | undefined>
```

**Type parameters**

- `K` (`extends keyof Interceptors`)

Source: [src/extensions/api/hooks.ts:228](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L228)

### `ItemOrigin`

Type.

Who put an item in a catalog.

```ts
type ItemOrigin =
  | { kind: 'builtin' }
  | { kind: 'config' }
  | { kind: 'mcp'; server: string }
  | { id: string; kind: 'extension' }
```

Source: [src/extensions/api/catalogs.ts:28](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L28)

### `Json`

Type.

A JSON value.

```ts
type Json = string | number | boolean | null | readonly Json[] | { [key: string]: Json }
```

Source: [src/extensions/api/storage.ts:14](https://github.com/Tahul/zidane/blob/main/src/extensions/api/storage.ts#L14)

### `JsonSchema`

Type.

A plain JSON Schema object. Values validated by it are typed `unknown`.

```ts
type JsonSchema = Readonly<Record<string, unknown>>
```

Source: [src/extensions/api/core.ts:77](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L77)

### `KeyScope`

Type.

Focus areas a keybinding can be limited to. `panel:<id>` and `screen:<id>` name an extension's own.

```ts
type KeyScope =
  | 'global'
  | 'composer'
  | 'transcript'
  | 'sidebar'
  | 'modal'
  | `panel:${string}`
  | `screen:${string}`
```

Source: [src/extensions/api/commands.ts:26](https://github.com/Tahul/zidane/blob/main/src/extensions/api/commands.ts#L26)

### `LinkSource`

Type.

Where a link was clicked.

```ts
type LinkSource = 'transcript' | 'chip' | 'panel' | 'badge' | 'terminal' | 'other'
```

Source: [src/extensions/api/ui.ts:424](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L424)

### `Live`

Type.

The state of something another extension provides (a contract, a
registry owner, an RPC). Read it where you use it: it changes as the
provider starts, stops and reloads.

```ts
type Live<T> =
  | { readonly status: 'pending' }
  | { readonly generation: number; readonly status: 'active'; readonly value: T }
  | { readonly reason?: string; readonly status: 'inactive' }
```

**Type parameters**

- `T`

Source: [src/extensions/api/core.ts:65](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L65)

### `LoadedExtensionSource`

Type.

Where a loaded extension came from. Mirrors [`SkillSource`](https://zidane.si/docs/reference/skills.md#SkillSource) so a Settings
panel can show "project" vs "user" badges using the same vocabulary.

- `'project'` — discovered under `<git-root>/.{agents,zidane}/extensions/`.
- `'user'`    — discovered under `~/.{agents,zidane}/extensions/`, or installed from config.
- `'inline'`  — host passed it programmatically (e.g. via
  `RunTuiOptions.extensions` / `inlineLoadedExtension`).
- `'builtin'` — reserved; no built-in extensions ship today.

```ts
type LoadedExtensionSource = 'project' | 'user' | 'inline' | 'builtin'
```

Source: [src/extensions/types.ts:44](https://github.com/Tahul/zidane/blob/main/src/extensions/types.ts#L44)

### `McpToolDescriptor`

Type.

One upstream tool an MCP server lists, before it is namespaced.

```ts
type McpToolDescriptor = HookEvents['mcp:tools:filter']['tools'][number]
```

Source: [src/extensions/api/hooks.ts:140](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L140)

### `PanelContentItem`

Type.

One entry in a panel section: a row, Markdown, key/value pairs, stats, a heatmap, a bar chart, or a custom view.

```ts
type PanelContentItem =
  | PanelRowItem
  | PanelMarkdownItem
  | PanelKeyValueItem
  | PanelStatsItem
  | PanelHeatmapItem
  | PanelBarsItem
  | PanelCustomItem
```

Source: [src/extensions/panels.ts:262](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L262)

### `PanelItem`

Type.

A side or home panel: an [`ExtensionPanel`](https://zidane.si/docs/reference/extensions.md#ExtensionPanel) (load, subscribe, onAction, controls, focus), plus an optional component.

```ts
type PanelItem = ExtensionPanel & { component?: ComponentRef }
```

Source: [src/extensions/api/ui.ts:37](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L37)

### `PanelLoadScope`

Type.

What a delivered load context is bound to: a session, or just a folder.

```ts
type PanelLoadScope = 'session' | 'project'
```

Source: [src/extensions/panels.ts:383](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L383)

### `PanelSurface`

Type.

Where a panel shows (`ExtensionPanel.surfaces`): `'side'`, a tab in the
side panel (TUI rail, GUI side panel); `'home'`, a block on the GUI's
project home (the new-chat screen of a folder, and of no folder).

```ts
type PanelSurface = 'side' | 'home'
```

Source: [src/extensions/panels.ts:365](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L365)

### `PanelView`

Type.

A panel's view state, by control id: the picked option, or the picked options of a `multi` control.

```ts
type PanelView = Readonly<Record<string, string | readonly string[]>>
```

Source: [src/extensions/panels.ts:412](https://github.com/Tahul/zidane/blob/main/src/extensions/panels.ts#L412)

### `RendererTarget`

Type.

What a renderer draws: a custom block id, a code-block language, a tool's result, or an artifact kind's detail.

```ts
type RendererTarget =
  | { block: string }
  | { language: string }
  | { tool: string | readonly string[] }
  | { artifact: string }
```

Source: [src/extensions/api/ui.ts:131](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L131)

### `RpcClient`

Type.

A typed client. Methods reject with [`RpcCallError`](https://zidane.si/docs/reference/extensions.md#RpcCallError) on a declared error, validation failure, missing provider or abort.

```ts
type RpcClient<C extends RpcContract> = { [K in keyof C['methods']]: (input: InputOf<C['methods'][K]>, opts?: { signal?: AbortSignal }) => Promise<OutputOf<C['methods'][K]>> } & { readonly events: RpcEvents<C['events']> }
```

**Type parameters**

- `C` (`extends RpcContract`)

Source: [src/extensions/api/rpc.ts:96](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L96)

### `RpcImplementation`

Type.

The implementation of a contract.

```ts
type RpcImplementation<C extends RpcContract> = { [K in keyof C['methods']]: (input: InputOf<C['methods'][K]>, ctx: RpcCallContext<C['methods'][K]>) => OutputOf<C['methods'][K]> | RpcError | Promise<OutputOf<C['methods'][K]> | RpcError> }
```

**Type parameters**

- `C` (`extends RpcContract`)

Source: [src/extensions/api/rpc.ts:73](https://github.com/Tahul/zidane/blob/main/src/extensions/api/rpc.ts#L73)

### `Schema`

Type.

Either a Standard Schema (zod, valibot, arktype) or a plain JSON Schema.

```ts
type Schema<T = unknown> = StandardSchemaLike<T> | JsonSchema
```

**Type parameters**

- `T` (default `unknown`)

Source: [src/extensions/api/core.ts:80](https://github.com/Tahul/zidane/blob/main/src/extensions/api/core.ts#L80)

### `SessionFacetTrigger`

Type.

When a host computes a facet again: a session was created, a run settled, or its metadata changed.

```ts
type SessionFacetTrigger = 'created' | 'settled' | 'metadata'
```

Source: [src/extensions/api/sessions.ts:156](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L156)

### `SessionListStatus`

Type.

A session's run state, the same in `ctx.sessions.get` and list rows:
`idle` (never ran, or between runs), `running`, `blocked` (a run waits on
the user: a question or an approval), `completed` (the last run ended
well) or `error` (the last run failed).

```ts
type SessionListStatus = 'idle' | 'running' | 'blocked' | 'completed' | 'error'
```

Source: [src/extensions/api/sessions.ts:49](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L49)

### `Setting`

Type.

One setting.

```ts
type Setting =
  | BooleanSetting
  | NumberSetting
  | StringSetting
  | EnumSetting
  | ModelSetting
  | ActionSetting
```

Source: [src/extensions/api/settings.ts:141](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L141)

### `SettingApply`

Type.

What a change of the setting needs before it applies.

```ts
type SettingApply = 'live' | 'agent-rebuild' | 'restart'
```

Source: [src/extensions/api/settings.ts:12](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L12)

### `SettingScope`

Type.

Where a setting's value is stored.

```ts
type SettingScope = 'user' | 'project' | 'session'
```

Source: [src/extensions/api/settings.ts:9](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L9)

### `SettingValue`

Type.

The value type of one setting.

```ts
type SettingValue<I extends Setting> = I extends BooleanSetting ? boolean : I extends NumberSetting ? number : I extends StringSetting ? string : I extends EnumSetting ? I['options'][number]['value'] : I extends ModelSetting ? I['multi'] extends true ? readonly string[] : string : never
```

**Type parameters**

- `I` (`extends Setting`)

Source: [src/extensions/api/settings.ts:184](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L184)

### `SidebarChip`

Type.

A chip a decoration adds to a session row: literal `text` (blank or
whitespace-only: no chip), a `template` (field paths in braces, `{{` and
`}}` for a brace; see `escapeTemplate`), or one chip per value of a
`facet`.

```ts
type SidebarChip =
  | { icon?: ExtensionBadgeIcon; text: string; tone?: ExtensionBadgeTone }
  | { icon?: ExtensionBadgeIcon; template: string; tone?: ExtensionBadgeTone }
  | { facet: FacetPath; icon?: ExtensionBadgeIcon; tone?: ExtensionBadgeTone }
```

Source: [src/extensions/api/ui.ts:306](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L306)

### `SidebarRowOpen`

Type.

What opening an extension row does. `command` resolves and gets its
argument as a [`SidebarRowAction`](https://zidane.si/docs/reference/extensions.md#SidebarRowAction)'s does. `panel` and `screen` name
this extension's own panel or screen by that id when it has one, else the
id as written (`<extension>/<id>`, or a built-in panel such as `todos`).

```ts
type SidebarRowOpen =
  | { command: string }
  | { panel: string }
  | { screen: string }
  | { session: string }
```

Source: [src/extensions/api/ui.ts:369](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L369)

### `SidebarRowStatus`

Type.

Run state an extension row shows, like a session's.

```ts
type SidebarRowStatus = 'idle' | 'running' | 'blocked' | 'completed' | 'error'
```

Source: [src/extensions/api/ui.ts:335](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L335)

### `SidebarText`

Type.

A plain string drawn as given (blank or whitespace-only: no text), or
`{ template }` with field paths in braces: `'{facet.git.branch} · {modelId}'`.

```ts
type SidebarText = string | { template: string }
```

Source: [src/extensions/api/ui.ts:298](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L298)

### `SlotName`

Type.

Named places every app knows. An app without the place ignores the item.

The sidebar has three:

- `'sidebar.top'`: full-width block rows pinned under the sidebar's search
  row, above the session list. Desktop and web: between the search well and
  the list. Terminal: on the sessions screen, between the search box and
  the list.
- `'sidebar.bottom'`: full-width block rows pinned under the session list,
  above the footer strip. Terminal: right under the sessions list.
- `'sidebar.footer'`: compact chips inside the footer strip itself, next to
  the app's status (terminal: a line under the sessions list).

`'sidebar.top'` and `'sidebar.bottom'` never scroll with the list. Each row
draws the item's icon (or loader), text, count, tone and highlight, or its
component. Each block takes at most part of the sidebar's height (desktop
and web: 30%; it scrolls on its own past that), so the list keeps the rest.
An empty block draws nothing.

```ts
type SlotName =
  | 'app.statusbar'
  | 'app.titlebar'
  | 'session.header'
  | 'composer.above'
  | 'composer.below'
  | 'composer.badges'
  | 'sidebar.top'
  | 'sidebar.bottom'
  | 'sidebar.footer'
  | 'transcript.turn-end'
  | 'home.block'
  | 'settings.section'
```

Source: [src/extensions/api/ui.ts:59](https://github.com/Tahul/zidane/blob/main/src/extensions/api/ui.ts#L59)

### `StoragePathScope`

Type.

Folders for `storage.path`.

```ts
type StoragePathScope = StorageScope | 'cache' | 'data'
```

Source: [src/extensions/api/storage.ts:11](https://github.com/Tahul/zidane/blob/main/src/extensions/api/storage.ts#L11)

### `StorageScope`

Type.

Where kv and stores keep their data.

```ts
type StorageScope = 'user' | 'project' | 'session'
```

Source: [src/extensions/api/storage.ts:8](https://github.com/Tahul/zidane/blob/main/src/extensions/api/storage.ts#L8)

### `StoredExtensionConfigItem`

Type.

A config item as STORED on the registry / contributions — the authored
item plus the resolved `category` id it belongs to. The owning
extension is implied by the namespacing key on
`ExtensionRegistry.configItems`.

```ts
type StoredExtensionConfigItem = ExtensionConfigItem & { category: string }
```

Source: [src/extensions/config.ts:282](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L282)

### `SyncInterceptorName`

Type.

Interceptors that run on a synchronous hot path: their handlers must not return a promise.

```ts
type SyncInterceptorName = 'tracing.redact'
```

Source: [src/extensions/api/hooks.ts:225](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L225)

### `ToolCallDecision`

Type.

`tool.call` verdict. `'ask'` sends the call through the approval flow.
`patch` replaces the input, re-validated before execution. `result`
answers the call without running it. `block` and `result` end the chain.

```ts
type ToolCallDecision =
  | 'allow'
  | 'ask'
  | { block: string }
  | { patch: Record<string, unknown> }
  | { result: string | ToolResultContent[] }
```

Source: [src/extensions/api/hooks.ts:95](https://github.com/Tahul/zidane/blob/main/src/extensions/api/hooks.ts#L95)

### `Transform`

Type.

A registered transform.

```ts
type Transform<E> = (editor: E) => void
```

**Type parameters**

- `E`

Source: [src/extensions/api/catalogs.ts:47](https://github.com/Tahul/zidane/blob/main/src/extensions/api/catalogs.ts#L47)

### `ValueKeys`

Type.

Keys of the settings that hold a value (not actions).

```ts
type ValueKeys<S extends SettingsSchema> = { [K in keyof S['items']]: S['items'][K] extends ActionSetting ? never : K }[keyof S['items']] & string
```

**Type parameters**

- `S` (`extends SettingsSchema`)

Source: [src/extensions/api/settings.ts:193](https://github.com/Tahul/zidane/blob/main/src/extensions/api/settings.ts#L193)

### `WireExtensionConfigItem`

Type.

A config item flattened for the wire — carries `category` + `extension`, drops `validate`.

```ts
type WireExtensionConfigItem =
  | (Omit<ExtensionConfigBooleanItem, 'validate'> & WireConfigExtras)
  | (Omit<ExtensionConfigNumberItem, 'validate'> & WireConfigExtras)
  | (Omit<ExtensionConfigStringItem, 'validate'> & WireConfigExtras)
  | (Omit<ExtensionConfigEnumItem, 'validate'> & WireConfigExtras)
  | (Omit<ExtensionConfigModelItem, 'validate'> & WireConfigExtras)
```

Source: [src/extensions/config.ts:597](https://github.com/Tahul/zidane/blob/main/src/extensions/config.ts#L597)

### `WorkspaceDomain`

Type.

`ctx.workspace`: exec and files in the session's execution context (sandbox-correct).

```ts
type WorkspaceDomain = ExtensionWorkspaceSurface
```

Source: [src/extensions/api/sessions.ts:288](https://github.com/Tahul/zidane/blob/main/src/extensions/api/sessions.ts#L288)

## Re-exports

These names are documented on the entry point that owns them.

- [zidane/chat](https://zidane.si/docs/reference/chat.md): [`AgentProfile`](https://zidane.si/docs/reference/chat.md#AgentProfile), [`AnswerValue`](https://zidane.si/docs/reference/chat.md#AnswerValue), [`CommandAgentResult`](https://zidane.si/docs/reference/chat.md#CommandAgentResult), [`CommandAttachment`](https://zidane.si/docs/reference/chat.md#CommandAttachment), [`CommandInteraction`](https://zidane.si/docs/reference/chat.md#CommandInteraction), [`CommandOutputBlock`](https://zidane.si/docs/reference/chat.md#CommandOutputBlock), [`CommandSpawnResult`](https://zidane.si/docs/reference/chat.md#CommandSpawnResult), [`CommandSpawnTask`](https://zidane.si/docs/reference/chat.md#CommandSpawnTask), [`CommandStep`](https://zidane.si/docs/reference/chat.md#CommandStep), [`CommandStepContext`](https://zidane.si/docs/reference/chat.md#CommandStepContext), [`CommandStepFn`](https://zidane.si/docs/reference/chat.md#CommandStepFn), [`CommandStepResult`](https://zidane.si/docs/reference/chat.md#CommandStepResult), [`ConfirmQuestion`](https://zidane.si/docs/reference/chat.md#ConfirmQuestion), [`InteractionResponse`](https://zidane.si/docs/reference/chat.md#InteractionResponse), [`PlanDecision`](https://zidane.si/docs/reference/chat.md#PlanDecision), [`PlanProposal`](https://zidane.si/docs/reference/chat.md#PlanProposal), [`PlanProposalStep`](https://zidane.si/docs/reference/chat.md#PlanProposalStep), [`PlanResponse`](https://zidane.si/docs/reference/chat.md#PlanResponse), [`Question`](https://zidane.si/docs/reference/chat.md#Question), [`QuestionChoice`](https://zidane.si/docs/reference/chat.md#QuestionChoice), [`QuestionPayload`](https://zidane.si/docs/reference/chat.md#QuestionPayload), [`QuestionResponse`](https://zidane.si/docs/reference/chat.md#QuestionResponse), [`QuestionType`](https://zidane.si/docs/reference/chat.md#QuestionType), [`SelectQuestion`](https://zidane.si/docs/reference/chat.md#SelectQuestion), [`TextQuestion`](https://zidane.si/docs/reference/chat.md#TextQuestion)
- [zidane/chat/pure](https://zidane.si/docs/reference/chat-pure.md): [`CommandArgSuggestion`](https://zidane.si/docs/reference/chat-pure.md#CommandArgSuggestion), [`compileQuery`](https://zidane.si/docs/reference/chat-pure.md#compileQuery), [`escapeTemplate`](https://zidane.si/docs/reference/chat-pure.md#escapeTemplate), [`FacetPath`](https://zidane.si/docs/reference/chat-pure.md#FacetPath), [`QueryBound`](https://zidane.si/docs/reference/chat-pure.md#QueryBound), [`querySessions`](https://zidane.si/docs/reference/chat-pure.md#querySessions), [`QueryValue`](https://zidane.si/docs/reference/chat-pure.md#QueryValue), [`SessionCondition`](https://zidane.si/docs/reference/chat-pure.md#SessionCondition), [`SessionFieldName`](https://zidane.si/docs/reference/chat-pure.md#SessionFieldName), [`SessionFieldPath`](https://zidane.si/docs/reference/chat-pure.md#SessionFieldPath), [`SessionGroupBy`](https://zidane.si/docs/reference/chat-pure.md#SessionGroupBy), [`SessionGroupOrder`](https://zidane.si/docs/reference/chat-pure.md#SessionGroupOrder), [`SessionQuery`](https://zidane.si/docs/reference/chat-pure.md#SessionQuery), [`SessionQueryAll`](https://zidane.si/docs/reference/chat-pure.md#SessionQueryAll), [`SessionQueryAny`](https://zidane.si/docs/reference/chat-pure.md#SessionQueryAny), [`SessionQueryEnvironment`](https://zidane.si/docs/reference/chat-pure.md#SessionQueryEnvironment), [`SessionQueryError`](https://zidane.si/docs/reference/chat-pure.md#SessionQueryError), [`SessionQueryIssue`](https://zidane.si/docs/reference/chat-pure.md#SessionQueryIssue), [`SessionQueryNot`](https://zidane.si/docs/reference/chat-pure.md#SessionQueryNot), [`SessionSort`](https://zidane.si/docs/reference/chat-pure.md#SessionSort)
- [zidane](https://zidane.si/docs/reference/index.md): [`Schedule`](https://zidane.si/docs/reference/index.md#Schedule), [`ScheduleAction`](https://zidane.si/docs/reference/index.md#ScheduleAction), [`ScheduleCatchUp`](https://zidane.si/docs/reference/index.md#ScheduleCatchUp), [`ScheduleCreator`](https://zidane.si/docs/reference/index.md#ScheduleCreator), [`ScheduleFire`](https://zidane.si/docs/reference/index.md#ScheduleFire), [`ScheduleFireOutcome`](https://zidane.si/docs/reference/index.md#ScheduleFireOutcome), [`ScheduleInput`](https://zidane.si/docs/reference/index.md#ScheduleInput), [`ScheduleListFilter`](https://zidane.si/docs/reference/index.md#ScheduleListFilter), [`ScheduleNewSession`](https://zidane.si/docs/reference/index.md#ScheduleNewSession), [`SchedulePatch`](https://zidane.si/docs/reference/index.md#SchedulePatch), [`ScheduleTrigger`](https://zidane.si/docs/reference/index.md#ScheduleTrigger)
- [zidane/session](https://zidane.si/docs/reference/session.md): [`SessionArtifact`](https://zidane.si/docs/reference/session.md#SessionArtifact), [`SessionArtifactInput`](https://zidane.si/docs/reference/session.md#SessionArtifactInput)
