name: hd-workspace-lifecycle description: Workspace machine (Adom-Workspace) lifecycle management for Hydrogen Desktop on macOS. Import/export/remove/terminate, code-server-as-HD-child, the resume reality-check, recovery after sleep/hibernate, and every hard-won rule about what NOT to do — above all, NEVER run a global teardown; touch ONLY Adom-Workspace so the user's other Lima VMs / machines stay safe. MUST READ before any workspace operation. Trigger words — machine, workspace, Adom-Workspace, restart workspace, terminate machine, remove, machinectl import-tar, machinectl remove, code-server, workspace broken, workspace unhealthy, machine hung, fix workspace, /workspace/status.

Hydrogen Desktop — Workspace Machine Lifecycle

This is the machine-runtime version (default). The legacy Docker equivalent (HD_RUNTIME=docker) is in the docker/ bucket.

Under the machine runtime the workspace is the Adom-Workspace machine (Ubuntu, a systemd-nspawn machine imported with machinectl import-tar), running locally inside HD's hd-builder Lima VM on the user's Mac. /home/adom/project lives inside the machine — there is no Docker volume.

ABSOLUTE RULE — NEVER do a global teardown

Operate ONLY on Adom-Workspace. Never run any global teardown that hits the shared Lima VM or other machines.

Forbidden, no exceptions:

  • ❌ stopping or deleting the hd-builder Lima VM itself (kills every machine inside it)
  • machinectl terminate on any machine other than Adom-Workspace
  • ❌ blanket killing of machinectl / nsenter processes
  • ❌ restarting / re-provisioning the hd-builder Lima VM
  • machinectl remove on anything but Adom-Workspace
  • ❌ global machinectl teardown

Why this matters: the user may run other Lima VMs or machinectl machines, and Docker-for-Mac keeps its own VM. Any global teardown — stopping/deleting the shared hd-builder VM or wiping other machines — would knock those out. It's harmless to HD's own Adom-Workspace, but it looks to the user like HD broke their other VMs / Docker — terrible first-run UX. So every HD operation must be scoped to Adom-Workspace and nothing else.

Allowed, scoped operations:

  • machinectl terminate Adom-Workspace (this is what "Restart" does)
  • machinectl remove Adom-Workspace (destructive wipe, this machine only)
  • machinectl import-tar Adom-Workspace <tarball> (fresh import)
  • limactl shell hd-builder -- sudo nsenter -t <leader> -a -S 1001 -G 1001 -- bash -lc '<cmd>' (exec inside the machine)

In-machine exec — NEVER docker exec

To run a command inside the workspace:

limactl shell hd-builder -- sudo nsenter -t <leader> -a -S 1001 -G 1001 -- bash -lc '<cmd>'
# or, root variant (drop -S/-G):
limactl shell hd-builder -- sudo nsenter -t <leader> -a -- bash -lc 'su - adom -c "..."'

<leader> is the machine's leader PID. There is no docker exec under this runtime, and no Docker container to exec into.

Workspace Lifecycle

Import (fresh setup)

setup_and_startMacosVmRuntime::setup_and_startfresh_import: download adom-golden.tar.gz (the full pre-baked golden image, downloaded anonymously from the adom-inc/hd-lima-image GitHub release, SHA256-verified) then machinectl import-tar Adom-Workspace adom-golden.tar.gz, then start code-server. Log proof: [golden-tarball] downloaded … SHA256 OK[setup] machine setup_and_start completed and machinectl list shows Adom-Workspace running.

code-server is an HD-OWNED CHILD process

code-server (CODE_SERVER_CHILD in runtime/macos.rs) runs as a child of HD, deliberately tied to HD's lifetime — NOT a detached nohup (a detached process dies when the machine tears down the session anyway). Consequence: every HD restart (rebuild / crash / relaunch) orphans the old code-server, so a fresh HD can come up with the machine running but the editor DEAD ("Starting AI Environment" forever) even when setup is otherwise complete.

Fix (already in HD): HD re-ensures code-server on every launch ([macos-startup] re-ensured code-server on launch). And the resume reality-check in run_all_machine requires code-server reachable on the host port 7380 — not just "machine present" — before it trusts the workspace as ready.

Restart

