bb Plugin API 2.0 design overview

The 2.0 API gives app, server, and host plugins one contract model, one winner model, and one authoring flow.

Start here

This page gives the model and the page map. It does not define final method signatures. The settled design record defines the decisions behind this site.

The research starts at the 2026-08-26 research index. The allocation brief defines the page roster and the old API ownership. The frontend synthesis and backend synthesis provide the evidence.

The model in brief

A plugin is a package with static declarations and separate artifacts for the app, server, and host tiers. The manifest declares claims, new contracts, dependencies, exports, lineage, and artifact paths. The build adds contract.json with full method and type schemas. The kernel validates both files before it loads code.

The headless rule

This rule is a first-party design principle.

A domain service ships headless whenever it has consumers beyond its own UI. Its default presentation is a separate -ui plugin. Presentation-only affordances are child surfaces declared by the default implementation that renders them, never by the domain.

The first-party roster applies this rule to threads, workspace, files, version control, and commands. A data plugin declares no surfaces. Its UI plugin requires the data service and owns the default presentation.

The bb.vcs plugin owns the generic version-control contract. The bb.vcs-ui plugin renders only that contract.

The bb.git plugin claims bb.vcs as its declared default provider. It also exports bb.git.* services for Git-only work.

Presentation-only surfaces follow the implementation that renders them. For example, the default thread view declares bb.thread-ui.sidePanels. A replacement view can omit that child surface without changing bb.threads.

Contracts

A contract is a named, typed, versioned capability. A UI region is a surface contract. A server capability is a service contract. A private server-to-host capability is a host role. All contracts use owner-namespaced IDs:

type FirstPartyContractId = `bb.${string}.${string}`;
type PluginContractId = `${string}.${string}`;

interface ContractDeclaration {
  id: string;
  kind: "single" | "list" | "keyed" | "chain";
  version: string;
  stability: "stable" | "experimental";
  replaceable?: boolean;
}

The kernel seeds bb.app.root as a single surface. A winning surface can declare typed child surfaces. A service owner declares its default provider when the service can fall back after a failure.

Use a contract when the user can replace the capability or when another plugin needs the current winner. Use a module import when the consumer needs one exact implementation.

import { Surface } from "@get-bb/plugin/app";
import { Composer } from "@bb/thread-ui/components";

// The current winner follows the user's choice.
<Surface id="bb.thread-ui.composer" props={{ threadId }} />;

// This import always uses this concrete module.
<Composer threadId={threadId} />;

Service tokens use the same rule on the server. A service consumer gets a live in-process object, and a host call uses an explicit typed host role.

Four kinds

The kind states how a contract combines claims. The same four kinds apply to app surfaces and backend services.

Kind Active result User choice Typical examples
single One implementation Pick one winner when replaceable Composer, drafts service
list All claims, in deterministic order Hide or reorder items Side panels, event listeners
keyed One implementation for each key Pick a winner for each key when replaceable Timeline item type, tool name, provider ID
chain Ordered wrappers around a base Inspect and reorder the chain Send interception, command interception

A non-replaceable collision fails at load with a clear error. A list does not have a winner conflict. A chain has visible order. A keyed contract has one winner per key.

Winners and defaults

The kernel stores one global winner for each replaceable single contract and each replaceable keyed key. A fresh install selects the first-party claimant or the declared default provider. A second claimant does not change the active result without a user choice.

The frontend winner of a single surface receives the typed Original component. Original always means the built-in default. It never means another claimant. The backend has no Original handle. A replaceable backend contract declares a default provider instead.

A surface failure reaches a per-surface error boundary. The host shows a notice and uses Original or the default claimant. A service failure uses the declared default provider. Safe mode disables overrides and keeps kernel recovery, defaults, and ports available.

Forks

A fork is a new plugin ID. Its manifest records the parent ID and parent revision:

