bro

What's New

Human-readable release notes β€” what each bro release lets you do, grouped by capability.

Release notes for people, not for git log. Every release gets one section β€” what you can now do, grouped by capability, plus whatever upgrading actually asks of you. The canonical ledger stays in CHANGELOG.md; this page is its narrative twin.

0.3.0 β€” the rig wakes up (upcoming)

Not yet on npm β€” this section tracks the upcoming release. Latest published is 0.2.5.

Watch a worker think

A running agent used to read as "frozen, then β€” everything at once." The wire always streamed; nothing surfaced it. Now it does:

  • bro fleet agents log <ref> --follow (flat alias bro agents log --follow) β€” a live tail of any managed agent's recorded log, by agent id or molecule step. Janitor truncation and respawn-reopen are announced on stderr, never silently skipped; stdout carries log bytes only, so it pipes clean.
  • The same tail over HTTP: GET /api/v1/agents/<ref>/log?follow on bro fleet serve β€” server-sent events, gated by the serve bearer token (agent logs can carry secrets; loopback alone is not the auth boundary).
  • Underneath, a generic seam: ACP onUpdate notifications are now a streaming surface providers can ride β€” chat/call stream where the backend supports it, and the acp conductor keeps one session per client conversation instead of respawning per turn.

bro fleet serve grew a catalog

The HTTP facade stopped being a pile of hand-written routes:

  • GET /api/v1/planes β€” the plane index: every registered plane with declared reads, verbs, and live capabilities. Reads (/api/v1/planes/<plane>, /<plane>/<read|ref>) and verbs (POST /api/v1/planes/<plane>/<verb>) are generated from the same descriptors the MCP server consumes β€” REST and MCP can never disagree about what a plane exposes.
  • GET /ui β€” a dashboard generated from that index: one panel per plane, live capability badges, degraded planes dim instead of faking empty lists, and an SSE upgrade when the events plane can stream. The index is the layout contract.
  • GET /api/v1/events/stream β€” serverβ†’client SSE over the local bus with native Last-Event-ID resume; asyncapi.json ships the generated schema next to it.
  • The ACP conductor re-landed: POST /v1/messages rides devin acp β€” claude-class models through the operator's existing devin auth, no Anthropic key β€” now with image content blocks on the wire and retained sessions (see the provider plane).

One engine under the orchestration

loop, drive, and convoy each reinvented fragments of the same lifecycle. The rig engine is the single state machine they now share β€” worktree = materialized work item, replay from durable state as the resume model:

  • bro work queue <subject> β€” frame-scoped intake: rank-ordered items (ls, bump, rm) that promote to drill frames with bro work queue drill <id> β€” the queue is labels on beads, so it syncs with the store.
  • bro work drill park --wake "<predicate>" / bro work drill wake β€” a frame can suspend itself until something is true; the waiting stack (waiting) stops cluttering the active set.
  • bro fleet agents up <step> mints the worktree itself β€” enter β†’ claim β†’ spawn is one transition. No more manual git worktree add mid-flow.
  • bro rig next β€” the engine's stateless re-entry verdict (step|gate|wait|done|blocked); loop and drive re-entry now ride it instead of keeping private schedulers.

Design notes: the rig engine.

A human in the merge gate

drive.merge:auto could land agent output with zero human sign-off β€” a green exit gate meant threads, CI, reviewers, and SAST settled, never that a human approved the code. act.requireApproval: true (in bro.config) adds the sign-off: auto-merge waits for a trusted human's approving review on the PR's current head β€” the latest decision review per reviewer decides, a standing CHANGES_REQUESTED vetoes, bot approvals never count, and act.approvers narrows "trusted" to named logins so a machine account can't sign off on the agent's own output. GitLab approvals map lazily β€” probed only while the gate is on β€” and an unanswerable probe reads as not approved, never a pass. On GitLab, current-head binding rides the project's reset-approvals-on-push rule; keep drive.merge: 'never' plus branch protection as the server-side boundary either way.

The site you're reading

The docs caught up with the product: the landing rewritten around one job-to-be-done ("your agent opened a PR β€” who drives it to merge?"), a glossary β€” one line per concept β€” a generated command reference with one page per registry command so docs can't drift from the CLI, a curated design section for the load-bearing specs, and this page.

Upgrading to 0.3.0

  • Package: @theplenkov/bro is deprecated β€” install @broject/bro (npx -y @broject/bro@0). The npx pin now derives from the plugin's own major, so it can't lag a release again.
  • Commands: nothing was removed. Grouped spellings (bro <group> <member>) are canonical; flat spellings still dispatch. The flatDeprecated knob shipped β€” a flagged flat name warns once and points at its grouped form β€” and no built-in name is flagged yet. Retirement, when it comes, is per-name, never in bulk.
  • Config: act.requireApproval defaults off β€” opt in for human sign-off on auto-merge.
  • Also in the ledger: bro fleet status surfaces stale-checkout drift (a sync row when you're behind upstream); worktree removal refuses while processes are rooted in it; drive enumerates remote-only fleet branches as PR candidates; a devin session plane rides a read-mostly connector; the claude-plugin dogfood scenario joined the self-test runbook. Fixes, test work, and CI bumps stay in CHANGELOG.md.

On this page