Hydrogen Desktop Bootstrap (apps + skills)
Public Made by Adomby adom
Layer Hydrogen Desktop's workspace onto a standard Adom workstation.
name: hd-ui description: > HD's user interface: menus, dialogs, panels, login/logout, profile menu, workspace layout, setup panel — and how to DRIVE them from the workspace via the UI command bus (GET /ui/actions → POST /ui/invoke), the first-class way to open/close/toggle any HD menu or dialog (no CDP clicking). READ when the user asks you to open/close a dialog or menu, operate HD's UI, or you need to know where a UI element is. Trigger words — HD menu, HD dialog, HD panel, open dialog, open menu, close dialog, drive UI, ui/actions, ui/invoke, command bus, ports.open, settings.open, about dialog, profile menu, login, logout, settings, setup panel, Adom menu, HD UI.
Hydrogen Desktop — UI Reference
Window Layout
HD's window has these regions (top to bottom, left to right):
Title Bar
- Left: "jlauer12 / Hydrogen Desktop" — shows user + app name
- Right: CPU/RAM badges, window controls (minimize/maximize/close)
Tab Bar
- VS Code tab — the main code editor (iframe to code-server)
- Webview tab — wiki/app content panel
- Additional tabs for bridges, sensors, etc.
Main Content Area
- Left pane: Usually VS Code iframe
- Right pane: Usually webview (wiki, shotlog, etc.)
- Panes are split and resizable
Setup Panel (bottom)
- Collapsible panel showing the setup-cascade steps (27 steps under the WSL2 runtime)
- See
hd-setupskill for details
Menus
Adom Menu (top-left logo dropdown)
The main menu, opened by clicking the Adom logo at the top-left. Items are grouped into labelled sections (in order, top to bottom):
(top, unlabelled)
- Go to Dashboard — switches to the Hydrogen dashboard view
- Settings — opens the Settings dialog
- Ports... — opens the port configuration dialog (see hd-ports)
- API Explorer... — opens the control-API endpoint explorer dialog
DESKTOP (Tauri-only — won't appear in browser-served HD; in order)
- Adom Desktop — brings the embedded Adom Desktop window to the foreground (taskbar); bus id
adom-desktop.open - Zoom — webview zoom controls (− % +) with persistence across launches
- Fullscreen — toggle fullscreen
- Console — show/hide the HD debug console window
- Developer Tools — open WebView2 DevTools
- 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-Workspacedistro and re-ensures code-server, under the Docker runtime it'sdocker restart <container>. - Stop — stops the workspace; under WSL2 this terminates the
Adom-Workspacedistro, under the Docker runtime it'sdocker stop <container>.
ADMIN
- Setup Steps — opens the setup panel (the setup cascade for the active runtime; 27 steps under WSL2); 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
Profile Menu (top-right avatar)
Click the user avatar (circular photo) in the top-right corner.
- Your profile — view Adom profile
- Your repositories — list repos
- Your molecules — list molecules
- Log out — signs out of Adom, removes session token
CRITICAL: Logout is ONLY in the profile menu (top-right avatar), NOT in the Adom menu (top-left). Future AI threads: don't look for logout in the wrong menu.
Dialogs
Port Settings Dialog
Access: Adom menu → Ports...
Shows all configurable ports with live conflict detection.
Fields: Code Editor, Workspace Proxy, Control API, DevTools (CDP), Hostname.
See hd-networking skill for port details.
Settings Dialog
Access: Adom menu → Settings Application-level preferences.
Browser Picker Dialog
Appears when clicking external links. Shows detected browser profiles (Edge, Chrome, etc.) with per-domain "remember" option.
Driving the UI — the command bus (PREFERRED, first-class)
⭐ Every menu / dialog / panel HD has wired is a first-class action you drive over the control
API — no CDP, no .click(), no selector guessing. This is how you operate HD's UI when the
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:
CTRL="$(cat ~/.adom/hd-control-url)"
Always do this in order:
- Discover what's drivable (ids + descriptions):
curl -s "$CTRL/ui/actions" # → {ok, count, actions:[{id,label,description,group}], _hints} - Drive one — returns ONLY after the frontend actually ran it:
curl -s -X POST "$CTRL/ui/invoke" \ -H 'Content-Type: application/json' -d '{"id":"ports.open"}' # → {ok:true, id:"ports.open", value:…} - Not in the list? That absence is the signal: the element isn't wired to the bus yet. It
needs a 2-line
registerUiAction(...)in its Svelte component (a dev change in the hydrogen-desktop repo — see that repo'shd-ui-actionsskill). Don't fall back to clicking; wire it. The response's_hints.if_missingsays the same.
Common ids (always GET /ui/actions for the live set): adom-menu.open/.close,
profile-menu.open/.close, ports.open/.close, settings.open/.close,
api-explorer.open/.close, browser-picker.open/.close, about.open/.close,
adom-desktop.open, setup-panel.show, virgin-reset.open, dashboard.go,
fullscreen.toggle, console.toggle, devtools.open, dev-toolbar.toggle,
container.start/.stop/.restart.
Menu ITEMS, not just open/close: the profile menu also exposes per-item actions —
profile.view, profile.repositories, profile.molecules, profile.logout —
so you can trigger a specific item directly (it navigates as if the human clicked it),
WITHOUT opening the menu + screen-clicking. (profile.logout is the canonical logout — see
the logout note above.) GET /ui/actions for the live set; the Adom menu will get the same
item-level treatment over time.
Note: there is no
port-mappings.open/.closeid — that action was never registered. Don't try to invoke it. Gap:setup-panelhas.showbut no.hide— to close it, evalwindow.__hdSetSetupPanel(false)(via/eval-in) or open another surface. Asetup-panel.hideaction is on the wishlist.
Open a surface, then screenshot it (the killer combo)
Combine the bus with HD's canonical capture endpoint to grab any menu/dialog/panel with
no screen-clicking: POST /ui/invoke {id:"<x>.open"} → POST /screenshot {target:"shell", selector:"<open-state selector>"} → POST /ui/invoke {id:"<x>.close"}.
The /screenshot region-flash lands on that selector. Resolved selectors (verified live):
Adom & profile menus → .dropdown-content.open (one open at a time); Setup panel →
.setup-panel; API Explorer → .dialog. Full /screenshot reference (target/selector/
b64/silent) is in hd-self-screenshot.
This is HD-desktop-only and SEPARATE from
adom-cli.adom-clidrives web-hydrogen's UI via the SSE bridge (ADOM_HYDROGEN_URL) and is unchanged. For HD desktop's far richer UI control, use the command bus above — neveradom-clifor this.
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.
Find and click menu items
# 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
Click setup panel buttons
# 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
Query step states
echo 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
| Element | Selector |
|---|---|
| VS Code iframe | iframe.vis-studio-iframe or iframe[title="code"] |
| Setup panel | .setup-panel |
| Run All button | .run-all |
| Virgin Reset button | .virgin-reset-btn |
| Wipe Selected button | .virgin-go |
| Step rows | .step-row |
| Step icon (✅/❌/○) | .step-icon |
| Step label | .step-label |
| Adom menu button | .logo-button |
| Profile menu button | .profile-dropdown-button |
| Tab bar | tab container at top |
---
name: hd-ui
description: >
HD's user interface: menus, dialogs, panels, login/logout, profile menu,
workspace layout, setup panel — and how to DRIVE them from the workspace via
the UI command bus (GET /ui/actions → POST /ui/invoke), the first-class way to
open/close/toggle any HD menu or dialog (no CDP clicking). READ when the user
asks you to open/close a dialog or menu, operate HD's UI, or you need to know
where a UI element is. Trigger words — HD menu, HD dialog, HD panel, open
dialog, open menu, close dialog, drive UI, ui/actions, ui/invoke, command bus,
ports.open, settings.open, about dialog, profile menu, login, logout, settings,
setup panel, Adom menu, HD UI.
---
# Hydrogen Desktop — UI Reference
## Window Layout
HD's window has these regions (top to bottom, left to right):
### Title Bar
- **Left**: "jlauer12 / Hydrogen Desktop" — shows user + app name
- **Right**: CPU/RAM badges, window controls (minimize/maximize/close)
### Tab Bar
- **VS Code** tab — the main code editor (iframe to code-server)
- **Webview** tab — wiki/app content panel
- Additional tabs for bridges, sensors, etc.
### Main Content Area
- **Left pane**: Usually VS Code iframe
- **Right pane**: Usually webview (wiki, shotlog, etc.)
- Panes are split and resizable
### Setup Panel (bottom)
- Collapsible panel showing the setup-cascade steps (27 steps under the WSL2 runtime)
- See `hd-setup` skill for details
## Menus
### Adom Menu (top-left logo dropdown)
The main menu, opened by clicking the Adom logo at the top-left. Items are grouped into labelled sections (in order, top to bottom):
**(top, unlabelled)**
- **Go to Dashboard** — switches to the Hydrogen dashboard view
- **Settings** — opens the Settings dialog
- **Ports...** — opens the port configuration dialog (see hd-ports)
- **API Explorer...** — opens the control-API endpoint explorer dialog
**DESKTOP** (Tauri-only — won't appear in browser-served HD; in order)
- **Adom Desktop** — brings the embedded Adom Desktop window to the foreground (taskbar); bus id `adom-desktop.open`
- **Zoom** — webview zoom controls (− % +) with persistence across launches
- **Fullscreen** — toggle fullscreen
- **Console** — show/hide the HD debug console window
- **Developer Tools** — open WebView2 DevTools
- **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>`.
**ADMIN**
- **Setup Steps** — opens the setup panel (the setup cascade for the active runtime; 27 steps under WSL2); 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
### Profile Menu (top-right avatar)
Click the user avatar (circular photo) in the top-right corner.
- **Your profile** — view Adom profile
- **Your repositories** — list repos
- **Your molecules** — list molecules
- **Log out** — signs out of Adom, removes session token
**CRITICAL**: Logout is ONLY in the profile menu (top-right avatar),
NOT in the Adom menu (top-left). Future AI threads: don't look for
logout in the wrong menu.
## Dialogs
### Port Settings Dialog
Access: Adom menu → Ports...
Shows all configurable ports with live conflict detection.
Fields: Code Editor, Workspace Proxy, Control API, DevTools (CDP), Hostname.
See `hd-networking` skill for port details.
### Settings Dialog
Access: Adom menu → Settings
Application-level preferences.
### Browser Picker Dialog
Appears when clicking external links. Shows detected browser profiles
(Edge, Chrome, etc.) with per-domain "remember" option.
## Driving the UI — the command bus (PREFERRED, first-class)
⭐ **Every menu / dialog / panel HD has wired is a first-class action you drive over the control
API — no CDP, no `.click()`, no selector guessing.** This is how you operate HD's UI when the
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`:
```bash
CTRL="$(cat ~/.adom/hd-control-url)"
```
**Always do this in order:**
1. **Discover** what's drivable (ids + descriptions):
```bash
curl -s "$CTRL/ui/actions"
# → {ok, count, actions:[{id,label,description,group}], _hints}
```
2. **Drive** one — returns ONLY after the frontend actually ran it:
```bash
curl -s -X POST "$CTRL/ui/invoke" \
-H 'Content-Type: application/json' -d '{"id":"ports.open"}'
# → {ok:true, id:"ports.open", value:…}
```
3. **Not in the list?** That absence is the signal: the element isn't wired to the bus yet. It
needs a 2-line `registerUiAction(...)` in its Svelte component (a dev change in the
hydrogen-desktop repo — see that repo's `hd-ui-actions` skill). Don't fall back to clicking;
wire it. The response's `_hints.if_missing` says the same.
Common ids (always `GET /ui/actions` for the live set): `adom-menu.open`/`.close`,
**`profile-menu.open`/`.close`**, `ports.open`/`.close`, `settings.open`/`.close`,
`api-explorer.open`/`.close`, `browser-picker.open`/`.close`, `about.open`/`.close`,
`adom-desktop.open`, `setup-panel.show`, `virgin-reset.open`, `dashboard.go`,
`fullscreen.toggle`, `console.toggle`, `devtools.open`, `dev-toolbar.toggle`,
`container.start`/`.stop`/`.restart`.
**Menu ITEMS, not just open/close:** the profile menu also exposes per-item actions —
**`profile.view`**, **`profile.repositories`**, **`profile.molecules`**, **`profile.logout`** —
so you can trigger a specific item directly (it navigates as if the human clicked it),
WITHOUT opening the menu + screen-clicking. (`profile.logout` is the canonical logout — see
the logout note above.) `GET /ui/actions` for the live set; the Adom menu will get the same
item-level treatment over time.
> Note: there is **no** `port-mappings.open`/`.close` id — that action was never
> registered. Don't try to invoke it.
> **Gap:** `setup-panel` has `.show` but **no `.hide`** — to close it, eval
> `window.__hdSetSetupPanel(false)` (via `/eval-in`) or open another surface. A
> `setup-panel.hide` action is on the wishlist.
### Open a surface, then screenshot it (the killer combo)
Combine the bus with HD's canonical capture endpoint to grab any menu/dialog/panel with
**no screen-clicking**: `POST /ui/invoke {id:"<x>.open"}` → `POST /screenshot
{target:"shell", selector:"<open-state selector>"}` → `POST /ui/invoke {id:"<x>.close"}`.
The `/screenshot` region-flash lands on that selector. Resolved selectors (verified live):
**Adom & profile menus** → `.dropdown-content.open` (one open at a time); **Setup panel** →
`.setup-panel`; **API Explorer** → `.dialog`. Full `/screenshot` reference (target/selector/
b64/silent) is in **[hd-self-screenshot](../hd-self-screenshot/SKILL.md)**.
> **This is HD-desktop-only and SEPARATE from `adom-cli`.** `adom-cli` drives *web-hydrogen's*
> UI via the SSE bridge (`ADOM_HYDROGEN_URL`) and is unchanged. For HD desktop's far richer UI
> control, use the command bus above — never `adom-cli` for this.
## 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.
### 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
```
### 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
```
### Query step states
```bash
echo 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
| Element | Selector |
|---------|----------|
| VS Code iframe | `iframe.vis-studio-iframe` or `iframe[title="code"]` |
| Setup panel | `.setup-panel` |
| Run All button | `.run-all` |
| Virgin Reset button | `.virgin-reset-btn` |
| Wipe Selected button | `.virgin-go` |
| Step rows | `.step-row` |
| Step icon (✅/❌/○) | `.step-icon` |
| Step label | `.step-label` |
| Adom menu button | `.logo-button` |
| Profile menu button | `.profile-dropdown-button` |
| Tab bar | tab container at top |