name: hd-setup description: > HD setup panel: 16 install steps, Run All, Rollback All, Virgin Reset with toggles, and automated testing patterns. MUST READ before running setup, testing steps, or doing virgin resets. Covers the step list, the virgin reset toggle panel, how to keep auth during resets, and how Run All handles failures. Trigger words — setup panel, install steps, run all, virgin reset, rollback, step failed, 18 steps, wipe, reset workspace, keep auth, test setup.

Hydrogen Desktop — Setup Panel & Virgin Reset

Machine-runtime version (default). The legacy 24-step Docker cascade (HD_RUNTIME=docker) is in the docker/ bucket.

Zero-Click Goal

The HD setup process targets ZERO manual clicks for the user. The heavy lifting is already done at image-build time: the Adom-Workspace golden image ships with code-server, the 8 Adom CLIs, the claude CLI + Code extension, VS Code settings, and all hd-* skills BAKED IN. Setup just imports that image, injects the user's session, wires up the relay, and walks the single human auth gate. If something is missing, HD downloads it — never tell the user to install something manually. See the hd-golden-image skill for the baked-image model.

The 16 Install Steps

The machine cascade is executed by setup_steps_macos.rs (step_defs_machine() / run_all_machine()). run_all_machine is halt-on-failure, resume-not-restart, with per-step 3× auto-retry. State is tracked in setup-steps-macos.json (the Docker flow uses setup-steps.json). The Docker-only pull-image / create-container / start-container steps are SUBSUMED into step 1, ensure-workspace, which imports the golden image into the workspace machine via machinectl import-tar Adom-Workspace.

# ID Label Rollback?
1 ensure-workspace Ensure the Lima VM hd-builder is up (provision it if missing — no host reboot needed on macOS), import golden image, create adom user, start code-server, verify code-server reachable from the Mac on 7380
2 wait-codeserver Host TCP probe of code-server port (default 7380), 120s
3 install-adom-vscode "Activate editor extensions" — installs NOTHING (binary+extension baked); waits for Adom sign-in, reloads editor iframe, proves the :8821 editor-control API answers
4 set-env-vars ADOM_CARBON_URL / ADOM_HYDROGEN_URL / ADOM_HD_CONTROL_URL / VSCODE_PROXY_URI / ADOM_DESKTOP_MODE
5 inject-api-key Write the Adom session token to /var/run/adom/api-key (mode 644)
6 configure-vscode settings.json / trusted-domains / activity-bar are BAKED; re-assert theme + workbench backstops idempotently; apply per-session layout via :8821
7 ensure-adom-desktop Verify the Adom Desktop companion app is running on the Mac
8 start-relay Start the adom-desktop relay inside the workspace (8765/8766)
9 test-direct-connect Prove the fast container→desktop command path
10 test-relay Register the relay with Adom Desktop for file streaming
11 test-adom-cli GATE: carbon path + hydrogen-proxy reachability via adom-cli (6 retries)
12 claude-auth The single human gate; restore creds or drive in-editor Claude.ai sign-in; runs LAST before payoff
13 ensure-sse GATE: editor browser SSE session connected so Welcome's webview-open doesn't 409
14 verify-workspace GATE: battery confirming the proxy holds a real layout
15 welcome Opens Claude Code, authenticates if needed, sends the first prompt
16 open-welcome GATE (final): opens welcome.html in HD's right pane; hard-fails if the Welcome tab doesn't appear

Steps that NO LONGER EXIST (baked into the golden image)

These are NOT setup steps anymore — they are baked at image-build time and must not be listed or "run": install-hd-skills, verify-adom-desktop, install-claude-cli, install-claude-ext, write-vscode-settings, set-trusted-domains, clean-layout. The 8 Adom CLIs, the claude CLI + Code extension, code-server, settings, and all hd-* skills are baked into the adom-golden.tar.gz image. See hd-golden-image.

Panel Buttons

  • Run All — executes all pending steps sequentially. STOPS on first failure.
  • Rollback All — rolls back all completed steps in reverse order.
  • Virgin Reset ▾ — opens the toggle panel (see below).
  • Run (per-step) — runs a single step.
  • Rollback (per-step) — rolls back a single step.

CRITICAL: Run All Stops on Failure

If any step fails, Run All ABORTS (halt-on-failure in run_all_machine(), after the per-step 3× auto-retry is exhausted). Remaining steps are NOT executed. run_all_machine resumes — it does NOT restart from step 1 — so to recover after a failure: fix the issue, then either:

  • Click "Run All" again (it resumes from the first not-done step)
  • Click "Run" on the failed step to retry just that one

Virgin Reset Toggle Panel

Click "Virgin Reset ▾" to expand the wipe options. Each toggle has a live status badge showing the current state. The ONLY programmatic trigger is POST /setup/panel/run-virgin-reset (see below).