{
  "id": "acme.github-fork",
  "fork": {
    "parent": "bb.github",
    "parentRevision": "1.4.2"
  },
  "claims": [
    { "surface": "bb.thread-ui.sidePanels" },
    { "service": "bb.github.issueCache", "version": "^1" }
  ]
}

The fork claims each parent contract that it still implements. The install checks those claims against the parent's contract.json. The fork receives fresh service storage. Consumers keep the same contract ID across a winner change.

The normal fork path is short:

  1. Resolve the active contract and its source.
  2. Copy the parent into a new plugin package.
  3. Record the parent ID and revision.
  4. Edit the package and build its artifacts.
  5. Install the fork and choose it in the winner picker.
  6. Merge parent updates from the recorded revision.

Three tiers

The app, server, and host tiers have separate runtime planes. App code shares the browser page, React, and the DOM. Server code runs in the bb server process. Host code runs in the machine daemon. Server code reaches host code only through an explicit typed host role.

Tier Main work Author entry Shared capability
App Surfaces, commands, composer integration, and app state One app factory with api Surface contracts and direct module exports
Server Domain services, tools, RPC, settings, and events One server factory with api Service tokens and kernel ports
Host Machine-local provider, AI, environment, and native work One host factory with api Private host roles

One package can provide one or more tiers. The loader stages each factory and commits registrations as one atomic plugin unit. A failed candidate does not affect the active generation.

Required, optional, and watched edges define service dependencies:

Edge Activation rule Provider change
required The consumer needs the provider before activation Restart required dependents in graph order
optional The consumer can work without the provider Stay live and observe availability
watched The consumer needs provider changes but not provider startup Stay live and observe the new generation

On a winner change, the new provider becomes ready before cutover. Old calls drain to a deadline. Surfaces remount. Required dependents restart with fresh handles. Optional and watched consumers stay live.

First-party roster

The kernel is not a plugin. Seventeen core plugins ship on the ordinary path.

Unit ID Owns
Kernel (none) Boot, loader, manifest + contract.json, claim/winner registry, arbitration, safe mode, error surfaces, install/rollback, bb plugin CLI core verbs, marketplace install sources, artifact verification, host daemon runtime and host-role transport, and the ports: bb.storage, bb.secrets, bb.realtime, bb.http, bb.rpc, bb.plugins (introspection), diagnostics/cost attribution.
Layout bb.layout The app shell. Claims bb.app.root. Declares bb.layout.sidebar (single), bb.layout.main (single), bb.layout.statusbar (list), bb.layout.panels (list), bb.layout.modals (list). Owns themes (bb.layout.theme, keyed) and shell chrome.
Threads (data) bb.threads The headless thread domain. Service bb.threads owns records, execution, timeline data, thread events, subscriptions, drafts, and selection. It declares no surfaces. Its data model has no presentation assumptions.
Thread UI bb.thread-ui The thread presentation. It consumes bb.threads. Surfaces: bb.thread-ui.list (single), bb.thread-ui.view (single), bb.thread-ui.composer (single), bb.thread-ui.composer.actions (list), bb.thread-ui.composer.send (chain), and bb.thread-ui.timeline.item (keyed by item type). The default view declares the bb.thread-ui.sidePanels child surface. It exports ThreadChat, Composer, Markdown, and timeline components.
Workspace (data) bb.workspace Headless service bb.workspace owns projects, environments, and routing. It declares bb.workspace.envProvider as a keyed environment provider contract. It declares no surfaces.
Workspace UI bb.workspace-ui The project switcher and environment pages. It requires the bb.workspace service.
Files (data) bb.files Headless service bb.files provides read, write, watch, and upload operations. It declares no surfaces.
Files UI bb.files-ui Surfaces: bb.files-ui.opener (keyed), bb.files-ui.source (single), bb.files-ui.diff (single), and bb.files-ui.preview (keyed by extension). It requires the bb.files service.
Version control (domain) bb.vcs Headless service bb.vcs provides generic status, changed files, commits, heads, history, and diff data. It declares bb.git as its default provider.
Version control UI bb.vcs-ui The commit button, changes panel, head indicator, and history views. It requires bb.vcs and uses bb.files-ui.diff.
Git (default provider) bb.git The default bb.vcs provider. It claims bb.vcs through a private Git host role. It also exports bb.git.staging, bb.git.worktrees, and bb.git.stash.
Providers bb.providers Provider registry service. Provider contract (bb.providers.provider, keyed by provider ID, replaceable). The whole provider bridge protocol (requests, notifications, deltas, items, interactions, maintenance, recovery) as its contract surface. Provider host machinery as declared host roles. Usage, health, maintenance.
Agents bb.agents Agent tools (bb.agents.tool, keyed by tool name, replaceable). AI services (bb.agents.ai, keyed by service ID, replaceable). Skills. Agent configuration. Tool-call interception (bb.agents.toolCalls, chain).
Commands (data) bb.commands Headless app command registry, keybindings, and command interception chain. It declares bb.commands.cli as a keyed plugin CLI verb contract. The kernel keeps core verbs. It declares no surfaces.
Palette bb.commands-ui The single, replaceable command palette surface. It requires the bb.commands service.
Settings bb.settings Presentation-only settings UI pages, settings schema rendering, and secrets UI. The kernel port bb.preferences owns the preferences service.
Mentions bb.mentions Headless mention provider contract, search service, and resolve service. The default bb.thread-ui.composer implementation declares the mention popover child surface.
UI kit bb.ui The shared component kit. Pure module exports; no claims. Buttons, lists, forms, markdown, virtualized lists — the current shared/core UI component surface.

