Kernel

The kernel starts bb, verifies plugins, resolves contracts, supplies stable ports, and keeps recovery available.

Purpose and boundary

The kernel is not a plugin. It owns only the functions that must remain available after a plugin failure.

The kernel owns these functions:

  • Boot, discovery, verification, load, reload, rollback, and unload.
  • The manifest schema and the generated contract.json schema.
  • Contract declarations, claims, global winners, list order, and chain order.
  • Safe mode, error surfaces, plugin logs, status, and cost records.
  • Install sources, the artifact store, marketplaces, and core bb plugin verbs.
  • The host daemon transport and the private host-role runtime.
  • The stable ports bb.storage, bb.secrets, bb.preferences, bb.realtime, bb.http, bb.rpc, and bb.plugins.

The kernel does not own threads, workspaces, files, providers, agents, commands, settings presentation, mentions, or layout. First-party plugins own those domains through the normal plugin path. Plugins remain fully trusted. Artifact checks and role limits do not create a security sandbox.

Boot and loader

Boot has nine ordered phases. Each phase writes a diagnostic record before it starts the next phase.

Phase Kernel action Failure result
1. Recovery Read --safe, the previous boot marker, and the winner store. The kernel starts safe mode if recovery data is not valid.
2. Discover Read bundled rows, installed rows, local development rows, and enabled state. The kernel isolates the bad row and continues.
3. Verify Verify the source record, artifact digest, file digests, manifest, and contract.json. The plugin becomes incompatible or failed. No code runs.
4. Index Read declarations, claims, edges, exports, settings, skills, themes, and host roles. A schema error stops that plugin.
5. Plan Resolve semver ranges and build the required-edge graph. A missing required edge puts the plugin in waiting. A cycle fails all cycle members.
6. Arbitrate Resolve defaults, stored winners, keyed winners, list order, and chain order. An undeclared collision fails the later claimant.
7. Stage Start host roles and server factories in graph order. Hold all registrations in a stage. The old generation stays live. The candidate does not commit.
8. Commit Commit one plugin generation as one atomic unit. Then mount its app artifact. A failed app surface uses its default implementation.
9. Settle Emit one boot result with ready, waiting, failed, and disabled rows. Recovery remains available through kernel routes and surfaces.

The loader never imports plugin code during discovery, verification, indexing, or planning. It reads bb.plugin.json, contract.json, and artifact.json as data.

Required dependents start after their providers become ready. Optional and watched edges do not block activation. The loader restarts required dependents after a provider cutover. It restarts them in topological order.

The loader gives an old service generation a bounded drain. It rejects new calls and cancels calls after the deadline. The loader remounts a surface after a winner change. It does not preserve surface-local state.

The plugin manifest

Authors write bb.plugin.jsonc. The build writes a strict dist/bb.plugin.json file. The build also copies name and version into artifact.json for package-manager checks.

Fields

Field Type Required Rule
$schema string No Points to the published manifest schema.
schemaVersion integer Yes Equals 2 for this design.
id string Yes Uses the owner dot grammar. First-party IDs start with bb..
version semver Yes Identifies this plugin release.
name string Yes Contains 1 to 120 display characters.
description string Yes Contains at most 2,000 characters.
category string No Groups marketplace results. The default is other.
engines object Yes Declares compatible bb and plugin SDK semver ranges.
fork object No Records parent and parentRevision. A fork has a new id.
branding object No Declares one icon, light and dark logos, and named icons.
artifacts object Yes Names the optional app, server, and host outputs. At least one exists.
claims array No Lists contracts that this plugin can provide.
surfaces array No Declares new owned UI contracts.
services array No Declares new owned server contracts.
requires array No Declares hard service edges. A missing edge blocks activation.
optional array No Declares soft service edges. A change does not restart the consumer.
watched array No Declares live service observations. A change calls the watcher.
exports object No Maps public module subpaths to built modules.
settings object No Names the settings schema and its public field declarations.
skills array No Names safe plugin-relative skill roots.
themes array No Declares static theme assets. The build makes keyed bb.layout.theme claims.
hostRoles array No Declares private typed roles that the host artifact can fulfill.

A contract declaration contains id, version, kind, replaceable, and stability. A replaceable backend declaration also contains defaultProvider. A replaceable surface declaration contains defaultClaimant.

A claim uses exactly one of surface or service. A keyed claim also contains key. A list or chain claim can contain before, after, and order hints. The winner store, not the manifest, holds the user's final choice and order.

Nested field shapes

Object Field Type Rule
engines bb semver range Selects compatible bb releases.
engines sdk semver range Selects a compatible author SDK.
fork parent plugin ID Names the copied plugin. It differs from id.
fork parentRevision version or revision Gives the agent a stable merge base.
branding icon relative SVG path Names the compact plugin icon.
branding.logo light, dark relative SVG paths Names the two logo variants. dark can be absent.
branding icons record of relative SVG paths Publishes plugin-owned named icons.
artifacts app, server, host relative module paths Names built tier entries. At least one entry exists.
claims[] surface or service contract ID Names exactly one claimed contract.
claims[] version semver range Selects compatible contract versions.
claims[] key string Identifies one keyed claim. Other kinds omit it.
claims[] order integer Gives an initial list or chain order hint.
claims[] before, after arrays of plugin IDs Give stable relative order hints.
surfaces[] id, version contract ID and semver Identify one owned surface contract.
surfaces[] kind contract kind Selects single, list, keyed, or chain.
surfaces[] replaceable boolean Allows global arbitration for single or keyed claims.
surfaces[] defaultClaimant plugin ID Names the default surface implementation.
surfaces[] props exported type reference Gives the surface props schema source.
surfaces[] stability stability tier Selects stable or experimental.
services[] id, version contract ID and semver Identify one owned service contract.
services[] kind contract kind Selects single, list, keyed, or chain.
services[] replaceable boolean Enables the global winner store.
services[] defaultProvider plugin ID Names the backend fallback. A replaceable service requires it.
services[] contract exported type reference Gives the method schema source.
services[] stability stability tier Selects stable or experimental.
Edge row service, range contract ID and semver range Selects one compatible service.
Edge row key string Selects one key from a keyed service.
exports property name module subpath Starts with ./ and stays inside the artifact.
settings schema relative JSON Schema path Defines stored setting values.
settings fields display descriptor record Gives labels and secret or required marks.
skills[] item relative directory path Names one contained skill root.
themes[] id, name, description strings Identify and describe one theme claim.
themes[] css relative CSS path Names the theme stylesheet.
themes[].codeTheme light, dark relative JSON paths Names editor theme data.
hostRoles[] name role name Forms the private ID <pluginId>.host.<name>.
hostRoles[] contract exported type reference Names the role method and signal contract.
hostRoles[] scope host or environment Selects the role placement key.
hostRoles[].launch kind module or exec Selects the role launch method.
hostRoles[].launch export, command, args module or process fields Supplies fields for the selected launch kind.
hostRoles[] sharedPorts integer array Declares ports that can use stable daemon tunnels.
hostRoles[].limits limit fields nonnegative integers Bounds start, stop, idle, memory, request, and response cost.

Full annotated example