"Restart Workspace" = machinectl terminate Adom-Workspace + re-ensure code-server. NOT docker restart. This is the fix for a workspace that's gone unreachable after laptop sleep/hibernate.

Stop

machinectl terminate Adom-Workspace. The machine stays present (and your project files persist); it just isn't running.

Export / backup

machinectl export-tar Adom-Workspace <file>.tar snapshots the machine to a tarball. Re-import with machinectl import-tar Adom-Workspace <file>.tar. (Scoped to this machine, so safe.)

Remove (DESTRUCTIVE wipe)

machinectl remove Adom-Workspace — deletes the machine AND everything in it, including /home/adom/project. This is the only destructive wipe, and it names ONLY Adom-Workspace. Never remove any other machine.

Control API

The HD control API is on loopback http://127.0.0.1:<dynamic> (NOT 9001). The port is dynamic per launch — read the live URL from ~/.adom/hd-control-url. From inside the machine, reach the host via the adom-host gateway alias (vz does NOT mirror loopback, so 127.0.0.1 inside the machine is NOT the Mac).

Endpoint What it does
GET /workspace/status Reports the machine state — present? running? code-server reachable on :7380?
POST /workspace/unregister Destructive: machinectl remove Adom-Workspace (this machine only)
GET /container-stats Live CPU/RAM/disk from the workspace_stats() probe (see hd-container-stats)
BASE="$(cat ~/.adom/hd-control-url)"   # http://127.0.0.1:<dynamic>

# Workspace status (from inside the machine, via the adom-host gateway)
curl -s "$BASE/workspace/status"

# Destructive wipe of ONLY Adom-Workspace
curl -s -X POST "$BASE/workspace/unregister"

Diagnosing Workspace Problems

"Workspace unhealthy" / editor stuck on "Starting AI Environment"

  • Cause: code-server child was orphaned by an HD restart, or the machine went unreachable after sleep.
  • Check: [macos] Workspace unhealthy … in the HD log (the real signal). NOTE: a [docker] Container runtime unhealthy … line under the machine runtime is benign noise — a leftover heartbeat with no container bound. Ignore it; look at the [machine] line.
  • Fix: Restart Workspace (Adom menu) = machinectl terminate Adom-Workspace + re-ensure code-server. Verify code-server answers on :7380.

Machine running but editor dead

  • Cause: code-server (HD's child) isn't up even though machinectl list shows running.
  • Fix: relaunch HD (it re-ensures code-server on launch), or Restart Workspace. Confirm via the resume reality-check — code-server reachable on :7380, not just "machine present."

Lima VM not available at all

  • Cause: the hd-builder Lima VM isn't up / hasn't been provisioned.
  • Fix: the "Lima VM not available" floaty → "Run Setup Steps" walks the user through provisioning it. See hd-workspace-monitoring.

Recovery Checklist

When the workspace is broken, follow this order:

  1. Check the Lima VM itself: limactl list / limactl shell hd-builder -- systemctl status (NOT stopping or deleting hd-builder).
  2. Check the machine: machinectl list — is Adom-Workspace listed and running?
  3. If running but editor dead: code-server child orphaned → Restart Workspace (machinectl terminate Adom-Workspace + re-ensure code-server), or relaunch HD.
  4. Verify code-server: it must answer on host :7380 (the resume reality-check).
  5. Last resort (destructive): machinectl remove Adom-Workspace then re-import via setup_and_start — wipes the machine and re-imports adom-golden.tar.gz.
  6. NEVER reach for a global teardown to "fix" things — stopping/deleting the hd-builder VM or running global machinectl teardown breaks the user's other Lima VMs / machines, doesn't help your machine, and angers the user.

What NOT To Do (learned the hard way)

  • Do NOT stop or delete the hd-builder Lima VM — global, kills every machine in it, breaks the user's other Lima VMs / Docker-for-Mac's VM.
  • Do NOT machinectl terminate or machinectl remove any machine except Adom-Workspace.
  • Do NOT blanket-kill machinectl / nsenter processes — same blast radius as tearing down the VM.
  • Do NOT use docker exec / docker restart — there is no container in this runtime.
  • Do NOT trust "machine present" as healthy — require code-server reachable on :7380.
  • Do NOT treat [docker] … unhealthy in the log as a real failure under the machine runtime — it's benign; the real signal is [macos] Workspace unhealthy ….