The shipping provider plugins are ordinary built-in plugins. They are bb.claude-code, bb.codex, bb.pi, and bb.acp.

Each provider claims bb.providers.provider and ships its own host role and bridge artifacts. Marketplace providers claim the same contract.

The built-in github plugin requires bb.vcs. It uses optional bb.git.* edges only for Git-specific features.

How the pages divide the work

The pages use the same order as the new API. Read pages 03–14 for first-party contracts.

Page 15 contains coverage. Page 16 contains complete rebuild stories.

Page Topic Read it for
01 — Kernel Boot, loader, manifest, claims, ports, and recovery The runtime boundary that stays outside plugins
02 — Authoring Package shape, factories, api, kinds, forks, tiers, testing, and exports How to write and test a plugin
03 — bb.layout Shell, root claim, chrome, themes, and layout surfaces How the app shell becomes replaceable
04 — bb.threads Records, execution, timeline data, events, drafts, and selection The headless thread domain service
05 — bb.thread-ui Thread list, view, composer, timeline, and shared components Thread presentation and its hierarchical surface graph
06 — bb.workspace and bb.workspace-ui Projects, environments, routing, environment providers, and workspace UI The headless workspace service and its default presentation
07 — bb.files and bb.files-ui File access, openers, source, diffs, and previews The headless file service and its default presentation
08 — bb.vcs, bb.vcs-ui, and bb.git Generic version-control data, presentation, and the default Git provider The replaceable VCS contract and the two-lane provider rule
09 — bb.providers Provider registry, bridge protocol, host roles, and health Provider replacement and recovery
10 — bb.agents Tools, AI services, skills, configuration, and tool-call chains Agent capability contracts
11 — bb.commands and bb.commands-ui Commands, palette, keybindings, CLI verbs, and chains The headless command service and its default palette
12 — bb.settings Settings pages, preferences, schemas, and secrets UI User configuration contracts
13 — bb.mentions Mention providers, search, resolve, and composer use Mention integration
14 — bb.ui Buttons, lists, forms, markdown, and virtualized lists Shared exact implementations with no claims
15 — Coverage The generated old-to-new matrix Every inventory item and its destination
16 — Plugin rebuilds Twenty-two shipping plugin rebuild stories The practical effect on existing plugins