// bb.plugin.jsonc
{
  "$schema": "https://getbb.app/schemas/plugin-v2.schema.json",
  "schemaVersion": 2,

  // The plugin ID owns every new acme.github.* contract.
  "id": "acme.github",
  "version": "2.3.0",
  "name": "GitHub",
  "description": "Adds GitHub issues, pull requests, and review tools.",
  "category": "integrations",

  "engines": {
    "bb": "^2.0.0",
    "sdk": "^2.0.0"
  },

  // A fork uses a new ID and records the merge base.
  // "fork": { "parent": "bb.github", "parentRevision": "2.2.1" },

  "branding": {
    "icon": "./assets/icon.svg",
    "logo": {
      "light": "./assets/logo-light.svg",
      "dark": "./assets/logo-dark.svg"
    },
    "icons": {
      "pull-request": "./assets/pull-request.svg",
      "issue": "./assets/issue.svg"
    }
  },

  // Paths point to built files in the installed artifact.
  "artifacts": {
    "app": "./dist/app.mjs",
    "server": "./dist/server.mjs",
    "host": "./dist/host.mjs"
  },

  // Claims refer to contracts that another owner declared.
  "claims": [
    { "surface": "bb.thread-ui.sidePanels", "version": "^1.0.0", "order": 40 },
    { "surface": "bb.thread-ui.timeline.item", "version": "^1.0.0", "key": "acme.github.pullRequest" },
    { "service": "bb.agents.tool", "version": "^1.0.0", "key": "github.searchIssues" },
    { "service": "acme.github.issueCache", "version": "^1.2.0" }
  ],

  // Declarations create contracts that this plugin owns.
  "surfaces": [
    {
      "id": "acme.github.pullRequest.actions",
      "version": "1.0.0",
      "kind": "list",
      "replaceable": false,
      "props": "./contracts.ts#PullRequestActionProps",
      "stability": "stable"
    }
  ],
  "services": [
    {
      "id": "acme.github.issueCache",
      "version": "1.2.0",
      "kind": "single",
      "replaceable": true,
      "defaultProvider": "acme.github",
      "contract": "./contracts.ts#IssueCache",
      "stability": "stable"
    }
  ],

  // These edges apply to the server artifact.
  "requires": [
    { "service": "bb.threads", "range": "^1.0.0" }
  ],
  "optional": [
    { "service": "bb.secrets", "range": "^1.0.0" }
  ],
  "watched": [
    { "service": "bb.providers.provider", "range": "^1.0.0", "key": "github" }
  ],

  // Module imports select exact code and do not follow winners.
  "exports": {
    "./components": "./dist/components.mjs",
    "./contracts": "./dist/contracts.mjs"
  },

  // The Settings plugin renders this schema. The kernel validates it at install.
  "settings": {
    "schema": "./settings.schema.json",
    "fields": {
      "token": { "label": "GitHub token", "secret": true, "required": true },
      "defaultRepository": { "label": "Default repository" }
    }
  },

  // These declarations become ordinary Agent and Layout contract claims.
  "skills": ["./skills"],
  "themes": [
    {
      "id": "acme.github.dim",
      "name": "GitHub Dim",
      "description": "A low-contrast theme.",
      "css": "./assets/theme.css",
      "codeTheme": {
        "light": "./assets/code-light.json",
        "dark": "./assets/code-dark.json"
      }
    }
  ],

  // Roles are private links between this plugin's server and host artifacts.
  "hostRoles": [
    {
      "name": "git-credential",
      "contract": "./contracts.ts#GitCredentialRole",
      "scope": "host",
      "launch": { "kind": "module", "export": "gitCredential" },
      "limits": {
        "startTimeoutMs": 10000,
        "stopGraceMs": 5000,
        "idleMs": 300000,
        "maxRssBytes": 1073741824,
        "maxRequestBytes": 33554432,
        "maxResponseBytes": 8388608
      }
    }
  ]
}

The parser rejects unknown fields. It reports all schema and cross-field errors in one result. The build rejects a claim that has no compatible declaration in contract.json.

contract.json

The build generates contract.json. Authors do not edit it. The file contains the full reviewable shape that short manifest rows reference.

{
  "$schema": "https://getbb.app/schemas/contract-v2.schema.json",
  "schemaVersion": 2,
  "plugin": { "id": "acme.github", "version": "2.3.0" },
  "manifestDigest": "sha256-...",
  "declarations": [
    {
      "id": "acme.github.issueCache",
      "owner": "acme.github",
      "tier": "server",
      "type": "service",
      "version": "1.2.0",
      "kind": "single",
      "replaceable": true,
      "defaultProvider": "acme.github",
      "stability": "stable",
      "methods": {
        "get": {
          "input": { "type": "object", "required": ["repo", "number"] },
          "output": { "$ref": "#/$defs/Issue" },
          "call": "query",
          "timeoutMs": 5000,
          "drain": "finish"
        },
        "invalidate": {
          "input": { "type": "object", "required": ["repo"] },
          "output": { "type": "null" },
          "call": "mutation",
          "timeoutMs": 5000,
          "drain": "cancel"
        }
      }
    },
    {
      "id": "acme.github.pullRequest.actions",
      "owner": "acme.github",
      "tier": "app",
      "type": "surface",
      "version": "1.0.0",
      "kind": "list",
      "replaceable": false,
      "stability": "stable",
      "props": { "$ref": "#/$defs/PullRequestActionProps" }
    }
  ],
  "hostRoles": [
    {
      "name": "git-credential",
      "scope": "host",
      "methods": {
        "read": {
          "input": { "$ref": "#/$defs/CredentialRequest" },
          "output": { "$ref": "#/$defs/CredentialResult" },
          "timeoutMs": 30000,
          "cancellable": true
        }
      },
      "signals": {
        "expired": { "payload": { "$ref": "#/$defs/CredentialExpired" } }
      }
    }
  ],
  "$defs": {
    "Issue": { "type": "object" },
    "PullRequestActionProps": { "type": "object" },
    "CredentialRequest": { "type": "object" },
    "CredentialResult": { "type": "object" },
    "CredentialExpired": { "type": "object" }
  }
}

The build resolves all TypeScript contract references into JSON Schema. It keeps TypeScript declaration names for diagnostics and generated types.

The kernel validates the manifest and contract.json as one unit. It checks these rules:

  • Each declaration ID starts with the plugin ID.
  • Each declaration appears once with one version and one kind.
  • Each claim names a compatible ID, version, type, and key form.
  • Each required, optional, or watched edge names a service range.
  • Each default claimant implements the declared contract.
  • Each backend default provider is installed or bundled with the owner.
  • Each exported schema reference stays inside the artifact.
  • Stable contracts use semver. Experimental contracts carry the explicit marker.

Contract identity uses the ID and semver. It never uses JavaScript object identity.

Claim registry and arbitration

The kernel keeps one normalized record for each declared contract and each claim. It keeps one global arbitration record for each replaceable contract or keyed contract key.

type ContractKind = "single" | "list" | "keyed" | "chain";
type EdgeKind = "required" | "optional" | "watched";

interface ContractRecord {
  id: string;
  ownerPluginId: string;
  version: string;
  tier: "app" | "server";
  type: "surface" | "service";
  kind: ContractKind;
  replaceable: boolean;
  stability: "stable" | "experimental";
  defaultClaimant?: string;
  defaultProvider?: string;
}

interface ClaimRecord {
  contractId: string;
  pluginId: string;
  pluginVersion: string;
  range: string;
  key?: string;
  generation?: string;
  state: "indexed" | "staged" | "ready" | "draining" | "failed" | "disabled";
}

interface ArbitrationRecord {
  contractId: string;
  key?: string;
  winner?: string;
  source: "default" | "user" | "fallback" | "safe-mode";
  orderedClaimants: string[];
  hiddenClaimants: string[];
  revision: number;
}

Kind rules

Kind Active claims User control Failure action
single One claimant. Select one winner when replaceable is true. Use the surface default or backend default provider.
list All ready claimants. Hide and order rows. Remove only the failed row.
keyed One claimant for each key. Select one winner for each replaceable key. Use that key's default provider.
chain All ready claimants around one base. Enable and order chain members. Remove the failed member and continue.

A collision on a non-replaceable single or keyed key fails before activation. The kernel does not use install time, activation time, or lexical order to select a winner.

A fresh install selects the declared default. A stored choice wins after compatibility checks. Fork lineage groups choices in the inspector. It does not change arbitration.

The 0.x replacement sentinels become stored arbitration data during migration. AUTOMATIC_REPLACEMENT_PROVIDER maps to source: "default", and BUILT_IN_REPLACEMENT_PROVIDER maps to the declared default claimant. The stored identity is the pair of contract ID and optional key. The kernel does not expose replacementProviderKey() in 2.0.

Winner transaction

  1. The kernel verifies the candidate and starts a candidate generation.
  2. The candidate registers all claimed implementations in a private stage.
  3. The candidate reports readiness for each claimed service.
  4. The kernel commits the candidate plugin as one atomic generation.
  5. The kernel stops new calls to the old service winner.
  6. The kernel drains old calls to the declared deadline.
  7. The kernel changes the global winner record.
  8. The kernel restarts required dependents in graph order.
  9. The kernel reports the cutover result.

A failed candidate never changes the running winner. A failed winner triggers the same transaction to the declared default provider.

Frontend single winners receive the typed default component as Original. Backend winners never receive an Original service handle.

Safe mode and recovery

The command bb --safe starts safe mode. The recovery UI can also set the next boot to safe mode.

Safe mode applies these rules:

  • The kernel loads only verified bundled default plugins.
  • The kernel ignores user winner records, list rows, and chain rows.
  • The kernel selects each declared default claimant or default provider.
  • The kernel does not start user host roles or user server artifacts.
  • The kernel keeps plugin management, logs, diagnostics, and boot routes available.
  • The kernel does not delete plugin data or winner choices.

The user can disable a bad plugin, change a winner, roll back an update, or inspect a failure. The next normal boot uses the repaired stored state.

The kernel automatically offers safe mode after two failed boots with the same boot plan. It never changes stored winner choices without a user action.

Build outputs and artifact verification

bb plugin build writes a stage directory and swaps dist/ only after all checks succeed.

Output Condition Purpose
bb.plugin.json Always Strict normalized manifest.
contract.json Always Full contract, claim, edge, and host-role schemas.
artifact.json Always File digests, toolchain versions, source facts, and root digests.
app.mjs, app.css, maps artifacts.app exists Browser code and styles.
server.mjs, map artifacts.server exists Server factory.
host.mjs, map artifacts.host exists Host-role factory.
exported modules exports is not empty Exact code imports for other plugins.
copied assets Referenced by the manifest Icons, logos, schemas, skills, themes, and guides.

