bb-plugin-boat
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Gecti
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Run bb (getbb.app) threads on Boat (boat.dev) sandboxes: a bb machine-provider plugin. Experimental.
bb-plugin-boat
Run bb threads on Boat sandboxes. Each new
thread can get its own fresh cloud box, forked from a base box you prepared once, with your
agents, credentials and repos ready. bb on your own machine stays the hub; the boxes are
disposable runners.
Status: experimental, v0.1. An earlier hub completed the end-to-end lifecycle, and
the 2026-10-09 Amp-orb hub acceptance test passed in full (create → conversion →
enrollment → real LLM thread with an independently verified result → suspend/resume
with the same identity → removal), after an earlier same-day run failed. Two known
issues remain open (a conversion boot-publication race and an idle-suspend-after-resume
bug); see the acceptance record and
base box contract. Manual enrollment and mocked tests do not by
themselves establish that the automatic path works.
What it does
- Machine provider
boat:bb machine create --provider boatforks the base box,
converts the fork into a bb runner, and enrolls it as a bb machine. Suspend, resume and
remove map to Boat stop, resume and delete. - "Boat sandbox" in the New Thread picker: two environment options,
Boat sandbox (Git worktree) and Boat sandbox (project checkout). Each creates a
new box for that thread. - Project runners: define projects (a name plus a set of GitHub repos) on the Boat page.
Pick one when creating a thread or machine and its repos are cloned on the box and
registered as bb project sources. - Boat page in bb's sidebar: every box on the account with state, auto-stop, health and
its bb machine; resume, stop, fork (plain or as a bb runner), set TTL, save snapshot and
delete, each confirmed first. Plus the Projects editor with a GitHub repo picker. - Lifecycle: suspends idle machines, and extends or suspends before Boat's auto-stop
(TTL) so work isn't cut off.
How it fits together:
your machine (bb hub) ──── Tailscale ──── Boat box (runner, forked from your base box)
bb server :38886 bb host daemon ← installed by bb at enrollment
Tailscale Serve :443 (tailnet only) claude / codex / pi … run the thread here
this plugin → Boat REST API repos in ~/workspace/repos/<name>
The model, files and commands for a thread all live on the box. The hub sends prompts and
shows output.
Requirements
- bb ≥ 0.45 (plugin SDK 0.6.15).
- A Boat account with an API key, ideally scoped to a team wallet.
- Tailscale on the hub and on the boxes. The hub's bb server is published to the tailnet
only (Tailscale Serve), and boxes may reach only that port. See
BOX-CONTRACT.md for the policy. - A base box that meets the contract: Tailscale joining per box,
agent CLIs with credentials in Boat's box environment, passwordless sudo, and a complete
npm installation. The plugin does not repair npm missing files after a restore.
Install
On the hub:
# 1. Set BB_APP_URL in the bb service to this same HTTPS origin, then restart bb.
# Use your actual bb HTTP port in place of 38886 if it differs.
tailscale serve --bg --https=443 http://127.0.0.1:38886
bb settings general machineServerUrl 'https://<hub>.<tailnet>.ts.net'
bb settings general defaultMachineAccess direct
# 2. Install the plugin (pin a tag).
bb plugin install git:github.com/WyrdWerk/[email protected]
# 3. Enter the Boat API key manually in bb's plugin settings. Do not put it in argv.
# Configure the non-secret settings here or in the UI.
bb plugin config boat set org "<boat org id or name>"
bb plugin config boat set source fork
bb plugin config boat set from bx_xxxxxxxx # your base box
bb plugin config boat set githubOwners '<you>,<your-org>' # optional: repo picker
For bb 0.45, BB_APP_URL, machineServerUrl and Tailscale Serve must agree on the
current origin. A reachable TLS endpoint can still return 403 forbidden_host if they
disagree. During a temporary tailnet test the Portal hostname may therefore be rejected.
Restore the original service environment and machine URL at the end, restart only the
bb service, reset temporary Serve bindings, and disconnect the temporary node. Do not
leave service startup dependent on an on-demand Tailscale connection.
The apiKey setting is hidden from frontend read-back. In bb 0.45 it is stored as plaintext
in a private, mode-0600 hub file; “secret” does not mean encrypted on disk. Keep it out
of screenshots, logs, command arguments and Git.
Then, in bb: New thread → pick a project with a Git remote → environment
"Boat sandbox", or:
bb machine create --provider boat --key '<unique-test-key>' --no-wait --json
# Wait for the returned machine to connect, then use that machine, not another fork.
bb thread spawn --project '<project-id>' --machine '<machine-id>' \
--new-environment worktree --provider '<provider>' --model '<model>' --prompt "…"
Settings
| Key | Default | Meaning |
|---|---|---|
apiKey |
— | Boat API key (secret, never sent to the frontend) |
org |
— | Boat org new boxes bill to |
source |
fork |
fork a box, or create from a named snapshot |
from |
— | Base box id (fork) or snapshot name |
type |
default |
Box size |
ttlHours |
4 | Boat auto-stop set on create/resume |
idleMinutes |
15 | Suspend idle machines (0 = never) |
preTtlMarginMinutes |
15 | Act this long before auto-stop |
githubOwners |
— | Owners the repo picker lists (gh repo list on the hub) |
createMissingProjects |
off | Create bb projects for cloned repos that match none |
renameProbeOk |
6 | Disk-settled gate: renames in a row before enrolling |
renameProbeTimeoutMinutes |
20 | Give up on the gate after this long |
waitForAgentUpdates |
off | Wait for the base's agent-update marker before enrolling |
Live acceptance status
Full acceptance passed on 2026-10-09 (second attempt, thread
T-01a12020): on a fresh Amp-orb bb 0.45 hub with the stock v0.1 plugin, one
provider-owned fork completed the entire flow — automatic create →
conversion → enrollment, a real LLM thread whose box-only fixture result
matched an independently computed answer, provider suspend, two resumes
that each reconnected with the same identity, more real LLM work after
resume, thread-environment cleanup, and provider removal (machine record
and Boat box both gone). Mid-test the orb's 3 GiB workload slice
OOM-killed bb and the on-demand Tailscale daemon; after a fresh
human-approved Tailscale connect and a Serve republish the runner
reconnected automatically with the same identity.
| Path | Observed result (pass run) | Notes |
|---|---|---|
| Automatic fork → conversion → enrollment | Passed | runner-conversion=ok bb-app=inactive/disabled port38886=free serve=off runner-ensure=ok |
| Real remote LLM thread and independently checked result | Passed | claude-sonnet-5-5 in a worktree of a remote Git clone; fixture answer matched independently computed values |
| Plugin suspend → resume → reconnect | Passed | Two resumes, same identity each time |
| More work after resume | Passed | Second thread (haiku) read persisted state and computed a new verified result |
| Provider removal after environment cleanup | Passed | Machine record and box gone (Box API 404) |
Known issues confirmed by the pass run
bb-server-still-on-tailnetis a boot-publication race. Settle waits
only fortailscale-rejoin;pi-boot-init(which callsbb-ensure.sh→tailscale serve --https=443 → 127.0.0.1:38886) can still be running.chmod -xand thesed -imarker guard cannot stop an already-runningbb-ensure.shinstance (bash keeps executing the old inode). If it
publishes between the conversion'sserve off/resetand its verify, the
check fails. Fixed in code (pending a live re-test): settle now also
waits, bounded by its timeout, forpi-boot-initto finish and for nobb-ensure.shprocess to be running (conversionRacePendinginsrc/policy.ts), and the unpublish retriesserve off/resetuntilservedis false (unpublishServeScriptinsrc/conversion.ts).- Lifecycle bug: idle suspend fires immediately after resume.
resume()
never reset the storedlastActive, so the idle sweep suspended a freshly
resumed idle machine 25 s after resume completed. Fixed in code (pending a
live re-test):resume()now resets the host's idle clock when it
completes (markActive, wired to the same storage key the sweep reads). - The earlier
502 box_direct_failed: The socket connection was closed unexpectedlydid not reproduce across one create, two suspends and
two resumes; the cause remains unknown (Boat-side, intermittent). The
fail-fast on non-restoring 502s remains correct — a closed socket does
not prove the command never ran.
The first same-day run (five owned forks) failed as recorded in the
project's Sandbox Experiments log; its evidence led to the npm/contract
documentation. The separate manual enrollment/remote-command/reconnect test
passed earlier and does not, by itself, validate automatic conversion.
For a complete acceptance run, use one owned runner at a time and:
- Verify the base's npm installation and wait for any active agent updater before an
installer. On the tested base it runs global npm updates for about ten minutes after
every resume. See npm checks and repair. - Configure matching hub origins and runner-to-hub TCP 443 only. Confirm
/healthfrom
the runner with normal TLS verification before treating enrollment as ready. - Create through the Boat provider, not manual enrollment. Record the machine id,
box id and a unique creation key; wait for a connected daemon and an active machine. - Check the runner's actual provider/model catalog (
bb provider models <provider> --machine <machine> --json). Run a real thread against a remote Git project with a
small asymmetric fixture. Check the exact output against an independently calculated
result; a connected badge or a created thread row is insufficient. - Stop and resume through the plugin, verify the same box and machine reconnect, and run
another command on that runner. Then remove it through the plugin and verify both the
Boat box and bb machine are gone, including the thread's environment cleanup. - Clean up once at the end. Verify no owned runner remains, restore temporary hub
settings/service overrides, reset temporary Serve bindings and disconnect Tailscale.
Preserve unrelated boxes and the owner-entered key.
Known issues
- Restored npm can be incomplete.
MODULE_NOT_FOUND node-gyp/bin/node-gyp.json the
tested Node 24.19.0 image was caused by missing files in npm itself. Repair the global
npm installation, not an isolated copy or an unrelated npm dependency. - Conversion can leave the standalone bb publication visible. The test saw
bb-server-still-on-tailneteven after the standalone server stopped. A later identical
Serve reset succeeded; concurrent boot publication is suspected but unproven. - Boat direct-command 502 has an ambiguous outcome. A command may have executed before
its response was lost. Inspect the same box/machine and logs before retrying a command
or creating another fork. Do not blindly replay side effects. - Temporary hub networking needs careful lifecycle handling. Repeated certificates
for one hostname can hit ACME rate limits; creating more boxes does not solve that.
After an approved node rename, wait for its current DNS name before resetting and
reapplying Serve. On Amp, restart the named bb service rather than all services during
an on-demand Tailscale lease. - The enrolled test exhausted the orb workload memory limit. It ran bb alongside
several Amp plugin runtimes. A killed hub cannot validate reconnect; this observation
does not establish that bb alone needs more memory. - Slow first start: ~6 min from "new thread" to a running agent on our setup. Most of
it is the disk-settled gate: Boat restores a fork's disk lazily, and until it settles bb
can't install its skills (renames fail with EIO). Reusing an existing runner machine for
the next thread avoids it. A warm pool of pre-forked runners is the planned fix. - The thread's bb project must have a Git remote for Boat sandbox environments (a bb
rule: "requires a project with a Git remote"). - Repos cloned by a project runner only become bb sources if a bb project with the same
remote exists (orcreateMissingProjectsis on). - The per-repo
branchfield in Projects is stored but not yet used when cloning. - Paths on the box (
/run/ascii-secrets/…, useruser) and the optional boot unit names
are fixed in code, not settings. - Settings → Machines → "Add a machine" only offers manual enrollment in bb 0.45; use the
New Thread picker, the Boat page's "Fork as bb runner", or the CLI. - Two bb bugs affect remote machines and are worked around here:
#4158 (an interrupted environment hook blocks
cleanup forever) and #4855 (a broken skill
store fails every thread start). See docs/UPSTREAM-BB-BUGS.md. - Tested only with Tailscale for connectivity; bb Connect was not tried.
Development
npm install
npm test # node --test; no Boat calls (fakes + the SDK's fake plugin host)
npm run typecheck
bb plugin build # dist/server.js + dist/app.js
npm run gen # after editing runner/*.sh (re-embeds them; a test checks drift)
| Path | Role |
|---|---|
server.ts |
Plugin entry: settings, provider + compositions, lifecycle schedule |
src/boat-api.ts |
Boat REST client (drops secret box fields at parse time) |
src/provider.ts |
create / suspend / resume / remove / cleanup |
src/conversion.ts |
Turns a fresh fork into a runner (root, idempotent, verified) |
src/policy.ts, fsgate.ts, hubgate.ts, boxprep.ts, envguard.ts |
Gates and box prep before enrollment |
src/lifecycle.ts |
Idle and pre-TTL sweep |
src/dashboard.ts, ui/, app.tsx |
Boat page (server RPCs + React UI) |
src/projects.ts, project-store.ts, github-repos.ts |
Project runners and the repo picker |
runner/ |
Scripts installed on each runner; runner/reference/ is an example repo sync |
components/, lib/, hooks/ |
UI components vendored from bb's plugin scaffold (MIT) |
docs/DESIGN.md |
Design notes and the evidence log from building it |
License
MIT. See LICENSE. Vendored bb components: see NOTICE.
Not affiliated with bb or Boat.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi