Use cases

Start from what you want to do. Each row links to the guide page that builds it. The list is generated from the guides' "Use this when" sections.

I want to… Guide
A private plugin for my team. You keep the source in your own repository and install it from a checkout or a tarball, never from npm. Getting started: a plugin from an empty directory
Try a plugin from a git checkout. Someone sent you a branch; you want it running in your bb in five minutes and gone in one. Getting started: a plugin from an empty directory
Ship a plugin to npm. You want bb plugin install npm:@acme/bb-plugin-counter to work for people who have never seen your code. Getting started: a plugin from an empty directory
Add one CLI word and one service to bb without touching bb. The counter is small on purpose; every later page grows it. Getting started: a plugin from an empty directory
Expose my data to agents and humans with one definition. One method() gives you bb ticket list, GET /api/v1/tickets/tickets/list, and sdk.plugins.tickets.tickets.list({}); the next page turns the same method into a tool. Services: one definition, every surface
Receive webhooks. A kind: "custom" method with auth: "none" is a raw HTTP endpoint under your plugin's route prefix, with the body and headers in your hands. Services: one definition, every surface
Call another plugin's service. requires in the manifest plus ctx.inject(contract, range) gives you a typed handle on threads/threads without importing its code. Services: one definition, every surface
Stream a feed. A stream method is SSE over HTTP, NDJSON on the CLI, and for await in the SDK. Services: one definition, every surface
Let agents file a ticket in my tracker. One expose flag plus a presentation; the agent gets tickets_tickets_create with a JSON Schema, a label, and an icon. Agent tools and agent configuration
Inject project rules into every agent. ctx.agents.contributeInstructions(text) appends to the system prompt of every thread, or of one project. Agent tools and agent configuration
Turn a tool off for manager threads. A resolver decides per turn which tools a thread sees; here top-level threads lose tickets_tickets_create and their child threads keep it. Agent tools and agent configuration
Ship a skill with my plugin. contributes.guide puts your prose in the generated bb skill today; contributes.skills ships a SKILL.md directory in the artifact. Agent tools and agent configuration
Block sends to a frozen thread. The project is archived, or your own policy freezes it, and the send never reaches the executor. Commands and interception
Add a footer to every prompt. A human or an agent sends a prompt; your text rides along as one more part. Commands and interception
Post to Slack when a thread goes idle. The trigger is a status transition on the thread row, not a command. Commands and interception
Auto-archive threads older than N days. A background service runs the sweep once an hour through the bus. Commands and interception
Audit every thread.create. One log line per dispatch, with the actor and the duration. Commands and interception
Keep an API token out of my code. You hold a reference; the value never passes through your logs or your database. Data and settings
Remember a per-thread preference. A sort order the user sets on one thread stays on that thread. Data and settings
Own a table with migrations. Your rows live in your own SQLite file, and the schema evolves with the plugin. Data and settings
Expose a setting to Settings and to agents. The user edits it in Settings, agents read it through the CLI, and the plugin says "I need configuration" instead of failing. Data and settings
Show a live dashboard of my rows. It updates when the CLI, an agent, or another browser changes them. Realtime
Update a badge when a thread changes status. bb's own entity events reach your component the same way. Realtime
Stream a long job's progress. Each job's frames reach the browser under the job's own key; nothing refetches a list. Realtime
Listen on the server without polling. Your own events and bb's arrive on one bus. Realtime
Add a button to the sidebar. sidebar.footer is a list slot; every occupant renders. UI slots
Replace bb's thread list. sidebar.body is a single slot, and Original keeps the stock list inside your wrapper. UI slots
Badge only the thread rows that need one. threadList.row.trailing is a list slot filtered with when. UI slots
Paint one kind of timeline row. timeline.row is a keyed slot with one winner per key. UI slots
Let other plugins extend your panel. Declare a child slot with children and they register into it. UI slots
A dashboard page with its own URL. A pane kind plus a route such as /deploy/:releaseId. Pages, panes, navigation, and commands
Open your pane next to a thread. A thread.header.actions button opens it in a new split. Pages, panes, navigation, and commands
A keyboard shortcut for your command. deploy.open bound to Mod+Shift+D by default. Pages, panes, navigation, and commands
A toast when a background job finishes. A query invalidated by the job's wire event drives useToasts. Pages, panes, navigation, and commands
Confirm before a destructive action. The shell's ui-shell/dialogs service asks the question. Pages, panes, navigation, and commands
Render your tool's result as a card. The tool-ui:<pluginId>/<renderer> rung of timeline.row. Timeline rows, interactions, and the composer
A custom row for your provider's events. The <providerId>:<kind> and <pluginId>/<kind> rungs. Timeline rows, interactions, and the composer
Ask the user a structured question. providers/interactions.request on the server plus an interaction.renderer occupant. Timeline rows, interactions, and the composer
A /deploy action in the composer. A composer.plusMenu row and a composer.actions button. Timeline rows, interactions, and the composer
A banner or a submit gate. composer.stack for a branch-behind banner, composer.submit for a gate while a release runs. Timeline rows, interactions, and the composer
Run a linter over the workspace and report. The server half calls a host command, the role spawns eslint in the workspace, and the result comes back typed. The host tier
Read a config file from the repo on demand. A service method answers bb repo config <root> .bbrc from the host that owns the directory. The host tier
Tail a log file and push lines to the server. The role emits a log-line signal per line; the server half receives it through onSignal. The host tier
Run a long job on a remote machine's host. The same command with { hostId } runs on an enrolled host; timeoutMs sets the deadline. The host tier
Run a workspace-local build tool. pnpm exec tsc in the repo's own node_modules, which only the host has. The host tier
A scratch directory per thread. A throwaway root under the role's data dir; env-local/scratch does this, and the example below adds a repo copy. Environment providers
Run threads in a container. A custom handle is the spec's answer, but as built it cannot run a thread (see What you build); mount a local-path root the container shares instead. Environment providers
An environment on a remote host. The same provider runs on any enrolled host once its artifact is ensured there; environments.provision { hostId } picks the host. Environment providers
Isolate experiments from the checkout. A copy that never touches the user's working tree, unlike local-dir. Environment providers
Add a new coding agent to bb. Any agent with a scriptable interface (a CLI, an SDK, an HTTP stream) becomes a provider users pick in the composer. Provider plugins
Override how your provider's commands render. A keyed timeline.row occupant at acme:command with Original as the fallback. Provider plugins
Report rate limits to the UI. One provider.rateLimits delta plus a provider.error { category: "rate_limit" } when a turn is refused. Provider plugins
Ask the user before the agent runs a command. A blocking interaction/request with a command subject; core auto-denies it under escalation: "deny". Provider plugins
Unit-test a handler with its real schema. Defaults filled, bad input refused, the mutation reachable as a command and as a tool. Testing
Render a slot component in isolation. The owner props the real owner would pass, and a fake server service behind useService. Testing
Guard the derived surfaces in CI. The CLI word and the agent tool derive from defineService before anyone runs bb plugin build. Testing
Prove a realtime refetch. An event on the socket refetches your defineQuery without a reload. Testing
Call a host command without a process. The machine tier's handler runs over a fake RoleContext. Testing
Customize a first-party screen. The thread list, the timeline, or the composer, without maintaining a fork of bb. Composition, forks, and distribution
Make my thread list the default. You wrote your own and want it to win sidebar.body on this machine. Composition, forks, and distribution
Ship an update with a rollback. One command updates an installed plugin; one command puts the old version back. Composition, forks, and distribution
Flip an experiment or a bundled row. Enable an experiment that ships disabled, or disable a bundled plugin. Composition, forks, and distribution
Boot a development plugin from a patch file. bb-server --patch, as the smoke does. Composition, forks, and distribution
Port custom-instructions. The smallest 0.4 plugin: one RPC, one CLI word, one instructions contribution, one settings section. Migrating from 0.4
Port keep-awake. A plugin with a host tier: a host entry with one command, a server reconciler, a settings section. Migrating from 0.4
Port a plugin with a nav panel. Decide whether to wait for the page slots or ship on a built slot today. Migrating from 0.4
Know what is deleted outright. Which 0.4 members have no successor, and what to remove from docs/api_to_audit.md. Migrating from 0.4