The build pins its bundler, CSS processor, SDK transform, and schema generator. App builds keep React and bb runtime imports as host-provided imports. Server and host builds keep only documented runtime packages as external imports.

The build validates SVG assets. It rejects scripts, external references, unsafe URLs, and unstable dimensions. The app CSS scan follows source imports and declared exported modules. It does not accept arbitrary package globs.

The component registry generator stays kernel build tooling. It creates the registry index and item files that package @bb/ui source exports. The generated registry records do not become runtime contracts or claims.

artifact.json contains these fields:

interface ArtifactManifest {
  schemaVersion: 2;
  plugin: { id: string; version: string; packageName?: string };
  builtWith: { bb: string; sdk: string; toolchain: Record<string, string> };
  createdAt: string;
  manifestDigest: string;
  contractDigest: string;
  files: Record<string, { sha256: string; bytes: number; mode: number }>;
  artifactDigest: string;
  source?: { kind: InstallSource["kind"]; resolved: string; integrity?: string };
  signature?: { keyId: string; algorithm: "ed25519"; value: string };
}

The verifier uses this order:

  1. Resolve the exact source version, commit, built-in revision, or local path.
  2. Materialize bytes in a new stage directory.
  3. Reject links, path escapes, unsafe modes, and files outside size limits.
  4. Verify package-manager integrity or the resolved Git commit when the source supplies it.
  5. Verify each file digest and the artifact root digest.
  6. Verify the optional publisher signature and the required bundled release signature.
  7. Parse the manifest, contract.json, and artifact.json as strict data.
  8. Check engine ranges, contract rules, and artifact path containment.
  9. Promote the stage to an immutable content-addressed directory.

path: sources have a visible local-unverified trust mark. The development loop rehashes them before each reload. The kernel never imports from the mutable source directory during a normal install.

Install sources and marketplaces

The source parser accepts these canonical forms:

Source Form Resolution
Local path path:./plugin Uses a development link and records the absolute canonical path.
Built-in builtin:bb-threads Resolves one artifact from the signed bb release index.
npm npm:@scope/package@^2 Selects one exact version and verifies registry integrity.
Git ref git:https://host/repo.git#ref:v2.1.0 Resolves one immutable commit.
Git range git:https://host/repo.git#semver:plugin-v:^2 Selects the highest matching tag and records its commit.
Collection Any source plus --plugin <name> Selects one safe relative entry from bb.plugins.json.
Marketplace marketplace:<market>/<entry> Resolves the entry to one npm or Git source before confirmation.

A Git source can use --subdirectory. The path must use safe POSIX relative syntax. A collection entry selects a safe relative subdirectory. Nested plugin roots remain distinct immutable artifacts.

The installer never runs package lifecycle scripts. It bounds command time and output. It stores npm and Git downloads in content-addressed caches. Promotion never overwrites an existing digest directory.

An interrupted promotion leaves the active install unchanged. The next operation removes only the incomplete stage. Update planning compares the stored resolved source with the latest compatible resolved source.

Marketplace file

{
  "$schema": "https://getbb.app/schemas/marketplace-v2.schema.json",
  "schemaVersion": 2,
  "name": "community",
  "displayName": "BB Community",
  "description": "Community plugins for bb.",
  "plugins": [
    {
      "id": "acme.github",
      "displayName": "GitHub",
      "description": "GitHub issues and pull requests.",
      "icon": { "url": "./icons/acme.github.svg", "sha256": "..." },
      "tags": ["github", "review"],
      "author": { "name": "Acme", "url": "https://example.com" },
      "source": { "npm": { "package": "@acme/bb-github", "range": "^2.0.0" } }
    }
  ]
}

The marketplace is an index, not a trust grant. The installer verifies the resolved plugin artifact separately. Removing a marketplace does not remove installed plugins. It converts their source records to direct resolved sources.

The bb plugin CLI

Core verbs remain available in safe mode. Plugin-contributed verbs belong to bb.commands.cli.

Verb Result
bb plugin search <query> Search all refreshed marketplace indexes.
bb plugin list List installed state, source, version, winners, and failures.
bb plugin source <id> Show the canonical and resolved source record.
bb plugin install <source> Plan, confirm, verify, promote, enable, and activate one plugin.
bb plugin outdated Show compatible updates without changing state.
bb plugin update [id] Stage and cut over one or all managed plugin updates.
bb plugin rollback <id> Select the previous verified artifact and cut over.
bb plugin remove <id> Disable and remove the install row. Keep data unless --purge-data is explicit.
bb plugin enable <id> Enable and activate an installed plugin.
bb plugin disable <id> Disable and unload a plugin.
bb plugin reload [id] Build a candidate generation from the current artifact and cut over.
bb plugin winners [contract] List claimants and current global winners.
bb plugin winner set <contract> <plugin> Set a global single or keyed winner after validation.
bb plugin order <contract> Read or change list and chain order.
bb plugin logs <id> Read or follow structured plugin logs.
bb plugin doctor [id] Verify artifacts, graph edges, claims, roles, and diagnostics.
bb plugin config <id> Read or change declared settings through bb.preferences.
bb plugin token <id> Read or rotate the token for authenticated plugin HTTP routes.
bb plugin new <id> Create a 2.0 plugin package.
bb plugin migrate [path] Convert an older package to the 2.0 manifest and SDK.
bb plugin build [path] Build and verify all declared artifacts.
bb plugin dev [path] Build, install as path:, watch, and reload.
bb plugin types [path] Generate or check contract and SDK types.
bb plugin run <id> <verb> Run a verb declared through bb.commands.cli.
bb marketplace add <source> Add and verify one marketplace index.
bb marketplace list List marketplace state.
bb marketplace refresh [name] Refresh one or all indexes.
bb marketplace remove <name> Remove one index and its index assets.

Mutating verbs accept --yes for planned actions and --json for automation. Machine output uses stable result objects and stable error codes.

The CLI reserves plugin, marketplace, and other core words. The bb.commands.cli keyed contract arbitrates all plugin-contributed top-level words.

Kernel port services

Kernel ports use service-token syntax for a uniform author experience. They are fixed, stable, non-replaceable services. The global winner store does not contain them.

The factory receives handles that are bound to the plugin ID, generation, actor, and lifecycle scope. All handles reject work after scope disposal.

Port summary

ID Kind Replaceable Scope Purpose
bb.storage single No Plugin and generation Private key-value, SQLite, and migration storage.
bb.secrets single No Plugin and actor Secret references and controlled secret reads.
bb.preferences single No Plugin and actor Validated profile and thread preferences.
bb.realtime single No Plugin and session Typed server-to-app events and client command delivery.
bb.background single No Plugin and generation Restartable services and durable schedules.
bb.http single No Plugin Contained HTTP routes and authenticated loopback calls.
bb.rpc single No Plugin Typed app-to-server and cross-plugin RPC.
bb.plugins single No Caller Read-only plugin, contract, claim, winner, and diagnostic introspection.

bb.storage

interface StoragePort {
  kv(namespace?: string): KvStore;
  database(name?: string): Promise<SqliteDatabase>;
  migrate(db: SqliteDatabase, plan: readonly Migration[]): Promise<MigrationResult>;
  usage(): Promise<{ bytes: number; databases: number; keys: number }>;
}

interface KvStore {
  get<T extends JsonValue>(key: string): Promise<T | undefined>;
  set(key: string, value: JsonValue): Promise<void>;
  delete(key: string): Promise<boolean>;
  list(options?: { prefix?: string; cursor?: string; limit?: number }): Promise<{
    keys: string[];
    cursor?: string;
  }>;
  compareAndSet(key: string, expected: JsonValue | undefined, value: JsonValue): Promise<boolean>;
  watch(prefix: string, listener: (change: KvChange) => void): Disposer;
}

interface Migration {
  id: string;
  statements: readonly string[];
  checksum: string;
}

interface SqliteDatabase {
  run(sql: string, params?: readonly JsonValue[]): Promise<SqliteRunResult>;
  get<T>(sql: string, params?: readonly JsonValue[]): Promise<T | undefined>;
  all<T>(sql: string, params?: readonly JsonValue[]): Promise<T[]>;
  batch(statements: readonly SqliteStatement[]): Promise<void>;
  transaction<T>(work: (tx: SqliteTransaction) => Promise<T>): Promise<T>;
  close(): Promise<void>;
}

Storage starts fresh for a fork. A plugin shares data only through an exported service. The kernel contains keys and database names inside the plugin data root.

bb.secrets

interface SecretsPort {
  ref(name: string): SecretRef;
  has(name: string): Promise<boolean>;
  read(ref: SecretRef, options?: { signal?: AbortSignal }): Promise<SecretValue | undefined>;
  require(ref: SecretRef, options?: { signal?: AbortSignal }): Promise<SecretValue>;
  watch(name: string, listener: (state: "set" | "unset") => void): Disposer;
}

