Repository navigation
Fleet Panel: setup wizard + fleet lifecycle (create/add/remove/dismantle) #354
Copy link
Copy link
Closed
Labels
enhancementNew feature or requestNew feature or requesthitlNeeds human review before mergeNeeds human review before merge
Description
Important
Approach
Implement the fully automated setup wizard and fleet lifecycle management. The wizard
SSHs into the target machine, validates connectivity, configures both machines
(fleet.json, guard, tunnel, canonical server), and validates end-to-end. Post-setup,
the panel supports adding machines, removing machines, dismantling the fleet, and
reconfiguring the canonical server's coordinates.
Acceptance Criteria
Create Fleet
- "Create Fleet" button visible when standalone; launches the wizard
- Topology choice: "This machine is the server" or "A remote machine is the server"
- SSH target input: text input for SSH alias or
user@host; validates connectivity
with a test command (ssh <target> echo ok) - Pre-flight checklist (rendered live, step by step):
- SSH reachable (green check or red X with error)
- Opencode binary present on remote (if missing: offer to SCP it)
- Target port available on remote (
lsofcheck)
- Remote configuration (over SSH):
- Writes
~/.amico/ops/fleet/fleet.jsonwithrole: "server" - Installs guard script to
~/.local/bin/ - Starts canonical server as launchd service (macOS) or systemd (Linux)
- Generates fleet token, stores at 0600
- Writes
- Local configuration:
- Writes
fleet.jsonwithrole: "client"+ canonical coordinates - Installs guard + tunnel plist
- Stores fleet token locally
- Writes
- End-to-end validation: tunnel connects, health probe passes, topology graph
updates to show two nodes with solid connection line - Failure handling: any step failure shows specific error + suggested fix; wizard
does not proceed past a failed step; user can retry or cancel
Add Machine
- "Add Machine" button in topology section (visible when fleet exists)
- Same SSH validation + pre-flight as Create, but skips server setup
- Configures new machine as client; node appears in graph on success
Remove Machine
- Node popover → "Remove from Fleet" action
- SSHs into target, writes
{"role": "standalone"}to fleet.json, unloads
tunnel/guard; node disappears from graph - Cannot remove the server node (shows explanation: dismantle instead)
Dismantle Fleet
- Offered when removing the last client, or via overflow menu
- Stops canonical server on remote, reverts all machines to standalone
- Removes
canonicalfrom fleet.json (not just sets role to standalone) — this is
what distinguishes "dismantled" from "disconnected" - Topology graph returns to single-node standalone state with "Create Fleet" button
Reconnect Fleet
- When fleet.json has
role: "standalone"BUTcanonicalcoordinates are present
(user went standalone but the fleet still exists), panel shows "Reconnect Fleet"
button instead of "Create Fleet" - One click: validates SSH/tunnel connectivity to the stored canonical, switches role
back toclient, reinstalls tunnel, validates end-to-end - If validation fails: shows error with option to retry or dismantle (remove canonical)
Reconfigure
- Edit canonical coordinates (host, port, SSH alias) from the panel
- Validates new connection before committing the change
- Updates fleet.json on both machines; restarts tunnel
Testing Decisions
- Unit test:
fleet_wizard.test.ts— mock SSH execution (child_process.spawn), verify
correct command sequences for each flow (create, add, remove, dismantle) - Unit test: pre-flight check logic — given SSH success/failure, binary present/absent,
port available/taken → correct checklist state - Integration test: full wizard flow with mocked SSH → fleet.json written correctly on
both sides, topology message emitted to webview - Manual verification (HITL): test against a real remote machine before merge
Key Decisions
| Decision | Rationale |
|---|---|
SSH via child_process.spawn("ssh", [...]) |
No external SSH library; Node.js native, works with user's existing SSH config/keys |
| Key-based auth only (no password prompt) | Extension context cannot do interactive TTY auth; key auth is the only reliable path |
| Wizard is idempotent | Re-running on an already-configured machine checks state, skips done steps, validates final state |
| One fleet at a time | fleet.json declares a single canonical; reconfigure to change, dismantle to start fresh |
Constraints & Invariants
- Server survives client disconnect: the canonical server is a system service
(launchd/systemd) with NO dependency on any client or editor being connected. Sessions
and solves continue running when all clients close. Zero connected clients is normal. - SSH commands MUST use the user's SSH config (
-F ~/.ssh/configor default) — never
bypass their key/host setup - Wizard MUST NOT store SSH passwords or private keys — it uses whatever auth the user
has configured - Fleet token generated with
crypto.randomBytes(32).toString("hex"); stored at 0600 - All remote file writes use atomic tmp+mv pattern (same as fleet_registry.ts)
Additional Acceptance Criteria: Server Independence
- Canonical server installed as a system service (launchd on macOS, systemd on
Linux) — NOT as a child process of any VS Code instance or editor session - Sessions and solves launched on the server continue running when ALL clients
disconnect (close laptop, quit VS Code, lose network) - On client reconnect, the panel/dropdown reflect the current state of sessions that
ran while disconnected (completed solves show results, running sessions show progress) - The server process has NO dependency on any client being connected — zero clients
connected is a normal operating state
Source
Part of #350
Blocked by #352, #353
ADR 0007: docs/adr/0007-fleet-panel-and-profile-ui.md
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requesthitlNeeds human review before mergeNeeds human review before merge
Activity
feat(fleet-panel): setup wizard + fleet lifecycle (#354)
feat(fleet-panel): setup wizard + fleet lifecycle (#354)
aarontrowbridge commentedon Aug 27, 2026
Hygiene note 2026-08-27: Related to #363 (skill-guided replacement). Keep this as the current wizard spec; close as superseded if #363 is adopted, or absorb #363's design if iterating on this wizard.
jeonghun-jj-lee commentedon Sep 12, 2026
Closing — the Fleet Panel UI series was never built. Fleet is currently ops-managed through the fleet skill and CLI tooling. The Fleet thin client PRD (#792) supersedes this approach. Re-file UI issues under the new architecture if a Fleet Panel resurfaces.