By guide

Getting started: a plugin from an empty directory

  • A private plugin for my team. You keep the source in your own repository and install it from a checkout or a tarball, never from npm.
  • Try a plugin from a git checkout. Someone sent you a branch; you want it running in your bb in five minutes and gone in one.
  • Ship a plugin to npm. You want bb plugin install npm:@acme/bb-plugin-counter to work for people who have never seen your code.
  • Add one CLI word and one service to bb without touching bb. The counter is small on purpose; every later page grows it.

Services: one definition, every surface

  • Expose my data to agents and humans with one definition. One method() gives you bb ticket list, GET /api/v1/tickets/tickets/list, and sdk.plugins.tickets.tickets.list({}); the next page turns the same method into a tool.
  • Receive webhooks. A kind: "custom" method with auth: "none" is a raw HTTP endpoint under your plugin's route prefix, with the body and headers in your hands.
  • Call another plugin's service. requires in the manifest plus ctx.inject(contract, range) gives you a typed handle on threads/threads without importing its code.
  • Stream a feed. A stream method is SSE over HTTP, NDJSON on the CLI, and for await in the SDK.

Agent tools and agent configuration

  • Let agents file a ticket in my tracker. One expose flag plus a presentation; the agent gets tickets_tickets_create with a JSON Schema, a label, and an icon.
  • Inject project rules into every agent. ctx.agents.contributeInstructions(text) appends to the system prompt of every thread, or of one project.
  • Turn a tool off for manager threads. A resolver decides per turn which tools a thread sees; here top-level threads lose tickets_tickets_create and their child threads keep it.
  • Ship a skill with my plugin. contributes.guide puts your prose in the generated bb skill today; contributes.skills ships a SKILL.md directory in the artifact.

Commands and interception

  • Block sends to a frozen thread. The project is archived, or your own policy freezes it, and the send never reaches the executor.
  • Add a footer to every prompt. A human or an agent sends a prompt; your text rides along as one more part.
  • Post to Slack when a thread goes idle. The trigger is a status transition on the thread row, not a command.
  • Auto-archive threads older than N days. A background service runs the sweep once an hour through the bus.
  • Audit every thread.create. One log line per dispatch, with the actor and the duration.

Data and settings

  • Keep an API token out of my code. You hold a reference; the value never passes through your logs or your database.
  • Remember a per-thread preference. A sort order the user sets on one thread stays on that thread.
  • Own a table with migrations. Your rows live in your own SQLite file, and the schema evolves with the plugin.
  • Expose a setting to Settings and to agents. The user edits it in Settings, agents read it through the CLI, and the plugin says "I need configuration" instead of failing.

Realtime

  • Show a live dashboard of my rows. It updates when the CLI, an agent, or another browser changes them.
  • Update a badge when a thread changes status. bb's own entity events reach your component the same way.
  • Stream a long job's progress. Each job's frames reach the browser under the job's own key; nothing refetches a list.
  • Listen on the server without polling. Your own events and bb's arrive on one bus.

UI slots

  • Add a button to the sidebar. sidebar.footer is a list slot; every occupant renders.
  • Replace bb's thread list. sidebar.body is a single slot, and Original keeps the stock list inside your wrapper.
  • Badge only the thread rows that need one. threadList.row.trailing is a list slot filtered with when.
  • Paint one kind of timeline row. timeline.row is a keyed slot with one winner per key.
  • Let other plugins extend your panel. Declare a child slot with children and they register into it.

Pages, panes, navigation, and commands

  • A dashboard page with its own URL. A pane kind plus a route such as /deploy/:releaseId.
  • Open your pane next to a thread. A thread.header.actions button opens it in a new split.
  • A keyboard shortcut for your command. deploy.open bound to Mod+Shift+D by default.
  • A toast when a background job finishes. A query invalidated by the job's wire event drives useToasts.
  • Confirm before a destructive action. The shell's ui-shell/dialogs service asks the question.