Toggle (option key) What it wipes Status badges
Install step state (install_state) Resets all 18 steps to pending (setup-steps-macos.json) CLEAN / EXISTS
Workspace machine (container) PRISTINE machinectl remove Adom-Workspace + reimport (ONLY that machine) GONE / RUNNING / EXISTS
Machine tarball (tarball, legacy image) Deletes cached adom-golden.tar.gz (full image re-download) CACHED / GONE
Webview storage (webview_storage) Queued wipe, flushed at next HD launch (restart_required) CLEAN / EXISTS
VS Code state (vscode_state) Queued wipe, flushed at next HD launch (restart_required) CLEAN / EXISTS
Adom session token (adom_token) Deletes hydrogen-session.txt CLEAN / EXISTS
Claude credentials (claude_token) Deletes the host-side Claude creds backup CLEAN / EXISTS

confirmed_destructive must be set for the reset to proceed. "Wipe Selected" at the bottom executes the reset for all checked toggles.

The machine reset is a PRISTINE machinectl remove + reimport — it backs up Claude creds first UNLESS claude_token is checked. The webview_storage / vscode_state wipes are queued and flushed at the next HD launch (restart_required), NOT immediate; there is no reboot for the wipe.

CRITICAL — the machine virgin reset only ever touches Adom-Workspace. It runs machinectl remove Adom-Workspace — NEVER a global teardown (stopping/deleting the hd-builder Lima VM itself or running global machinectl teardown), which would knock out the user's other Lima VMs / machinectl machines (e.g. Docker-for-Mac's own VM). There is NO Docker actions.

Automated Testing Pattern

For AI-driven ralph loop testing, keep auth tokens so steps don't fail:

Checked:   install_state, container
Unchecked: tarball (cached, saves the full-image re-download),
           adom_token, claude_token

This gives a freshly-imported machine while keeping auth working — step 5 (inject-api-key) and step 12 (claude-auth) won't fail.

Programmatic triggers (the ONLY supported headless paths)

# Virgin reset — the ONE allowed programmatic trigger
curl -X POST http://127.0.0.1:47084/setup/panel/run-virgin-reset \
  -H Content-Type:application/json \
  -d '{"confirmed_destructive":true,"install_state":true,"container":true,
       "tarball":false,"webview_storage":false,"vscode_state":false,
       "adom_token":false,"claude_token":false}'

# Re-run a single step (optional continue_after to keep going)
curl -X POST http://127.0.0.1:47084/setup/step/test-direct-connect \
  -H Content-Type:application/json -d '{"continue_after":true}'

DEPRECATED — do NOT use these; they are now REFUSED (deprecated headless triggers): POST /workspace/unregister (destructive machinectl remove Adom-Workspace), POST /setup/virgin-reset, POST /setup/run-all, POST /setup/run-step.

Key Steps Explained

Step 1 — ensure-workspace

The big one. Ensures the Lima VM hd-builder is up (provisions it if missing — no host reboot needed on macOS), then machinectl import-tar Adom-Workspace from the full pre-baked golden image adom-golden.tar.gz (pulled from the adom-inc/hd-lima-image GitHub release — NOT a thin ~30 MB tarball, NOT a 390 MB Docker image), creates the adom user, starts code-server, and verifies code-server reachable from the Mac on port 7380. This single step replaces the old Docker pull-image / create-container / start-container trio. The machine's DEFAULT user is adom (UID 1001; under systemd-nspawn there's no wsl.conf — the default user comes from the machine config / nsenter -S 1001 -G 1001), NOT root; in-machine exec = limactl shell hd-builder -- sudo nsenter -t <leader> -a -S 1001 -G 1001 -- bash -lc '<cmd>' (root variant drops -S 1001 -G 1001) — NEVER docker exec.

Step 5 — inject-api-key

Writes the Adom session token into the machine at /var/run/adom/api-key (mode 644) so adom-cli works. Requires the user to be signed in. Keep the adom_token toggle UNCHECKED during automated test resets.

Step 9 — test-direct-connect

Proves the fast container→desktop command path. The CLI auto-probes the host control API (wired to the adom-host gateway by /etc/init-host-internal.sh) and routes through Adom Desktop's direct connect API.

Step 10 — test-relay (register relay)

Registers the relay (started by step 8, start-relay) with Adom Desktop for file streaming via the code-server proxy path. This enables pull_file, send_files, and shell_execute.

Step 12 — claude-auth

The single human gate. Restores / validates Claude creds in the machine (backed up host-side) and, when needed, drives the in-editor Claude.ai sign-in via the native browser Browser Picker. Runs LAST before the payoff steps.

Steps 13-16 — the final gates

ensure-sse confirms the editor browser SSE session is connected (so the Welcome webview-open doesn't 409); verify-workspace confirms the proxy holds a real layout; welcome opens Claude Code and sends the first prompt; the final open-welcome gate opens welcome.html in HD's right pane and HARD-FAILS if the Welcome tab doesn't appear.

Note: the Adom CLIs, the claude CLI + Code extension, VS Code settings, and hd-* skills are NOT setup steps — they are baked into adom-golden.tar.gz. See hd-golden-image.

Machine Recreation

When the machine is removed and re-imported (step 1), the new machine is a fully pre-baked Ubuntu from adom-golden.tar.gz. code-server binds 0.0.0.0:7380 inside the machine and Lima exposes it to the Mac at localhost:7380 — there is no Docker port-mapping layer, so the port-conflict / stale-mapping class of bug that affected the Docker runtime does not apply here. Other services tunnel through the code-server /proxy/{port}/ path.