interface SecretRef {
  pluginId: string;
  name: string;
}

interface SecretValue {
  expose<T>(use: (value: string) => Promise<T> | T): Promise<T>;
}

Plugin code can read only its own declared secrets. It cannot list secret values. Only a human or an approved kernel flow can write or remove secret values. Logs, errors, traces, and RPC serialization redact SecretValue.

bb.preferences

export type PreferenceKey = `${string}/${string}`;

export type PreferenceAddress =
  | { key: PreferenceKey; scope: "profile" }
  | { key: PreferenceKey; scope: "thread"; threadId: string };

export interface PreferenceCell<T extends JsonValue = JsonValue> {
  address: PreferenceAddress;
  value: T;
  source: "stored" | "default";
  /** `null` means that no stored row exists. */
  revision: string | null;
  updatedAt: number | null;
}

export interface PreferenceQuery {
  ownerPluginId?: string;
  scope?: "profile" | "thread";
  threadId?: string;
  prefix?: string;
}

export interface PreferenceWriteOptions {
  /** Omit this member for a last-write-wins update. */
  expectedRevision?: string | null;
}

export interface PreferenceChange<T extends JsonValue = JsonValue> {
  previous: PreferenceCell<T>;
  current: PreferenceCell<T>;
  cause: "set" | "clear" | "default-changed";
}

export interface PreferencesPort {
  get<T extends JsonValue>(address: PreferenceAddress): Promise<PreferenceCell<T>>;
  set<T extends JsonValue>(
    address: PreferenceAddress,
    value: T,
    options?: PreferenceWriteOptions,
  ): Promise<PreferenceCell<T>>;
  clear(
    address: PreferenceAddress,
    options?: PreferenceWriteOptions,
  ): Promise<PreferenceCell>;
  list(query?: PreferenceQuery): Promise<readonly PreferenceCell[]>;
  reload(query?: PreferenceQuery): Promise<readonly PreferenceCell[]>;
  watch<T extends JsonValue>(
    query: PreferenceQuery,
    listener: (change: PreferenceChange<T>) => void,
  ): Disposer;
}

The port reads each declared preference schema from the plugin manifest. It validates stored values and manifest defaults.

The port has no presentation. The bb.settings plugin supplies the default settings UI.

The port stores profile and thread cells. It uses <ownerPluginId>/<name> keys.

A plugin actor can write only keys in its namespace. A human actor can write any visible preference.

The port rejects undeclared keys and secret keys. Secret writes use the human-only bb.secrets flow.

expectedRevision supports compare-and-set updates. null requires that no stored row exists.

watch() reports committed effective changes. A preference change does not restart a healthy plugin.

The contracts package exports PreferencesPort, PreferenceAddress, PreferenceCell, PreferenceQuery, and PreferenceChange.

bb.realtime

interface RealtimePort {
  declare<E extends EventContract>(event: E): RealtimeEventHandle<E>;
  publish<E extends EventContract>(event: E, payload: InputOf<E>, target?: RealtimeTarget): Promise<PublishResult>;
  subscribe<E extends EventContract>(event: E, listener: (payload: OutputOf<E>, meta: EventMeta) => void): Disposer;
  command<C extends ClientCommandContract>(input: {
    target: RealtimeTarget;
    command: C;
    input: InputOf<C>;
    timeoutMs?: number;
  }): Promise<{ delivered: number; outcomes: ClientCommandOutcome[] }>;
  connection(listener: (state: "connected" | "disconnected") => void): Disposer;
}

type RealtimeTarget =
  | { kind: "all" }
  | { kind: "session"; sessionId: string }
  | { kind: "thread"; threadId: string };

command() replaces the old separate hub concept. It keeps actor and session attribution. Thread state streams belong to bb.threads, not this transport port.

bb.background

interface BackgroundPort {
  service(name: string, definition: BackgroundService): Disposer;
  schedule(name: string, cron: string, handler: ScheduledTask): Disposer;
}

interface BackgroundService {
  start(signal: AbortSignal): void | Promise<void>;
}

type ScheduledTask = (context: {
  signal: AbortSignal;
  scheduledAt: string;
}) => void | Promise<void>;

The kernel restarts a failed service with bounded backoff. It stores each five-field cron schedule by plugin ID and name. Generation disposal stops services and removes the active schedule registration.

bb.http

interface HttpPort {
  route<I, O>(definition: HttpRoute<I, O>, handler: HttpHandler<I, O>): Disposer;
  url(path?: string): URL;
  fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
}

interface HttpRoute<I, O> {
  method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
  path: `/${string}`;
  auth: "local" | "token" | "none";
  input?: StandardSchema<I>;
  output?: StandardSchema<O>;
  maxBodyBytes?: number;
  timeoutMs?: number;
}

type HttpHandler<I, O> = (input: I, context: HttpContext) => Promise<O> | O;

interface HttpContext {
  actor: Actor;
  session?: Session;
  signal: AbortSignal;
  request: Request;
}

Routes mount below /api/plugins/<pluginId>/. A route cannot shadow a kernel or another plugin route. The kernel derives OpenAPI data from route schemas and contract.json.

bb.rpc

interface RpcPort {
  register<C extends RpcContract>(contract: C, handlers: RpcHandlers<C>): Disposer;
  call<C extends RpcContract, M extends keyof C["methods"]>(
    pluginId: string,
    contract: C,
    method: M,
    input: RpcInput<C, M>,
    options?: { signal?: AbortSignal; timeoutMs?: number },
  ): Promise<RpcOutput<C, M>>;
}

interface RpcContract {
  id: string;
  version: string;
  methods: Record<string, { input: StandardSchema; output: StandardSchema }>;
}

interface RpcError {
  code: string;
  message: string;
  issues?: readonly { path: string; message: string }[];
  traceId: string;
}

The contract ID and semver select an RPC contract. The caller does not supply an untyped method schema. App calls cross a typed transport. Server-to-server service calls remain direct in-process calls.

The contracts package exports JsonValue, Standard Schema types, RPC method types, RpcError, and defineRpcContract(). The app package exports useRpc(), useRealtime(), and useRealtimeConnectionState() as typed adapters for these ports. The connection hook reports "connecting", "connected", or "reconnecting".

bb.plugins

interface PluginsPort {
  list(options?: { state?: PluginState; includeBuiltins?: boolean }): Promise<PluginSummary[]>;
  get(pluginId: string): Promise<PluginDetail | undefined>;
  status(): Promise<KernelStatus>;
  contracts(options?: { owner?: string; tier?: "app" | "server" }): Promise<ContractRecord[]>;
  claims(contractId?: string): Promise<ClaimRecord[]>;
  winners(contractId?: string): Promise<ArbitrationRecord[]>;
  edges(pluginId?: string): Promise<DependencyEdge[]>;
  hostRoles(pluginId?: string): Promise<HostRoleStatus[]>;
  diagnostics(pluginId: string, options?: DiagnosticQuery): Promise<PluginDiagnostics>;
  watch(listener: (event: PluginIntrospectionEvent) => void): Disposer;
  reportStatus(status: PluginReportedStatus): Disposer;
}

interface PluginReportedStatus {
  state: "ready" | "degraded" | "needs-configuration";
  message?: string;
  detail?: JsonValue;
}

This service provides introspection. It does not install, remove, enable, reload, or select winners. Kernel UI and CLI flows use privileged control commands for those operations.

Scope and cleanup

The old broad scope object becomes the factory lifecycle context. It is not a claimable service.

interface PluginScope {
  pluginId: string;
  generation: string;
  signal: AbortSignal;
  actor: Actor;
  session: Session;
  effect(register: () => void | Disposer | Promise<void | Disposer>): Disposer;
  child(meta: Record<string, string>): PluginScope;
  dispose(reason?: string): Promise<void>;
}

All factory registrations become scope effects. The factory can also return one disposer. The runtime runs child disposal first. It then runs effects in last-in, first-out order.

Host daemon and host roles

The host daemon supplies transport and contained machine ports. Domain plugins define role behavior. The kernel does not include provider, workspace, or AI protocol verbs in its public plugin API.

Role identity

A host role has the private ID <pluginId>.host.<name>. It never enters the global winner store. A public server service can require one role with the same plugin owner.

The server half owns the public service token. Consumers do not know that the service uses a host. This rule keeps one public identity for a capability that uses two tiers.

interface HostRolesPort {
  use<C extends HostRoleContract>(name: string, contract: C, target: HostTarget): Promise<HostRoleClient<C>>;
  watch(name: string, listener: (event: HostRoleEvent) => void): Disposer;
}

interface HostRoleClient<C extends HostRoleContract> {
  call<M extends keyof C["methods"]>(
    method: M,
    input: HostInput<C, M>,
    options?: { signal?: AbortSignal; timeoutMs?: number | null },
  ): Promise<HostOutput<C, M>>;
  onSignal<S extends keyof C["signals"]>(name: S, listener: HostSignalListener<C, S>): Disposer;
  retain(): HostRoleLease;
  dispose(): Promise<void>;
}

type HostTarget =
  | { kind: "host"; hostId: string }
  | { kind: "environment"; environmentId: string };

Host factory and context

export default defineHostPlugin((api) => {
  api.roles.provide("git-credential", GitCredentialRole, {
    read: async (input, context) => readCredential(input, context),
  });
});

interface HostRoleContext {
  pluginId: string;
  generation: string;
  role: string;
  hostId: string;
  target: HostTarget;
  signal: AbortSignal;
  paths: { dataDir: string; tempDir: string };
  fs: ScopedFs;
  exec: ScopedExec;
  vcs: ScopedVcs;
  process: ScopedProcess;
  watch(paths: string[], options: WatchOptions, listener: WatchListener): Disposer;
  emitSignal(name: string, payload: JsonValue): void;
  retain(): HostRoleLease;
  log: PluginLogger;
}

The role gets only the ports allowed by its target scope. Paths stay inside the declared root and write roots. The daemon removes runtime-owned environment variables before it starts a role.

Daemon protocol

The server and daemon use one versioned session. The protocol supports these generic operations:

Operation Purpose
session.open Negotiate the daemon version, host facts, leases, watch sets, and active generations.
role.start Verify and start one role generation.
role.call Run one typed role method with a call ID and deadline.
role.cancel Abort one active call.
role.signal Relay a validated role signal.
role.dispose Stop one role generation after its drain.
role.exited Report exit data, bounded stderr, and cost facts.
session.events Relay typed daemon events with accepted and rejected counts.
tunnel.ensure Create a shared-port tunnel with a stable identity.
local.status Report daemon health, connection state, version, and platform.
local.openTargets List local application targets.
local.openInTarget Open a contained path in a selected local target.

Provider model, health, usage, installation, bridge, tool-call, and interaction verbs move to bb.providers roles. The daemon carries their typed role calls. It does not define their domain grammar.

Each role process has call, input, output, line, memory, start, idle, and stop limits. The daemon kills a role that violates a hard transport limit. It does not automatically restart a failed role. The next required call starts a new verified generation.

Error surfaces and rollback

The kernel uses stable error codes. A plugin can add only codes below its own plugin ID.

Code Meaning Recovery path
invalid_manifest The strict manifest parser found an error. Fix the manifest and rebuild.
invalid_contract contract.json disagrees with the manifest or schema. Fix contract declarations and rebuild.
artifact_integrity A file, root digest, or required signature failed verification. Install a verified artifact.
incompatible An engine or contract semver range does not match. Install a compatible release.
claim_collision A non-replaceable contract has two claims. Disable one claimant or change the declaration.
missing_required A required service edge has no ready provider. Install or enable a compatible provider.
activation_failed A factory failed before its atomic commit. Keep the old generation and inspect diagnostics.
readiness_failed A claimed service did not become ready. Keep the old winner and inspect the service result.
drain_timeout Old calls exceeded the cutover deadline. Cancel the old calls and complete the cutover.
host_role_failed A role failed to start, call, or stop. Start a new verified role generation.
safe_mode Safe mode blocked a user plugin or override. Repair state and start a normal boot.

An app surface error boundary shows the plugin ID, surface ID, trace ID, and fallback result. It never shows secret values or an unfiltered stack.

The kernel keeps the current and previous verified artifacts for each managed plugin. A rollback stages the previous artifact through the normal winner transaction. It never restores storage from another plugin ID.

Diagnostics and cost attribution

The kernel assigns every operation a pluginId, generation, contract ID, call ID, trace ID, and tier. It keeps bounded structured logs and aggregate cost samples.

interface PluginDiagnostics {
  pluginId: string;
  generation: string;
  state: PluginState;
  boot: { verifyMs: number; loadMs: number; readyMs: number };
  app: { mounts: number; renderMs: number; longTasks: number; errors: number };
  server: { calls: number; callMs: number; errors: number; activeCalls: number };
  host: { starts: number; calls: number; callMs: number; exits: number; peakRssBytes?: number };
  io: { httpInBytes: number; httpOutBytes: number; realtimeBytes: number; storageBytes: number };
  restarts: { count: number; reasons: Record<string, number> };
  logs: DiagnosticLogSummary;
  sampledAt: string;
}

The kernel records these measures:

  • Manifest, contract, and artifact verification time.
  • Factory start, readiness, commit, drain, disposal, and restart time.
  • Service and RPC call count, duration, failure code, cancellation, and bytes.
  • Surface mount count, render duration, long tasks, and error-boundary events.
  • Host role starts, exits, peak memory, calls, output, and lease time.
  • HTTP, realtime, storage, and secret-read counts. Secret values never enter diagnostics.

The first release reports cost. It does not enforce a budget. The inspector can compare a fork with its recorded parent revision.

Covers

This table maps every allocated old item to its 2.0 home.

<!-- GENERATED_COVERS_START -->

Old item ID New contract or verb Note
build.app bb plugin build: app build stage
build.app.options.minify bb plugin build --mode production: app minification
build.app.output.css dist/app.css
build.app.output.js dist/app.mjs
build.app.output.meta artifact.json: files for app.mjs and app.css
build.app.result build result: app artifact paths and digests
build.app.runtimeShims app runtime import map The host supplies React and the bb app runtime.
build.app.shimmedTypePackages 2.0 SDK app runtime allowlist
build.artifactMeta bb plugin build: create artifact.json
build.artifactMeta.fields artifact.json: ArtifactManifest
build.devLoop bb plugin dev: verified candidate loop
build.devLoop.deps bb plugin dev: build, verify, install, and reload adapters
build.devLoop.dispose bb plugin dev: stop watcher and candidate work
build.devLoop.handleChange bb plugin dev: queue changed source
build.devLoop.ignore bb plugin dev: source filter
build.devLoop.settled bb plugin dev: await current candidate
build.host bb plugin build: host build stage
build.host.output.js dist/host.mjs
build.host.output.map dist/host.mjs.map
build.host.output.meta artifact.json: files for host.mjs
build.host.result build result: host artifact paths and digest
build.server bb plugin build: server build stage
build.server.externals 2.0 SDK server runtime allowlist
build.server.output.js dist/server.mjs
build.server.output.map dist/server.mjs.map
build.server.output.meta artifact.json: files for server.mjs
build.server.result build result: server artifact paths and digests
build.svg.compactIcon bb plugin build: safe SVG validator
build.svg.icon bb plugin build: safe SVG validator
build.svg.logo bb plugin build: safe SVG validator
build.toolchain.pins artifact.json: builtWith.toolchain
build.toolchain.resolve bb plugin build: pinned toolchain resolver
build.toolchain.type 2.0 PluginBuildToolchain
cli.marketplace.add bb marketplace add
cli.marketplace.list bb marketplace list
cli.marketplace.parent bb marketplace parent
cli.marketplace.refresh bb marketplace refresh
cli.marketplace.register kernel CLI registration: bb marketplace
cli.marketplace.remove bb marketplace remove
cli.plugin.build bb plugin build
cli.plugin.config bb plugin config
cli.plugin.dev bb plugin dev
cli.plugin.disable bb plugin disable
cli.plugin.enable bb plugin enable
cli.plugin.install bb plugin install
cli.plugin.install.json bb plugin install option: --json
cli.plugin.install.plugin bb plugin install option: --plugin
cli.plugin.install.subdirectory bb plugin install option: --subdirectory
cli.plugin.install.tagPrefix bb plugin install option: --tag-prefix
cli.plugin.install.yes bb plugin install option: --yes
cli.plugin.list bb plugin list
cli.plugin.logs bb plugin logs
cli.plugin.logs.follow bb plugin logs option: --follow
cli.plugin.logs.lines bb plugin logs option: --lines
cli.plugin.migrate bb plugin migrate
cli.plugin.migrate.yes bb plugin migrate option: --yes
cli.plugin.new bb plugin new
cli.plugin.outdated bb plugin outdated
cli.plugin.parent bb plugin parent
cli.plugin.register kernel CLI registration: bb plugin
cli.plugin.reload bb plugin reload
cli.plugin.remove bb plugin remove
cli.plugin.run bb plugin run
cli.plugin.search bb plugin search
cli.plugin.source bb plugin source
cli.plugin.token bb plugin token
cli.plugin.token.rotate bb plugin token option: --rotate
cli.plugin.types bb plugin types
cli.plugin.types.check bb plugin types option: --check
cli.plugin.update bb plugin update
cli.plugin.update.all bb plugin update option: --all
cli.plugin.update.yes bb plugin update option: --yes
cli.pluginCall bb plugin run <id> <verb>
cli.reservedCommands kernel CLI reserved word set
host.api.dispose host factory disposer
host.api.hosts host factory: api.roles
host.api.hosts.client HostRolesPort.use()
host.api.hosts.declarePorts host role manifest: shared port declarations
host.api.hosts.ensureTunnel host daemon: tunnel.ensure
host.api.tunnelIdentity host daemon: tunnel identity
host.call.options HostRoleClient.call(): signal and timeoutMs
host.client HostRoleClient
host.client.call HostRoleClient.call()
host.client.signal HostRoleClient.onSignal()
host.client.workerExit HostRolesPort.watch(): role.exited
host.daemon.bridgeLaunch bb.providers private bridge host role The Providers plugin owns bridge launch behavior.
host.daemon.events host daemon: session.events
host.daemon.interaction bb.providers private host role The Providers plugin owns tool and interaction behavior.
host.daemon.interactionInterrupt bb.providers private host role The Providers plugin owns tool and interaction behavior.
host.daemon.local.client host daemon local API: typed local client
host.daemon.local.health host daemon local API: local.health
host.daemon.local.openInTarget host daemon local API: local.openInTarget
host.daemon.local.openTargets host daemon local API: local.openTargets
host.daemon.local.status host daemon local API: local.status
host.daemon.local.statusType host daemon local API: LocalStatus
host.daemon.pluginHostCall host daemon: role.call
host.daemon.pluginHostCancel host daemon: role.cancel
host.daemon.pluginHostDispose host daemon: role.dispose
host.daemon.pluginHostSignal host daemon: role.signal
host.daemon.pluginHostWorkerExited host daemon: role.exited
host.daemon.providerHealth bb.providers private host role The daemon carries the typed call. The Providers plugin owns the verb.
host.daemon.providerInstallRun bb.providers private host role The daemon carries the typed call. The Providers plugin owns the verb.
host.daemon.providerInstallStatus bb.providers private host role The daemon carries the typed call. The Providers plugin owns the verb.
host.daemon.providerModels bb.providers private host role The daemon carries the typed call. The Providers plugin owns the verb.
host.daemon.providerUsage bb.providers private host role The daemon carries the typed call. The Providers plugin owns the verb.
host.daemon.sessionOpen host daemon: session.open
host.daemon.sessionOpenRequest host daemon: SessionOpenRequest
host.daemon.sessionOpenResponse host daemon: SessionOpenResponse
host.daemon.toolCall bb.providers private host role The Providers plugin owns tool and interaction behavior.
host.daemon.tunnelIdentity host daemon: tunnel.ensure identity
host.defineEntry defineHostPlugin()
host.entry defineHostPlugin() result
host.entry.contract contract.json: hostRoles[]
host.entry.dispose host factory disposer and HostRoleContext.signal
host.entry.experimental_apiVersion host artifact protocol version The version field is stable in 2.0.
host.entry.experimental_signals contract.json: hostRoles[].signals Signals are stable typed role members.
host.entry.handlers host factory: api.roles.provide() handlers
host.paths HostRoleContext.paths
host.rpc.context HostRoleContext
host.rpc.context.emitSignal HostRoleContext.emitSignal()
host.rpc.context.lifecycle HostRoleContext.signal and role lifecycle
host.rpc.context.paths HostRoleContext.paths
host.rpc.context.retainWorker HostRoleContext.retain()
host.rpc.context.signal HostRoleContext.signal
host.rpc.context.watch HostRoleContext.watch()
host.rpc.handlers host factory: typed role handlers
host.signal.contract contract.json: hostRoles[].signals
host.signal.event HostRoleEvent: role.signal
host.signals host role signal map
host.watch.change WatchEvent
host.watch.changeType WatchEvent.kind
host.watch.event HostRoleContext.watch() event
host.watch.options WatchOptions
host.watch.subscription HostRoleContext.watch() disposer
host.worker.lease HostRoleLease
install.collection.entryName bb.plugins.json: plugins[].name
install.collection.entrySource bb.plugins.json: plugins[].source
install.collection.entrySubdirectory kernel installer: resolve selected collection path
install.collection.name bb.plugins.json: name
install.collection.parse kernel installer: parse bb.plugins.json
install.collection.plugins bb.plugins.json: plugins
install.collection.read kernel installer: read bb.plugins.json as data
install.collection.schema bb.plugins.json: collection schema version 2
install.collection.schemaUrl bb.plugins.json: $schema
install.collection.schemaVersion bb.plugins.json: schemaVersion
install.collection.select kernel installer: select collection root, path, or name
install.defaultGitRef kernel installer: resolved default Git ref
install.gitCache kernel artifact store: commit-addressed Git cache
install.gitRangeSpec kernel installer: canonical Git semver source
install.gitTagName kernel installer: Git release-tag formatter
install.gitTagVersion kernel installer: Git release-tag parser
install.hashDir artifact verifier: artifact root digest
install.isCommitSha kernel installer: Git commit selector validator
install.nestedRoots kernel installer: preserve nested collection roots
install.normalizeSubdirectory kernel installer: validate safe repository subdirectory
install.normalizeTagPrefix kernel installer: Git tag-prefix validator
install.npmCache kernel artifact store: content-addressed npm cache
install.npmPrefix kernel artifact store: npm stage directory
install.parsedSource kernel installer: InstallSource union
install.parseSource kernel installer: parse canonical source
install.promoteDir kernel artifact store: immutable promotion
install.promoteGit kernel artifact store: contained Git promotion
install.recoverGit kernel artifact store: remove incomplete stage The active immutable artifact never changes during recovery.
install.rootDir kernel installer: resolve contained plugin root
install.runCommand kernel installer: bounded Git or npm process
install.source.builtin kernel installer: InstallSource.builtin
install.source.collection kernel installer: InstallSource.collection
install.source.git kernel installer: InstallSource.git
install.source.git.range kernel installer: InstallSource.git.range
install.source.git.ref kernel installer: InstallSource.git.ref
install.source.npm kernel installer: InstallSource.npm
install.source.path kernel installer: InstallSource.path
manifest.bb.app bb.plugin.jsonc: artifacts.app
manifest.bb.branding bb.plugin.jsonc: branding
manifest.bb.branding.experimental_icons bb.plugin.jsonc: branding.icons Named icons are stable manifest data.
manifest.bb.branding.icon bb.plugin.jsonc: branding.icon
manifest.bb.branding.logo bb.plugin.jsonc: branding.logo
manifest.bb.branding.logo.dark bb.plugin.jsonc: branding.logo.dark
manifest.bb.branding.logo.light bb.plugin.jsonc: branding.logo.light
manifest.bb.description bb.plugin.jsonc: description
manifest.bb.host bb.plugin.jsonc: artifacts.host
manifest.bb.hostArtifact bb.plugin.jsonc: artifacts.host and artifact.json One verified host artifact fulfills declared roles.
manifest.bb.name bb.plugin.jsonc: name
manifest.bb.server bb.plugin.jsonc: artifacts.server
manifest.bb.skills bb.plugin.jsonc: skills The build makes ordinary bb.agents skill claims.
manifest.bb.themes bb.plugin.jsonc: themes The build makes keyed bb.layout.theme claims.
manifest.bb.themes.codeTheme bb.plugin.jsonc: themes[].codeTheme
manifest.bb.themes.css bb.plugin.jsonc: themes[].css
manifest.bb.themes.description bb.plugin.jsonc: themes[].description
manifest.bb.themes.id bb.plugin.jsonc: themes[].id
manifest.bb.themes.name bb.plugin.jsonc: themes[].name
manifest.noCurrentArtifacts bb.plugin.jsonc: artifacts The new manifest names built tier artifacts.
manifest.noCurrentContributes bb.plugin.jsonc: claims, surfaces, services, settings, skills, themes, and hostRoles The 2.0 manifest has explicit static declarations.
manifest.normalized kernel loader: NormalizedPluginRecord
manifest.normalized.appEntry NormalizedPluginRecord.artifacts.app
manifest.normalized.branding NormalizedPluginRecord.branding
manifest.normalized.description NormalizedPluginRecord.description
manifest.normalized.hostEntry NormalizedPluginRecord.artifacts.host
manifest.normalized.id NormalizedPluginRecord.id
manifest.normalized.name NormalizedPluginRecord.name
manifest.normalized.packageName NormalizedPluginRecord.provenance.packageName
manifest.normalized.rootDir kernel artifact store: verified immutable root
manifest.normalized.serverEntry NormalizedPluginRecord.artifacts.server
manifest.normalized.skillNames bb.agents skill claims The Agents plugin owns skill discovery and names.
manifest.normalized.skillsRootPaths NormalizedPluginRecord.skills.roots
manifest.normalized.themes NormalizedPluginRecord.themes
manifest.normalized.version NormalizedPluginRecord.version
manifest.package.bb bb.plugin.jsonc The manifest moves from package.json to a strict standalone file.
manifest.package.engines bb.plugin.jsonc: engines
manifest.package.name bb.plugin.jsonc: id and artifact.json: plugin.packageName The plugin ID is explicit. The package name stays provenance data.
manifest.package.pluginTailwindContent dropped The app build scans the source import graph and declared exported modules.
manifest.package.version bb.plugin.jsonc: version
manifest.reader kernel loader: read and validate bb.plugin.json plus contract.json
marketplace.entry.author marketplace-v2.json: plugins[].author
marketplace.entry.description marketplace-v2.json: plugins[].description
marketplace.entry.displayName marketplace-v2.json: plugins[].displayName
marketplace.entry.icon marketplace-v2.json: plugins[].icon
marketplace.entry.id marketplace-v2.json: plugins[].id
marketplace.entry.source marketplace-v2.json: plugins[].source
marketplace.entry.tags marketplace-v2.json: plugins[].tags
marketplace.manifest.description marketplace-v2.json: description
marketplace.manifest.displayName marketplace-v2.json: displayName
marketplace.manifest.name marketplace-v2.json: name
marketplace.manifest.plugins marketplace-v2.json: plugins
marketplace.manifest.schema marketplace-v2.json: catalog schema
marketplace.manifest.schemaUrl marketplace-v2.json: schemaUrl
marketplace.manifest.schemaVersion marketplace-v2.json: schemaVersion
marketplace.materialize kernel marketplace cache: verified materialization
marketplace.parse kernel marketplace index parser
marketplace.parseJson kernel marketplace index parser
marketplace.registerRoutes kernel marketplace control routes Kernel UI and CLI use authenticated control routes.
marketplace.resolveSource kernel marketplace resolver: entry to canonical InstallSource
marketplace.routes kernel marketplace control routes Kernel UI and CLI use authenticated control routes.
marketplace.service kernel marketplace control API This API is privileged and is not a plugin service.
marketplace.service.add kernel marketplace control API: add()
marketplace.service.install kernel marketplace control API: install()
marketplace.service.installPlan kernel marketplace control API: installPlan()
marketplace.service.list kernel marketplace control API: list()
marketplace.service.refresh kernel marketplace control API: refresh()
marketplace.service.remove kernel marketplace control API: remove()
marketplace.service.search kernel marketplace control API: search()
marketplace.service.status kernel marketplace control API: status()
marketplace.source.git.range marketplace-v2.json: plugins[].source.git.range
marketplace.source.git.ref marketplace-v2.json: plugins[].source.git.ref
marketplace.source.npm marketplace-v2.json: plugins[].source.npm
marketplace.sourceDisplay kernel marketplace source formatter
marketplace.sourceParser kernel marketplace source parser
registry.applyUpdate bb plugin update
registry.bindSdk dropped The old bb.sdk facade delegates to named 2.0 services during migration.
registry.builtin.root kernel bundled release index: verified artifact root
registry.builtin.source kernel bundled release index: InstallSource
registry.bundled.autoInstall kernel bundled release index: entries[].installByDefault
registry.bundled.categories kernel bundled release index: categories
registry.bundled.category kernel bundled release index: entries[].category
registry.bundled.defaultEnabled kernel bundled release index: entries[].enabledByDefault
registry.bundled.definition kernel bundled release index: BundledPluginDefinition
registry.bundled.list bb.plugins.list({ includeBuiltins: true })
registry.bundled.name kernel bundled release index: entries[].name
registry.bundled.pluginId kernel bundled release index: entries[].pluginId
registry.bundled.plugins kernel bundled release index: entries
registry.checkUpdates bb plugin outdated
registry.events bb.plugins.watch()
registry.findAgentTool bb.agents.tool keyed contract: resolve key
registry.getApi plugin factory: tier-specific api object
registry.getAppAsset kernel verified artifact route: app assets
registry.getBrandingAsset kernel verified artifact route: branding assets
registry.getHttpRoute bb.http: route registry
registry.getIconAsset kernel verified artifact route: named icons
registry.getRpcHandler bb.rpc: registered contract handler
registry.getSettings bb.settings service: get plugin settings
registry.getSource bb.plugins.get(): source
registry.handleHostSignal host role runtime: role.signal
registry.handleHostWorkerExit host role runtime: role.exited
registry.handleUncaughtException kernel diagnostics: generation failure and fallback
registry.httpToken bb plugin token and bb.http token authentication
registry.install bb plugin install
registry.installCatalog bb plugin install marketplace:<market>/<entry>
registry.installOfficial bb plugin install builtin:<name>
registry.installPath bb plugin install path:<directory>
registry.invokeAgentTool bb.agents tool service: execute()
registry.invokeHttpRoute bb.http: route dispatch
registry.invokeRpcHandler bb.rpc.call()
registry.isBuiltin bb.plugins: PluginSummary.source.kind
registry.list bb.plugins.list()
registry.listAgentTools bb.agents.tool keyed contract: list claims
registry.listCli bb.commands.cli keyed contract: list claims
registry.listHostArtifactGenerations bb.plugins.hostRoles()
registry.listInstructions bb.agents instructions service: list()
registry.listMentions bb.mentions provider contract: list claims
registry.listSkills bb.agents skill service: list()
registry.listThemes bb.layout.theme keyed contract The kernel indexes theme claims. The Layout plugin owns theme behavior.
registry.listUpdateResults bb.plugins.get(): update facts
registry.readLogTail bb.plugins.diagnostics(): logs
registry.readThemeCodeTheme bb.layout.theme service: read code theme asset
registry.readThemeCss bb.layout.theme service: read CSS asset
registry.reload bb plugin reload
registry.reloadOutcome kernel loader: ReloadResult
registry.remove bb plugin remove
registry.resolveAgentConfiguration bb.agents configuration service: resolve()
registry.resolveCatalogNpm kernel marketplace resolver: npm InstallSource
registry.resolveMention bb.mentions service: resolve()
registry.runCli bb plugin run <id> <verb>
registry.searchMentions bb.mentions service: search()
registry.service kernel PluginRuntimeRegistry
registry.setEnabled bb plugin enable and bb plugin disable
registry.skillContribution bb.agents skill claim
registry.start kernel loader: boot and activate
registry.startUpdateChecks kernel marketplace update scheduler
registry.stop kernel loader: drain and unload
registry.stopUpdateChecks kernel marketplace update scheduler: dispose
registry.sweepSchedules kernel loader lifecycle: remove generation-owned schedules
registry.updateSettings bb.settings service: update plugin settings
registry.watchDispatch bb.plugins.watch()
server.hosts plugin factory: api.hosts
server.hosts.client.call HostRoleClient.call()
server.hosts.client.experimental_onSignal HostRoleClient.onSignal()
server.hosts.client.experimental_onWorkerExit HostRolesPort.watch(): role.exited
server.hosts.client.options HostRoleClient.call(): options
server.hosts.client.signalEvent HostRoleEvent: role.signal
server.hosts.clientArgs.contract contract.json: hostRoles[]
server.hosts.clientArgs.experimental_signals contract.json: hostRoles[].signals
server.hosts.declareSharedPorts bb.plugin.jsonc: hostRoles[].sharedPorts
server.hosts.ensureSharedPortTunnel host daemon: tunnel.ensure
server.hosts.experimental_client HostRolesPort.use()
server.hosts.sharedPortIdentity host daemon: tunnel identity
server.http bb.http service
server.http.handler bb.http: HttpHandler
server.http.route bb.http: route()
server.http.route.options bb.http: HttpRoute
server.http.route.options.auth bb.http: HttpRoute.auth
server.import.defineRpcContract defineRpcContract() from @get-bb/plugin/contracts
server.log plugin factory: api.log and kernel diagnostics
server.log.debug PluginLogger.debug()
server.log.error PluginLogger.error()
server.log.info PluginLogger.info()
server.log.warn PluginLogger.warn()
server.onDispose PluginScope.effect() or the factory disposer
server.pluginId PluginScope.pluginId
server.realtime bb.realtime service
server.realtime.publish bb.realtime: publish()
server.rpc bb.rpc service
server.rpc.contract bb.rpc: RpcContract and contract.json methods
server.rpc.error bb.rpc: RpcError
server.rpc.register bb.rpc: register()
server.sdk deprecated bb.sdk facade over named services The facade drains during migration.
server.sdk.plugins bb.plugins introspection plus privileged kernel controls
server.sdk.plugins.applyUpdate dropped Use the privileged bb plugin update command or the recovery UI.
server.sdk.plugins.callRpc bb.rpc.call()
server.sdk.plugins.catalog kernel marketplace control API This API is privileged and is not a plugin service.
server.sdk.plugins.catalog.install dropped Use the privileged bb plugin install flow.
server.sdk.plugins.catalog.installPlan dropped Use the privileged bb plugin install flow.
server.sdk.plugins.catalog.search kernel marketplace query: search()
server.sdk.plugins.catalog.status kernel marketplace query: status()
server.sdk.plugins.checkUpdates bb plugin outdated
server.sdk.plugins.disable dropped Use the privileged bb plugin disable command or the plugin management UI.
server.sdk.plugins.enable dropped Use the privileged bb plugin enable command or the plugin management UI.
server.sdk.plugins.getSource bb.plugins.get(): source
server.sdk.plugins.install dropped Use the privileged bb plugin install command or the plugin management UI.
server.sdk.plugins.list bb.plugins.list()
server.sdk.plugins.listUpdateResults bb.plugins.get(): update facts
server.sdk.plugins.marketplaces kernel marketplace control API This API is privileged and is not a plugin service.
server.sdk.plugins.marketplaces.add dropped Use the privileged bb marketplace add command or the plugin management UI.
server.sdk.plugins.marketplaces.list dropped Use the privileged bb marketplace list command or the plugin management UI.
server.sdk.plugins.marketplaces.refresh dropped Use the privileged bb marketplace refresh command or the plugin management UI.
server.sdk.plugins.marketplaces.remove dropped Use the privileged bb marketplace remove command or the plugin management UI.
server.sdk.plugins.reload dropped Use the privileged bb plugin reload command or the plugin management UI.
server.sdk.plugins.remove dropped Use the privileged bb plugin remove command or the plugin management UI.
server.sdk.plugins.token bb plugin token and bb.http token authentication
server.sdk.status bb.plugins: status() Thread and workspace fields move to their domain services.
server.sdk.status.get bb.plugins: status() Thread and workspace fields move to their domain services.
server.server plugin factory facts and kernel ports
server.server.experimental_dataDir dropped Use bb.storage. The kernel does not expose its data directory.
server.server.loopbackBaseUrl bb.http: url()
server.status bb.plugins: reportStatus()
server.status.needsConfiguration bb.plugins: reportStatus({ state: 'needs-configuration' })
server.storage bb.storage service
server.storage.database bb.storage: database()
server.storage.kv bb.storage: kv()
server.storage.kv.delete bb.storage: KvStore.delete()
server.storage.kv.get bb.storage: KvStore.get()
server.storage.kv.list bb.storage: KvStore.list()
server.storage.kv.set bb.storage: KvStore.set()
server.storage.migrate bb.storage: migrate()
app.contracts.PluginRealtimeConnectionState @get-bb/plugin/app: RealtimeConnectionState The app adapter keeps the shared connection states.
app.contracts.PluginRpcClient @get-bb/plugin/app: RpcClient The client binds one plugin RPC contract.
app.contracts.PluginRpcClient.call @get-bb/plugin/app: RpcClient.call() The call remains typed by method input and output.
app.hooks.useRealtime @get-bb/plugin/app: useRealtime() The hook adapts the bb.realtime port.
app.hooks.useRealtimeConnectionState @get-bb/plugin/app: useRealtimeConnectionState() The hook reports the shared transport state.
app.hooks.useRpc @get-bb/plugin/app: useRpc() The hook returns a typed client for bb.rpc.
app.replacement.AUTOMATIC_REPLACEMENT_PROVIDER ArbitrationRecord.source: default The migration converts the automatic sentinel to the declared default.
app.replacement.BUILT_IN_REPLACEMENT_PROVIDER ContractRecord.defaultClaimant The migration pins the declared built-in default claimant.
app.replacement.replacementProviderKey arbitration identity: contractId plus key The kernel stores the normalized contract identity directly.
app.rpc.JsonValue @get-bb/plugin/contracts: JsonValue The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcCallArgs @get-bb/plugin/contracts: RpcCallArgs The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcContract @get-bb/plugin/contracts: RpcContract The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcError @get-bb/plugin/contracts: RpcError The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcErrorCode @get-bb/plugin/contracts: RpcErrorCode The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcHandlers @get-bb/plugin/contracts: RpcHandlers The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcIssuePathSegment @get-bb/plugin/contracts: RpcIssuePathSegment The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcMethodContract @get-bb/plugin/contracts: RpcMethodContract The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcMethodContract.input @get-bb/plugin/contracts: RpcMethodContract.input The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcMethodContract.output @get-bb/plugin/contracts: RpcMethodContract.output The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcResult @get-bb/plugin/contracts: RpcResult The contracts package keeps the typed RPC boundary.
app.rpc.PluginRpcValidationIssue @get-bb/plugin/contracts: RpcValidationIssue The contracts package keeps the typed RPC boundary.
app.rpc.StandardSchemaV1 @get-bb/plugin/contracts: StandardSchemaV1 The contracts package keeps the typed RPC boundary.
app.rpc.StandardSchemaV1InferInput @get-bb/plugin/contracts: StandardSchemaV1InferInput The contracts package keeps the typed RPC boundary.
app.rpc.StandardSchemaV1InferOutput @get-bb/plugin/contracts: StandardSchemaV1InferOutput The contracts package keeps the typed RPC boundary.
app.rpc.StandardSchemaV1Issue @get-bb/plugin/contracts: StandardSchemaV1Issue The contracts package keeps the typed RPC boundary.
app.rpc.StandardSchemaV1Result @get-bb/plugin/contracts: StandardSchemaV1Result The contracts package keeps the typed RPC boundary.
app.rpc.defineRpcContract @get-bb/plugin/contracts: defineRpcContract The contracts package keeps the typed RPC boundary.
registry.componentBuild bb plugin build: component registry generator Build tooling generates @bb/ui registry records.
registry.componentRegistry bb plugin build: @bb/ui component registry The registry remains build input, not a runtime contract.
registry.index bb plugin build: generated component registry index The index remains build output.
registry.item bb plugin build: generated component registry item The item remains build output.
registry.item.file bb plugin build: generated component registry file The file remains build output.
server.background bb.background port The kernel port owns generation-scoped background work.
server.background.schedule bb.background: schedule() The kernel keeps the durable five-field cron row.
server.background.service bb.background: service() The kernel restarts failed services with bounded backoff.
server.background.service.start bb.background: BackgroundService.start() The generation signal stops the service.
server.sdk.guide bb guide static renderer The kernel keeps static CLI guide rendering.
server.sdk.guide.render bb guide: render chapter The renderer reads verified packaged guide data.
server.sdk.subscribe bb.realtime: subscribe() Named domain services replace entity selectors.
server.sdk.subscribe.connection bb.realtime: connection() The connection listener reports transport state.
server.sdk.system named owner services and kernel ports The broad system facade splits by contract owner.
server.sdk.system.version bb.plugins: status().version Kernel status supplies the server version.
server.settings bb.preferences port The fixed kernel port replaces the factory property.
server.settings.define dropped Declare the schema in the kernel manifest. Read values through bb.preferences.
server.settings.handle.get bb.preferences: get() Returns one effective typed value.
server.settings.handle.onChange bb.preferences: watch() Returns a disposable subscription.
server.settings.descriptor dropped The kernel manifest settings schema replaces the runtime descriptor union.
server.settings.descriptor.type dropped The kernel manifest settings schema owns the field type.
server.settings.descriptor.label dropped The kernel manifest settings schema owns the field label.
server.settings.descriptor.description dropped The kernel manifest settings schema owns the field description.
server.settings.descriptor.secret dropped The kernel manifest marks a secret field. The UI uses the kernel bb.secrets port.
server.settings.descriptor.experimental_multiline dropped The kernel manifest settings schema selects the text editor.
server.settings.descriptor.options dropped The kernel manifest settings schema owns select choices.
server.settings.descriptor.default dropped The kernel manifest settings schema owns the effective default.
settings.namespace bb.preferences port The fixed kernel port replaces the old runtime settings namespace.
settings.define dropped Declare settings in the kernel manifest settings schema.
settings.descriptor dropped The kernel manifest settings schema owns the descriptor union.
settings.string.fields dropped The kernel manifest settings schema owns string field declarations.
settings.boolean.fields dropped The kernel manifest settings schema owns boolean field declarations.
settings.select.fields dropped The kernel manifest settings schema owns select field declarations.
settings.project.fields dropped The kernel manifest settings schema owns project field declarations.
settings.descriptors dropped The kernel manifest settings schema owns the settings map.
settings.value bb.preferences: PreferenceCell.value The new value type is JsonValue after schema validation.
settings.handle.get bb.preferences: get() Returns the effective stored or default cell.
settings.handle.onChange bb.preferences: watch() Reports committed effective changes.
server.sdk.plugins.getSettings bb.preferences: list() plus bb.plugins manifest read The schema comes from bb.plugins. Values come from bb.preferences.
server.sdk.plugins.updateSettings bb.preferences: set() and clear() Secret changes use the kernel human-only secret flow.
server.sdk.system.config bb.preferences: list() This port returns the settings slice. Other named services return the old system facts.
server.sdk.system.updateExperiments bb.preferences: set() The bb.settings manifest declares the experiment keys.
server.sdk.system.updateGeneralSettings bb.preferences: set() Individual keys replace the old bulk object update.
server.sdk.subscribe.systemConfigChanged bb.preferences: watch() The preference watcher reports effective configuration changes.
server.sdk.system.reloadConfig bb.preferences: reload() The kernel port reloads external configuration.
server.sdk.system.updateKeyboardSettings bb.preferences: set() Declared keyboard keys replace the bulk update.
<!-- GENERATED_COVERS_END -->