Timeline rows, interactions, and the composer

  • Render your tool's result as a card. The tool-ui:<pluginId>/<renderer> rung of timeline.row.
  • A custom row for your provider's events. The <providerId>:<kind> and <pluginId>/<kind> rungs.
  • Ask the user a structured question. providers/interactions.request on the server plus an interaction.renderer occupant.
  • A /deploy action in the composer. A composer.plusMenu row and a composer.actions button.
  • A banner or a submit gate. composer.stack for a branch-behind banner, composer.submit for a gate while a release runs.

The host tier

  • Run a linter over the workspace and report. The server half calls a host command, the role spawns eslint in the workspace, and the result comes back typed.
  • Read a config file from the repo on demand. A service method answers bb repo config <root> .bbrc from the host that owns the directory.
  • Tail a log file and push lines to the server. The role emits a log-line signal per line; the server half receives it through onSignal.
  • Run a long job on a remote machine's host. The same command with { hostId } runs on an enrolled host; timeoutMs sets the deadline.
  • Run a workspace-local build tool. pnpm exec tsc in the repo's own node_modules, which only the host has.

Environment providers

  • A scratch directory per thread. A throwaway root under the role's data dir; env-local/scratch does this, and the example below adds a repo copy.
  • Run threads in a container. A custom handle is the spec's answer, but as built it cannot run a thread (see What you build); mount a local-path root the container shares instead.
  • An environment on a remote host. The same provider runs on any enrolled host once its artifact is ensured there; environments.provision { hostId } picks the host.
  • Isolate experiments from the checkout. A copy that never touches the user's working tree, unlike local-dir.

Provider plugins

  • Add a new coding agent to bb. Any agent with a scriptable interface (a CLI, an SDK, an HTTP stream) becomes a provider users pick in the composer.
  • Override how your provider's commands render. A keyed timeline.row occupant at acme:command with Original as the fallback.
  • Report rate limits to the UI. One provider.rateLimits delta plus a provider.error { category: "rate_limit" } when a turn is refused.
  • Ask the user before the agent runs a command. A blocking interaction/request with a command subject; core auto-denies it under escalation: "deny".

Testing

  • Unit-test a handler with its real schema. Defaults filled, bad input refused, the mutation reachable as a command and as a tool.
  • Render a slot component in isolation. The owner props the real owner would pass, and a fake server service behind useService.
  • Guard the derived surfaces in CI. The CLI word and the agent tool derive from defineService before anyone runs bb plugin build.
  • Prove a realtime refetch. An event on the socket refetches your defineQuery without a reload.
  • Call a host command without a process. The machine tier's handler runs over a fake RoleContext.

Composition, forks, and distribution

  • Customize a first-party screen. The thread list, the timeline, or the composer, without maintaining a fork of bb.
  • Make my thread list the default. You wrote your own and want it to win sidebar.body on this machine.
  • Ship an update with a rollback. One command updates an installed plugin; one command puts the old version back.
  • Flip an experiment or a bundled row. Enable an experiment that ships disabled, or disable a bundled plugin.
  • Boot a development plugin from a patch file. bb-server --patch, as the smoke does.

Migrating from 0.4

  • Port custom-instructions. The smallest 0.4 plugin: one RPC, one CLI word, one instructions contribution, one settings section.
  • Port keep-awake. A plugin with a host tier: a host entry with one command, a server reconciler, a settings section.
  • Port a plugin with a nav panel. Decide whether to wait for the page slots or ship on a built slot today.
  • Know what is deleted outright. Which 0.4 members have no successor, and what to remove from docs/api_to_audit.md.

By tier

Tier Guides
contracts Services · Agent tools · Migrating from 0.4
server Commands and interception · Data and settings · Realtime · Agent tools
app UI slots · Pages, panes, and commands · Timeline and composer · Realtime
host The host tier · Environment providers · Provider plugins
all Getting started · Testing · Composition, forks, and distribution