Repository navigation
Multi-machine v1: pick the machine a task runs on - #624
Merged
Merged
Conversation
Product plan and UI mockups for multi-daemon support: machine picker in the environment picker, machine-independent projects, guided setup, Machines settings pane, pairing over LAN and bb connect, skill sync design. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add the independent multiMachine experiment across domain, database, server, app, and CLI fallback surfaces. - Restore experiment-gated explicit host routing while preserving primary-host default resolution. - Restore multi-host routing coverage and generate the Drizzle migration.
Composer environment picker (multiMachine experiment, >1 host):
- Menu groups options per machine: status dot, name, "this machine"
badge, per-host Work locally / Work in checkout + New worktree rows
encoded with that machine's host id, checkout-path hints.
- Machines without a project source render a disabled "Not set up for
this project" row (guided setup lands in S7).
- Offline machines stay visible with options disabled and a relative
"last seen" in the section header.
- Trigger chip names the machine when the selection isn't the primary
host ("Mac Studio · New worktree").
Selection survival: resolveRootComposeEffectiveEnvironmentValue no
longer force-rewrites the host id to the primary host when the
experiment is on and the selected host still exists with a source for
the project; unknown/destroyed hosts fall back to primary as before.
ConnectedThreadModeBranch feeds the picker the selected machine instead
of always the primary host.
Machine surfacing elsewhere:
- ReuseThreadOption rows carry a right-aligned machine hint (>1 host).
- EnvironmentDisplayHostContext gains a nullable identity
{name, connected}; ThreadMetadataContent's environment row names the
machine and its connection state.
- Follow-up composer chip prefixes the machine name for non-primary
hosts; the thread host-disconnected notice names the machine.
Also fixes pre-existing S5 typecheck fallout: test/story project
fixtures missing the new gitRemoteUrl field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
buildProjectSourceFromOptions always builds a local_path source; narrow its return type so project create keeps compiling against the S5 source union. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ProjectMachineSetupDialog (multi-machine plan §4.2, Mockup B): a one-time
"Set up <project> on <machine>" flow reached from the environment picker.
Machines without a project source now render an enabled "Set up on
<machine>…" row when their daemon is connected (offline machines keep the
disabled "Not set up for this project" row).
Dialog behavior:
- Git-anchored projects default to "Clone from the project remote",
showing the remote URL and the daemon's default destination (new
GET /hosts/:id/clone-default-path helper + query) with an inline
"change" edit. Non-git projects see only the existing-folder option,
without radio chrome.
- "Use an existing folder" reuses RemotePathBrowser and re-validates the
picked folder via /hosts/:id/paths/exist before submitting.
- Submit posts to POST /projects/:id/sources ({type:"clone"} or
{type:"local_path"}) through a new useAddProjectSource mutation with
the global error toast suppressed: clone failures (git stderr,
target_not_empty with a "pick another path / use the folder option"
hint) render inline with retry. While a clone runs the form is
disabled, shows "Cloning onto <machine>…", and the dialog refuses to
dismiss.
- Success invalidates project-source-dependent queries and moves the
composer selection onto the machine in worktree mode; the existing
non-git downgrade effect falls back to local work when needed.
Project Settings' add-source flow is left on its local-host picker; S8
covers that surface.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Settings → Machines (Mockup C): live host list with status dot, 'this machine' badge on the primary host, platform + project-count meta line, and a ⋯ menu with rename (small dialog → PATCH /hosts/:id) and remove (confirm dialog → DELETE /hosts/:id, disabled client-side for the primary; server errors render inline). Nav entry and section are gated on the multiMachine experiment. - Add-a-machine dialog (Mockup D): mints a join code on open, shows the copyable install one-liner with an expiry countdown and re-mint, and flips the waiting row to '<name> connected' live by diffing the host list against the set captured at open time. - Project Settings → Sources (Mockup E): rows show their machine (status dot + name, offline label); with >1 host the add flow becomes an 'Add on a machine' menu — the local host keeps the native picker, other machines open ProjectMachineSetupDialog. - Extract MachineStatusDot as the shared machine-status presentation (environment picker, settings pane, source rows). - Add createHostJoinCode/updateHost/deleteHost API client functions, host rename/remove mutations, and invalidateHostListQueries cache effect. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
project.clone's optional targetPath joins the intentional-optional allowlist (omission means the daemon derives the default checkout path). Rebuild the plugin-sdk bundled types and regenerate the templates that embed them after the S5 source-union change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Minting a join code pre-created a pending-<id> host row, so every open of the Add-machine dialog (and any unredeemed code) left an offline phantom in the Machines pane, and stray rows could break single-host primary fallback. Mint now only issues the key; the host row is created at enroll with the daemon-reported name, so the mint-time hostName field is gone from the join-codes contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When composing without a project (multiMachine experiment, >1 host), the environment slot now shows a machine chip that picks which machine's personal workspace the thread runs in. The effective-value resolver keeps a known-host selection for projectless threads (normalized to local mode, no project source required) and still falls back to the primary host for stale or unknown selections. Selection persists via the existing personal-project-scoped environment preference; experiment off or single host keeps today's chip-less UI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Squash the branch's three drizzle migrations (multi_machine experiment, projects.git_remote_url, hosts.last_rejected_protocol_version) into a single generated 0064 before review. Dev data dirs that applied the interim migrations need a reset. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
toHostDaemonProcessEnv serialized a boolean config field straight into ProcessEnv; env values are strings, so booleans now serialize to the form parseBooleanEnvValue accepts. The bb-app artifact service trusted NODE_ENV to pick its package layout, which broke when CI's integration harness ran repo sources under a production env (resolved apps/ as the package root); it now probes both layouts and validates each candidate's package.json, and the detected layout also picks the build strategy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- /system/config now carries the server-resolved primaryHostId (null only on a fresh server with no enrolled host); selectPrimaryHost consumes it and keeps the connected-first heuristic only as a null fallback - Add-machine pairing command targets the connect serverUrl when a machine code is present; browser origin only for the direct/LAN variant - Root compose provider-CLI status, update action, and submit blocking key off the effective selected host instead of always the primary - Project source rows show machine chrome only with >1 host (same gate as the pickers) - bb machine list checks the server's Multi-machine experiment and errors when it is off (same for --json) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SawyerHood
force-pushed
the
bb/multi-daemon-setup-support-thr_tqsxqmfdmz
branch
from
July 12, 2026 02:32
51ccd80 to
69adac6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
bb becomes honestly multi-machine: the server orchestrates daemons on any number of computers, gated behind a new Multi-machine experiment (independent of bb connect). Product plan + mockups + status:
plans/multi-machine-v1.html.curl -fsSL <server>/install.sh | sh -s -- --join-code … --host-id … --server …— installs bb-app, joins, registers launchd/systemd service. Works over LAN or through bb connect (daemonx-bb-connect-machinecredential wiring, gate/api/v1machine access, defense-in-depth preserved)./install/bb-app.tgz); installs prefer it over npm (unpublished versions work by construction) and daemons self-update on protocol mismatch (newer-server-only, rate-limited, downgrade-refusing) with a "Needs update" state in the UI.AGENTS.md+ project skills read via daemon RPC — fixes the silent instruction/skill loss that sank the earlier multi-host attempt (bb connect: multi-host execution, cloud tunnel, getbb.app site + prod staging #510/Remove multi-host execution; rename experiment to bb connect #536).bb machine list,--machineonthread spawn/project source add(+ clone variant), guide/skill/docs updated.Also fixes two pre-existing bugs found along the way: enroll keys lived ~10.4 days instead of 15 minutes (better-auth
defaultExpiresInis seconds), and join-code minting left phantom "pending" host rows.Verification
Every step was live-verified on a two-daemon rig (second daemon with fresh identity/data dir) including browser QA of the picker, guided setup (success +
target_not_emptyerror paths), Machines pane, add-machine dialog, and a projectless thread on the second machine. Capstone: one CLI command provisioned a managed worktree on the second machine and the agent answered from planted workspace instructions. Full repo typecheck green; all package suites green. The bb connect machine path is covered by a full workerd auth-matrix (cross-tenant 403s, header stripping, revocation) — a real staging tunnel run remains (needs staging gate/web deploys).Migrations are consolidated into a single generated
0064(dev data dirs that applied interim migrations need a reset).🤖 Generated with Claude Code