Hydrogen Desktop (macOS / Lima)
Public Made by Adomby adom
The macOS platform layer for Hydrogen Desktop.
name: hd-container description: Context for Claude Code running inside a Hydrogen Desktop workspace machine. Documents the exact OS (Ubuntu 24.04, code-server 4.112.0, the Adom-Workspace machine), explains how setup differs from Adom cloud containers (setup-steps NOT bootstrap.sh), what bridges are available, and how to use the relay. Trigger on startup, adom-cli errors, bridge commands, screenshot requests, container-platform questions, code-server / VS Code extension issues, or when the AI needs concrete facts about its environment instead of guessing.
Hydrogen Desktop Workspace (Machine)
Machine-runtime version (default). Legacy Docker container runtime (HD_RUNTIME=docker) is in the docker/ bucket.
You are running inside the Adom-Workspace machine managed by Hydrogen Desktop (HD). HD is the flagship Adom desktop app — it manages your workspace machine, bridges to desktop apps, and provides VS Code + Claude Code.
The workspace — exact facts (don't guess)
| Field | Value |
|---|---|
| Machine name | Adom-Workspace (fixed — there is no random container suffix) |
| Imported from | golden image adom-golden.tar.gz (full pre-baked image) via machinectl import-tar |
| Base | Ubuntu 24.04 |
| Architecture | aarch64 (arm64) — the macOS golden image is a Rosetta-hybrid: native arm64 code-server / node / claude, with the x86-64 Adom CLIs run translated under Rosetta inside the Lima VM. So uname -m returns aarch64 and node's process.arch is arm64, but adom-* x86-64 binaries still run (via Rosetta) |
| code-server | 4.112.0 (pinned via setup step) |
| code-server binary | /usr/lib/code-server/bin/code-server |
| Extensions dir | ~/.local/share/code-server/extensions/ |
| Settings | ~/.local/share/code-server/User/settings.json |
| Machine default user | adom (UID 1001; under systemd-nspawn there's no wsl.conf — the default user comes from the machine config / nsenter -S 1001 -G 1001) — in-machine exec via limactl shell hd-builder -- sudo nsenter -t <leader> -a -S 1001 -G 1001 -- bash -lc '<cmd>'; root variant drops -S 1001 -G 1001 |
| Work user | adom (UID 1001, passwordless sudo, home /home/adom) |
| Workspace | /home/adom/project (lives directly in the machine's ext4 filesystem) |
| Pre-installed | Node 18 + npm, Python 3.12, git, gh, curl, wget, jq, build-essential, cmake, pkg-config, libssl-dev |
| Code-server runs as | code-server --bind-addr 0.0.0.0:7380 --auth none --disable-telemetry /home/adom/project (binds 0.0.0.0:7380; Lima exposes it to the Mac at localhost:7380) |
| Runtime source | hydrogen-desktop/src-tauri/crates/hd-app/src/runtime/macos.rs (selector runtime/mod.rs::select_runtime()) |
If you ever need to confirm: cat /etc/os-release, uname -m (expect aarch64 on Apple Silicon), /usr/lib/code-server/bin/code-server --version. Don't speculate about alpine — it's Ubuntu 24.04, same distro as the cloud container (the cloud is amd64; this macOS port is arm64 + Rosetta for the x86-64 Adom CLIs).
Setup is via HD's setup-steps
HD provisions this machine through its own setup-steps flow (Rust code in hydrogen-desktop/src-tauri/crates/hd-app/src/setup_steps_macos.rs, with the runtime mechanics in hydrogen-desktop/src-tauri/crates/hd-app/src/runtime/macos.rs), shown as the "Install Tools" panel in the HD UI. It is a different code path than cloud containers.
The machine cascade is 18 steps (state file setup-steps-macos.json) vs the legacy Docker flow's 24. Most tooling is NOT installed by a step — it's BAKED into adom-golden.tar.gz at image-build time (the 8 Adom CLIs, the claude CLI + Code extension, code-server, VS Code settings, and all hd-* skills). The Docker pull-image / create-container / start-container steps are collapsed into a single step 1, ensure-workspace, which runs machinectl import-tar of adom-golden.tar.gz if the machine isn't already present. The relay is started by the start-relay step. See hd-golden-image.
When debugging install issues here, the source of truth is setup_steps_macos.rs (and runtime/macos.rs) — its step IDs (ensure-workspace, install-adom-vscode, set-env-vars, inject-api-key, start-relay, claude-auth, etc.) map 1:1 to what ran on this machine. There is NO install-claude-ext / install-claude-cli / write-vscode-settings step anymore — those are baked. (For the legacy Docker setup_steps.rs flow see the docker/ bucket.)
VS Code extension caveats
- The Claude Code extension and
code-serversettings (includingextensions.autoUpdate: true/extensions.autoCheckUpdates: true) are BAKED into the golden image — there is nowrite-vscode-settingsorinstall-claude-extsetup step. Auto-update must stay on so every installed extension auto-updates from the marketplace; the image bakes it on. Do not regress this. - Bare
code-server --install-extension <id>(no version pin) historically resolves to the universal target-platform build. For some extensions (notablyanthropic.claude-codeafter 2.1.89), Anthropic stopped shipping universal builds — so bare install permanently sticks at 2.1.89 even when newerlinux-x64builds exist. The golden-image bake installs the latestlinux-x64build pinned, so the workspace ships current. It also heals orphanextensions.jsonentries (entries pointing to deleted dirs cause a permanent "Invalid extensions detected" banner). - Marketplace: code-server uses Open VSX (open-vsx.org), not Microsoft Marketplace. No
EXTENSIONS_GALLERYenv override is set;product.jsonhas no gallery URL — it falls through to Open VSX defaults.
adom-cli is authenticated
HD auto-injects the user's session token on every launch. To verify:
adom-cli carbon user get
If this returns user data, all adom-cli commands work (containers, repos, orgs, wiki, etc.). If it fails, the user needs to log in via HD's login page.
Relay server is running
The adom-desktop relay runs on ports 8765 (WebSocket) / 8766 (HTTP) inside this machine. The start-relay setup step launches it.
Check health: curl -sf http://127.0.0.1:8766/health
Check desktop connection: adom-desktop ping
The macOS host control API is reachable from inside the machine via the adom-host gateway alias — vz does NOT mirror loopback, so 127.0.0.1 inside the machine is NOT the Mac. The port is dynamic per launch, so read the live URL from ~/.adom/hd-control-url: BASE="$(cat ~/.adom/hd-control-url)"; curl "$BASE/health".
Available bridge commands (when desktop is connected)
Screenshots (zero dialogs, instant)
adom-desktop desktop_screenshot_screen # full screen capture
adom-desktop desktop_screenshot_screen '{"maxWidth":1500}' # resized for Claude vision
adom-desktop desktop_screenshot_window '{"hwnd": N}' # capture specific window
adom-desktop desktop_list_windows # list all windows with HWNDs
Default to maxWidth: 1500, format: "png" for UI screenshots. Use "jpeg" for natural photos, "webp" for smaller files.
Browser automation (Puppeteer)
adom-desktop browser_open_window '{"url": "https://..."}'
adom-desktop browser_screenshot '{"sessionId": "default"}'
adom-desktop browser_eval '{"js": "document.title"}'
adom-desktop browser_navigate '{"url": "..."}'
KiCad bridge
adom-desktop kicad_open_board '{"path": "/Users/john/path/to/board.kicad_pcb"}'
adom-desktop kicad_screenshot_all
adom-desktop kicad_run_drc '{"path": "..."}'
adom-desktop kicad_window_info
Fusion 360 bridge
adom-desktop fusion_start
adom-desktop fusion_import_step '{"path": "..."}'
adom-desktop fusion_export_step '{"path": "..."}'
File transfer
adom-desktop send_files '{"files": [{"path": "/home/adom/file.txt"}]}'
adom-desktop pull_file '{"remotePath": "/Users/john/file.txt", "localPath": "/tmp/file.txt"}'
Desktop interaction
adom-desktop notify_user '{"message": "Build complete", "duration_ms": 3000}'
adom-desktop desktop_open_url '{"url": "https://..."}'
adom-desktop desktop_open_folder '{"path": "/Users/john/project"}'
What's different from Adom cloud containers
| Feature | Adom Cloud | HD Local (machine) |
|---|---|---|
| Workspace provisioning | Adom platform API | machinectl import-tar of adom-golden.tar.gz inside the Lima VM on the user's Mac |
| Relay connection | wss:// through Cloudflare | ws://localhost:8765 (direct, no TLS) |
| Bridge latency | ~50-100ms (internet round-trip) | <1ms (localhost) |
| VSCODE_PROXY_URI | Coder proxy URL | http://localhost:7380/proxy/{{port}}/ |
| Socket.IO (collab) | Connected to iron.adom.inc | Disabled (single-user) |
| Service containers | Adjacent containers | Remote via Adom cloud |
Environment variables
ADOM_DESKTOP_MODE=local— indicates HD local modeHD_RUNTIME=macos— indicates the machine runtime (default);dockerselects the legacy container runtimeVSCODE_PROXY_URI=http://localhost:7380/proxy/{{port}}/— code-server's proxy
Related skills
hd-topology— the three-tier topology; tier 3 is this workspace machinehd-volume— where your files live, what persists, and how to back up / copy out the machine
---
name: hd-container
description: Context for Claude Code running inside a Hydrogen Desktop workspace machine. Documents the exact OS (Ubuntu 24.04, code-server 4.112.0, the Adom-Workspace machine), explains how setup differs from Adom cloud containers (setup-steps NOT bootstrap.sh), what bridges are available, and how to use the relay. Trigger on startup, adom-cli errors, bridge commands, screenshot requests, container-platform questions, code-server / VS Code extension issues, or when the AI needs concrete facts about its environment instead of guessing.
---
# Hydrogen Desktop Workspace (Machine)
Machine-runtime version (default). Legacy Docker container runtime (`HD_RUNTIME=docker`) is in the docker/ bucket.
You are running inside the **`Adom-Workspace` machine** managed by Hydrogen Desktop (HD). HD is the flagship Adom desktop app — it manages your workspace machine, bridges to desktop apps, and provides VS Code + Claude Code.
## The workspace — exact facts (don't guess)
| Field | Value |
|-------|-------|
| Machine name | `Adom-Workspace` (fixed — there is no random container suffix) |
| Imported from | golden image `adom-golden.tar.gz` (full pre-baked image) via `machinectl import-tar` |
| Base | Ubuntu 24.04 |
| Architecture | `aarch64` (arm64) — the macOS golden image is a **Rosetta-hybrid**: native arm64 code-server / node / claude, with the x86-64 Adom CLIs run **translated under Rosetta** inside the Lima VM. So `uname -m` returns `aarch64` and `node`'s `process.arch` is `arm64`, but `adom-*` x86-64 binaries still run (via Rosetta) |
| code-server | 4.112.0 (pinned via setup step) |
| code-server binary | `/usr/lib/code-server/bin/code-server` |
| Extensions dir | `~/.local/share/code-server/extensions/` |
| Settings | `~/.local/share/code-server/User/settings.json` |
| Machine default user | `adom` (UID 1001; under systemd-nspawn there's no wsl.conf — the default user comes from the machine config / nsenter `-S 1001 -G 1001`) — in-machine exec via `limactl shell hd-builder -- sudo nsenter -t <leader> -a -S 1001 -G 1001 -- bash -lc '<cmd>'`; root variant drops `-S 1001 -G 1001` |
| Work user | `adom` (UID 1001, passwordless sudo, home `/home/adom`) |
| Workspace | `/home/adom/project` (lives directly in the machine's ext4 filesystem) |
| Pre-installed | Node 18 + npm, Python 3.12, git, gh, curl, wget, jq, build-essential, cmake, pkg-config, libssl-dev |
| Code-server runs as | `code-server --bind-addr 0.0.0.0:7380 --auth none --disable-telemetry /home/adom/project` (binds 0.0.0.0:7380; Lima exposes it to the Mac at `localhost:7380`) |
| Runtime source | `hydrogen-desktop/src-tauri/crates/hd-app/src/runtime/macos.rs` (selector `runtime/mod.rs::select_runtime()`) |
If you ever need to confirm: `cat /etc/os-release`, `uname -m` (expect `aarch64` on Apple Silicon), `/usr/lib/code-server/bin/code-server --version`. Don't speculate about alpine — it's Ubuntu 24.04, same distro as the cloud container (the cloud is amd64; this macOS port is arm64 + Rosetta for the x86-64 Adom CLIs).
## Setup is via HD's setup-steps
HD provisions this machine through its own **setup-steps** flow (Rust code in `hydrogen-desktop/src-tauri/crates/hd-app/src/setup_steps_macos.rs`, with the runtime mechanics in `hydrogen-desktop/src-tauri/crates/hd-app/src/runtime/macos.rs`), shown as the "Install Tools" panel in the HD UI. It is a **different code path** than cloud containers.
The machine cascade is **18 steps** (state file `setup-steps-macos.json`) vs the legacy Docker flow's 24. Most tooling is NOT installed by a step — it's BAKED into `adom-golden.tar.gz` at image-build time (the 8 Adom CLIs, the claude CLI + Code extension, code-server, VS Code settings, and all `hd-*` skills). The Docker `pull-image` / `create-container` / `start-container` steps are collapsed into a single step 1, `ensure-workspace`, which runs `machinectl import-tar` of `adom-golden.tar.gz` if the machine isn't already present. The relay is started by the `start-relay` step. See `hd-golden-image`.
When debugging install issues here, the source of truth is `setup_steps_macos.rs` (and `runtime/macos.rs`) — its step IDs (`ensure-workspace`, `install-adom-vscode`, `set-env-vars`, `inject-api-key`, `start-relay`, `claude-auth`, etc.) map 1:1 to what ran on this machine. There is NO `install-claude-ext` / `install-claude-cli` / `write-vscode-settings` step anymore — those are baked. (For the legacy Docker `setup_steps.rs` flow see the docker/ bucket.)
## VS Code extension caveats
- The Claude Code extension and `code-server` settings (including `extensions.autoUpdate: true` / `extensions.autoCheckUpdates: true`) are BAKED into the golden image — there is no `write-vscode-settings` or `install-claude-ext` setup step. Auto-update **must** stay on so every installed extension auto-updates from the marketplace; the image bakes it on. Do not regress this.
- Bare `code-server --install-extension <id>` (no version pin) historically resolves to the **universal** target-platform build. For some extensions (notably `anthropic.claude-code` after 2.1.89), Anthropic stopped shipping universal builds — so bare install permanently sticks at 2.1.89 even when newer `linux-x64` builds exist. The golden-image bake installs the latest `linux-x64` build pinned, so the workspace ships current. It also heals orphan `extensions.json` entries (entries pointing to deleted dirs cause a permanent "Invalid extensions detected" banner).
- Marketplace: code-server uses **Open VSX** (open-vsx.org), not Microsoft Marketplace. No `EXTENSIONS_GALLERY` env override is set; `product.json` has no gallery URL — it falls through to Open VSX defaults.
## adom-cli is authenticated
HD auto-injects the user's session token on every launch. To verify:
```bash
adom-cli carbon user get
```
If this returns user data, all adom-cli commands work (containers, repos, orgs, wiki, etc.). If it fails, the user needs to log in via HD's login page.
## Relay server is running
The adom-desktop relay runs on ports 8765 (WebSocket) / 8766 (HTTP) inside this machine. The `start-relay` setup step launches it.
Check health: `curl -sf http://127.0.0.1:8766/health`
Check desktop connection: `adom-desktop ping`
The macOS host control API is reachable from inside the machine via the `adom-host` gateway alias — vz does NOT mirror loopback, so 127.0.0.1 inside the machine is NOT the Mac. The port is dynamic per launch, so read the live URL from `~/.adom/hd-control-url`: `BASE="$(cat ~/.adom/hd-control-url)"; curl "$BASE/health"`.
## Available bridge commands (when desktop is connected)
### Screenshots (zero dialogs, instant)
```bash
adom-desktop desktop_screenshot_screen # full screen capture
adom-desktop desktop_screenshot_screen '{"maxWidth":1500}' # resized for Claude vision
adom-desktop desktop_screenshot_window '{"hwnd": N}' # capture specific window
adom-desktop desktop_list_windows # list all windows with HWNDs
```
Default to `maxWidth: 1500, format: "png"` for UI screenshots. Use `"jpeg"` for natural photos, `"webp"` for smaller files.
### Browser automation (Puppeteer)
```bash
adom-desktop browser_open_window '{"url": "https://..."}'
adom-desktop browser_screenshot '{"sessionId": "default"}'
adom-desktop browser_eval '{"js": "document.title"}'
adom-desktop browser_navigate '{"url": "..."}'
```
### KiCad bridge
```bash
adom-desktop kicad_open_board '{"path": "/Users/john/path/to/board.kicad_pcb"}'
adom-desktop kicad_screenshot_all
adom-desktop kicad_run_drc '{"path": "..."}'
adom-desktop kicad_window_info
```
### Fusion 360 bridge
```bash
adom-desktop fusion_start
adom-desktop fusion_import_step '{"path": "..."}'
adom-desktop fusion_export_step '{"path": "..."}'
```
### File transfer
```bash
adom-desktop send_files '{"files": [{"path": "/home/adom/file.txt"}]}'
adom-desktop pull_file '{"remotePath": "/Users/john/file.txt", "localPath": "/tmp/file.txt"}'
```
### Desktop interaction
```bash
adom-desktop notify_user '{"message": "Build complete", "duration_ms": 3000}'
adom-desktop desktop_open_url '{"url": "https://..."}'
adom-desktop desktop_open_folder '{"path": "/Users/john/project"}'
```
## What's different from Adom cloud containers
| Feature | Adom Cloud | HD Local (machine) |
|---------|-----------|-----------------|
| Workspace provisioning | Adom platform API | `machinectl import-tar` of `adom-golden.tar.gz` inside the Lima VM on the user's Mac |
| Relay connection | wss:// through Cloudflare | ws://localhost:8765 (direct, no TLS) |
| Bridge latency | ~50-100ms (internet round-trip) | <1ms (localhost) |
| VSCODE_PROXY_URI | Coder proxy URL | http://localhost:7380/proxy/{{port}}/ |
| Socket.IO (collab) | Connected to iron.adom.inc | Disabled (single-user) |
| Service containers | Adjacent containers | Remote via Adom cloud |
## Environment variables
- `ADOM_DESKTOP_MODE=local` — indicates HD local mode
- `HD_RUNTIME=macos` — indicates the machine runtime (default); `docker` selects the legacy container runtime
- `VSCODE_PROXY_URI=http://localhost:7380/proxy/{{port}}/` — code-server's proxy
## Related skills
- `hd-topology` — the three-tier topology; tier 3 is this workspace machine
- `hd-volume` — where your files live, what persists, and how to back up / copy out the machine