1.0 archive. This section describes the previous 1.0 API. The current model is the 2.0 design.

Reference

Draft 1, 2026-08-21. Assembled from @get-bb/plugin-sdk/api.lock.json (the locked surface), the SDK README, the spec sections under next/docs/sections/, the as-built notes in next/docs/stage-2/04-kernel-as-built.md, and the reference plugin next/examples/plugins/hello-slot. Source tree: branch bb/rewrite-bb-app-from-scratch-thr_e2n9n5n7i6 at dc07292bf plus the accepted kernel delta e1efe72a3 (its direct child; next/packages only; local only). The sections were written against 6f3d4592f, updated for the dc07292bf delta listed in §0.7, and updated again for the e1efe72a3 delta listed in §0.8.

0. How to read this document

0.1 Scope

This document describes what a plugin author can import, declare, and call. It does not describe the kernel's internals. Where the spec and the built kernel differ, the built kernel wins; the "As built" column names the deviation (D1–D20, see Appendix A) or the source file.

0.2 Entry points

A plugin imports one package, @get-bb/plugin-sdk, through seven entry points. Each entry runs in one place.

Entry Runs in Section
@get-bb/plugin-sdk (root) the core process; same as /server §3
@get-bb/plugin-sdk/server the core process (in-process, or a plugin:<id> worker for marketplace installs) §3
@get-bb/plugin-sdk/app the browser, through the import map §4, §5
@get-bb/plugin-sdk/host a host-role child process on a machine §6
@get-bb/plugin-sdk/bridge the provider bridge child process; the declaration also loads in core §7
@get-bb/plugin-sdk/contracts every tier and the browser; schemas only, no runtime side effects §2
@get-bb/plugin-sdk/testing tests only §9

A plugin may also import @bb/ui (the component kit, on the import map) and other plugins' published contracts modules (@get-bb/plugin-<id>/contracts). It imports nothing else from bb.

0.3 Tiers at a glance

(The import and reducers tiers, and the build outputs per tier, are in §1.6.)

Tier Manifest key Default export Receives
server bb.server definePlugin({ activate(ctx, config), background? }) ctx: PluginContext (§3)
app bb.app definePluginApp({ setup(app, config) }) app: PluginAppApi (§4)
host bb.host defineHostEntry({ roles, signals, dispose }) RoleContext per role (§6)
contracts bb.contracts named exports built with defineService, defineEvent, … — (§2)
cli bb.cli defineOfflineHandlers({...}) — not built; the entry is spec-only (03 §5.9; Appendix B) local files only

At least one of server, app, host is required. A package with a non-empty provides must set contracts.

0.4 One definition, five surfaces

A service method is defined once with defineService/method. The kernel derives the HTTP route (/api/v1/<pluginId>/<service>/<kebab-method>), the typed SDK call, the bb CLI word, the agent tool (<plugin>_<service>_<method>), and the reference docs from that one definition (§8). Every mutation method is also a command on the bus with an actor, before interceptors, and after listeners (§3.4).

0.5 Conventions

  • Signatures are abridged: optional fields carry ?, defaults are shown as = value.
  • Spec cites are NN §x.y (section file NN-*.md). Built cites are D# or a path under next/packages/. README deviation N is the numbered entry under "Deviations from the spec" in packages/plugin-sdk/README.md; kernel-host README deviation likewise.
  • Identifiers: plugin ids match ^[a-z0-9][a-z0-9-]{0,63}$ (PLUGIN_ID_RE, §1.1); service ids are <pluginId>/<serviceName>; event names are <pluginId>/<name> (kernel events are kernel/<name>); command names are <noun>.<verb>; extension kinds are <pluginId>/<kind>; core kinds are bare snake_case (file_change, web_search).
  • No member carries an experimental_ prefix. The surface is reviewed through api.lock.json; adding or renaming an export edits that file in the same change.
  • Sentences use present tense and active voice.

0.6 Known open questions for authors

Product decisions this document does not make. Each line names the gap, the fact as built, and what is undecided.

  • engines.bb and peer["@bb/ui"] for a 1.0 plugin (§1.2): the core and @bb/ui are 0.0.0 in the tree (apps/bb-app/package.json, packages/ui/package.json) and hello-slot omits both, so the defaults * apply. The version strings a 1.0 plugin should pin are not decided.
  • Published dependency ranges (§1.5): @get-bb/plugin-sdk is 1.0.0-next.0 (packages/plugin-sdk/package.json), @bb/ui has no published version, and the example uses workspace:*. The ranges an out-of-tree plugin writes are not decided.
  • target: "host" (§2.2, D5): answers 503 service_unavailable. Which release flips D5 is not decided.
  • bb plugin new (§1.7, 01 §3.1): not in @bb/plugin-build. Whether it ships, and with which skeleton, is not decided; §1.5 has the hand-written starter.
  • ctx.hostClient in the product (§3.9, D15): resolved at dc07292bf — core passes createHostClients(...).clientFor to the loader (packages/core/src/core.ts), so a server tier reaches its rpc role. The stage-2/04 D15 note predates this commit.

0.7 Changes at dc07292bf (the Stage 2 domain integration)

  • @get-bb/plugin-sdk/server exports withDefaults(def, handlers) (§3.3).
  • contributes.commands.nouns admits dotted nouns: ^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)*$ (§1.3).
  • New kernel services: kernel/store.eventsAppend, kernel/host-runtime, kernel/bridge-driver; kernel/store gains queueGet, projectsGet, environmentsGet, attachmentsGet, threadsByEnvironment (§3.11).
  • EnvironmentProvider.provision receives source: ProjectSource | null; the role answers env/describe; EnvironmentsPort gains summarize and describe; provision progress rides env.progress notifications, not a stored event (§6.5).
  • HostView.homeDir: string | null on kernel/hosts.list|get (§3.11).
  • ctx.hostClient is wired in core (§3.9; supersedes D15).
  • CLI: a variadic positional of structured items keeps a non-JSON word as a string (§8.4); bb plugin install <source> has its positional (closes D9's gap).
  • A uses re-run is one observable step: teardown and re-activation in one registry batch; a handle follows a same-generation re-provide instead of stale_handle (§3.3).

0.8 Changes at e1efe72a3 (the Stage 2 UI workstream requests)

Every plugin-visible change in the delta, one line each. Source: git show e1efe72a3 -- next/packages; api.lock.json gains 26 entries (17 distinct names) and drops none. "Before" means dc07292bf.

  • @get-bb/plugin-sdk/contracts (re-listed on /server) exports kernel-store's row schemas rowSchema, storedEventSchema, threadHeadSchema, threadRowSchema, threadListItemSchema, interactionRowSchema and the types Row, StoredEvent, ThreadHead (§2.11; plugin-sdk/src/contracts/index.ts over the new @bb/kernel-store/schemas subpath, which imports only zod and @bb/kernel-core, so the entry stays browser-safe).
  • @get-bb/plugin-sdk/server exports the types HubApi, HubCommandInput, HubCommandResult; ctx.hub.command({ target, name, input, timeoutMs }) sends a client command over the realtime hub with the plugin as actor and answers { delivered } (§3.2, §3.5, §3.13; in-process rows only).
  • @get-bb/plugin-sdk/app exports LayoutRoot and the types LayoutRootProps, DragSession (§4.5): a plugin's own root occupant can now mount the pane tree. §4.5's "not exported" sentence is withdrawn.
  • @get-bb/plugin-sdk/app exports useCommands(): ClientCommands (run(id, input?), has(id)) and the type ClientCommands (§4.6): the caller side of the client command bus.
  • RowState.exhausted: boolean is a required member: true once a page came back shorter than pageSize. A plugin apply that builds a RowState literal must set it (§4.8; kernel-ui/src/data/define-row-store.ts).
  • defineRowStore's apply(state, ops, { threadId }) gains a third argument; a two-argument apply still type-checks (§4.8).
  • A pane kind's children are slot-tree declarations while the kind's plugin wins the kind; before, a registration into a pane-kind child (thread.timeline) failed the load with slot … is not declared (§4.2, §4.5; slot-tree.ts kindReg, create-ui-kernel.ts kindLive).
  • app.contributions.json declares carries pane-kind children (owner: "pane:<kind>") and the children of registrations an inject thunk makes; the thunk runs at bb plugin build against a recorder (§4.1, §4.12). contributions_mismatch compares the whole file, so an artifact built before this delta fails to load after it, and vice versa, when it has either.
  • The slot instance key gains |<registration id>, so two list registrations of one plugin into one slot keep separate React keys, stores and crash latches (§4.3; slot-tree.ts instanceKey).
  • A bootstrap or wire preference row for a key no plugin has defined yet is parked and applied at that key's define, so the first paint shows the stored value instead of the default (§4.7; services/preferences.ts).
  • Plugin stylesheets load: core keys cssUrl on meta.digests["app.css"] (before: "dist/app.css", a key the build never writes, so cssUrl was always null and no plugin sheet ever loaded) (§4.11, §4.12; core/src/app.ts).
  • kernel-ui/dockOpenDefault defaults to false (before: true), and a new pane's dock opens only when the kind's dock.default(state).open is true and the preference is true; a pane kind whose dock opened by default now starts closed until the user flips the preference (§4.5; layout/layout-store.ts).
  • threadListItemSchema.displayStatus mirrors today's resolveThreadRuntimeState: only a running thread (active | starting | stopping) on a remote-host environment waits on a host session (host-reconnecting after a closed session, else waiting-for-host); the primary host is always connected; an idle thread is idle whatever its host does. Before, an idle thread on any environment with no session row showed waiting-for-host (§2.11; kernel-store/src/threads.ts).
  • Item rows carry payload.startedAt (the open event's time) and payload.completedAt (the close event's time; null while open); rows in a store.db written before the delta lack both until rebuilt (§2.11; kernel-store/src/reducers.ts).
  • A manifest requires id every provider of which is app-only (no server tier) is satisfied by the provider's presence in the plan and still orders the load; before, such a row sat waiting forever (§1.3; kernel-loader/src/loader/graph.ts appTierServices, load.ts).
  • Smaller: the overlay: true chain keeps the owner fallback in one stable wrapper across a takeover, so its DOM state survives (§4.3); browser back/forward reports cause: "pop" (before: replace, §4.5); a keydown during IME composition (isComposing or keyCode 229) never dispatches a chord (§4.6); dist/contracts.mjs is built without the Node ESM banner so a sibling app tier bundles it (plugin-build/src/bundle.ts); createAppHarness({ shell: { panes: true } }) mounts LayoutRoot and registers no / route (§9.3, plugin-sdk/src/testing/app.ts).

0.9 The kernel-domain tier (decision, 2026-08-26)

Three tiers, not two. The kernel is mechanism: container, store, loader, UI kernel, host runtime. The kernel domain is the set of first-class services for the concepts the kernel already hard-codes in its schema and scoping: threads (threads/*, the thread-head projection, the timeline row model, pending interactions, lifecycle events), projects (projects/*), environments (environments/*: entity, lifecycle, provision), files (files/files), terminals (terminals/sessions), and the provider framework (providers/registry|models|usage, the bridge protocol). Plugins are everything else.

Kernel-domain rules: core provides these services; they are always present and cannot be disabled; their contracts version with the SDK major, not with any plugin; a consumer injects them like kernel/* services and declares no requires edge. The extension points stay pluggable: provider drivers and environment providers are ordinary plugins behind the framework, and every rendered surface over the domain is a slot occupant. Earlier sections of this reference describe threads, projects, and environments as domain plugins — that was the rewrite's packaging; read those contract shapes as the kernel-domain surface. Rationale and migration sequencing: plan-papi-to-idealized-1.0.md; empirical motivation (36 of 82 marketplace plugins depend on these contracts): marketplace-feasibility-2026-08-26.md.