← Commit history
README.md+7−6
@@ -83,14 +83,15 @@ The Carbon API key, `DefaultUid=1001`, the `host.docker.internal` alias.  ## Open decisions / remaining work -- ✅ **Skills bundled into `skills/`** — all 46 `hd-*` (flat copy from-  `hydrogen-desktop/skills/public-facing/{shared,wsl2}`). Decided: bundled, not-  a separate `adom/hd-skills` package.-- ⚠ **InstaPCB embargo:** the bundle currently **includes `hd-instapcb`** (and+- ✅ **Skills bundled into `skills/`** — the **31 platform-generic** `hd-*` skills.+  The other 15 are Windows-specific (in `adom/hd-windows-bootstrap`); 13 mixed+  skills were split, generic core here + a `<name>-windows` companion in the+  Windows layer. Decided: bundled, not a separate `adom/hd-skills` package.+- ⚠ **InstaPCB embargo:** the generic bundle **includes `hd-instapcb`** (and   `hd-who-am-i`'s InstaPCB lines) on purpose — to demo/plan InstaPCB pre-launch.   InstaPCB stays embargoed on public surfaces until ~Nov 2026. **An embargo-  scan is due before this package's public launch (~2026-07-24, 5 weeks out)**-  to strip InstaPCB content. Until then, do not treat the bundle as launch-ready.+  scan is due before this package's public launch (~2026-07-24)** to strip+  InstaPCB content. Until then, do not treat the bundle as launch-ready. - **Edit `adom/core` to add `adom-google` / `adom-tts` / `adom-gchat`** so HD   inherits them (all three verified anon + sudo-free). Needs core's source   (wiki-git) + a republish.
docs/hero.html+4−4
@@ -22,13 +22,13 @@ Resolving via wiki.adom.inc...   <span class="s">adom/core</span>          4.9.1    <span class="ok">✓</span>  <span class="dim">108-guide hub · distributor search · KiCad/Fusion · adom-cli</span>   <span class="s">adom/adom-desktop</span>  1.8.147  <span class="ok">✓</span>  <span class="dim">laptop relay (KiCad/Fusion/pup bridges)</span>-  <span class="dim">+ 35 Hydrogen Desktop skills (bundled)   running postinstall…</span> <span class="ok">✓</span>+  <span class="dim">+ 31 platform-generic HD skills (bundled)   running postinstall…</span> <span class="ok">✓</span>  <span class="p">$</span> <span class="c">ls ~/.claude/skills/</span>          <span class="dim"># where the generic HD skills land</span>-<span class="path">hd-adom-auth/</span>   <span class="path">hd-bridges/</span>       <span class="path">hd-eval/</span>          <span class="path">hd-recording/</span>    <span class="path">hd-ui/</span>-<span class="path">hd-adom-menu/</span>   <span class="path">hd-browser-pick/</span>  <span class="path">hd-monitor/</span>       <span class="path">hd-screen-lock/</span>  <span class="path">hd-welcome/</span>+<span class="path">hd-adom-auth/</span>   <span class="path">hd-bridges/</span>       <span class="path">hd-eval/</span>          <span class="path">hd-container/</span>    <span class="path">hd-ui/</span>+<span class="path">hd-adom-menu/</span>   <span class="path">hd-permissions/</span>  <span class="path">hd-monitor/</span>       <span class="path">hd-setup/</span>  <span class="path">hd-welcome/</span> <span class="path">hd-api/</span>         <span class="path">hd-claude-auth/</span>   <span class="path">hd-notifications/</span> <span class="path">hd-settings/</span>     <span class="path">hd-who-am-i/</span>-<span class="path">hd-captions/</span>    <span class="path">hd-eda-discovery/</span> <span class="path">hd-open-url/</span>      <span class="path">hd-self-update/</span>  <span class="dim">…  35 total</span>+<span class="path">hd-captions/</span>    <span class="path">hd-eda-discovery/</span> <span class="path">hd-open-url/</span>      <span class="path">hd-self-update/</span>  <span class="dim">…  31 total</span> </pre>   </div> </div></body></html>
docs/hero.png
⋯ 1 unchanged line ⋯
package.json+1−1
@@ -4,7 +4,7 @@   "type": "bootstrap",   "title": "Hydrogen Desktop",   "brief": "Layer Hydrogen Desktop's workspace onto a standard Adom workstation.",-  "version": "0.1.0",+  "version": "0.2.0",   "description": "Hydrogen Desktop's PLATFORM-GENERIC workspace layer on top of adom/core. Installs adom/core for the full Adom ecosystem, then adds everything common to running inside Hydrogen Desktop on ANY platform: the runtime-neutral hd-* skills and the generic HD editor configuration (Claude Code CLI + extension, VS Code settings, trusted domains). Platform-specific layers depend on THIS: adom/hd-windows-bootstrap (WSL2), adom/hd-mac-bootstrap, adom/hd-ubuntu-bootstrap. The reference design other orgs copy to build their own bootstrap on adom/core.",   "org": "adom",   "platform": "any",
page.json+1−5
@@ -4,7 +4,7 @@   "type": "bootstrap",   "title": "Hydrogen Desktop",   "brief": "Layer Hydrogen Desktop's workspace onto a standard Adom workstation.",-  "version": "0.1.0",+  "version": "0.2.0",   "description": "Hydrogen Desktop's PLATFORM-GENERIC workspace layer on top of adom/core. Installs adom/core for the full Adom ecosystem, then adds everything common to running inside Hydrogen Desktop on ANY platform: the runtime-neutral hd-* skills and the generic HD editor configuration (Claude Code CLI + extension, VS Code settings, trusted domains). Platform-specific layers depend on THIS: adom/hd-windows-bootstrap (WSL2), adom/hd-mac-bootstrap, adom/hd-ubuntu-bootstrap. The reference design other orgs copy to build their own bootstrap on adom/core.",   "org": "adom",   "platform": "any",@@ -26,9 +26,5 @@   "author": {     "name": "John Lauer",     "email": "[email protected]"-  },-  "hero": {-    "type": "image",-    "path": "docs/hero.png"   } }\ No newline at end of file
skills/hd-adom-auth/SKILL.md+22−16
@@ -7,8 +7,8 @@ description: >   READ when troubleshooting Adom login failures, session token expiry, the   profile dropdown, or virgin-reset Adom-auth options. Trigger words —   adom login, login, logout, auth, session token, auth intent, confirmation-  code, profile menu, avatar, sign in, sign out, hydrogen-session.txt, auth-  proxy, clear session, HD adom login, Your profile, Your repositories.+  code, profile menu, avatar, sign in, sign out, auth proxy, clear session,+  HD adom login, Your profile, Your repositories. ---  # Hydrogen Desktop -- Authentication Reference@@ -16,13 +16,13 @@ description: > ## Auth Flow Overview  HD uses an **auth intent** flow (no email/password entry in the app).-The Tauri backend creates a short-lived intent token on the Carbon API,+The backend creates a short-lived intent token on the Carbon API, opens the user's default browser to the Adom login page, and polls until the user completes sign-in in the browser.  ### Sequence -1. HD calls `invoke('auth_intent_start')` -> Rust POSTs to+1. HD calls `invoke('auth_intent_start')` -> backend POSTs to    `https://carbon.adom.inc/auth/intents` with `{"max_age": 7776000}`    (90-day session). 2. Carbon returns `{token, confirmation_code, expires_at, auth_url}`.@@ -31,17 +31,17 @@ the user completes sign-in in the browser.    token as a query param — NOT `/auth/intents/{token}`). 4. HD displays the confirmation code on screen and shows a spinner. 5. Frontend polls `invoke('auth_intent_poll', {token})` every 2 seconds.-   Rust GETs `https://carbon.adom.inc/auth/intents/{token}/status`.+   Backend GETs `https://carbon.adom.inc/auth/intents/{token}/status`. 6. When the user confirms in the browser, the response includes    `{state: "authenticated", session_token: "..."}`.-7. Rust saves the session token to `%APPDATA%\hydrogen-desktop\hydrogen-session.txt`-   and a replay copy to `%APPDATA%\hydrogen-desktop\replay-session.txt`.+7. The backend saves the session token to HD's app-data directory on the host+   (the `hydrogen-session.txt` file) and a replay copy alongside it. 8. Frontend redirects to the dashboard.  ### Source files  - **Login page**: `src/routes/auth/login/+page.svelte`-- **Auth Rust backend**: `src-tauri/crates/hd-app/src/lib.rs` (functions+- **Auth backend**: `src-tauri/crates/hd-app/src/lib.rs` (functions   `auth_intent_start`, `auth_intent_poll`, `auth_proxy`,   `check_replay_credentials`, `replay_adom_login`). NOTE: the old   `src-tauri/src/lib.rs` is a pre-crate-split vestige — the live code is in the@@ -54,7 +54,8 @@ the user completes sign-in in the browser.  ## Session Token -**Location**: `%APPDATA%\hydrogen-desktop\hydrogen-session.txt`+**Location**: HD's app-data directory on the host (the `hydrogen-session.txt`+file).  A plain-text file containing the Adom session cookie value. Created by either: - The auth intent flow (on successful poll)@@ -68,7 +69,7 @@ as a `Cookie: session_token=...` header on every request to `carbon.adom.inc`. - **Created**: on login (auth intent or browser set-cookie capture) - **Refreshed**: automatically when the auth proxy receives a new set-cookie - **Cleared**: on logout (`auth_proxy({path: "/auth/clear-local"})`) or on-  401 response (Rust auto-deletes the file)+  401 response (backend auto-deletes the file) - **Max age**: 90 days (set at intent creation)  ### Reading the token programmatically@@ -78,15 +79,18 @@ as a `Cookie: session_token=...` header on every request to `carbon.adom.inc`. curl http://127.0.0.1:47084/auth-token  # From inside the workspace (injected by setup step inject-api-key, mode 644)-# run inside the workspace — WSL2: `wsl -d Adom-Workspace -u adom -- cat /var/run/adom/api-key`; Docker: `docker exec <container> cat /var/run/adom/api-key` cat /var/run/adom/api-key ``` +For the host-specific path table and the runtime-specific way to read+`/var/run/adom/api-key` from outside the workspace, see the+[[hd-adom-auth-windows]] companion skill.+ ---  ## Auth Proxy -The Tauri command `auth_proxy` is the gateway for all authenticated requests+The backend command `auth_proxy` is the gateway for all authenticated requests to the Adom Carbon API. It:  1. Reads the session token from disk@@ -114,7 +118,7 @@ On login page mount, HD checks for saved credentials before starting the full auth intent flow:  1. `invoke('check_replay_credentials')` checks if replay files exist on disk.-2. If `replay-session.txt` exists (has_adom = true), HD shows a "REPLAY"+2. If the replay-session file exists (has_adom = true), HD shows a "REPLAY"    badge and a 5-second countdown. 3. `invoke('replay_adom_login')` attempts to authenticate using the saved    session token.@@ -128,7 +132,8 @@ preserve the Adom session token.  ## Claude Credentials -**Location**: `%APPDATA%\hydrogen-desktop\replay-claude-credentials.json`+**Location**: HD's app-data directory on the host (the+`replay-claude-credentials.json` file).  Stores Claude Code OAuth credentials so they can be replayed into the workspace during bootstrap. The setup step `inject-api-key` reads the@@ -226,7 +231,7 @@ avatar ? avatar.alt : 'unknown';  1. User clicks "Log out" in profile menu. 2. `showConfirm('Are you sure you want to log out?', 'Log Out')` -- confirmation dialog.-3. If confirmed (Tauri mode):+3. If confirmed (app mode):    - `invoke('auth_proxy', {path: '/auth/logout', method: 'DELETE'})` -- server-side logout    - `invoke('auth_proxy', {path: '/auth/clear-local', method: 'POST'})` -- deletes `hydrogen-session.txt`    - Clears auth-related domain preferences from `localStorage['hd-url-routing-prefs']`@@ -238,7 +243,7 @@ avatar ? avatar.alt : 'unknown';  **Route**: `/auth/login` -### Tauri mode (auth intent)+### App mode (auth intent) - Adom logo + "Log in to Hydrogen" header - Confirmation code in a monospace box (`.confirmation-code`) - Spinner + "Waiting for you to sign in..."@@ -319,6 +324,7 @@ full endpoint reference.  ## Cross-references +- **hd-adom-auth-windows** -- host app-data path table + WSL2 specifics - **hd-ui** -- menu layout, where profile menu lives - **hd-setup** -- bootstrap steps that depend on auth - **hd-settings** -- API Explorer (auth endpoints tab)
skills/hd-adom-desktop/SKILL.md+47−48
@@ -4,12 +4,12 @@ description: >   What Hydrogen Desktop (HD) and Adom Desktop (AD) are, what each does, and how   they work together — so the AI in the workspace knows it has HANDS on the   user's real operating system. HD is the workspace app the user looks at; AD is-  the bridge that reaches the user's actual Windows machine (macOS/Linux coming-  soon) to create files & folders, run shell commands, take OS screenshots,-  launch apps, open browsers (Pup / native), and drive KiCad / Fusion 360. HD-  bundles AD during install and runs it in embedded mode, but AD is a standalone-  product that ALSO connects Adom cloud containers to a user's machine. HD also-  has a BUILT-IN desktop bridge of its own that serves a subset of AD's verbs.+  the bridge that reaches the user's actual machine to create files & folders,+  run shell commands, take OS screenshots, launch apps, open browsers (Pup /+  native), and drive KiCad / Fusion 360. HD bundles AD during install and runs+  it in embedded mode, but AD is a standalone product that ALSO connects Adom+  cloud containers to a user's machine. HD also has a BUILT-IN desktop bridge of+  its own that serves a subset of AD's verbs.   READ THIS to understand your reach beyond the workspace and how to invoke it.   Trigger words — adom desktop, AD, ad cli, what can you do on my computer, reach   my machine, create a file on my pc, make a folder on my desktop, run a command@@ -23,16 +23,18 @@ description: >  # Hydrogen Desktop ↔ Adom Desktop — your reach onto the user's real machine -You (the AI) run inside the **HD workspace** (a WSL2 Ubuntu distro by default).-That's a sandbox. **Adom Desktop (AD) is how you reach OUT of it onto the user's-actual operating system** — their real files, shell, screen, and desktop apps.-Knowing AD exists is the difference between "I can only work in here" and "I can-create that file on your Desktop, screenshot your screen, and open it in KiCad."+You (the AI) run inside the **HD workspace** (a local Linux workspace on the+user's machine). That's a sandbox. **Adom Desktop (AD) is how you reach OUT of it+onto the user's actual operating system** — their real files, shell, screen, and+desktop apps. Knowing AD exists is the difference between "I can only work in+here" and "I can create that file on your Desktop, screenshot your screen, and+open it in KiCad." -> **Platform reality (2026-06-12):** AD reaches the user's real **Windows**-> machine. macOS and Linux are *coming soon* — HD's host layer (screenshots,-> notifications, captions, window control) is currently Windows-only. Don't-> promise file/shell/screenshot actions on a Mac or Linux box yet.+> **Platform note:** HD's host layer (file/shell/screenshot/notification/window+> control) is platform-specific. Before promising a host action on a given OS,+> verify the capability with `adom-desktop status` rather than assuming it.+> For Windows/WSL2-specific host behavior, see the [[hd-adom-desktop-windows]]+> companion skill.  ## Two apps, two jobs @@ -84,7 +86,7 @@ bridge is — so recording / multi-monitor / glob-pull aren't available until AD is up. Screenshots, window control, files, shell, captions, notifications and the KiCad/Fusion/browser bridges all work off HD's built-in bridge regardless. -## What AD/HD let you do on the user's real Windows machine+## What AD/HD let you do on the user's real machine  All via the `adom-desktop` CLI from inside the workspace. Rather than re-document every verb here, this is a **capability map → the focused skill**:@@ -93,7 +95,7 @@ re-document every verb here, this is a **capability map → the focused skill**: |---|---|---| | **Create files/folders on the host** | `send_files` (container → desktop) | [hd-file-transfer](../hd-file-transfer/SKILL.md) | | **Pull files from the host** | `pull_file` (desktop → container, SHA256-verified); browse + watch via `list_files` / `watch_files` | [hd-file-transfer](../hd-file-transfer/SKILL.md) |-| **Run a shell command on the host** | `shell_execute` (real PowerShell/shell) | shell-trust model below |+| **Run a shell command on the host** | `shell_execute` (real host shell) | shell-trust model below | | **Screen/window control + screenshots** | `desktop_screenshot_screen` / `desktop_screenshot_window` / `desktop_list_windows`, `desktop_set_window_state`, `desktop_bring_to_front` | [hd-self-screenshot](../hd-self-screenshot/SKILL.md) | | **Record the screen / a tab** | `desktop_record_*` (whole screen), `browser_record_*` (one tab) | [hd-recording](../hd-recording/SKILL.md) — AD-served, verify `record` capability | | **Desktop notifications** | `notify_user` (title/body/level + action buttons) | [hd-notifications](../hd-notifications/SKILL.md) |@@ -107,8 +109,8 @@ For the complete verb list run `adom-desktop list_commands` (or see the  ### Host shell-trust model -`shell_execute` runs a **real command on the user's machine** (`cmd /C` on-Windows). In **embedded mode HD auto-approves** shell commands so the AI isn't+`shell_execute` runs a **real command on the user's machine** (the host's native+shell). In **embedded mode HD auto-approves** shell commands so the AI isn't blocked on per-command approval dialogs — convenient, but it means anything you run there really runs. Revoke the standing auto-approval at any time: @@ -119,22 +121,18 @@ adom-desktop shell_auto_approve '{"duration_secs":0}'   # turn auto-approve off When you *don't* need a free-form shell, prefer the **no-escape structured runners** over hand-quoted `shell_execute` (AD ≥ 1.8.50): `adom-desktop run_script '{"interpreter":"bash|cmd|powershell","scriptB64":"<b64>"}'`-and `adom-desktop wsl_exec '{"distro":"Adom-Workspace","user":"adom","scriptB64":"<b64>"}'`-— base64 the script so no quoting survives to be mangled.+and `adom-desktop wsl_exec '{"distro":"<workspace-distro>","user":"adom","scriptB64":"<b64>"}'`+— base64 the script so no quoting survives to be mangled. (`wsl_exec` is a+Windows/WSL2 path — see the [[hd-adom-desktop-windows]] companion.) -### Auto-installing missing apps (winget)+### Auto-installing missing apps -If KiCad or Node.js is missing on the host, you don't have to stop at a download-link — trigger an unattended winget install:--```bash-adom-desktop desktop_install_kicad '{}'   # winget install KiCad-adom-desktop desktop_install_node  '{}'   # winget install Node.js (unblocks the Pup bridge)-```--(`install_kicad` fires when `kicad_list_versions` returns-`errorCode:"kicad_not_installed"`; `install_node` when a `browser_*` call returns-`errorCode:"node_not_found"`.)+If KiCad or Node.js is missing on the host, HD can trigger an unattended+install on platforms that support it (see the [[hd-adom-desktop-windows]]+companion for the Windows winget verbs). The triggers: `install_kicad` fires+when `kicad_list_versions` returns `errorCode:"kicad_not_installed"`;+`install_node` when a `browser_*` call returns `errorCode:"node_not_found"`+(Node.js unblocks the Pup bridge).  ### KiCad project auto-sync @@ -153,8 +151,8 @@ over a WebSocket to the desktop client(s). **Host shell + files:** ```bash adom-desktop shell_execute '{"command":"<cmd>","timeoutSeconds":60}'-adom-desktop pull_file  '{"filePaths":["C:\\path\\file"],"saveTo":"/tmp"}'-adom-desktop send_files '{"filePaths":["/tmp/x"],"saveTo":"C:\\Users\\<you>"}'+adom-desktop pull_file  '{"filePaths":["<host path>"],"saveTo":"/tmp"}'+adom-desktop send_files '{"filePaths":["/tmp/x"],"saveTo":"<host dir>"}' adom-desktop desktop_list_windows ``` @@ -168,8 +166,8 @@ adom-desktop hd_launch            # start HD detached adom-desktop hd_api '{"method":"POST","path":"/setup/run-all","body":{}}' adom-desktop hd_api '{"method":"GET","path":"/health"}' ```-`hd_api` hits HD's **control API**, discovering its real port from-`%APPDATA%\hydrogen-desktop\ports.json` key `control` (fallback **47084**).+`hd_api` hits HD's **control API** on its discovered port (fallback **47084**).+See the [[hd-adom-desktop-windows]] companion for the host port-discovery file.  **Embedded-mode introspection (AD-served):** ```bash@@ -180,19 +178,17 @@ adom-desktop desktop_embedded_status   # embedded=true/false, enteredVia=launch-  ``` You (AI in the workspace)-  └─ adom-desktop <verb> '<json>'        ← CLI in the distro+  └─ adom-desktop <verb> '<json>'        ← CLI in the workspace        └─ relay  (adom-desktop serve: WS :8765 + HTTP :8766, started in the workspace)-            └─ WebSocket ──► HD's built-in bridge AND/OR the embedded AD on the user's Windows machine+            └─ WebSocket ──► HD's built-in bridge AND/OR the embedded AD on the user's machine                  └─ acts on the OS / KiCad / Fusion / Chrome ```  - In HD the relay is started for you by the **`start-relay`** setup step; HD's-  built-in bridge and the embedded AD both connect to it. Under WSL2 the relay-  binds `0.0.0.0:8765` in the distro and WSL2 forwards it to the host's-  `localhost:8765` (HTTP on `8766`), which is how the host-side clients reach-  your in-workspace relay (see the `hd-networking` skill). It's reached-  **same-port** under WSL2 — there's no host 47081/47082 remap (that was the old-  Docker model).+  built-in bridge and the embedded AD both connect to it. The host-side clients+  reach your in-workspace relay — the exact networking depends on the runtime+  (see the `hd-networking` skill, and the [[hd-adom-desktop-windows]] companion+  for the WSL2 loopback-forwarding details). - **Always verify the bridge before acting on the host:**   ```bash   adom-desktop ping       # → {"status":"connected", ...} means a client is reachable@@ -205,11 +201,13 @@ You (AI in the workspace)  ## What NOT to do -- **Never `taskkill /F /IM adom-desktop.exe`** — the host AD is your relay bridge;+- **Never kill the host AD process** — the host AD is your relay bridge;   killing it severs your control channel (you can't get it back from in here).+  (Windows-specific `taskkill` warnings live in the+  [[hd-adom-desktop-windows]] companion.) - **Never hardcode `:9001` as HD's control API.** `9001` is real — it's AD's   liveness beacon that AD probes to detect HD — but HD's actual control API is-  **47084** (use `hd_api`, which reads `ports.json` → `control`).+  **47084** (use `hd_api`, which reads the discovered port). - **Don't broad-kill `node`** — VS Code Server runs as node; killing it kills the   whole workspace. - Resize screenshots to `<1500px` before reading them, and inject every screenshot@@ -224,6 +222,7 @@ workspace itself (editor, files under `/home/adom/project`, the runtime), that's **HD**. Lead with what you can do, verify with `adom-desktop ping`, then act.  ## Related skills+- [[hd-adom-desktop-windows]] — Windows/WSL2 host specifics (paths, winget installs, loopback forwarding, taskkill) - [hd-embedded-ad](../hd-embedded-ad/SKILL.md) — how HD bundles + embeds AD (tray, lifecycle, standalone↔embedded) - [hd-bridges](../hd-bridges/SKILL.md) — the KiCad / Fusion / Puppeteer bridge ecosystem - [hd-file-transfer](../hd-file-transfer/SKILL.md) — send/pull files, browse + watch the host filesystem@@ -232,4 +231,4 @@ workspace itself (editor, files under `/home/adom/project`, the runtime), that's - [hd-notifications](../hd-notifications/SKILL.md) — desktop toasts; [hd-captions](../hd-captions/SKILL.md) — on-screen caption overlay - [hd-open-url](../hd-open-url/SKILL.md) — the ways to open a URL (Pup, native browser, picker, …) - `pup` — driving Pup browser windows; `adom-desktop` — the full CLI verb reference-- [hd-runtime-mode](../hd-runtime-mode/SKILL.md) — the HD↔AD relationship is identical on WSL2 and Docker+- [hd-runtime-mode](../hd-runtime-mode/SKILL.md) — the HD↔AD relationship is identical across runtimes
skills/hd-api/SKILL.md+32−69
@@ -2,16 +2,16 @@ name: hd-api description: >   Complete reference for Hydrogen Desktop control API endpoints. The control-  API runs on a dynamic port (find it in the HD log or via port discovery). Use-  these endpoints to drive HD programmatically: manage the workspace runtime (WSL2 distro or legacy Docker container), control-  Claude Code, manipulate VS Code, manage workspace tabs, run setup steps, trigger+  API runs on a dynamic port (find it via port discovery). Use these endpoints+  to drive HD programmatically: manage the workspace runtime, control Claude+  Code, manipulate VS Code, manage workspace tabs, run setup steps, trigger   virgin reset, and more. ~159 endpoints. Two self-documenting sources of truth   list them live: GET /_manifest (curated grouped list) and GET /test/help   (the /test/* diagnostics).   Trigger words: HD API, control API, HD endpoint, container exec, claude api,-  iframe eval, workspace tabs, setup run-all, docker status, reload vscode,-  browser profiles, open url, virgin reset api, reboot api, diagnostics,-  ad health, test window-tree, ai cursor, setup panel, screenshot mode.+  iframe eval, workspace tabs, setup run-all, runtime status, reload vscode,+  browser profiles, open url, virgin reset api, diagnostics, ad health,+  test window-tree, ai cursor, setup panel, screenshot mode. ---  # HD Control API Reference@@ -25,10 +25,9 @@ sources of truth you should hit first: | `GET /_manifest` | Curated, grouped, machine-readable list of the highest-value endpoints (path, method, args, description, `visibility`). `hd_api` forwards anything not listed. | `lib.rs:9144` | | `GET /test/help` | Lists the `/test/*` diagnostics (window enumeration, UIA click, dialog classification, cascade reset). Gated behind `HD_TEST_API_ENABLED=1`. | `lib.rs:9723` | -**Base URL:** `http://127.0.0.1:<dynamic>` — the same loopback address from inside the-workspace (WSL2 mirrored networking shares loopback with the Windows host) and on the-Windows host. The port is dynamic per launch; read the live URL from-`~/.adom/hd-control-url` — see "Finding the Control Port" below.+**Base URL:** `http://127.0.0.1:<dynamic>` — the loopback address. The port is+dynamic per launch; read the live URL from `~/.adom/hd-control-url` — see+"Finding the Control Port" below.  ## Finding the Control Port @@ -38,11 +37,8 @@ The control API port is dynamic (default 47084, auto-resolves conflicts). # From HD log adom-desktop hd_log '{"tail":100}' | grep "control=" -# From ports.json-type %APPDATA%\hydrogen-desktop\ports.json--# From inside the WSL2 workspace — USE THIS. HD writes its live control URL to a discovery-# file every launch (mirrored loopback), so you never hunt for the dynamic port:+# From inside the workspace — USE THIS. HD writes its live control URL to a discovery+# file every launch, so you never hunt for the dynamic port: CTRL="$(cat ~/.adom/hd-control-url)"; curl -sf "$CTRL/health" ``` @@ -52,6 +48,10 @@ rewrites it with the live dynamic port every launch. This is the channel for the the live ports map, Claude control, etc. — distinct from `adom-cli` (`ADOM_HYDROGEN_URL` → SSE), which is unchanged for web-hydrogen parity. +> For the host-side ways to discover the port (HD log/`ports.json`) and the+> host runtime endpoints (`/wsl/*`, `/docker/*`, `/system/reboot`), see the+> [[hd-api-windows]] companion skill.+ ## Health & Status  | Method | Path | Description |@@ -59,7 +59,7 @@ which is unchanged for web-hydrogen parity. | GET | `/health` | HD alive check — returns `{ok, port, service}` | | GET | `/buildinfo` | Running build git SHA + build metadata (the only trustworthy "did my build ship?" check) | | GET | `/ports` | The 4 editable PortConfig ports (proxy, control, cdp, code_server) |-| GET | `/ports/all` | LIVE full port map — every host + WSL2 port HD has bound, with status + mirrored-mode info |+| GET | `/ports/all` | LIVE full port map — every port HD has bound, with status info |  ## AD-health diagnostics (`/ad/*`) @@ -92,7 +92,7 @@ Open/close/toggle any HD menu, dialog, or panel — the first-class alternative  ## Workspace / Container Management -These endpoints manage the active workspace runtime (a WSL2 distro by default, or a Docker container under `HD_RUNTIME=docker`).+These endpoints manage the active workspace runtime.  | Method | Path | Body | Description | |---|---|---|---|@@ -102,7 +102,6 @@ These endpoints manage the active workspace runtime (a WSL2 distro by default, o | POST | `/container-stop` | — | Stop the active workspace runtime | | POST | `/container-exec` | `{"command":"..."}` | Run command in the workspace as user `adom` | | POST | `/container-delete` | — | Remove the workspace |-| POST | `/volume-delete` | — | Remove project volume (DESTRUCTIVE). **Docker runtime only** — no volume exists under WSL. | | POST | `/image-delete` | — | Remove workspace image | | GET | `/container-images` | — | List available workspace images | | POST | `/container-switch-image` | `{"image":"..."}` | Switch to different image |@@ -113,42 +112,9 @@ These endpoints manage the active workspace runtime (a WSL2 distro by default, o | GET | `/container/disk` | — | Disk usage inside the workspace | | POST | `/container/restart` | — | Alias for `/container-restart` | -### WSL runtime endpoints (default runtime)--When HD runs the workspace as a WSL2 distro, it additionally exposes:--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/wsl/status` | — | WSL distro state (registered, running, code-server reachable) |-| GET | `/workspace/health` | — | Deep workspace health (distro + code-server + host reachability) |-| GET | `/virgin-reset-progress` | — | Live progress of an in-flight virgin reset |-| POST | `/workspace/terminal-profile` | — | Ensure the stable `Adom-Workspace` Windows Terminal profile (idempotent) |-| POST | `/workspace/terminal-profile/remove` | — | Remove the `Adom-Workspace` Windows Terminal profile(s) |-| POST | `/workspace/check-updates` | — | Check upstream for newer code-server + Claude extension; stage them |-| POST | `/workspace/apply-updates` | — | Apply staged code-server/extension updates + reload editor |--> ⛔ `POST /wsl/unregister` is **REFUSED as deprecated** — it was a headless-> destructive reset (deletes `/home/adom/project`). Use the Setup panel's Virgin-> Reset or `POST /setup/panel/run-virgin-reset` instead.--## Docker Desktop (legacy Docker runtime only — `HD_RUNTIME=docker`)--This `/docker/*` table applies only when HD is running the legacy Docker runtime.--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/docker/status` | — | Docker Desktop running state |-| GET | `/docker/version` | — | Docker engine version |-| GET | `/docker/containers` | — | List all Docker containers |-| GET | `/docker/images` | — | List all Docker images |-| POST | `/docker/start` | — | Launch Docker Desktop + start container |-| POST | `/docker/stop` | — | Stop Docker Desktop |-| POST | `/docker/restart` | — | Restart Docker Desktop |-| POST | `/docker/wait-ready` | — | Block until Docker daemon responds |-| POST | `/docker/install` | — | Install Docker Desktop (downloads ~730 MB) |-| POST | `/docker/uninstall` | — | Uninstall Docker Desktop |-| POST | `/docker/clean-reinstall` | — | Uninstall + reinstall Docker Desktop |-| GET | `/docker/install-progress` | — | Current install step + progress |+> Runtime-specific endpoints — the WSL `/wsl/*` tables, the legacy Docker+> `/docker/*` tables, and `/volume-delete` (Docker-only) — live in the+> [[hd-api-windows]] companion skill.  ## WebView & VS Code @@ -266,8 +232,8 @@ glides it, and can click. Use for demos or when the user should see where the AI | POST | `/config-reset` | — | Reset HD config |  > ⛔ **REFUSED as deprecated** (headless runs with no visible UI):-> `POST /setup/run-all`, `POST /setup/run-step`, `POST /setup/virgin-reset`,-> `POST /wsl/unregister`. They return a refusal pointing at the UI-visible path.+> `POST /setup/run-all`, `POST /setup/run-step`, `POST /setup/virgin-reset`.+> They return a refusal pointing at the UI-visible path. > To run steps: use `POST /setup/step/<id>` or relaunch HD to auto-run the cascade.  ### Setup panel control@@ -293,15 +259,6 @@ glides it, and can click. Use for demos or when the user should see where the AI | GET | `/workspace/tabs/find?name=X` | — | Find tab by name (404 if not found) | | POST | `/workspace/tabs` | `{tab spec}` | Add a new tab | -## System--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/system/nonce` | — | Get nonce for authenticated reboot |-| GET | `/system/reboot-state` | — | Check reboot pending state |-| POST | `/system/reboot` | `{"nonce":"..."}` | Reboot Windows (nonce-authenticated) |-| POST | `/system/cancel-reboot` | — | Cancel pending reboot |- ## App lifecycle & window  | Method | Path | Body | Description |@@ -310,6 +267,9 @@ glides it, and can click. Use for demos or when the user should see where the AI | POST | `/app/relaunch-frontend` | — | Relaunch the HD GUI (kill+respawn) while it is responsive | | POST | `/window/foreground` | — | Bring the HD window to the foreground (unminimize + focus) | +> Host OS reboot (`/system/*`) is platform-specific — see the+> [[hd-api-windows]] companion skill.+ ## Diagnostics (`/test/*`)  Window enumeration, UIA clicking, native-dialog classification, and cascade@@ -323,10 +283,13 @@ disabled" otherwise). `GET /test/help` self-lists the whole cluster. | POST | `/test/focus` | `{"window":"..."}` | Focus HD (`self`) or a window by title substring | | POST | `/test/click-uia` | `{...}` | Poll UIAutomation for a Button by Name; Invoke when found | | GET | `/test/setup-steps` | — | Raw setup-steps.json + derived summary (alias: `/test/install-steps`) |-| POST | `/test/dump-state` | `{...}` | Write a diagnostic bundle (logs, install-steps, docker, tasklist, window-tree) |+| POST | `/test/dump-state` | `{...}` | Write a diagnostic bundle (logs, install-steps, runtime state, tasklist, window-tree) | | POST | `/test/reset-cascade` | — | Delete install-steps.json + emit setup-reset event | | POST | `/test/screenshot-hd-window` | `{...}` | Capture HD's own window to a PNG file |-| GET | `/test/probe-dialogs` | — | Enumerate visible windows, classify against the cascade-blocker catalog (UAC, WSL2 update, MSI installer, Docker EULA, …); returns `kind` + `is_blocking` per window |++> The `/test/probe-dialogs` endpoint (classifies UAC / WSL2-update / MSI /+> Docker-EULA blocker windows) is Windows-specific — see the+> [[hd-api-windows]] companion.  ## Key Patterns @@ -348,7 +311,7 @@ POST /container-exec {"command":"ls /home/adom/project"} ```  ### Trigger setup re-run after completion-The trigger file poller STOPS when all steps are done. Use the API instead:+The trigger file poller STOPS when all steps are done. Use the step API instead: ```-POST /setup/run-all+POST /setup/step/<id> {"continue_after": true} ```
skills/hd-captions/SKILL.md+61−124
@@ -1,73 +1,63 @@ --- name: hd-captions description: >-  Paint labeled caption text on screen for demos/walkthroughs — captions are-  CAPTURED BY RECORDINGS so they show up in the finished video. HD has TWO caption-  surfaces: (1) a WORKSPACE caption rendered inside the HD window via-  `adom-cli hydrogen caption` — THE default, identical on web-Hydrogen AND HD-  (text positional; `-d` duration in SECONDS not ms; 30s auto-expire by default, 5-min-  hard cap, newest-wins, `hide` to clear; a raw-HTTP `POST .../current/caption` fallback-  exists for scripts hitting HD's API directly), and-  (2) a full-DESKTOP overlay over ALL windows via `adom-desktop desktop_caption` — HD's-  built-in Win32 always-on-top, click-through overlay (duration in MILLISECONDS — opposite-  unit). Pick by what you're recording: workspace recording → workspace-  caption; whole-screen / other-apps (KiCad, browser) recording → desktop overlay.-  Covers both, the desktop-overlay args (text, id, position top/center/bottom/corners,-  normalized x/y, size/fontSize, duration, action: hide|force-clear) and the id rule-  (same id replaces, different ids coexist). Windows-only for the desktop overlay.-  Distinct from toasts (notifications) and TTS (audio). Trigger words — caption,-  on-screen caption, workspace caption, hydrogen caption, screen overlay, screen-  label, callout, annotate the screen, step label, put text on screen, overlay text,-  always on top text, click-through overlay, desktop caption, caption command,-  adom-cli hydrogen caption, walkthrough label, demo callout, status overlay, label-  the screen, point at the screen, hide caption, clear captions, step 3 callout,-  caption duration, caption seconds, caption auto-expire, caption stuck on screen,-  caption units, caption position, caption size, persist caption.+  Paint labeled caption text on the Hydrogen Desktop workspace for demos/walkthroughs —+  captions are CAPTURED BY RECORDINGS so they show up in the finished video. Drive the+  WORKSPACE caption with `adom-cli hydrogen caption` — THE default, identical on+  web-Hydrogen AND HD (text positional; `-d` duration in SECONDS not ms; 30s auto-expire+  by default, 5-min hard cap, newest-wins, `hide` to clear; a raw-HTTP+  `POST .../current/caption` fallback exists for scripts hitting HD's API directly).+  Distinct from toasts (notifications) and TTS (audio). NOTE: a full-DESKTOP overlay+  (over every window, on top of other apps) exists as a platform-specific companion —+  see [[hd-captions-windows]]. Trigger words — caption, on-screen caption, workspace+  caption, hydrogen caption, screen overlay, screen label, callout, annotate the screen,+  step label, put text on screen, overlay text, caption command, adom-cli hydrogen+  caption, walkthrough label, demo callout, status overlay, label the screen, hide+  caption, clear captions, step 3 callout, caption duration, caption seconds, caption+  auto-expire, caption stuck on screen, caption units, caption position, caption size,+  persist caption. ---  # Hydrogen Desktop — On-Screen Captions -You can **paint labeled caption text on screen** for demos and walkthroughs — and-because captions are real pixels, **they're captured by recordings**, so they end up-in the finished video ("Step 3: approve the UAC dialog →").+You can **paint labeled caption text on the Hydrogen Desktop workspace** for demos and+walkthroughs — and because captions are real pixels, **they're captured by recordings**,+so they end up in the finished video ("Step 3: run DRC →").  > Captions are **visual on-screen narration** — centered status / countdowns / "what > I'm doing," great during demos and recordings. Distinct from: > - **toasts** — corner pop-ups via `POST /ui/toast` (transient notifications, see >   `hd-notifications`); a caption is centered narration, a toast is a corner alert. > - **TTS** *audio* narration (`adom-tts`) — pair a caption with TTS for a narrated walkthrough.-> - the **native Win32 auth-overlay caption** — a separate internal surface HD draws for->   login/auth flows; not something you trigger for demos. The two surfaces below are the->   ones you drive.+> - the internal **auth-overlay caption** HD draws for login/auth flows — not something+>   you trigger for demos. The workspace caption below is the one you drive.  ## Two caption surfaces — pick by WHAT you're recording -HD has **two** caption surfaces. Choosing the right one is the key decision, because-each is captured by a *different* kind of recording:+HD has **two** caption surfaces, each captured by a *different* kind of recording:  | Surface | Command | Renders | Captured by | Use when | |---|---|---|---|---| | **Workspace caption** | `adom-cli hydrogen caption` | **inside the HD workspace** (webview overlay, web-Hydrogen style) | a recording/screenshot of the **HD window** (panel/workspace) | the demo is **inside HD** — captioning the workspace itself |-| **Desktop overlay** | `adom-desktop desktop_caption` | **over the WHOLE desktop**, above every window (Win32) | a **full-screen / desktop** recording (native `recording --share screen`, AD desktop) | the demo shows **other apps** (KiCad, Fusion, a browser) or the whole screen |+| **Desktop overlay** | platform-specific (see [[hd-captions-windows]]) | **over the WHOLE desktop**, above every window | a **full-screen / desktop** recording | the demo shows **other apps** (KiCad, Fusion, a browser) or the whole screen | -**Match the caption to the recording.** A native `screenshot panel` / workspace-Element-Capture sees the **webview** content, so it captures the **workspace** caption-but NOT the desktop overlay (a separate OS window). A full-**screen** recording-captures the **desktop overlay** (it's screen pixels). Pick wrong and your caption-won't be in the video.+**Match the caption to the recording.** A `screenshot panel` / workspace capture sees the+**webview** content, so it captures the **workspace** caption but NOT a desktop overlay (a+separate OS window). A full-**screen** recording captures the **desktop overlay** (it's+screen pixels). Pick wrong and your caption won't be in the video.  > Quick rule: "caption the Hydrogen workspace" → `adom-cli hydrogen caption`;-> "caption over the whole screen / while I record KiCad / a corner status label" →-> `adom-desktop desktop_caption` (the only one with corners, ids, and x/y).+> "caption over the whole screen / while I record KiCad / a corner status label" → the+> desktop overlay in the platform companion (the only one with corners, ids, and x/y). -## (1) Workspace caption — `adom-cli hydrogen caption` ⭐ THE DEFAULT+## Workspace caption — `adom-cli hydrogen caption` ⭐ THE DEFAULT -**Reach for this FIRST.** It's the *same* command on web Hydrogen and HD (adom-cli-routes through HD's workspace-events server → SSE → the frontend `captionStore`), so it-stays consistent across both — John's principle, same as screenshots. Renders centered-**inside the HD workspace webview**. `show` takes the TEXT as a **positional arg** (NOT-`--text`); the only flags are `-d`/`--duration`, `-p`/`--position`, `-s`/`--size` (no-`id`, `x`/`y`, or `fontSize` — those are desktop-overlay-only). Subcommands: `show` / `hide`.+**Reach for this FIRST.** It's the *same* command on web Hydrogen and HD (adom-cli routes+through HD's workspace-events server → SSE → the frontend `captionStore`), so it stays+consistent across both — same principle as screenshots. Renders centered **inside the HD+workspace webview**. `show` takes the TEXT as a **positional arg** (NOT `--text`); the only+flags are `-d`/`--duration`, `-p`/`--position`, `-s`/`--size` (no `id`, `x`/`y`, or+`fontSize` — those are desktop-overlay-only). Subcommands: `show` / `hide`.  ```bash adom-cli hydrogen caption show "Step 1: open the board" -p center -s large     # 30s auto-expire@@ -76,26 +66,24 @@ adom-cli hydrogen caption hide ```  ### ⚠️⚠️ `-d` / `duration` is in **SECONDS — NOT milliseconds** ⚠️⚠️-THE gotcha. `-d 30` = 30 seconds. `-d 4000` = **66 MINUTES**, not 4 seconds. (This bit-the build thread — `-d 4000` left a caption stuck on screen for over an hour.) If you're+THE gotcha. `-d 30` = 30 seconds. `-d 4000` = **66 MINUTES**, not 4 seconds. If you're thinking in ms you're off by **1000×**. You almost never need a big number — the 30s default already covers "leave it up while I do a thing." (Note: the *desktop overlay* in-§2 uses **milliseconds** — the two surfaces differ; don't cross the units.)--> **Web-Hydrogen vs HD parity (checked live 2026-06-14):** the **command + the SECONDS-> unit + `hide` are identical** on both (verified by firing `adom-cli hydrogen caption` in-> a cloud web-Hydrogen workspace — center/large rendered, `-d 20` held visibly). BUT the-> sane **lifecycle below (30s default / 300s cap / persist) is verified on HD v0.1.34+**;-> web Hydrogen still returns the *older terse `_hint`* ("auto-hides after the specified-> duration") and may not enforce the 30s-default/300s-cap yet. **So on web Hydrogen, don't-> assume a fat `-d` self-heals — pass a sane duration.** (Web-Hydrogen backend sync is a-> Colby/carbon item.)--### Lifecycle (HD v0.1.34+, verified live 2026-06-14 — sane, never abandoned)+the platform companion uses **milliseconds** — the two surfaces differ; don't cross the+units.)++> **Web-Hydrogen vs HD parity:** the **command + the SECONDS unit + `hide` are identical**+> on both (center/large rendering, `-d 20` held visibly). BUT the sane **lifecycle below+> (30s default / 300s cap / persist)** is verified on HD; web Hydrogen may still return the+> *older terse `_hint`* ("auto-hides after the specified duration") and may not enforce the+> 30s-default/300s-cap yet. **So on web Hydrogen, don't assume a fat `-d` self-heals — pass+> a sane duration.**++### Lifecycle (sane, never abandoned) - **No `-d` (or `-d 0`) → auto-expires after 30s.** The right default — you do NOT need   to `hide` it. - **Positive `-d <seconds>` → holds that many seconds, HARD-CAPPED at 300s (5 min).** A-  larger value still clears at 5 min, so a fat-fingered `-d 4000` now self-heals.+  larger value still clears at 5 min, so a fat-fingered `-d 4000` self-heals. - **Newest wins:** showing another caption replaces the current one; `hide` clears immediately. - **No "forever" via adom-cli** — its `-d` is an unsigned int (rejects negatives) by   design. This is a **feature, not a gap**: adom-cli is the same binary on web-Hydrogen and@@ -103,8 +91,7 @@ default already covers "leave it up while I do a thing." (Note: the *desktop ove   captions). A persist-until-hidden escape exists ONLY on the raw HTTP endpoint   (`{"duration":-1}`, below) — rarely needed. - **No `caption status` verb (yet).** There's no way to query "is a caption up / how long-  left" from adom-cli — and with newest-wins + the 30s auto-expire you rarely need to. (A-  read-only `caption status` is a possible future verb, not a current one.)+  left" from adom-cli — and with newest-wins + the 30s auto-expire you rarely need to. - `-p` position: `top` / `center` / `bottom` (NO corners — use the desktop overlay for   those). `-s` size: `small` / `medium` / `large`. - Needs a live workspace/editor session (the server returns 409 if none).@@ -126,73 +113,23 @@ curl -s -X POST "$ADOM_HYDROGEN_URL/api/workspaces/editor/<owner>/<repo>/current # persist until hidden (HTTP-ONLY escape — adom-cli can't send a negative): #   -d '{"text":"Recording…","duration":-1}' ```-Body: `{text, duration (SECONDS), position, size}`; clear with `{hide:true}`. Returns the-same `_hint` as adom-cli (verified live).--## (2) Desktop overlay caption — `adom-desktop desktop_caption`--HD's built-in **Win32 always-on-top, click-through overlay** — floats over every-window, doesn't steal focus or intercept clicks (the user works "through" it). The-full-featured surface (ids, corners, x/y, force-clear). **Windows-only** (non-Windows-no-ops).--## Firing a caption--Source: `src-tauri/crates/hd-app/src/caption.rs` (`handle_caption`). The AD CLI verb is-**`desktop_caption`** (the internal message type is `caption`; `adom-desktop status`-lists the `caption` capability). Plain `adom-desktop caption` is NOT a verb — it errors.--```bash-adom-desktop desktop_caption '{"text":"Step 3: approve the UAC dialog →","position":"center","size":"large","duration":6000}'-```+Body: `{text, duration (SECONDS), position, size}`; clear with `{hide:true}`. -### Arguments+## Desktop overlay caption (over the whole screen) -| Arg | Type | Meaning |-|---|---|---|-| `text` | string | The caption text. Omit (with no `action`) to hide. |-| `id` | string | Caption identity. **Same id → replaces** that caption; **different ids → coexist.** Defaults to `_default`. |-| `position` | string | `top`, `bottom` (default), `center`, `top-left`, `top-right`, `bottom-left`, `bottom-right`. |-| `x` / `y` | float | **Normalized 0.0–1.0** screen coordinates (clamped). Use for precise placement instead of a named `position`. |-| `size` | string | `large` / `medium` (default) / `small`. |-| `fontSize` | int | Explicit pixel font height (also accepts `font_size`). Overrides `size`. |-| `duration` | int | **Milliseconds** on screen (default 4000), then a short fade-out. ⚠️ **NOTE: this surface is ms — the OPPOSITE of the §1 workspace caption, whose `-d` is SECONDS.** `4000` here = 4s; `4000` there = 66 min. |-| `action` | string | `hide` (dismiss this id, or all if id empty) or `force-clear` (destroy **all** captions regardless of id). |--### The id rule (this is the powerful part)--Captions are keyed by `id`. **Reuse an id to update a caption in place**; **use-different ids to show several at once.** That lets you run, e.g., a persistent-status caption in a corner *and* a moving center callout simultaneously:--```bash-# persistent status in the corner-adom-desktop desktop_caption '{"id":"status","text":"Recording…","position":"top-right","size":"small","duration":60000}'--# step callouts in the center, each replacing the last (same id)-adom-desktop desktop_caption '{"id":"step","text":"Step 1: open the board","position":"center","duration":4000}'-adom-desktop desktop_caption '{"id":"step","text":"Step 2: run DRC","position":"center","duration":4000}'--# clear just the step callout-adom-desktop desktop_caption '{"id":"step","action":"hide"}'--# nuke everything-adom-desktop desktop_caption '{"action":"force-clear"}'-```+For a caption that floats over **every window** (above other apps, the whole desktop) —+with ids, corners, and normalized x/y placement — HD provides a native always-on-top,+click-through desktop overlay. That surface and its arguments are **platform-specific**;+see **[[hd-captions-windows]]**.  ## Patterns -- **Walkthrough / demo callouts** — drop a `center` caption per step (same `id` so-  each replaces the last). Combine with a recording (see Related skills) so the-  callouts end up in the finished video. Pair with TTS for narration.-- **Status corner** — a long-`duration` small caption in a corner (`top-right`),-  separate `id`, while you drive the rest of the screen.-- **Point at a thing** — use normalized `x`/`y` to sit a label next to a button or-  dialog you're about to act on.-- **Cleanup** — `action:"hide"` per id when a step is done; `action:"force-clear"`-  to wipe the screen of all captions at the end of a tour.+- **Walkthrough / demo callouts** — drop a `center` caption per step. Combine with a+  recording so the callouts end up in the finished video. Pair with TTS for narration.+- **Status corner / point-at-a-thing** — these need named corners or normalized x/y, which+  only the desktop overlay provides; see [[hd-captions-windows]].  ## Related skills-- [hd-recording](../hd-recording/SKILL.md) — captions are captured *into* screen recordings; record a walkthrough with live callouts-- [hd-adom-desktop](../hd-adom-desktop/SKILL.md) — AD carries the `caption` / `desktop_caption` verb to the host; verify the `caption` capability via `adom-desktop status`+- [hd-adom-desktop](../hd-adom-desktop/SKILL.md) — the relay that carries caption verbs to the host - `adom-tts` — *audio* narration to pair with on-screen captions (captions are visual-only)+- [[hd-captions-windows]] — the full-desktop always-on-top overlay caption surface
skills/hd-claude-auth/SKILL.md+11−11
@@ -1,6 +1,6 @@ --- name: hd-claude-auth-description: How Claude Code authenticates inside HD — the OAuth flow that opens in your browser via the Browser Picker, where credentials are stored on host vs container, how HD backs them up so a container rebuild doesn't make you re-auth, the virgin-reset toggle that wipes Claude creds, and the 4-technique auth cascade HD runs if Claude isn't authenticated. READ when troubleshooting "Claude not authenticated", expired Claude tokens, re-authenticating after a virgin reset, or wondering where Claude credentials live. Trigger words — claude auth, claude code login, claude code authentication, claude not authenticated, claude oauth, claude credentials, claude session, claude.ai subscription, replay-claude-credentials.json, claude-auth, claude credential backup, claude re-auth, claude expired, claude.ai subscription button.+description: How Claude Code authenticates inside HD — the OAuth flow that opens in your browser via the Browser Picker, where credentials are stored on host vs workspace, how HD backs them up so a workspace rebuild doesn't make you re-auth, the virgin-reset toggle that wipes Claude creds, and the 4-technique auth cascade HD runs if Claude isn't authenticated. READ when troubleshooting "Claude not authenticated", expired Claude tokens, re-authenticating after a virgin reset, or wondering where Claude credentials live. Trigger words — claude auth, claude code login, claude code authentication, claude not authenticated, claude oauth, claude credentials, claude session, claude.ai subscription, replay-claude-credentials.json, claude-auth, claude credential backup, claude re-auth, claude expired, claude.ai subscription button. ---  # HD Claude Auth — how Claude Code signs in@@ -16,14 +16,14 @@ For Adom auth (your hydrogen.adom.inc login), see [hd-adom-auth](../hd-adom-auth 3. HD's Browser Picker intercepts the URL (since it's a `*.claude.ai` link). The "Claude auth" branded variant of the picker appears with the work browser profile pre-selected and a 5-second auto-countdown. 4. The browser opens the Claude OAuth page; you complete sign-in (or it auto-completes if you're already signed in to claude.ai). 5. Claude returns OAuth credentials, which the extension stores at `/home/adom/.claude/.credentials.json` inside the workspace.-6. HD's setup step `claude-auth` notices the new credentials and **backs them up to the host** at `%APPDATA%\hydrogen-desktop\replay-claude-credentials.json` so future workspace rebuilds can replay them.+6. HD's setup step `claude-auth` notices the new credentials and **backs them up to the host** (in HD's app-data directory, as `replay-claude-credentials.json`) so future workspace rebuilds can replay them. The exact host path is platform-specific — see the platform layer for where it lives on your OS.  ## Where Claude credentials live -| Layer | Path | Purpose |-|-------|------|---------|+| Layer | Location | Purpose |+|-------|----------|---------| | Inside workspace (live) | `/home/adom/.claude/.credentials.json` | Active credentials the extension and `claude` CLI both read |-| Host-side backup | `%APPDATA%\hydrogen-desktop\replay-claude-credentials.json` | Backup so a fresh workspace can be re-authenticated without re-OAuth |+| Host-side backup | `replay-claude-credentials.json` in HD's app-data dir on the host | Backup so a fresh workspace can be re-authenticated without re-OAuth | | VS Code secret store (in code-server's user data) | webview-internal, can't be inspected directly | The extension also keeps a secret per panel; this is what dictates the chat UI showing vs the auth button |  **Key insight**: each Claude Code panel instance keeps its own auth state. If one panel says "not authenticated", opening a NEW Claude Code conversation panel often shows the auth button fresh and lets you sign in cleanly.@@ -33,7 +33,7 @@ For Adom auth (your hydrogen.adom.inc login), see [hd-adom-auth](../hd-adom-auth When you virgin-reset and rebuild the workspace (assuming you DON'T check the "Claude credentials" toggle):  1. Workspace deleted + recreated by setup steps-2. Step `claude-auth` runs early — reads `replay-claude-credentials.json` from `%APPDATA%`+2. Step `claude-auth` runs early — reads the `replay-claude-credentials.json` backup from HD's host app-data dir 3. If the file exists AND the `expiresAt` is still in the future → copies it into the new workspace at `/home/adom/.claude/.credentials.json` 4. Claude Code extension reads it on first launch → user stays signed in @@ -46,7 +46,7 @@ If Claude isn't authenticated after setup, HD tries each technique in order unti | # | Technique | What it does | |---|-----------|--------------| | 1 | Detect auth failure | Scans all VS Code webview contexts for the "Claude.ai Subscription" button / "How do you want to log in?" text. Confirms whether the auth UI is reachable. |-| 2 | Open NEW conversation + auto-click auth button | The new-conversation panel re-evaluates auth state and shows the button cleanly. HD clicks it via CDP. |+| 2 | Open NEW conversation + auto-click auth button | The new-conversation panel re-evaluates auth state and shows the button cleanly. HD clicks it via the webview eval channel. | | 3 | Open Claude editor + auto-click auth button | If technique 2 didn't trigger a fresh auth state, opens a Claude editor (different VS Code command) and tries the same click. | | 4 | CLI fallback (`claude auth login`) | Runs `claude auth login` inside the workspace, extracts the OAuth URL from stdout, opens it in your browser via the Browser Picker. You paste the returned code into a VS Code terminal. | @@ -58,7 +58,7 @@ The setup panel's Virgin Reset section has a per-Claude-creds toggle:  | Toggle | What happens to Claude auth | When to use | |--------|----------------------------|-------------|-| **Claude credentials** (default OFF) | Deletes `replay-claude-credentials.json` from host AND the credentials inside the workspace. **You will need to re-OAuth.** | When Claude is stuck in a broken auth state and you want a true fresh sign-in. |+| **Claude credentials** (default OFF) | Deletes the `replay-claude-credentials.json` backup from the host AND the credentials inside the workspace. **You will need to re-OAuth.** | When Claude is stuck in a broken auth state and you want a true fresh sign-in. | | **Workspace** (default ON) | The workspace is rebuilt. If Claude creds toggle is OFF (default), `claude-auth` replays the backup → you stay signed in. | Normal virgin reset for testing. | | **Workspace data** (default ON) | Wipes your `/home/adom/project/` work. Doesn't directly affect Claude creds, but rebuilds the workspace — same as above. | When you want a totally fresh `~/project/`. | @@ -70,17 +70,17 @@ The setup panel's Virgin Reset section has a per-Claude-creds toggle: - A SECOND panel still has stale auth state. Close all Claude Code panels and open one fresh — it'll read the new credentials.  **Credentials backup file exists but Claude says expired**-- Open `%APPDATA%\hydrogen-desktop\replay-claude-credentials.json` and check the `expiresAt` (epoch ms). Compare to current time. If past, you need to re-OAuth. HD's auth cascade will handle this on next setup run.+- Open the `replay-claude-credentials.json` backup (in HD's host app-data dir) and check the `expiresAt` (epoch ms). Compare to current time. If past, you need to re-OAuth. HD's auth cascade will handle this on next setup run.  **`claude auth status` says `loggedIn: true` but the extension says not authenticated** - **Known quirk**: the CLI and the VS Code extension use SEPARATE credential stores. `claude auth status` checks the CLI store; the extension uses VS Code secrets. Trust the extension UI (the "Claude.ai Subscription" button) over the CLI's status output.  **OAuth callback fails / browser shows "connection refused"**-- The callback URL is hitting a localhost port that HD hasn't bound on Windows. Check the HD log for `[oauth] Callback port N detected` — HD should auto-start a proxy for it. If not, register the port manually via `adom-cli port-forward register <port> --visibility external`.+- The callback URL is hitting a local port that HD hasn't forwarded to the host. Check the HD log for `[oauth] Callback port N detected` — HD should auto-start a proxy for it. If not, register the port manually via `adom-cli port-forward register <port> --visibility external`. (How host↔workspace port forwarding works is platform-specific — see the platform layer.)  ## Related skills  - [hd-adom-auth](../hd-adom-auth/SKILL.md) — Adom (hydrogen.adom.inc) login, separate from Claude - [hd-browser-picker](../hd-browser-picker/SKILL.md) — the Browser Picker that routes the Claude OAuth URL, including the branded "Claude auth" variant-- `hd-setup-steps` — the `claude-auth` step and the auth cascade are part of setup (the runtime-specific hd-setup-steps shows where it falls in the cascade)+- `hd-setup-steps` — the `claude-auth` step and the auth cascade are part of setup - `hd-volume` — explains why the host-side backup survives workspace rebuild
skills/hd-container-stats/SKILL.mdadded+134
@@ -0,0 +1,134 @@+---+name: hd-container-stats+description: HD's workspace stats indicator in the top-right of the title bar — two thin progress bars (CPU + RAM) labelled "Container" plus an info tooltip on hover that shows the workspace name, CPU vs total cores, RAM usage vs limit, disk usage, image, ID, and creation date. Polls once per second when running, every 5 seconds when stopped. Status badges show stopped / starting / restarting / restart-needed states. Use this skill when the user asks about CPU/RAM usage, the resource bars in HD's title bar, workspace disk usage, the "restart needed" badge, why bars are red/yellow, or what's in the tooltip. Trigger words — container stats, workspace stats, container cpu, container ram, container disk, resource bars, cpu bar, ram bar, container tooltip, container indicator, top bar stats, restart needed badge, container stopped badge, container starting, workspace_stats, workspace stats.+---++# HD Workspace Stats Indicator++The top-right of HD's title bar (next to the audio/video icons and your profile avatar) shows a tiny `Container` block with two horizontal progress bars — CPU% and RAM% — that animate in real-time. Hovering brings up a tooltip with the full workspace details. The numbers reflect your **local HD workspace**; the header reads "Container" on all platforms.++> Platform layers add a `*-windows` companion ([[hd-container-stats-windows]]) with the host-specific probe — the WSL `workspace_stats()` health check, `wsl --terminate` restart, the benign `[docker]` log line, and distro disk semantics.++## How often it polls++There's an active polling loop in HD's title bar that asks the runtime for fresh stats on a timer:++- **Every 1 second** when the workspace is `running` — for live, smooth bar animation+- **Every 5 seconds** when it's `stopped`, `starting`, `restarting`, or `restart needed` — saves cycles when nothing's changing++Each poll calls Tauri `invoke('get_container_stats')`, which dispatches through the runtime trait (`WorkspaceRuntime::get_stats`) to the active host's probe. The probe runs with short timeouts so a hung host subsystem can't freeze the UI.++If you ever want to lighten the load (e.g. on a battery-constrained laptop), the relevant code is in `EditorNav.svelte`'s `pollStats()` closure — adjust the `pollInterval` ternary.++## What the bars show++| Bar | What it measures |+|-----|------------------|+| CPU | % of the workspace's available CPU being consumed (1.0 = 1 full vCPU). Capped at 100% display |+| RAM | % of the workspace's memory in use vs its limit |++Both bars share the same color-threshold rules:+- **Teal / green** — ≤ 50% usage (normal)+- **Yellow** (`warn` class) — 51-80% usage+- **Red** (`danger` class) — > 80% usage++## What the tooltip shows++When you hover over the bars, a tooltip appears with:++| Line | Example |+|------|---------|+| Container | the workspace name |+| CPU + RAM totals | `CPU: 1.7% of 16 cores | RAM: 0.7 GB / 16.0 GB` |+| Disk | `Disk: 1.3 GB` (workspace disk usage) |+| Image | `Image: Ubuntu 24.04` |+| ID | the registered workspace identifier |+| Created | `5/24/2026, 3:18:09 PM` (locale-formatted) |++If the workspace is in a non-healthy state, the tooltip shows a single red line instead:+- `Workspace is stopped — start from the menu` (when stopped)+- `Workspace runtime is broken — restart from the menu` (when the workspace / code-server is unreachable, e.g. after sleep/hibernate)++## Status badge in the header++The `Container` text in the section header gets an inline status badge depending on state:++| Badge | Meaning | Color |+|-------|---------|-------|+| (no badge) | Running normally | normal |+| `stopped` | Workspace registered but not running | red |+| `starting` | HD is starting the workspace / code-server | yellow |+| `restarting` | HD is restarting the workspace | yellow |+| `restart needed` | The workspace or code-server is unreachable (usually a hiccup after the host wakes from sleep) | red |++When `restart needed` shows, open the Adom menu → Restart Workspace (see the `[[hd-ui]]` skill for the Adom menu). A "Restart" here terminates and re-ensures the workspace + code-server.++## How it works under the hood++- **Polling frequency**: see "How often it polls" above — 1s when running, 5s when not.+- **Backend command**: Tauri `invoke('get_container_stats')` → `WorkspaceRuntime::get_stats`, routed to the active host runtime's probe.+- **Two health levels** the probe checks: (1) is the host runtime itself available; (2) is the workspace registered + running with code-server reachable on host port 7380. If either fails, the probe returns a needs-restart signal instead of stats and the UI shows the red "restart needed" badge.+- **Rate-limited error logging**: the "needs restart" log line is printed at most once every 30 seconds, even though the frontend polls every 1s, so the log stays readable.++The authoritative "which runtime am I on" log line is `[app] Active workspace runtime: …`. (Platform-specific log signals — e.g. the benign Windows `[docker]` heartbeat — are covered in `[[hd-container-stats-windows]]`.)++## API access++If you want the same stats data your AI can hit directly via the control API:++```bash+# From inside the workspace — query the control API on the host+curl -s "$(cat ~/.adom/hd-control-url)/container-stats"+```++(Read the live URL from `~/.adom/hd-control-url` rather than hardcoding it — the port is **dynamic per launch**.)++Returns JSON like:+```json+{+  "ok": true,+  "container_name": "Adom-Workspace",+  "container_id": "Adom-Workspace",+  "container_created": "2026-05-24T20:18:09Z",+  "image": "Ubuntu 24.04",+  "cpu_percent": 1.7,+  "cpu_cores": 16,+  "mem_usage_mb": 716,+  "mem_limit_mb": 16384,+  "mem_percent": 4.4,+  "disk_usage_mb": 1300+}+```++Or if the workspace is in a broken state:+```json+{ "ok": false, "needs_restart": true, "error": "Workspace needs restart" }+```++## CSS selectors++| Element | Selector |+|---------|----------|+| The whole indicator block | `.resource-bars` |+| Header with title + status badge | `.resource-bars-header` |+| Title text ("Container") | `.resource-bars-title` |+| One bar row (CPU or RAM) | `.resource-bar-item` |+| Bar fill | `.resource-bar-fill` (modifier classes: `.warn`, `.danger`) |+| Bar percentage label | `.resource-bar-value` |+| Hover tooltip container | `.resource-bars-tooltip` |+| One tooltip line | `.resource-bars-tooltip-row` |++## Common questions++**"Why is CPU showing 200% / 1600%?"** It's not — the displayed % is capped at 100 for the bar fill, but the tooltip shows the real number. CPU of `100% of 16 cores` means 1 full vCPU pegged.++**"Why does RAM stay constant at ~4% even when I'm doing nothing?"** Code-server, the relay, gallia, the adom-vscode HTTP API, etc. all run in the workspace all the time. ~700 MB baseline is normal.++**"The 'restart needed' badge appeared — what happened?"** Almost always a hiccup after the host woke from sleep/hibernate, leaving the workspace or code-server unreachable. Click Restart Workspace in the Adom menu (top-left); HD restarts the workspace, re-ensures code-server, and the badge clears.++**"Disk is 1.3 GB — does that include my project files?"** Yes — `/home/adom/project` lives inside the workspace, so the `Disk:` figure includes your project.++## Related skills++- `[[hd-workspace-monitoring]]` — the 15s state poll + floaty states behind these badges+- `[[hd-container]]` — workspace context: relay, bridges, env vars
skills/hd-container/SKILL.mdadded+131
@@ -0,0 +1,131 @@+---+name: hd-container+description: Context for Claude Code running inside a Hydrogen Desktop workspace. Documents the exact OS (Ubuntu 24.04, code-server, the local workspace), explains how setup differs from Adom cloud containers (HD 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++You are running inside the **local workspace** managed by Hydrogen Desktop (HD). HD is the flagship Adom desktop app — it manages your workspace, bridges to desktop apps, and provides VS Code + Claude Code. HD runs on Windows, macOS, and Ubuntu; the platform-specific mechanics of how the workspace is hosted are abstracted away from inside the workspace — the facts below hold regardless of host OS.++> Platform layers add a `*-windows` companion to this skill (`[[hd-container-windows]]`) with the host-specific spine — the WSL2 `Adom-Workspace` distro, `wsl --import`, code-server port auto-forward, the runtime source, and the Cloud-vs-local comparison table.++## The workspace — exact facts (don't guess)++| Field | Value |+|-------|-------|+| Provisioned from | a pre-baked golden image (full image, not bootstrapped from scratch) |+| Base | Ubuntu 24.04 |+| Architecture | matches host (`dpkg --print-architecture`) — `linux-x64` or `linux-arm64` |+| code-server | pinned via the golden image |+| 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` |+| Work user | `adom` (passwordless sudo, home `/home/adom`) |+| Workspace | `/home/adom/project` |+| 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` |++If you ever need to confirm: `cat /etc/os-release`, `uname -m`, `/usr/lib/code-server/bin/code-server --version`. Don't speculate about alpine/arm64 — Ubuntu 24.04 matches the cloud container.++## Setup is via HD's setup-steps, NOT gallia bootstrap.sh++HD provisions this workspace through its own **setup-steps** flow, shown as the "Install Tools" panel in the HD UI. It is a **different code path** than cloud containers, which run `gallia/scripts/bootstrap.sh`.++Most tooling is NOT installed by a step — it's BAKED into the golden image at image-build time (gallia, the Adom CLIs, the claude CLI + Code extension, code-server, VS Code settings, and all `hd-*` skills). The provisioning step imports the golden image if the workspace isn't already registered, and the relay is started by the `start-relay` step. See `[[hd-setup-steps]]`.++When debugging install issues here, the source of truth is HD's setup-steps code — 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 workspace. There is NO `install-claude-ext` / `install-claude-cli` / `install-gallia` / `write-vscode-settings` step — those are baked. Do NOT chase bugs into `bootstrap.sh` — that script lives in the baked image but HD itself never invokes it.++## 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 per-arch builds exist. The golden-image bake installs the latest per-arch 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 workspace. 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 host control API is reachable from inside the workspace at `127.0.0.1`. The port is dynamic per launch, so read the live URL from `~/.adom/hd-control-url` (`http://127.0.0.1:<dynamic>`): `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 handles+```+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": "/path/to/board.kicad_pcb"}'+adom-desktop kicad_screenshot_all+adom-desktop kicad_run_drc '{"path": "..."}'+adom-desktop kicad_window_info+```+(Paths to host files use the host's native path convention.)++### 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": "<host path>", "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": "<host folder path>"}'+```++## What's different from Adom cloud containers++| Feature | Adom Cloud | HD Local |+|---------|-----------|----------|+| Workspace provisioning | Adom platform API | golden image imported on the user's machine |+| 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+- `GALLIA_SERVICE=local` — tells gallia this is a local workspace+- `VSCODE_PROXY_URI=http://localhost:7380/proxy/{{port}}/` — code-server's proxy++(Platform layers may set additional host-specific env vars — see `[[hd-container-windows]]`.)++## Related skills++- `[[hd-container-stats]]` — the title-bar CPU/RAM indicator for this workspace+- `[[hd-setup-steps]]` — what each setup step did to prepare your workspace
skills/hd-desktop-sse/SKILL.md+19−16
@@ -1,23 +1,28 @@ --- name: hd-desktop-sse-description: How HD's local workspace API + SSE works (a.k.a. the workspace API) — replaces Carbon for workspace commands so the workspace's adom-cli controls HD, not cloud Hydrogen. The workspace is the WSL2 Adom-Workspace distro by default (or a Docker container under HD_RUNTIME=docker). Covers the full pipeline, routing, env vars, field format differences, and hard-won lessons. Trigger words — HD SSE, workspace API, local API, adom-cli workspace, add-tab, move-tab, webview tab, EventSource, workspace_updated, ADOM_CARBON_URL, ADOM_HYDROGEN_URL.+description: How HD's local workspace API + SSE works (a.k.a. the workspace API) — replaces Carbon for workspace commands so the workspace's adom-cli controls HD, not cloud Hydrogen. Covers the full pipeline, routing, env vars, field format differences, port discovery, and hard-won lessons. Trigger words — HD SSE, workspace API, local API, adom-cli workspace, add-tab, move-tab, webview tab, EventSource, workspace_updated, ADOM_CARBON_URL, ADOM_HYDROGEN_URL, discovery port. ---  # Hydrogen Desktop — Local Workspace API + SSE +> Platform note: HD runs the same local workspace API on every platform (Windows/WSL2,+> macOS, Linux). For the WSL2-specific networking details (mirrored loopback,+> `%APPDATA%\hydrogen-desktop\ports.json`, the `HD_RUNTIME=docker` runtime, relay+> same-port behavior), see **[[hd-desktop-sse-windows]]**.+ ## Architecture  ```-Workspace adom-cli (WSL2 Adom-Workspace distro by default, or Docker container)+Workspace adom-cli (the local workspace)     → http://127.0.0.1:47083 (HD's proxy)     → HD handles workspace commands locally + broadcasts SSE     → HD frontend receives SSE, re-fetches workspace, renders -Cloud Docker's adom-cli (unchanged)+Cloud adom-cli (unchanged)     → carbon.adom.inc → Hydrogen web ``` -HD runs its own workspace API on port 47083 (reverse proxy, default — see PortConfig) so the workspace's adom-cli controls HD's UI, not cloud Hydrogen. No cross-talk between environments. (Under WSL2 the workspace reaches HD at `127.0.0.1:47083` — mirrored networking shares loopback with the Windows host.)+HD runs its own workspace API on port 47083 (reverse proxy, default — see PortConfig) so the workspace's adom-cli controls HD's UI, not cloud Hydrogen. No cross-talk between environments. The workspace reaches HD at `127.0.0.1:47083`.  ## Port 47083 routing (the hd-proxy / reverse-proxy) @@ -28,7 +33,7 @@ All requests hit port 47083 (reverse proxy, default — see PortConfig). The rou | `/api/workspaces/editor/{owner}/{repo}/current/*` | Local workspace API | In-memory | | `/api/panels/webview/*`, `/api/panels/sandbox/*` | Local panel API | SSE broadcast | | `/containers/*` | Local container discovery | Canned response |-| `/proxy/{port}/{path}` | Workspace proxy | TCP forward to the workspace (WSL2 distro) |+| `/proxy/{port}/{path}` | Workspace proxy | TCP forward to the workspace | | Everything else (`/api/*`, etc.) | Carbon proxy | HTTPS to carbon.adom.inc |  The dev file server on port 1420 forwards `/api/*` directly to `handle_request()` (same function, not TCP — supports SSE streaming via BoxBody).@@ -63,7 +68,7 @@ NOT `{"owner": "jlauer12", "repository": "workspace"}` — adom-cli reads `conta  ## Workspace Env Vars -Set when the workspace is created (e.g. `create_container()` in `hd-docker/src/lib.rs` under the Docker runtime):+Set when the workspace is created:  | Var | Value | Why | |---|---|---|@@ -72,7 +77,7 @@ Set when the workspace is created (e.g. `create_container()` in `hd-docker/src/l | `ADOM_HYDROGEN_URL` | `http://127.0.0.1:47083` | Workspace mutations (adom-cli sends these HERE, not to Carbon) | | `ADOM_DESKTOP_MODE` | `local` | Tells adom-cli it's a local environment | -Under WSL2, `127.0.0.1` reaches the Windows host directly — mirrored networking shares loopback with the host, so the same `127.0.0.1:<port>` works from inside the distro and on Windows. The canonical code-server port HD exposes on the host is 7380.+`127.0.0.1` reaches HD on the host from inside the workspace. The canonical code-server port HD exposes on the host is 7380.  **Also set in adom-cli config** (persists across sessions): ```bash@@ -184,18 +189,16 @@ Returns: } ``` -> **Relay ports:** under the WSL2 runtime the relay listens **same-port 8765-> (WS) / 8766 (HTTP)** inside the distro and is reached same-port via mirrored-> loopback (or via `/proxy/`). There are **no host 47081/47082 listeners**.-> Clients discover the relay ports from `~/.adom/cli-relay-ports.json` (fallback-> 8765/8766), not from `/discover`.+> **Relay ports:** clients discover the relay ports from `~/.adom/cli-relay-ports.json`+> (fallback 8765/8766), not from `/discover`. Relay port mapping/exposure varies by+> platform — see **[[hd-desktop-sse-windows]]**.  ### Who uses it  | Client | What it discovers | How | |---|---|---| | adom-desktop relay | Control API port (was hardcoded 9001) | `curl :47080/discover` → use `control` field |-| adom-cli in the workspace (WSL2 distro / Docker) | Proxy + Hydrogen URL | Already set via `ADOM_CARBON_URL` env var at workspace creation |+| adom-cli in the workspace | Proxy + Hydrogen URL | Already set via `ADOM_CARBON_URL` env var at workspace creation | | External tools / diagnostics | Any port | Hit discovery, get the full map | | Cloud Docker (this container) | All HD ports | `curl http://<desktop-ip>:47080/discover` via relay | @@ -223,10 +226,10 @@ std::thread::spawn(move || { | Proxy | 47083 | No | n/a | | Control API | 47084 | No | n/a | | CDP | 47085 | No | n/a |-| Relay WS | — (same-port under WSL2) | No | 8765 |-| Relay HTTP | — (same-port under WSL2) | No | 8766 |+| Relay WS | (platform-dependent) | No | 8765 |+| Relay HTTP | (platform-dependent) | No | 8766 | -Config stored at `%APPDATA%\hydrogen-desktop\ports.json`. On first launch, defaults are written without scanning. Workspace-side ports (8080, 8765, 8766) are always fixed — only host-side ports are dynamic. The relay (8765/8766) is reached **same-port** under WSL2 (mirrored loopback) — no host 47081/47082 mapping; discover it from `~/.adom/cli-relay-ports.json` (fallback 8765/8766).+On first launch, defaults are written without scanning. Workspace-side ports (8080, 8765, 8766) are always fixed — only host-side ports are dynamic. The `ports.json` location and relay host mapping are platform-specific — see **[[hd-desktop-sse-windows]]**.  ## Files 
skills/hd-eda-discovery/SKILL.md+13−7
@@ -28,14 +28,19 @@ detection in the background, then come back with a short, friendly summary + one adom-desktop status                       # relay up? caps include kicad / fusion360? adom-desktop kicad_list_versions '{}'     # KiCad installed (+ which versions) adom-desktop fusion_status '{}'           # Fusion 360 installed? ("installed but not running" = yes)-# No bridge for these — detect by install path / running process:-adom-desktop run_script '{"interpreter":"powershell","scriptB64":"<b64 of:>"}'-#   Get-ChildItem 'C:\Program Files','C:\Program Files (x86)' -Directory -EA 0 |-#     ? { $_.Name -match 'Altium|OrCAD|Cadence|Allegro|EAGLE|DipTrace|Eplan' } | % Name-#   plus: Get-Process | ? { $_.Name -match 'Altium|OrCAD|Capture|Allegro' } | % Name ```-(Base64 the PowerShell for `run_script`; use absolute paths, and treat **empty output as a-timeout**, not a negative result.)++The KiCad/Fusion bridges work the same on every platform. For tools with **no bridge** (Altium,+OrCAD, Cadence/Allegro, EAGLE, DipTrace, Eplan, ...), there's no bridge verb — detect them by+**install path / running process** using `adom-desktop run_script`. The exact probe is+platform-specific:++- **Windows:** scan `C:\Program Files` / `C:\Program Files (x86)` and `Get-Process` via a+  PowerShell `run_script` — see **[[hd-eda-discovery-windows]]** for the ready-to-run probe.+- **macOS:** scan `/Applications` (and `~/Applications`) for the app bundles, plus `pgrep`.+- **Linux:** `which`/`command -v` the CLI binaries and check common install dirs, plus `pgrep`.++(Whatever the platform: treat **empty output as a timeout**, not a negative result.)  ## 2. Branch on what you found @@ -98,5 +103,6 @@ they can **contribute the missing piece** in half an hour.  ## Related skills - [hd-adom-desktop](../hd-adom-desktop/SKILL.md) / [hd-bridges](../hd-bridges/SKILL.md) — the `adom-desktop` relay + KiCad/Fusion bridge verbs (in-distro names; the `adom-desktop-*` skills are the cloud-side equivalents)+- [[hd-eda-discovery-windows]] — the Windows/PowerShell no-bridge install-path + process probe - `pup` — driving fab-vendor upload pages; [hd-open-url](../hd-open-url/SKILL.md) — opening vendor sites - the Adom wiki publish skills — sharing the bridge/app you build with the community
skills/hd-notifications/SKILL.md+51−50
@@ -1,33 +1,37 @@ --- name: hd-notifications description: >-  How Hydrogen Desktop reaches the user OUTSIDE the window — native Windows toast-  notifications + taskbar attention — so the AI can proactively tell the user a+  How Hydrogen Desktop reaches the user OUTSIDE the window — native OS toast+  notifications + taskbar/dock attention — so the AI can proactively tell the user a   long job finished or that it needs them (great for hands-free / away-from-keyboard   work). Covers HD's notify handler (levels info|warning|error|emergency, optional-  <actions> buttons; emergency = a persistent orange taskbar flash via-  request_user_attention(Critical) until the user looks), how toasts route via a-  PowerShell AUMID so they may show an "Adom" title, and how to fire one with the-  `notify` desktop command / `adom-desktop notify_user`. Also Pup's-  browser_alert_window taskbar flash. Windows-only. Trigger words — notify the-  user, send a notification, desktop notification, toast, windows toast, taskbar-  flash, get the user's attention, alert the user, notify_user, emergency-  notification, urgent alert, notification actions, action buttons, ping the user,-  job done notification, tell me when it's done, flash the taskbar, request-  attention, browser_alert_window, in-app toast, ui toast, /ui/toast, show a toast-  in HD, toast inside the window.+  <actions> buttons; emergency = a persistent attention request until the user looks)+  and how to fire one with the `notify` desktop command / `adom-desktop notify_user`.+  Also the in-app `/ui/toast` (a message INSIDE the HD window) and Pup's+  browser_alert_window taskbar/dock nudge. The native OS-toast backend is+  platform-specific (see [[hd-notifications-windows]] for the Windows path);+  cross-platform behavior is documented here. Trigger words — notify the user, send a+  notification, desktop notification, toast, os toast, native toast, taskbar flash, dock+  bounce, get the user's attention, alert the user, notify_user, emergency notification,+  urgent alert, notification actions, action buttons, ping the user, job done+  notification, tell me when it's done, request attention, browser_alert_window, in-app+  toast, ui toast, /ui/toast, show a toast in HD, toast inside the window. ---  # Hydrogen Desktop — Notifications (reaching the user outside the window) -When the user isn't looking at HD — a long build is running, you've finished a job,-or you're **blocked and need them** — you can reach them on the OS level: a native-Windows **toast**, and for urgent cases a **persistent taskbar flash**. This is what-makes hands-free / away-from-keyboard work usable: don't just print a message into a-panel nobody's watching — fire a notification.+When the user isn't looking at HD — a long build is running, you've finished a job, or+you're **blocked and need them** — you can reach them on the OS level: a native **toast**,+and for urgent cases a **persistent attention request** (a taskbar flash / dock bounce,+depending on platform). This is what makes hands-free / away-from-keyboard work usable:+don't just print a message into a panel nobody's watching — fire a notification. -> **Windows-only** for the full experience (WinRT toasts + taskbar attention).-> macOS has a limited `osascript` fallback; Linux has no toast path.+> **Platform note:** the native OS toast is delivered by a per-platform backend. The full+> experience (a rich OS toast plus a persistent attention request) is best on Windows+> (WinRT toasts + taskbar attention — see [[hd-notifications-windows]]); macOS has a more+> limited path (an `osascript`-style notification); Linux has no native toast path. The+> `notify_user` API itself is the same everywhere; what differs is how richly the OS+> surfaces it.  ## Firing a notification @@ -51,33 +55,29 @@ Payload shape (`NotifyPayload`):  | Field | Notes | |---|---|-| `title` | Toast heading. If it doesn't already start with "Adom", HD prefixes it → `"Adom: <title>"`. |+| `title` | Toast heading. (On some platforms HD prefixes the app identity — see the platform companion.) | | `body` | The message. | | `level` | `info` / `warning` / `error` / `emergency`. `warning`/`error`/`emergency` render as **long-duration** toasts; `info` is short. |-| `actions` | Optional array of button labels rendered as `<actions>` in the toast template. Empty/omitted = no buttons. |+| `actions` | Optional array of button labels rendered as buttons in the toast. Empty/omitted = no buttons. | -### Levels — and the `emergency` taskbar flash+### Levels — and the `emergency` attention request -- `info` / `warning` / `error` — a standard toast (warnings and errors stay up-  longer).-- **`emergency`** — in addition to the toast, HD calls-  **`request_user_attention(Critical)`** on the main window and shows/unminimizes-  it. This produces a **persistent orange taskbar flash that keeps flashing until-  the user actually clicks the taskbar icon themselves** — it is *not* cleared by a-  programmatic focus. Reserve `emergency` for "I genuinely cannot proceed without-  you" — it's intentionally hard to ignore.+- `info` / `warning` / `error` — a standard toast (warnings and errors stay up longer).+- **`emergency`** — in addition to the toast, HD calls **`request_user_attention(Critical)`**+  on the main window and shows/unminimizes it. This produces a **persistent attention+  request** (a taskbar flash on Windows, a dock bounce on macOS) that **keeps going until+  the user actually interacts with the window/taskbar themselves** — it is *not* cleared by+  a programmatic focus. Reserve `emergency` for "I genuinely cannot proceed without you" —+  it's intentionally hard to ignore. -### The "Adom" title quirk (AUMID routing)--On Windows, HD's toasts route through a **PowerShell AUMID**. A side effect: toasts-may surface under an **"Adom"** identity/title rather than a per-app one. That's-expected — don't treat an "Adom"-labeled toast as a bug.+> The Windows-specific toast identity/title behavior (the AUMID "Adom" title quirk) and the+> WinRT/orange-taskbar-flash details live in [[hd-notifications-windows]].  ## In-app toast — `POST /ui/toast` (inside the HD window) -The notifications above reach the user **outside** the window (OS toast / taskbar).-For a lightweight message **inside** the HD window — the same toast UI the app uses-for its own success/error messages — fire a control-API toast:+The notifications above reach the user **outside** the window (OS toast / taskbar). For a+lightweight message **inside** the HD window — the same toast UI the app uses for its own+success/error messages — fire a control-API toast:  ```bash # via the control API (or adom-cli hydrogen api, or the API Explorer "Try it")@@ -92,12 +92,12 @@ POST /ui/toast { "message": "Build finished ✅", "type": "success", "duration": | `groupId` + `detail` | Optional: coalesce related toasts into one expandable group. |  It emits the `hd-toast` Tauri event, which the main window renders via the global-`toastStore` (bottom-stacked toasts). **OS toast vs in-app toast:** use a `notify`-OS toast when the user may be **away from / not looking at** HD; use `/ui/toast` for-an in-window status cue while they're working in HD. (HD's native recording uses this-for its auto-stop notice — see [hd-recording](../hd-recording/SKILL.md).)+`toastStore` (bottom-stacked toasts). **OS toast vs in-app toast:** use a `notify` OS toast+when the user may be **away from / not looking at** HD; use `/ui/toast` for an in-window+status cue while they're working in HD. (HD's native recording uses this for its auto-stop+notice — see [hd-recording](../hd-recording/SKILL.md).) -## Pup's taskbar flash (`browser_alert_window`)+## Pup's taskbar/dock nudge (`browser_alert_window`)  For AI-driven browser work, Pup has its own attention nudge: @@ -105,18 +105,18 @@ For AI-driven browser work, Pup has its own attention nudge: adom-desktop browser_alert_window '{"sessionId":"default"}' ``` -It **flashes the taskbar** for that browser window (and brings the page to front-within Chrome) **without stealing foreground focus** — a gentle "look here." (Use+It **flashes the taskbar / bounces the dock** for that browser window (and brings the page+to front within Chrome) **without stealing foreground focus** — a gentle "look here." (Use `browser_focus_window` if you actually want to raise the window.)  ## When you (the AI) should notify proactively -- **Long-job completion** — a build, a batch, a render, a deploy finished. Fire an-  `info` toast so the user can wander off and get pulled back.+- **Long-job completion** — a build, a batch, a render, a deploy finished. Fire an `info`+  toast so the user can wander off and get pulled back. - **You need the user** — an approval, a decision, a credential. Use `warning`, or   `emergency` if you're fully blocked.-- **Hands-free / driving** — pair a notification with audio (TTS) so the user gets-  both a glance-able toast and the spoken answer.+- **Hands-free / driving** — pair a notification with audio (TTS) so the user gets both a+  glance-able toast and the spoken answer.  Don't spam: one notification per meaningful event. Verify the bridge first (`adom-desktop ping`) before claiming you notified them.@@ -124,3 +124,4 @@ Don't spam: one notification per meaningful event. Verify the bridge first ## Related skills - [hd-adom-desktop](../hd-adom-desktop/SKILL.md) — AD is what carries `notify_user` to the host; `ping`/`status` to verify the bridge and the `notify` capability - [hd-bridges](../hd-bridges/SKILL.md) — the full AD capability list (`notify`, …) and Pup's `browser_alert_window`+- [[hd-notifications-windows]] — the Windows toast backend (WinRT, AUMID "Adom" title, orange taskbar flash)
skills/hd-overview/SKILL.md+45−66
@@ -1,90 +1,69 @@ --- name: hd-overview description: >-  Master index for all Hydrogen Desktop skills. Start here to find the right-  skill for any HD topic. Skills are split into a runtime-neutral "shared" set-  plus a runtime-specific set (WSL2 by default, Docker as legacy fallback).-  Trigger words: HD skills, hydrogen desktop, what skills, find skill, HD help,-  HD overview, skill index, HD reference.+  Master index for the platform-generic Hydrogen Desktop skills (the+  hd-bootstrap set). Start here to find the right skill for any HD topic.+  These skills are runtime-neutral and apply on every host HD runs on+  (Windows, macOS, Ubuntu); platform layers add their own *-windows (etc.)+  companions. Trigger words: HD skills, hydrogen desktop, what skills, find+  skill, HD help, HD overview, skill index, HD reference. ---  # Hydrogen Desktop — Skill Index  Hydrogen Desktop (HD) is Adom's standalone Tauri v2 app that runs the full Hydrogen experience locally. One exe manages your workspace, VS Code,-Claude Code, the bridges, and the Adom Wiki — zero cloud dependency.+Claude Code, the bridges, and the Adom Wiki — zero cloud dependency. HD runs+on Windows, macOS, and Ubuntu. -## ⚠️ First: know your runtime — **`hd-runtime-mode`**+This index lists the **platform-generic** HD skills (the `hd-bootstrap` set).+Every fact in these skills holds regardless of host OS. Where a topic has+host-specific mechanics (e.g. how the workspace is hosted, host networking,+host-side recording), the platform layer adds a companion skill — on Windows+those are the **`hd-windows-bootstrap`** `*-windows` skills (and equivalents+for other platforms). The generic skill cross-references its companion. -HD hosts your workspace one of two ways: a **WSL2 Ubuntu distro `Adom-Workspace`**-(the default) or a **Docker container** (legacy, `HD_RUNTIME=docker`). Almost every-fact below — container vs distro, files, ports, stats, setup steps — depends on-which is active. **Read `hd-runtime-mode` first** to confirm your runtime, then use-the matching runtime-specific skill. HD only installs the skills for the active-runtime, so in a given workspace you'll usually have exactly the right set.--## Shared skills (runtime-neutral — always installed)+## The generic HD skills (hd-bootstrap)  | Skill | What it covers | |---|---|-| **hd-runtime-mode** | WSL2 vs Docker runtime: how to tell which you're in and what differs. Read first. |-| **hd-golden-image** | Your workspace is a pre-baked golden WSL2 image — gallia, the CLIs, claude, code-server, settings, and these skills are baked in (not installed by setup steps); how updates work. **Lightweight by design: tools like ffmpeg/imagemagick aren't baked — install on demand (`sudo apt-get install`) rather than refusing.** |-| **hd-skill-loop** | (Maintainers) The loop to fix a wrong/stale HD skill: verify vs the live HD, fix it live, write it back to the repo, bake it into the next image. |-| **hd-who-am-i** | Answer "who am I / what can I do here" — identity, resources, environment intro. | | **hd-adom-auth** | Adom login/logout, session token, profile menu, how auth feeds setup. |-| **hd-claude-auth** | How Claude Code signs in: OAuth via Browser Picker, credential backup, the `claude-auth` step. |-| **hd-api** | Control API reference (`127.0.0.1:47084`). Runtime-neutral endpoints + runtime-specific notes. |-| **hd-desktop-sse** | Local workspace API + SSE — how adom-cli inside the workspace controls HD (replaces Carbon locally). |-| **hd-monitor** | Real-time SSE event stream + Monitor-tool patterns for watching workspace mutations. |-| **hd-ui** | HD's UI: menus, dialogs, panels, CDP-driven navigation, brand/CSS conventions. |-| **hd-open-url** | The decision guide for "open a website" — the six ways (webview tab, HD window, Pup, native browser, picker, headless curl) and when to pick each. |-| **hd-browser-picker** | URL interception — every link routes through the Browser Profile Dialog. |-| **hd-permissions** | Why mic/camera/clipboard/notifications "just work" in HD — WebView2 permissions are auto-granted, so webview apps see no Allow prompts. |-| **hd-tab-icons** | Webview tab icon system — `displayIcon`, icon resolution, SVG data URLs. |-| **hd-profile-menu** | The avatar dropdown: profile/repos/molecules links and logout. | | **hd-adom-desktop** | What HD and Adom Desktop (AD) are and how they work together — AD is your hands on the user's real OS (files, shell, OS screenshots, app launch, bridges). |-| **hd-bridges** | Built-in KiCad/Fusion/Puppeteer bridges + extensible wiki catalog (e.g. Blender) + AD capability list. |-| **hd-eval** | Inject JS into any HD surface (shell/workbench/wiki/Claude) via /eval-in — add-ons, overlays, highlights, drive UI. | | **hd-adom-menu** | The upper-left Adom logo menu (Settings, Ports, API Explorer, DevTools, Setup/Virgin Reset) + About dialog + version readout. |-| **hd-settings** | HD's Settings dialog + the full preferences tree (theme, vim mode, 3D control style, launch-on-boot, AD window behavior). |-| **hd-file-transfer** | Move files both ways between the WSL2 workspace and the Windows PC. |-| **hd-embedded-ad** | HD ↔ Adom Desktop embedded mode: the tray, why AD is hidden, the footer pill. |-| **hd-self-screenshot** | How the AI screenshots HD panels + any host window (window control, multi-monitor), injects to shotlog, runs visual self-checks. |+| **hd-api** | Control API reference. Runtime-neutral endpoints. |+| **hd-bridges** | Built-in KiCad/Fusion/Puppeteer bridges + extensible wiki catalog (e.g. Blender) + AD capability list. |+| **hd-captions** | Paint labeled text on the user's screen — an always-on-top caption overlay for demos / step callouts. | | **hd-capture-share** | The screen-share + "AI wants access" approval + countdown the AI triggers to capture the editor; tab/screen scopes, Webview/Pup window mode. |-| **hd-recording** | Record the screen/mic — the in-app `.webm` recorder (→ `recordings/`) and AD desktop recording, with the tab-vs-desktop footgun. |-| **hd-notifications** | Reach the user outside the window — native Windows toasts + emergency taskbar flash via `notify_user`. |-| **hd-captions** | Paint labeled text on the user's screen — a Win32 always-on-top caption overlay for demos / step callouts. |-| **hd-welcome** | The static welcome page shown after setup completes. |-| **hd-skill-catalog** | The catalog of skills your Claude has in this workspace. |-| **hd-overview** | This index. |--## Runtime-specific skills (you get the WSL2 *or* the Docker variant)--These topics exist in two parallel implementations — `wsl2/` (default) and-`docker/` (legacy) — with the same skill names. Trust the one for your active-runtime (see `hd-runtime-mode`).--| Skill | What it covers |-|---|---|+| **hd-claude-auth** | How Claude Code signs in: OAuth via Browser Picker, credential backup, the `claude-auth` step. | | **hd-container** | Context for Claude running inside the workspace: relay, direct connect, bridge commands, env vars. |-| **hd-topology** | The three-layer architecture and how to reach the workspace (WSL2: `wsl -d Adom-Workspace`; Docker: `docker exec`). |-| **hd-networking** | Port architecture, host access (`127.0.0.1` / mirrored networking), code-server proxy. Canonical port behavior. |-| **hd-ports** | Forwarding workspace services to Windows (WSL2 auto-forward vs Docker `-p` + `/proxy/`). |-| **hd-port-watcher** | The dynamic port-forward daemon for extension OAuth callbacks. |-| **hd-volume** | Where your files live, what persists, how to copy out, what a reset wipes. | | **hd-container-stats** | The title-bar CPU/RAM "Container" indicator and how its stats are gathered. |+| **hd-desktop-sse** | Local workspace API + SSE — how adom-cli inside the workspace controls HD (replaces Carbon locally). |+| **hd-eda-discovery** | EDA tool discovery / setup flow. |+| **hd-eval** | Inject JS into any HD surface (shell/workbench/wiki/Claude) via /eval-in — add-ons, overlays, highlights, drive UI. |+| **hd-instapcb** | InstaPCB integration in HD. |+| **hd-monitor** | Real-time SSE event stream + Monitor-tool patterns for watching workspace mutations. |+| **hd-notifications** | Reach the user outside the window — native OS toasts + emergency taskbar flash via `notify_user`. |+| **hd-open-url** | The decision guide for "open a website" — the ways (webview tab, HD window, Pup, native browser, picker, headless curl) and when to pick each. |+| **hd-overview** | This index. |+| **hd-permissions** | Why mic/camera/clipboard/notifications "just work" in HD — webview permissions are auto-granted, so webview apps see no Allow prompts. |+| **hd-profile-menu** | The avatar dropdown: profile/repos/molecules links and logout. |+| **hd-self-screenshot** | How the AI screenshots HD panels + any host window (window control, multi-monitor), injects to shotlog, runs visual self-checks. |+| **hd-self-update** | How HD updates itself. |+| **hd-settings** | HD's Settings dialog + the full preferences tree (theme, vim mode, 3D control style, launch-on-login, AD window behavior). | | **hd-setup** | The setup panel, Run All, Rollback, Virgin Reset. | | **hd-setup-steps** | What each setup step did to prepare your workspace. |+| **hd-tab-icons** | Webview tab icon system — `displayIcon`, icon resolution, SVG data URLs. |+| **hd-ui** | HD's UI: menus, dialogs, panels, CDP-driven navigation, brand/CSS conventions. |+| **hd-welcome** | The static welcome page shown after setup completes. |+| **hd-who-am-i** | Answer "who am I / what can I do here" — identity, resources, environment intro. |+| **hd-workspace-monitoring** | Workspace + code-server health monitoring, floaty states, the 15s poll, auto-start. |+| **hd-workspace-updater** | The workspace-tooling updater daemon. | -### WSL2-only-| Skill | What it covers |-|---|---|-| **hd-workspace-lifecycle** | WSL distro lifecycle: import/export/terminate/unregister, code-server as an HD-owned child, the never-global-WSL rule. |-| **hd-workspace-monitoring** | Distro + code-server health monitoring, floaty states, the 15s poll, auto-start. |+## Platform layers -### Docker-only (legacy `HD_RUNTIME=docker`)-| Skill | What it covers |-|---|---|-| **hd-docker-desktop** | Silently install/upgrade/start/monitor Docker Desktop as invisible infrastructure. |-| **hd-docker-lifecycle** | Docker Desktop + container lifecycle: WSL2 recovery, restart/stop rules, health checks. |-| **hd-docker-monitoring** | Frontend monitoring of the Docker container and Docker Desktop. |+Platform-specific mechanics live in a platform layer that ships alongside this+set and adds `*-windows`-style companion skills (e.g. `hd-container-windows`,+`hd-container-stats-windows`, `hd-networking`, `hd-volume`,+`hd-workspace-lifecycle`). When a generic skill above has a host-specific detail,+it cross-references its companion. On a given host you'll have the generic set+plus that host's platform layer.
skills/hd-permissions/SKILL.md+47−54
@@ -1,76 +1,69 @@ --- name: hd-permissions description: >-  Hydrogen Desktop AUTO-GRANTS every WebView2 permission — microphone, camera,-  clipboard-read, geolocation, notifications, sensors — so inside HD a webview-  app NEVER shows a "this site wants to use your microphone/camera/clipboard/-  location" prompt. READ THIS before building or debugging a webview app that-  uses getUserMedia / clipboard / geolocation: do NOT tell the user to click-  "Allow" — there is no prompt to click; it's suppressed by design. Distinguish-  this browser-permission auto-grant from the SEPARATE in-app screen-share / mic-  consent the AI itself requests (that one IS user-approved — see hd-capture--  share). Trigger words — permission, permissions, webview2 permission, allow-  microphone, allow camera, allow clipboard, clipboard read, getUserMedia, mic-  permission, camera permission, geolocation permission, notifications-  permission, sensors permission, site wants to use, permission prompt, click-  allow, no permission prompt, auto-grant, auto granted, why no prompt,-  permission denied webview.+  Hydrogen Desktop AUTO-GRANTS every webview permission — microphone, camera,+  clipboard-read, geolocation, notifications, sensors — so inside HD a webview app NEVER+  shows a "this site wants to use your microphone/camera/clipboard/location" prompt. READ+  THIS before building or debugging a webview app that uses getUserMedia / clipboard /+  geolocation: do NOT tell the user to click "Allow" — there is no prompt to click; it's+  suppressed by design. Distinguish this browser-permission auto-grant from the SEPARATE+  in-app screen-share / mic consent the AI itself requests (that one IS user-approved — see+  hd-capture-share). HD's webview engine is platform-specific; the per-engine+  implementation detail (e.g. WebView2 on Windows) lives in the platform companion (see+  [[hd-permissions-windows]]). Trigger words — permission, permissions, webview permission,+  allow microphone, allow camera, allow clipboard, clipboard read, getUserMedia, mic+  permission, camera permission, geolocation permission, notifications permission, sensors+  permission, site wants to use, permission prompt, click allow, no permission prompt,+  auto-grant, auto granted, why no prompt, permission denied webview. --- -# HD auto-grants every WebView2 permission+# HD auto-grants every webview permission -Hydrogen Desktop's webview (Windows / WebView2) registers a-`PermissionRequested` handler that returns **ALLOW for every permission kind** —-microphone, camera, clipboard-read, geolocation, notifications, sensors, etc. So-**inside HD the user never sees a "this site wants to use your microphone /-camera / clipboard / location" dialog.** Webview apps that call `getUserMedia`,-read the clipboard, or ask for geolocation simply *work*, with no prompt.+Hydrogen Desktop's webview registers a permission handler that returns **ALLOW for every+permission kind** — microphone, camera, clipboard-read, geolocation, notifications,+sensors, etc. So **inside HD the user never sees a "this site wants to use your microphone /+camera / clipboard / location" dialog.** Webview apps that call `getUserMedia`, read the+clipboard, or ask for geolocation simply *work*, with no prompt. -Evidence: `hd-app/src/lib.rs` (~lines 326-349):+Every request is unconditionally allowed. In the HD log you'll see lines like `[perm]+auto-granted permission kind …` and, at startup, `[perm] Registered PermissionRequested+auto-grant handler`. -```rust-// PermissionRequested: auto-grant EVERY permission kind (clipboard-// read, mic, camera, geolocation, notifications, sensors, …) so the-// user never sees a WebView2 "site wants to" dialog.-…-args.SetState(COREWEBVIEW2_PERMISSION_STATE_ALLOW)?;-hd_log::hd_log!("[perm] auto-granted permission kind {:?}", kind);-```--Every request is unconditionally set to `COREWEBVIEW2_PERMISSION_STATE_ALLOW`. In-the HD log you'll see lines like `[perm] auto-granted permission kind …` and, at-startup, `[perm] Registered PermissionRequested auto-grant handler`.+> **Platform note:** HD uses a different webview engine per platform (e.g. WebView2 on+> Windows, WebKit on mac/Linux). The auto-grant policy is the same everywhere — every+> permission is allowed up front — but the exact engine API is platform-specific. The+> Windows/WebView2 implementation and its code evidence are in [[hd-permissions-windows]].  ## Why HD does this -HD is the user's **trusted desktop app** — they've already chosen to run it.-Intermediate per-site Web permission prompts (especially the clipboard-paste-dialog) are pure friction with no added safety here, since there's no untrusted-third-party browsing context: the surfaces are HD's own panels and the user's own-webview apps. So HD grants them all up front.+HD is the user's **trusted desktop app** — they've already chosen to run it. Intermediate+per-site Web permission prompts (especially the clipboard-paste dialog) are pure friction+with no added safety here, since there's no untrusted third-party browsing context: the+surfaces are HD's own panels and the user's own webview apps. So HD grants them all up+front.  ## What this means for you when building webview apps -- **Don't instruct the user to "click Allow."** There is no prompt — telling them-  to look for one is wrong and confusing. `getUserMedia({ audio: true })`,-  clipboard reads, geolocation, notifications all resolve without a dialog.+- **Don't instruct the user to "click Allow."** There is no prompt — telling them to look+  for one is wrong and confusing. `getUserMedia({ audio: true })`, clipboard reads,+  geolocation, notifications all resolve without a dialog. - If a webview app *isn't* getting mic/camera data, the cause is **not** a denied-  permission prompt (HD never denies). Look elsewhere: no device present, the-  page served over a non-secure context, a code bug, or the OS-level Windows-  privacy toggle for the camera/mic being off for the app entirely.-- This is WebView2/Windows-specific behavior baked into HD's webview host — it's-  not something the web page or the user configures.+  permission prompt (HD never denies). Look elsewhere: no device present, the page served+  over a non-secure context, a code bug, or the OS-level privacy toggle for the camera/mic+  being off for the app entirely.+- This is behavior baked into HD's webview host — it's not something the web page or the+  user configures.  ## NOT the same as in-app screen-share / mic consent -This auto-grant is **only** the low-level WebView2 browser-permission layer.-It is separate from the **screen-share / microphone consent the AI itself-requests** when it wants to capture the user's screen or mic for a session — that-flow **is** explicitly user-approved (the user sees and accepts an in-app consent-UI). Don't conflate them: WebView2 site permissions are silently allowed; the AI's-capture/share request is a real, user-facing approval. See `hd-capture-share`.+This auto-grant is **only** the low-level webview browser-permission layer. It is separate+from the **screen-share / microphone consent the AI itself requests** when it wants to+capture the user's screen or mic for a session — that flow **is** explicitly user-approved+(the user sees and accepts an in-app consent UI). Don't conflate them: webview site+permissions are silently allowed; the AI's capture/share request is a real, user-facing+approval. See `hd-capture-share`.  ## Related skills - `hd-capture-share` — the SEPARATE, user-approved screen-share / mic consent the AI requests - [hd-open-url](../hd-open-url/SKILL.md) — opening URLs/webview apps inside HD (where these permissions apply)-- [hd-browser-picker](../hd-browser-picker/SKILL.md) — routing URLs to webviews vs native browsers vs Pup+- [[hd-permissions-windows]] — the WebView2 (Windows) implementation + lib.rs evidence
skills/hd-self-screenshot/SKILL.md+51−103
@@ -9,23 +9,21 @@ description: >   panel", "screenshot the editor", "screenshot my whole screen / the desktop",   "show me what HD looks like", or verifying a UI change (ralph loop). Use this   even for "my whole screen / my desktop / my monitor" — that's the `screen`-  scope, NOT adom-desktop. Do NOT curl host.docker.internal, do NOT use-  adom-desktop's OS screenshot for anything inside HD (or for the screen), and you-  do NOT need any image resizer. For a SPECIFIC element/region (a CPU meter, a menu,-  a dialog, a toolbar) or an inline-b64 PNG, use the canonical `POST /screenshot`-  control endpoint with a CSS `selector` (it ALWAYS region-clips to that element) —-  and combine it with the UI command bus (`hd-ui`: `ui/invoke` to open a menu/dialog,-  then `/screenshot` its selector). Trigger words — screenshot HD, screenshot the-  welcome page, screenshot the webview, screenshot a panel, screenshot a tab,-  screenshot the workspace, screenshot the editor, screenshot my screen, screenshot-  the whole screen, screenshot the desktop, capture my monitor, full screen capture,+  scope. You do NOT need any image resizer. For a SPECIFIC element/region (a CPU+  meter, a menu, a dialog, a toolbar) or an inline-b64 PNG, use the canonical+  `POST /screenshot` control endpoint with a CSS `selector` (it ALWAYS region-clips+  to that element) — and combine it with the UI command bus (`hd-ui`: `ui/invoke`+  to open a menu/dialog, then `/screenshot` its selector). Identical across web+  Hydrogen and HD. Trigger words — screenshot HD, screenshot the welcome page,+  screenshot the webview, screenshot a panel, screenshot a tab, screenshot the+  workspace, screenshot the editor, screenshot my screen, screenshot the whole+  screen, screenshot the desktop, capture my monitor, full screen capture,   screenshot everything on screen, what does HD look like, adom-cli hydrogen   screenshot, capture panel, capture workspace, capture screen, screenshot a region,   clip to selector, screenshot an element, screenshot a menu, screenshot a dialog,   region screenshot, b64 screenshot, POST /screenshot, /shot, screenshot without flash,-  no-flash screenshot, hd_shot, hd_screenshot, screenshot KiCad, screenshot another app,-  screenshot a non-HD window, desktop_screenshot_window, desktop_screenshot_screen, which-  screenshot tool, verify visually, ralph loop, shotlog, image resizer, resize screenshot.+  no-flash screenshot, which screenshot tool, verify visually, ralph loop, shotlog,+  image resizer, resize screenshot. ---  # HD — Screenshot a panel / webview / the workspace / the screen@@ -33,14 +31,12 @@ description: > The built-in way to screenshot anything inside HD is the **`adom-cli hydrogen screenshot`** command — the *same* `adom-cli` you already use. It captures the real rendered surface, drops a PNG into the container's `screenshots/` folder,-and prints the path. Just `Read` that path. **No `host.docker.internal`, no-ImageMagick.** (`adom-desktop`'s host verbs DO have a place — other apps, no-flash-grabs, the whole desktop — see the ladder; just not as the default for HD content.)+and prints the path. Just `Read` that path. **No image resizer needed.**  ## Which screenshot tool? — the priority ladder -You have HD-native capture AND AD's host verbs. **What** you're capturing (and whether-you want the teal flash) picks the tool. Default to HD-native:+What you're capturing (and whether you want the teal flash) picks the tool. Default to+HD-native:  1. **HD content — a panel, the workspace, the editor, a webview, the screen    (the 99% case): `adom-cli hydrogen screenshot panel|workspace|screen`. THIS IS THE@@ -55,52 +51,27 @@ you want the teal flash) picks the tool. Default to HD-native:    - **The one time you switch to CDP for an ordinary shot:** during another thread's      recording the `adom-cli` SSE path returns `capture_busy` — then fall to `POST /screenshot`      (CDP), which coexists (see "During a recording" below). That's a fallback, not the default.-2. **HD content, NO flash** (clean shot, or HD's CDP/SSE isn't mounted): `adom-desktop hd_shot-   '{"region":"full|titlebar|setup-panel|…"}'` (named HD-window regions) or `adom-desktop-   hd_screenshot` (the whole HD window). Host-side, deliberately **no teal flash**.-3. **A specific NON-HD app window** (KiCad, Fusion 360, a native dialog — **or an HD Tauri browser-   window, which is less-tested**): `adom-desktop desktop_list_windows` → `desktop_screenshot_window-   '{"hwnd":N}'`. OS PrintWindow of one window; coexists with a recording. See `hd-bridges`.-4. **Your app in a Pup browser window** (AI-driven Chrome — hero images, clean app shots):-   **`adom-desktop browser_screenshot '{"sessionId":"…"}'`** (the `pup` skill). Full-page, no HD-   chrome, no flash — separate Chrome, so it coexists with an HD recording.-5. **The whole physical desktop** (every app, taskbar): `adom-cli hydrogen screenshot screen` (HD-   scope) OR `adom-desktop desktop_screenshot_screen` (AD host GDI). Both **coexist with a recording**-   (independent of HD's WGC/DXGI recorder — corrected 2026-06-14; `ad_screen` can be intermittent-   under heavy load).  ## During a recording (multi-thread) — pick a coexisting method, never blind-retry -Adom users run **multiple AI threads on one HD**, so another thread may be recording the screen-while you capture. **Only the `adom-cli` SSE path (`screenshot panel/workspace/screen`) is affected**-— everything else coexists. HD makes this deterministic:+Adom users run **multiple AI threads on one HD**, so another thread may be recording the+screen while you capture. **Only the `adom-cli` SSE path (`screenshot panel/workspace/screen`)+is affected** — the CDP path coexists. HD makes this deterministic: -- **Pre-flight `GET /capture/availability`** → `{recording:{active,source}, methods:{cdp, ad_window,-  ad_screen, pup, sse} each w/ reliability + coexists_with_recording, recommended, _sharing_note,-  _hint}`. Check it **only when a recording might be running.**-  - **`recommended` is STATE-DEPENDENT (HD v0.1.40+) and agrees with the default:** when+- **Pre-flight `GET /capture/availability`** → reports the recording state plus, per method,+  reliability + whether it coexists with a recording, a `recommended` method, and a `_hint`.+  Check it **only when a recording might be running.**+  - **`recommended` is STATE-DEPENDENT and agrees with the default:** when     `recording.active === false` it returns **`"sse"`** (≡ `adom-cli hydrogen screenshot`, the-    web-Hydrogen-consistent default, rung #1); when `recording.active === true` it returns-    **`"cdp"`** (the SSE path would `capture_busy`, so CDP is correct). So you can follow-    `recommended` directly — it will never push you off `adom-cli` while idle. (Verified live-    2026-06-14: idle → `recommended:"sse"`.) Your everyday default remains `adom-cli`; CDP is the-    during-a-recording fallback.-  - **`_sharing_note`:** HD-native capture uses CDP, so there is **no real screen-share to-    detect** (any "sharing" field would be a meaningless `false`) — the truthful signal is the note-    + the recording status, not a sharing flag. The display-hold / screensaver-block footgun is a-    **web-Hydrogen-only** problem (its `getDisplayMedia` holds `ES_DISPLAY_REQUIRED`); if you hit a-    pinned display, the fix is **`adom-cli hydrogen sharing stop`**, not anything HD-side. See-    [hd-screen-lock](../hd-screen-lock/SKILL.md).+    web-Hydrogen-consistent default); when `recording.active === true` it returns **`"cdp"`**+    (the SSE path would `capture_busy`, so CDP is correct). So you can follow `recommended`+    directly — it will never push you off `adom-cli` while idle. Your everyday default remains+    `adom-cli`; CDP is the during-a-recording fallback. - **`capture_busy`:** the SSE path (`PATCH /current/screenshot`, i.e. `adom-cli screenshot   panel/workspace`) returns, the moment a recording is active, `{ok:false, error:"capture_busy",-  retry_after_ms, alternatives:[{method:"cdp"},{ad_window},{ad_screen},{pup}], _hint}` — never an-  empty body. **On `capture_busy`: read `alternatives` and SWITCH — do NOT blindly retry the SSE path.**-- **Coexistence matrix (verified live):** `POST /screenshot` (CDP) ✅ *best during a recording* ·-  `desktop_screenshot_window` ✅ · `desktop_screenshot_screen` ✅ (medium) · `pup browser_screenshot`-  ✅ · `adom-cli screenshot panel/workspace/screen` ⚠️ → `capture_busy`.-- Authoritative recording state: `GET /recording/native/status`. See `hd-recording`, `hd-screen-lock`.--**Quick map:** in-HD → #1 (or #2 for no-flash) · other app → #3 · whole desktop → #4.+  retry_after_ms, alternatives:[{method:"cdp"}], _hint}` — never an empty body. **On+  `capture_busy`: read `alternatives` and SWITCH — do NOT blindly retry the SSE path.**+- Authoritative recording state: `GET /recording/native/status`. See `hd-recording`.  ## Pick the scope — panel / workspace / screen @@ -111,9 +82,8 @@ while you capture. **Only the `adom-cli` SSE path (`screenshot panel/workspace/s | The whole **screen** — desktop, taskbar, OTHER apps | `adom-cli hydrogen screenshot screen` | `screen` |  **"My whole screen / my desktop / my monitor / everything"** → `adom-cli hydrogen-screenshot screen`. Do **NOT** reach for `adom-desktop` here — that's only for one-SPECIFIC non-HD window (KiCad, Fusion). The HD `screen` scope captures the real-desktop and saves the PNG into your container, same as the others (verified live).+screenshot screen`. The HD `screen` scope captures the real desktop and saves the PNG into+your container, same as the others.  ## Do this — it saves a PNG and prints the path; then Read it @@ -142,8 +112,8 @@ the webview tab you find by its `--tab-id`. ### What it returns — a saved path; just Read it The command saves the PNG into the container's `screenshots/` folder and prints the path. **Read it — done.** No decoding, no resizer, no second tool. The printed path-is **relative to `~/project`** (HD v0.1.27+ matches the cloud contract); the `_hint`-gives the full path:+is **relative to `~/project`** (matches the cloud contract); the `_hint` gives the full+path:  ``` screenshots/2026-06-13T20-04-43.png@@ -152,16 +122,11 @@ _hint: Screenshot saved to ~/project/screenshots/<ts>.png. Read the file to view → `Read ~/project/screenshots/<ts>.png` (prepend `~/project/` to the line-1 path, or just use the full path from the `_hint`). -(Legacy/edge case: an older HD build could return a doubled `~/project/~/project/`-prefix, or inline JSON with `"dataUrl"` + `"uploadFailed": true` — both fixed in-v0.1.27. If you ever see the `dataUrl` shape, base64-decode it to a .png and Read it;-don't build the capture around it.)- ### If a capture errors, retry once A COLD capture can occasionally fail with a proxy URL containing a literal `{{port}}` (e.g. `…/proxy/{{port}}/: error sending request`) — a known **adom-cli** cold-start race (the proxy port isn't substituted yet). Just **run the same command again**; the-warm retry succeeds. Don't switch tools or reach for adom-desktop over this.+warm retry succeeds.  ## Sharing must be active (it usually is; here's the gate) @@ -178,36 +143,28 @@ adom-cli hydrogen sharing request --share screen  # adds the 'screen' scope The `screen` scope is for the whole desktop; `panel`/`workspace` come from tab sharing. See `hd-capture-share` for the sharing/approval UX. -**Release SCREEN sharing when you're done.** A `screen` share (getDisplayMedia) holds-the display **awake** — leaving it active blocks the user's screensaver. After a-one-off `screen` capture, run `adom-cli hydrogen sharing stop` (and close any Pup-windows you opened). Tab `panel`/`workspace` sharing doesn't hold the display, so this-only matters once you've requested the `screen` scope.+**Release SCREEN sharing when you're done.** A `screen` share (getDisplayMedia) holds the+display **awake** — leaving it active blocks the user's screensaver. After a one-off+`screen` capture, run `adom-cli hydrogen sharing stop` (and close any Pup windows you+opened). Tab `panel`/`workspace` sharing doesn't hold the display, so this only matters+once you've requested the `screen` scope.  ## Why this works the same in HD as it does for web Hydrogen  `adom-cli` is **one binary** used by both web Hydrogen and HD — you can test these commands anywhere. The difference is purely *where the work runs*: HD intercepts what adom-cli talks to. `adom-cli hydrogen <cmd>` hits `ADOM_HYDROGEN_URL`, which-in HD points at **HD's local proxy** (`http://127.0.0.1:<proxy>`). HD's proxy-pulls out the **local hydrogen/SSE commands** (screenshot, webview, caption,-notify, recording…) and runs them against the HD frontend over SSE, while-**carbon/cloud calls pass straight through** to the cloud. For a screenshot:-`PATCH /current/screenshot` → HD broadcasts an SSE `screenshot_request` → the-frontend Element-Captures the panel → uploads it into **this container's**-`screenshots/` folder → the CLI returns the saved path. So the command, and the-returned path, behave the same — the bytes just land in your local container.+in HD points at **HD's local proxy**. HD's proxy pulls out the **local hydrogen/SSE+commands** (screenshot, webview, caption, notify, recording…) and runs them against+the HD frontend over SSE, while **carbon/cloud calls pass straight through** to the+cloud. For a screenshot: `PATCH /current/screenshot` → HD broadcasts an SSE+`screenshot_request` → the frontend Element-Captures the panel → uploads it into+**this container's** `screenshots/` folder → the CLI returns the saved path. So the+command, and the returned path, behave the same — the bytes just land in your local+container.  ## What NOT to do (these are the traps) -- **Don't curl `host.docker.internal`.** That's a Docker-ism HD does not use. HD's-  host services are reached at `http://127.0.0.1:<port>` (WSL2 mirrored-  networking); the live control URL is in `~/.adom/hd-control-url`. But for-  screenshots you don't need any of that — use the CLI above.-- **Don't use `adom-desktop desktop_screenshot_*` for an HD panel/webview.** That-  grabs the whole Windows window/desktop, not the panel — it's the wrong tool for-  anything inside HD. Use it only for **non-HD** apps (KiCad, Fusion, a native-  window — see `hd-bridges`). - **You do NOT need an image resizer.** `adom-cli hydrogen screenshot` produces a   normal PNG and the `Read` tool reads PNGs directly. (Don't reach for ImageMagick   `convert` or Pillow — neither is guaranteed in the golden image, and you don't@@ -240,21 +197,18 @@ A `selector` clips to the **first matching element** in that surface — grab JU meter, a menu, a dialog, a toolbar instead of the whole window (verified live: `{selector:".resource-bars"}` → 192×61, vs `{target:"full"}` → the whole window). -**Screenshot a tab by its display NAME — incl. a BACKGROUND tab (fixed in HD v0.1.42).**+**Screenshot a tab by its display NAME — incl. a BACKGROUND tab.** `POST /screenshot {target:"<tab name>"}` resolves the name → the workspace panel, **activates that tab** (so a *background* tab actually paints — a webview is an OOPIF and can't be CDP-shot while hidden), captures the shell cropped to that panel, then **restores the previously-active tab**. So in a pane stacked `VS Code | ScreenA | ScreenB` (ScreenB showing), `{target:"ScreenA"}`-returns ScreenA's pixels and leaves ScreenB active. **Verified live 2026-06-14:** CDP *and* the-`adom-cli` SSE path (`screenshot panel --name ScreenA`) both returned the background tab's content-(example.com, not the active httpbin tab) and restored the prior tab — `target:"<name>"` was-NO-PNG before v0.1.42. (The `adom-cli` SSE path has always activated; v0.1.42 brings the CDP-`/screenshot` by-name path to parity.) This is the right call for "shot tab #2 while #4 is showing."+returns ScreenA's pixels and leaves ScreenB active. The `adom-cli` SSE path+(`screenshot panel --name ScreenA`) also activates + restores. This is the right call for+"shot tab #2 while #4 is showing."  **The teal zap:** every HD-driven capture flashes a teal (`#00b8b0`) highlight on the captured **region** (just the panel/menu/region; full-window flash only for-`target:full`). Teal = HD-driven. (The `adom-desktop` host verbs `hd_shot`/`hd_screenshot`-deliberately do NOT flash — different tool.) Pass `silent:true` to suppress it.+`target:full`). Teal = HD-driven. Pass `silent:true` to suppress it.  ### Screenshot a menu / dialog / panel — open it, then clip to it The killer combo with the UI command bus (see **`hd-ui`**): **open a surface →@@ -276,13 +230,7 @@ Verify a UI change: make the change → (rebuild if needed) → repeat. Log shots for the user with `shotlog inject -c hd-ui -d "<desc>" <path>` (shotlog resizes internally — another reason you don't need `convert`). -## Host window control (for NON-HD windows only)-`adom-desktop desktop_list_windows` → `desktop_set_window_state {hwnd,state}` →-`desktop_bring_to_front {hwnd}` → then `desktop_screenshot_window`. Windows-only.- ## Related skills - [hd-capture-share](../hd-capture-share/SKILL.md) — the sharing/approval UX behind `screenshot`-- [hd-desktop-sse](../hd-desktop-sse/SKILL.md) — the adom-cli → HD-proxy → SSE interception model - [hd-recording](../hd-recording/SKILL.md) · [hd-captions](../hd-captions/SKILL.md) — sibling `adom-cli hydrogen` AV verbs-- [hd-bridges](../hd-bridges/SKILL.md) — `desktop_screenshot_*` for NON-HD apps - `shotlog` — the screenshot log viewer/injector
skills/hd-settings/SKILL.md+8−8
@@ -2,19 +2,19 @@ name: hd-settings description: >   Hydrogen Desktop's Settings dialog and the full preference tree the user can-  change — theme, vim mode, launch-on-boot, console-on-startup, 3D control style,+  change — theme, vim mode, launch-on-login, console-on-startup, 3D control style,   font, line numbers, schematic nudge, the embedded Adom Desktop options, and   more. READ THIS when the user asks "how do I turn on vim mode", "change the-  theme", "make HD launch on boot", "stop Adom Desktop's window popping up",+  theme", "make HD launch at startup", "stop Adom Desktop's window popping up",   "switch to blender/solidworks orbit controls", "hide line numbers", "show the   console on startup", "make the UI compact", or "where are the settings". Opened   from the Adom logo menu → Settings. Trigger words — settings, preferences,   settings dialog, options, config, theme, dark mode, light mode, high contrast,   compact ui, developer mode, vim mode, vim emulation, line numbers, code font,-  editor font, launch on boot, start with windows, show console, console on-  startup, 3d controls, control style, fusion solidworks blender orbit, schematic-  nudge, auto approve, foreground hd, adom desktop window, turn on, turn off,-  change setting, how do I configure.+  editor font, launch on login, launch on startup, launch on boot, show console,+  console on startup, 3d controls, control style, fusion solidworks blender orbit,+  schematic nudge, auto approve, foreground hd, adom desktop window, turn on, turn+  off, change setting, how do I configure. ---  # HD Settings — the preference tree@@ -50,7 +50,7 @@ override. Keys are dotted (`section.subsection.name`). | Key | Default | What it does | |---|---|---| | `desktop.show_console_on_startup` | `false` | Show the debug console window when HD starts (→ "show the console on startup") |-| `desktop.launch_on_boot` | `true` | Auto-launch HD when Windows starts (→ "make HD launch on boot" / "stop HD starting with Windows" = set false) |+| `desktop.launch_on_boot` | `true` | Auto-launch HD on login / at startup (→ "make HD launch at startup" / "stop HD launching on login" = set false) |  ### adom_desktop  *(the embedded Adom Desktop / AD that HD runs)* When HD is running it takes over AD, so AD's options live here. See@@ -97,7 +97,7 @@ extension-specific settings).  - **"Turn on vim mode"** → `code.vim_emulation_mode` = true - **"Change the theme / dark mode / high contrast"** → `general.appearance.theme`-- **"Make HD launch on boot"** / "don't start with Windows" → `desktop.launch_on_boot`+- **"Make HD launch on login / at startup"** / "don't launch on login" → `desktop.launch_on_boot` - **"Stop Adom Desktop's window popping up"** → `adom_desktop.show_window_on_launch` = false - **"Blender / SolidWorks orbit controls"** → `3d.control_style` - **"Hide line numbers / change code font"** → `code.line_numbers.enabled` / `code.appearance.font.family`
skills/hd-setup-steps/SKILL.mdadded+134
@@ -0,0 +1,134 @@+---+name: hd-setup-steps+description: What HD's setup steps did to prepare your workspace — the install sequence that provisions the golden workspace image, injects your Adom session, wires up the relay, and walks the Claude auth gate. Use this skill when the user asks "what did setup do", "why is X installed", "re-run a setup step", "what's a virgin reset", or "why did step N fail". Trigger words — setup steps, install steps, setup panel, virgin reset, re-run step, Run All, what did setup do, why is X installed, setup failed, install-tools, hd setup, claude code extension install, gallia install, hd workspace ready.+---++# HD Setup Steps — what was done to prepare your workspace++This is the platform-generic, user-facing Q&A about what HD's setup did. The+exact per-platform step list, the workspace-provisioning commands, and the+state-file name live in the companion [[hd-setup-steps-windows]] skill (for+Windows/WSL2).++When you first launched Hydrogen Desktop (or after a virgin reset), HD ran an+install sequence to turn a blank machine into a fully-tooled Adom workspace.+The heavy tooling (code-server, gallia, the Adom CLIs, the claude CLI + Code+extension, VS Code settings, and all `hd-*` skills) is already BAKED into the+golden image; setup just provisions that image, injects your Adom session,+wires up the relay, and walks the Claude auth gate. This skill explains what+each phase did so you can help the user understand their environment, re-run+failed steps, or wipe and rebuild. See `hd-golden-image` for the baked-image+model.++The cascade is halt-on-failure, resume-not-restart, with per-step 3x+auto-retry. The exact steps and ordering are platform-specific — see+[[hd-setup-steps-windows]].++## The setup state machine — what each phase does++| Phase | Purpose |+|---|---|+| Provision the workspace | Ensure the runtime is available (install it if needed), provision the workspace from the golden image, create the workspace user, start code-server, verify host loopback. SUBSUMES the old pull-image / create-instance / start-instance steps. |+| wait-codeserver | Host TCP probe of the code-server port until it answers |+| install-adom-vscode | "Activate editor extensions" — installs NOTHING (binary + extension are baked); waits for Adom sign-in, reloads the editor iframe, and proves the editor-control API answers |+| set-env-vars | Set `ADOM_CARBON_URL`, `ADOM_HYDROGEN_URL`, `ADOM_HD_CONTROL_URL`, `VSCODE_PROXY_URI`, `ADOM_DESKTOP_MODE` |+| inject-api-key | Write the Adom session token into the workspace so adom-cli works |+| configure-vscode | settings.json / trusted-domains / activity-bar are BAKED; re-asserts theme + workbench backstops idempotently, and applies the per-session layout |+| ensure-adom-desktop | Verify the Adom Desktop companion app is running (the relay's desktop bridge) |+| start-relay | Start the adom-desktop relay inside the workspace |+| test-direct-connect | Prove the fast workspace→desktop command path |+| test-relay | Register the relay with Adom Desktop for file streaming (file transfer + shell exec) |+| test-adom-cli | GATE: carbon path + hydrogen-proxy reachability via adom-cli |+| claude-auth | The single human gate — restore Claude creds or drive the in-editor Claude.ai sign-in via the native browser Browser Picker; runs LAST before the payoff steps |+| ensure-sse | GATE: confirm the editor browser SSE session is connected so Welcome's webview-open doesn't 409 |+| verify-workspace | GATE: battery confirming the proxy holds a real layout |+| welcome | Open Claude Code, authenticate if needed, send the first prompt |+| open-welcome | GATE (final): open 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:+`install-gallia`, `install-hd-skills`, `verify-adom-desktop`,+`install-claude-cli`, `install-claude-ext`, `write-vscode-settings`,+`set-trusted-domains`, `clean-layout`. If a user asks "what installed gallia /+the Claude extension / my skills / VS Code settings", the answer is: **baked+into the golden image at build time, not a setup step.** See `hd-golden-image`.++## Common user questions++**"Why is X installed in my workspace?"** → If X is gallia, an Adom CLI, the+claude CLI, the Claude Code extension, VS Code settings, or an `hd-*` skill, it+was **baked into the golden image** — not run as a setup step. The setup steps+only provision the image, inject your session, wire the relay, and walk Claude+auth. The setup panel (HD UI → bottom) lists every step with its current+status.++**"Setup failed at step N"** → The setup panel shows the error. Most common+failures: the provision step (runtime unavailable, or the golden-image+download), test-adom-cli (carbon/hydrogen-proxy not reachable yet), and+claude-auth (Claude credentials expired). Each step has a retry button (and the+cascade already retried it 3x). Platform-specific failure causes are in+[[hd-setup-steps-windows]].++**"Re-run a single step"** → In the setup panel, click the step row and use the+Re-run action. Or via API: `POST http://127.0.0.1:47084/setup/step/<id>`+(optional body `{"continue_after":true}` to keep going after it).++**"Re-run all steps"** → Click "Run All" in the setup panel; it resumes from the+first not-done step. (The old headless `POST /setup/run-all` is now REFUSED.)++## Virgin reset++Virgin reset wipes parts of your workspace so setup can rebuild them cleanly.+The ONLY programmatic trigger is `POST /setup/panel/run-virgin-reset`. Toggle+which artifacts to delete (option keys in parentheses):++| Toggle (key) | What gets wiped | When to use |+|---|---|---|+| Install step state (`install_state`) | Marks all steps as pending so they re-run | Always (default on) |+| Workspace (`container`) | PRISTINE wipe + re-provision — deletes the workspace AND everything in it, including your project files | Always (default on); your work is GONE |+| Image tarball (`tarball`, legacy `image`) | Deletes the cached golden image (full re-download) | Rarely — only if the image is corrupted |+| Webview storage (`webview_storage`) | Queued wipe, flushed at next HD launch (restart_required) | Rarely |+| VS Code state (`vscode_state`) | Queued wipe, flushed at next HD launch (restart_required) | Rarely |+| Adom session token (`adom_token`) | Deletes `hydrogen-session.txt`; forces re-login | Rarely |+| Claude credentials (`claude_token`) | Deletes the host-side Claude creds backup; forces Claude re-auth | When Claude auth is stuck |++`confirmed_destructive` must be set. After toggling, hit "Wipe Selected", then+"Run All" to rebuild. The workspace reset 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.++CRITICAL: the workspace reset ONLY ever wipes HD's own workspace. It never+touches other workspaces, distros, or runtimes the user may have on the+machine, and it performs NO reboot for the wipe. The platform-specific wipe+commands are in [[hd-setup-steps-windows]].++## Setup panel APIs (useful for AI automation)++| Endpoint | What it does |+|---|---|+| `GET /setup/state` | Current state — `never-run`, `in-progress`, `complete`, or `error` |+| `POST /setup/step/<id>` | Re-run a single named step (optional `{"continue_after":true}`) |+| `POST /setup/panel/run-virgin-reset` | Trigger virgin reset with the supplied toggle options |+| `POST /setup/panel/show` | Open the setup panel from anywhere |++All on HD's control API at `http://127.0.0.1:47084`.++**DEPRECATED — now REFUSED, do not use:** `POST /wsl/unregister`,+`POST /setup/virgin-reset`, `POST /setup/run-all`, `POST /setup/run-step`. Use+`POST /setup/panel/run-virgin-reset` and `POST /setup/step/<id>` instead.++## Setup state file++Setup writes its state to a per-step state file (one entry per step with+`status: pending|running|done|failed`, output text, percent complete). HD reads+this on launch to decide whether the setup panel auto-opens. The exact file+name and location are platform-specific — see [[hd-setup-steps-windows]].++## Related skills++- [[hd-setup-steps-windows]] — the concrete WSL2 16-step cascade, the import step, `wsl --unregister`, `setup-steps-wsl.json`, and the golden tarball+- `hd-golden-image` — the baked-image model: what's pre-installed vs. what setup does+- `hd-setup` — the setup-panel UX and virgin-reset toggles+- `hd-browser-picker` — used by claude-auth for the Claude auth OAuth flow+- `hd-adom-auth` — how the Adom session token (inject-api-key) gets injected
skills/hd-setup/SKILL.mdadded+192
@@ -0,0 +1,192 @@+---+name: hd-setup+description: >+  HD setup panel: the install-step cascade, 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, wipe, reset workspace, keep auth, test setup.+---++# Hydrogen Desktop -- Setup Panel & Virgin Reset++This is the platform-generic reference for the HD setup panel and virgin+reset. The host-platform specifics (the exact install cascade on Windows/WSL2,+distro import/unregister mechanics, the per-platform step list and state file)+live in the companion [[hd-setup-windows]] skill.++## 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 golden workspace image ships+with code-server, gallia, the Adom CLIs, the claude CLI + Code extension, VS+Code settings, and all `hd-*` skills BAKED IN. Setup just provisions 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 Install Steps++The setup cascade is a halt-on-failure, resume-not-restart sequence with+per-step 3x auto-retry. State is tracked per-step (status pending / running /+done / failed, output text, percent complete) and HD reads it on launch to+decide whether the setup panel auto-opens. The exact step list, ordering, and+state-file name are platform-specific — see [[hd-setup-windows]].++Conceptually the steps fall into these phases:++1. **Provision the workspace** — ensure the runtime is available, import the+   golden image, create the workspace user, start code-server, verify host+   loopback reachability. This single step subsumes any older+   pull-image / create-instance / start-instance trio.+2. **Activate the editor** — wait for code-server, activate editor extensions+   (baked, installs nothing), reload the editor iframe, prove the+   editor-control API answers.+3. **Wire identity + environment** — set the Adom env URLs, inject the Adom+   session token, re-assert VS Code config backstops idempotently, apply the+   per-session layout.+4. **Wire the relay** — verify the Adom Desktop companion app, start the+   relay inside the workspace, prove direct-connect and register the relay for+   file streaming.+5. **Gates + payoff** — gate on adom-cli reachability (carbon ++   hydrogen-proxy), walk the single Claude auth gate, confirm the editor SSE+   session, verify the proxy holds a real layout, open Claude Code and send the+   first prompt, and finally open 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-gallia`, `install-hd-skills`,+`verify-adom-desktop`, `install-claude-cli`, `install-claude-ext`,+`write-vscode-settings`, `set-trusted-domains`, `clean-layout`. gallia, the+Adom CLIs, the claude CLI + Code extension, code-server, settings, and all+`hd-*` skills are baked into the golden 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, after the per-step 3x+auto-retry is exhausted). Remaining steps are NOT executed. The cascade+resumes — it does NOT restart from the first step — 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 steps to pending | CLEAN / EXISTS |+| Workspace (`container`) | PRISTINE wipe + re-provision of the workspace (ONLY HD's own workspace) | GONE / RUNNING / EXISTS |+| Image tarball (`tarball`, legacy `image`) | Deletes the cached golden image (full 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 workspace reset is a PRISTINE wipe + re-provision — 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 virgin reset only ever touches HD's OWN workspace. It NEVER+touches other workspaces, distros, or runtimes the user may have on the+machine. The platform-specific commands (and the never-touch-global rule)+are in [[hd-setup-windows]].++## 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-provisioned workspace while keeping auth working — the+inject-api-key step and the claude-auth step won't fail.++### Programmatic triggers (the ONLY supported headless paths)++```bash+# 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 /wsl/unregister`, `POST /setup/virgin-reset`,+`POST /setup/run-all`, `POST /setup/run-step`.++## Key Steps Explained++### Provision the workspace (step 1)+The big one. Ensures the runtime is available (installing it if needed), then+provisions the workspace from the full pre-baked golden image, creates the+workspace user, starts code-server, and verifies host loopback reachability.+This single step replaces the old pull-image / create-instance /+start-instance trio. Platform-specific provisioning commands and any+runtime-install reboot are in [[hd-setup-windows]].++### inject-api-key+Writes the Adom session token into the workspace so adom-cli works. Requires+the user to be signed in. Keep the `adom_token` toggle UNCHECKED during+automated test resets.++### test-direct-connect+Proves the fast workspace→desktop command path. The CLI auto-probes the host+control API and routes through Adom Desktop's direct connect API.++### test-relay (register relay)+Registers the relay (started by the start-relay step) with Adom Desktop for+file streaming via the code-server proxy path. This enables `pull_file`,+`send_files`, and `shell_execute`.++### claude-auth+The single human gate. Restores / validates Claude creds in the workspace+(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.++### 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: gallia, the Adom CLIs, the claude CLI + Code extension, VS Code+> settings, and `hd-*` skills are NOT setup steps — they are baked into the+> golden image. See `hd-golden-image`.++## Workspace Recreation++When the workspace is wiped and re-provisioned (step 1), the new workspace is+a fully pre-baked image. Host port-forwarding for code-server is handled by the+runtime, so the port-conflict / stale-mapping class of bug does not apply.+Other services tunnel through the code-server `/proxy/{port}/` path. The+platform-specific port-forwarding behavior is in [[hd-setup-windows]].
skills/hd-ui/SKILL.md+28−34
@@ -33,7 +33,7 @@ HD's window has these regions (top to bottom, left to right): - Panes are split and resizable  ### Setup Panel (bottom)-- Collapsible panel showing the setup-cascade steps (16 steps under the WSL2 runtime)+- Collapsible panel showing the setup-cascade steps - See `hd-setup` skill for details  ## Menus@@ -52,17 +52,17 @@ The main menu, opened by clicking the Adom logo at the top-left. Items are group - **Zoom** — webview zoom controls (− %  +) with persistence across launches - **Fullscreen** — toggle fullscreen - **Console** — show/hide the HD debug console window-- **Developer Tools** — open WebView2 DevTools+- **Developer Tools** — open the webview developer tools - **Dev Toolbar** — show/hide the Adom Dev Toolbar window (eval-in / shot / Claude control endpoints); bus id `dev-toolbar.toggle`  > The Bridges section / "Bridge Manager" item was removed (it was a no-op with no backing panel). For the bridge panel itself, see `hd-bridges`.  **Workspace / runtime section** (section label shows live status badge: `RUNNING`, `STOPPED`, etc.)-- **Restart** — restarts the workspace; under WSL2 this terminates the `Adom-Workspace` distro and re-ensures code-server, under the Docker runtime it's `docker restart <container>`.-- **Stop** — stops the workspace; under WSL2 this terminates the `Adom-Workspace` distro, under the Docker runtime it's `docker stop <container>`.+- **Restart** — restarts the workspace (terminates and re-ensures code-server). The exact mechanism is runtime-specific.+- **Stop** — stops the workspace. The exact mechanism is runtime-specific.  **ADMIN**-- **Setup Steps** — opens the setup panel (the setup cascade for the active runtime; 16 steps under WSL2); see hd-setup-steps+- **Setup Steps** — opens the setup panel (the setup cascade for the active runtime); see hd-setup-steps - **Virgin Reset** — opens the virgin reset section of the setup panel; see hd-volume for what each toggle deletes - **Browser Picker Manager** — configure per-domain default browser/profile prefs; see hd-browser-picker @@ -100,9 +100,9 @@ API — no CDP, no `.click()`, no selector guessing.** This is how you operate H user says "open the Ports dialog", "open About", "show settings", etc.  **Get the control URL from the discovery file** `~/.adom/hd-control-url` (HD rewrites it with-the live, dynamic control port every launch; it's the host loopback, shared with the distro by-WSL2 mirrored networking). Read it from a file, not an env var — your Bash tool runs-non-interactive shells that don't source `.bashrc`/`profile.d`:+the live, dynamic control port every launch; it's the host loopback, reachable from the+workspace). Read it from a file, not an env var — your Bash tool runs non-interactive shells+that don't source `.bashrc`/`profile.d`:  ```bash CTRL="$(cat ~/.adom/hd-control-url)"@@ -162,43 +162,37 @@ b64/silent) is in **[hd-self-screenshot](../hd-self-screenshot/SKILL.md)**. ## Legacy: raw CDP clicking (deprecated fallback — the command bus above is canonical)  ⚠ The command bus (`/ui/actions` → `/ui/invoke`) is the canonical way to drive HD's UI. Before-it existed, UI was driven by CDP `.click()` on CSS selectors via hd-cdp.js. This is brittle-(selectors drift; multiple `localhost:1420` CDP targets) and the selectors below may be stale.-Reach for CDP ONLY for an element not yet on the bus — and the better fix is to register it.+it existed, UI was driven by CDP `.click()` on CSS selectors via the HD CDP eval channel. This+is brittle (selectors drift; multiple `localhost:1420` CDP targets) and the selectors below may+be stale. Reach for CDP ONLY for an element not yet on the bus — and the better fix is to+register it. Eval JS against the CDP endpoint (its port comes from `/discover` as `cdp`).  ### Find and click menu items-```bash-# Open Adom menu-echo document.querySelector('.logo-button')?.click() | node C:\Users\john\hd-cdp.js--# Find a menu item by text-echo var items=document.querySelectorAll('.dropdown-link,.menu-item');-var target=Array.from(items).find(function(e){return e.textContent.includes('Ports')});-if(target)target.click() | node C:\Users\john\hd-cdp.js+```js+// Open Adom menu+document.querySelector('.logo-button')?.click()++// Find a menu item by text+var items = document.querySelectorAll('.dropdown-link,.menu-item');+var target = Array.from(items).find(function(e){return e.textContent.includes('Ports')});+if (target) target.click() ```  ### Click setup panel buttons-```bash-# Run All-echo document.querySelector('.run-all').click() | node C:\Users\john\hd-cdp.js--# Virgin Reset dropdown-echo document.querySelector('.virgin-reset-btn')?.click() | node C:\Users\john\hd-cdp.js--# Wipe Selected (execute virgin reset)-echo document.querySelector('.virgin-go')?.click() | node C:\Users\john\hd-cdp.js--# Close setup panel-echo document.querySelector('.close-btn,.setup-close')?.click() | node C:\Users\john\hd-cdp.js+```js+document.querySelector('.run-all').click()                 // Run All+document.querySelector('.virgin-reset-btn')?.click()       // Virgin Reset dropdown+document.querySelector('.virgin-go')?.click()              // Wipe Selected (execute virgin reset)+document.querySelector('.close-btn,.setup-close')?.click() // Close setup panel ```  ### Query step states-```bash-echo JSON.stringify(Array.from(document.querySelectorAll('.step-row')).map(+```js+JSON.stringify(Array.from(document.querySelectorAll('.step-row')).map( function(e,i){   var icon=e.querySelector('.step-icon');   return{n:i+1, s:icon?.textContent?.trim()}-})) | node C:\Users\john\hd-cdp.js+})) ```  ## CSS Selectors for Key Elements
skills/hd-welcome/SKILL.md+8−8
@@ -24,16 +24,15 @@ It's served locally at `http://localhost:1420/welcome.html` by HD's dev file ser  ## When it appears -- Automatically as the final setup step. On the WSL2 runtime (default) that is-  the `open-welcome` gate (step 16 of 16); on the legacy Docker runtime it's-  the last of the 24 steps.+- Automatically as the final setup step — the `open-welcome` gate (the last step of the+  setup cascade for the active runtime). - Can be opened manually via the API  ## How to open it -### From inside the Docker container (the standard way)+### From inside the workspace (the standard way) -This is how the setup steps do it, and how any AI inside the container should:+This is how the setup steps do it, and how any AI inside the workspace should:  ```bash adom-cli hydrogen webview open-or-refresh \@@ -42,8 +41,9 @@ adom-cli hydrogen webview open-or-refresh \   --panel-id desktop-pane-right ``` -The URL is rendered by HD's WebView2 on Windows, so `localhost:1420` resolves-to HD's dev file server on Windows, NOT to anything inside the container.+`localhost:1420` is HD's dev file server running on the host (where HD itself runs),+NOT anything inside the workspace. HD's webview renders the URL against the host, so the+page resolves on whatever platform HD is running on.  ### From outside (via HD control API) @@ -67,7 +67,7 @@ curl -X POST http://127.0.0.1:47083/api/workspaces/editor/{owner}/{repo}/current ## IMPORTANT: This is NOT  - NOT the adom.inc homepage (https://adom.inc)-- NOT the wiki (https://git-wiki-*.adom.cloud)+- NOT the Adom wiki (https://wiki.adom.inc) - NOT the VS Code welcome tab inside code-server  It is a LOCAL static page at `http://localhost:1420/welcome.html`, bundled
skills/hd-workspace-monitoring/SKILL.mdadded+160
@@ -0,0 +1,160 @@+---+name: hd-workspace-monitoring+description: >+  How Hydrogen Desktop monitors and manages the local workspace and code-server.+  Covers the 15s workspace state poll, the two health levels (runtime available,+  workspace Running + code-server reachable), the floaty states, auto-start via+  setup_and_start, auto-reload of the VS Code iframe, and the lifecycle dialog+  system. Read BEFORE touching PanelVisualStudioCode.svelte,+  ContainerLifecycleDialog.svelte, or any workspace state handling code. Trigger+  words: workspace stopped, workspace monitoring, workspace poll, workspace floaty,+  start workspace, code-server reachable, lifecycle dialog, workspace state,+  workspace running.+---++# HD Workspace Monitoring++This is the platform-generic reference for how HD monitors workspace health.+The host-platform specifics (the runtime-unavailable floaty wording, the stop+command, the exact code-server reachability port, and the no-daemon framing)+live in the companion [[hd-workspace-monitoring-windows]] skill.++## Architecture++The workspace is HD's local code-server-backed dev environment. HD monitors+workspace health at two levels:++1. **Runtime available** — is the workspace runtime itself installed and+   responding on this machine?+2. **Workspace healthy** — is the workspace present AND Running AND is+   code-server reachable on its host port?++The second level is a real reachability check, not just "is the workspace+present." A resume reality-check (after sleep, or after an HD rebuild/relaunch)+requires code-server to actually answer before HD trusts the workspace as+healthy — a workspace can be Running while code-server is dead.++The VS Code panel (`PanelVisualStudioCode.svelte`) polls workspace state every+15s and shows appropriate UI for each state. These frontend components are+runtime-agnostic; they front the active runtime via the runtime trait.++## Workspace State Poll++`PanelVisualStudioCode.svelte` calls `get_container_status` (Tauri command)+every 15s. The command dispatches through the runtime trait to the active+runtime impl. Returns a status struct shaped like:+```rust+pub struct ContainerStatus {+    pub docker_available: bool,    // is the workspace runtime available?+    pub image_pulled: bool,        // is the workspace image/tarball present?+    pub container_exists: bool,    // is the workspace present (Running or Stopped)?+    pub container_running: bool,   // is it Running AND code-server reachable?+    pub container_id: Option<String>,+    pub error: Option<String>,+}+```+The field names are inherited from the Docker era; under any runtime they map+onto the two health levels above (runtime availability, then+workspace-present → workspace-Running + code-server-reachable).++## Floaty States++All floaties appear INSIDE the VS Code panel only — not as full-app modals.+They are draggable (grab header to move). The rest of the app (wiki tab, menu,+etc.) remains fully interactive.++### 1. Runtime Not Available (red dot)+- **When**: the workspace runtime itself is not installed / not responding+  (level-1 health fails)+- **Action**: "Run Setup Steps" button → dispatches `hd-show-setup` event+  (which walks the user through enabling the runtime)+- **Color**: Red dot in header++The exact runtime name and floaty message are platform-specific — see+[[hd-workspace-monitoring-windows]].++### 2. Workspace Stopped / Not Ready (red dot)+- **When**: the runtime is available but the workspace isn't Running, or it's+  Running but code-server isn't reachable on its host port+  (`container_running == false`)+- **Message**: "The Adom workspace is not running."+- **Action**: "Start Workspace" button → calls `setup_and_start` Tauri command+- **Lifecycle dialog**: Shows the draggable lifecycle dialog with live setup+  output+- **Auto-reload**: After the workspace + code-server come up, waits for+  code-server health, then reloads the VS Code iframe++## Auto-Start via `setup_and_start`++The "Start Workspace" path calls Tauri `setup_and_start`, which delegates to+the active runtime's `setup_and_start`:+- If the workspace isn't present yet, `fresh_import` = download the golden+  image + provision the workspace + start code-server.+- If the workspace is present but code-server is down, it just (re-)starts+  code-server.++Importantly, code-server runs as an **HD-owned child process** (not a detached+`nohup`) — it dies with HD. So HD also **re-ensures code-server on every+launch** (look for `re-ensured code-server on launch` in the log). Without+that, a freshly relaunched HD would show the workspace Running but the editor+stuck on "Starting AI Environment" forever, because the previous HD's+code-server child was orphaned. See `hd-workspace-lifecycle` for the full+lifecycle detail.++## Lifecycle Dialog++`ContainerLifecycleDialog.svelte` — a draggable floating card (no background+blur) that shows live command output for start/stop/restart operations on the+workspace.++### Events+Listens for `hd-container-lifecycle` CustomEvents on `window`:+- `action: 'restart' | 'stop' | 'start'` — opens dialog, starts spinner+- `action: 'step', step: string` — appends a log line+- `action: 'done'` — stops spinner, shows Close button, auto-reloads VS Code+- `action: 'stopped'` — stops spinner (for stop-only operations)+- `action: 'error', message: string` — shows error state++### Title+Dynamic based on `actionType`:+- Restarting: "Workspace Restarting..." → "Restart Complete"+- Stopping: "Stopping Workspace..." → "Workspace Stopped"+- Starting: "Starting Workspace..." → "Workspace Started"+- On error: "Restart/Stop/Start Failed"++### VS Code Auto-Reload+After the `done` event, the dialog polls code-server health (`/proxy/8080/`)+every 5s for up to 2 minutes. When healthy, it reloads all iframes whose src+points at the host-side code-server port, then shows "VS Code iframe reloaded"+and stops.++## Tauri Commands++| Command | What it does |+|---|---|+| `get_container_status` | Returns workspace status — runtime available, workspace present, Running + code-server reachable |+| `setup_and_start` | `fresh_import` (provision workspace) + start code-server, up to 10 min timeout |+| `stop_container` | Stops the workspace |+| `toggle_console` | Show/hide the debug console window |+| `is_console_visible` | Returns true if console window exists |++The exact stop command is platform-specific — see+[[hd-workspace-monitoring-windows]].++## Menu Items (Adom Menu → Workspace Section)+- **Restart Workspace** — stop the workspace + re-ensure code-server; emits+  lifecycle events, shows dialog+- **Stop Workspace** — stops the workspace; emits lifecycle events, shows+  dialog, triggers stopped floaty+- **Start Workspace** — available when stopped (from floaty button or menu)++## Settings (Desktop section in Settings dialog)+- `desktop.show_console_on_startup` — boolean, default false+- `desktop.launch_on_boot` — boolean, default true (auto-start on boot)++## Related skills++- [[hd-workspace-monitoring-windows]] — the WSL2 "Not Available" floaty, `wsl --terminate` stop, the 7380 reachability check, the no-daemon framing+- `hd-workspace-lifecycle` — provision/export/remove/stop, the never-touch-global rule, control endpoints+- `hd-container-stats` — the title-bar CPU/RAM bars and `workspace_stats()` probe+- `hd-networking` — code-server port, control port