bootstrap
Adom Hydrogen (Windows / WSL2)
Public Made by Adomby adom
The Windows (WSL2) platform layer for Hydrogen.
← Commit history
Publish 0.3.14
5 files changed
+710−2
package.json+1−1@@ -4,7 +4,7 @@ "type": "bootstrap", "title": "Adom Hydrogen (Windows / WSL2)", "brief": "The Windows (WSL2) platform layer for Hydrogen.",- "version": "0.3.13",+ "version": "0.3.14", "description": "The Windows platform layer for Hydrogen, where the workspace runs in a WSL2 Ubuntu distro. Depends on adom/hydrogen-bootstrap (the platform-generic layer, which bundles the generic hydrogen-* skills) and adds everything specific to the WSL2 runtime: the WSL2/networking/lifecycle hydrogen-* skills (BUNDLED here by design, John+Kyle 2026-07-16) and the WSL2 code-server workbench seed. Sibling adom/hydrogen-mac-bootstrap carries the parallel mac skills. This is the package the golden WSL2 image installs.", "org": "adom", "tags": [
page.json+1−1@@ -4,7 +4,7 @@ "slug": "hydrogen-windows-bootstrap", "title": "Adom Hydrogen (Windows / WSL2)", "brief": "The Windows (WSL2) platform layer for Hydrogen.",- "version": "0.3.13",+ "version": "0.3.14", "author": { "name": "John Lauer", "email": "[email protected]"
skills/hydrogen-bridges/SKILL.mdadded+391@@ -0,0 +1,391 @@+---+name: hydrogen-bridges+description: >+ Complete reference for the Hydrogen bridge ecosystem: the built-in KiCad, Fusion 360,+ and Puppeteer bridges, plus the extensible wiki bridge catalog (e.g. Blender)+ and the full set of Adom Bridge capabilities. How they connect through adom-bridge-cli, the Bridge Manager+ dialog, bridge status polling, and all bridge CLI commands. Use when the AI+ needs to take screenshots, control KiCad/Fusion/browser, transfer files,+ interact with the user's desktop, or check bridge status. Trigger words --+ screenshot, desktop screenshot, list windows, capture screen, kicad, fusion,+ browser, puppeteer, pup, send file, pull file, notify, desktop, bridge,+ bridge manager, bridge status, bridge install.+---++# Hydrogen -- Bridge Ecosystem++Hydrogen is the bridge between your Docker container and the user's desktop.+All commands go through the relay at ws://localhost:8765/.++---++## Bridge Architecture++Hydrogen launches external bridge processes **on demand**. This is an **extensible**+ecosystem, not a fixed list — new bridges ship via the wiki catalog (see+"Extensible bridge catalog" below). The core/first-party bridges:++| Bridge | Display name | Port (default) | Target app | Description |+|--------|-------------|------|------------|-------------|+| `kicad-bridge` | KiCad Bridge | 8771 | KiCad | Control KiCad PCB editor from Adom containers |+| `fusion-bridge` | Fusion 360 Bridge | 8773 | Fusion 360 | Control Fusion 360 CAD/CAM and EAGLE PCB |+| `puppeteer-bridge` | Puppeteer Bridge | 8851 | Chrome for Testing | Chrome automation, screenshots, and recording |++**Bridge ports have conventional defaults** (KiCad **8771**, Fusion **8773**, Pup **8851**), but adom-bridge-cli registers the **live** port at bridge launch and may pick a different one if a default is taken. To find the actual live port, run `adom-bridge-cli status` and look at `desktop.apps.<bridge>.bridgePort` (or `adom-bridge-cli bridge_list`). In practice you don't need the port directly — use the `adom-bridge-cli <verb>` CLI which routes to the right bridge automatically.++Bridges are launched on demand by Hydrogen. They are NOT always running. The Bridge+Manager polls status every 15 seconds via Tauri `invoke('get_bridge_status')`.++### What Adom Bridge can do (live capability list)++Bridges are only part of ab. Query the **authoritative, machine-specific** list:++```bash+adom-bridge-cli status # → .capabilities and .desktop.apps+```++On a typical machine `.capabilities` =+`notify, files, kicad, fusion360, shell, usb, screenshot, browser, caption, record`.+Mapping to where each is documented:++| capability | what it is | skill |+|---|---|---|+| `kicad` / `fusion360` / `browser` | the three built-in app bridges | this skill |+| `screenshot` / `record` / `caption` | OS screenshots, screen/tab recording, recording captions | this skill (screenshots/recording); `caption` is recording-caption support |+| `files` | send_files / pull_file | **hydrogen-file-transfer**, **hydrogen-adom-desktop** |+| `notify` | desktop toast notifications | this skill |+| `shell` | run a command on the user's PC (approval-gated) | **hydrogen-adom-desktop** |+| `usb` | USB passthrough to the workspace (e.g. workcell hardware over USBIP) | not yet covered — query `adom-bridge-cli status`; future skill |++> `.desktop.apps` also reports, per app: `bridgeRunning`, `installed`, `running`,+> `version` — use it to check whether the target app (KiCad/Fusion/Chrome) is+> present before driving its bridge.++### Bridge status values++| Status | Meaning | Icon | Color |+|--------|---------|------|-------|+| `running` | Bridge process is alive and connected | `mdi:circle` (filled) | `#00b8b0` (teal) |+| `stopped` | Bridge exists but not running | `mdi:circle-outline` | `#808080` (gray) |+| `not_installed` | Bridge binary not found | `mdi:download` | `#e8a838` (amber) |++### BridgeInfo type++```typescript+interface BridgeInfo {+ name: string // e.g. "kicad-bridge"+ display_name: string // e.g. "KiCad Bridge"+ version: string // e.g. "1.0.0"+ description: string+ port: number // conventional default; live port via `adom-bridge-cli status`+ status: 'running' | 'stopped' | 'not_installed'+ app_detected: boolean // true if target app (KiCad, Fusion, Chrome) is found+ app_name: string // e.g. "KiCad"+ install_url: string // e.g. "https://www.kicad.org/download/"+ install_method: string // "free_download" or "auto_download"+}+```++---++## Bridge Manager Dialog++**Access**: Adom menu (top-left logo) -> Desktop section -> Bridge Manager+**Source**: `src/lib/components/editor/BridgeManager.svelte`++Renders as a panel (not an overlay dialog) with a vertical card list showing+each bridge's status. Auto-refreshes every 15 seconds.++### Features+- Status badges with color-coded icons+- Per-bridge install links when the target app is missing+- "Browse Bridge Catalog" button linking to the wiki (`/apps?tag=hydrogen-bridge`)+- Polls `invoke('get_bridge_status')` on mount and every 15 seconds++> **App missing? You can auto-install it.** When the target app isn't installed,+> the dialog shows an install link — but the AI doesn't have to stop there. For+> KiCad and Node.js you can trigger an **unattended install** instead of+> asking the user to download:+> `adom-bridge-cli desktop_install_kicad '{}'` / `adom-bridge-cli desktop_install_node '{}'`.+> (The install mechanism is platform-specific; the verb reports if unsupported.+> Fusion 360 cannot be installed programmatically — surface the link for that.)++### CSS selectors++| Element | Selector |+|---------|----------|+| Container | `.bridge-manager` |+| Header title | `.bridge-manager .header h2` |+| Subtitle | `.bridge-manager .subtitle` |+| Bridge card grid | `.bridge-grid` |+| Bridge card | `.bridge-card` |+| Running bridge card | `.bridge-card.running` |+| Bridge icon | `.bridge-icon` |+| Bridge name | `.bridge-name` |+| Bridge version | `.bridge-version` |+| Bridge description | `.bridge-description` |+| Bridge status | `.bridge-status` |+| App missing link | `.bridge-app-missing a` |+| Browse catalog button | `.browse-btn` |++### CDP eval examples++```javascript+// Read bridge statuses+JSON.stringify(Array.from(document.querySelectorAll('.bridge-card')).map(function(card) {+ return {+ name: card.querySelector('.bridge-name')?.textContent?.trim(),+ status: card.querySelector('.bridge-status')?.textContent?.trim(),+ running: card.classList.contains('running')+ };+}));++// Click Browse Bridge Catalog+document.querySelector('.browse-btn')?.click();+```++### Opening the Bridge Manager from the Adom menu++```javascript+// Open Adom menu, then click Bridge Manager+document.querySelector('.logo-button')?.click();+setTimeout(function() {+ var items = document.querySelectorAll('.dropdown-link');+ Array.from(items).find(function(e) { return e.textContent.includes('Bridge Manager'); })?.click();+}, 200);+```++---++## Prerequisites++Check connection: `adom-bridge-cli ping` -- returns "pong" if Hydrogen is connected.+If not connected, the user needs to launch Hydrogen on their machine.++---++## Screenshots (zero dialogs, instant)++```bash+# Full screen capture+adom-bridge-cli desktop_screenshot_screen++# Resized for Claude vision (default to this)+adom-bridge-cli desktop_screenshot_screen '{"maxWidth": 1500}'++# Specific window by HWND+adom-bridge-cli desktop_screenshot_window '{"hwnd": 12345}'++# List all capturable windows+adom-bridge-cli desktop_list_windows+```++**AI guidance:**+- Default to `maxWidth: 1500` -- Claude vision hard limit is 2000px+- Use `format: "png"` for UI/text (default, lossless)+- Use `format: "jpeg", quality: 80` for photos/3D renders+- Use `format: "webp"` for smaller file sizes++---++## Browser Automation (Puppeteer Bridge)++Port: default **8851** (adom-bridge-cli registers the live port; see `adom-bridge-cli status`). Auto-downloads Chrome for Testing if not present.++```bash+# Open browser window+adom-bridge-cli browser_open_window '{"url": "https://example.com"}'++# Screenshot current tab+adom-bridge-cli browser_screenshot '{"sessionId": "default"}'++# Evaluate JavaScript+adom-bridge-cli browser_eval '{"js": "document.title", "sessionId": "default"}'++# Navigate+adom-bridge-cli browser_navigate '{"url": "https://...", "sessionId": "default"}'++# List open windows/tabs+adom-bridge-cli browser_list_windows++# Record tab (CDP screencast, zero dialogs)+adom-bridge-cli browser_record_start '{"sessionId": "default"}'+adom-bridge-cli browser_record_stop '{"sessionId": "default"}'+```++---++## KiCad Bridge++Port: default **8771** (adom-bridge-cli registers the live port; see `adom-bridge-cli status`). Requires KiCad to be installed on the user's machine.++```bash+adom-bridge-cli kicad_open_board '{"path": "<host path to board.kicad_pcb>"}'+adom-bridge-cli kicad_open_schematic '{"path": "<host path to schematic.kicad_sch>"}'+adom-bridge-cli kicad_open_3d_viewer+adom-bridge-cli kicad_run_drc '{"path": "..."}'+adom-bridge-cli kicad_screenshot_all+adom-bridge-cli kicad_window_info+adom-bridge-cli kicad_send_key '{"key": "ctrl+s"}'+adom-bridge-cli kicad_list_versions+adom-bridge-cli kicad_install_symbol '{"path": "/tmp/symbol.kicad_sym", "library": "MyLib"}'+adom-bridge-cli kicad_install_library '{"path": "/tmp/footprints", "name": "MyFootprints"}'+```++**Always run `kicad_window_info` BEFORE any KiCad operation** to check for modal dialogs —+and AFTER any save/DRC/open to catch errors KiCad raised.++### Finding + reading KiCad errors (modal dialogs)+`kicad_window_info` returns `hasModalDialogs` (bool) + a `modalDialogs` array — **this is how+you detect a KiCad error/blocking dialog** (a save-permission error, a file-format warning, a+DRC blocker). Each entry is `{hwnd, ownerHwnd, title}` (e.g. `title:"Error"`):++```bash+adom-bridge-cli kicad_window_info '{}'+# → { editors:[...], hasModalDialogs:true,+# modalDialogs:[{ "hwnd":200934, "ownerHwnd":6163368, "title":"Error" }], projectManager:{...} }+```+- ⚠️ `modalDialogs` gives the **title + hwnd, NOT the body text**. To read *what the error says*,+ **screenshot the dialog by its hwnd**: `adom-bridge-cli desktop_screenshot_window '{"hwnd":200934}'`+ → read the saved PNG. (Verified live 2026-06-15: a `ctrl+s` on a read-only board surfaced+ `hasModalDialogs:true` + a `title:"Error"` entry; screenshotting its hwnd read *"Insufficient+ permissions to save file …"*.)+- **Dismiss** it before proceeding: `kicad_send_key '{"hwnd":<dialog hwnd>,"key":"return"}'`+ (OK) or `"escape"` (Cancel). A lingering modal blocks every subsequent KiCad action.+- So the loop is: **operate → `kicad_window_info` → if `hasModalDialogs`, screenshot each+ `modalDialogs[].hwnd` to read it → handle/dismiss.** Don't assume an operation succeeded just+ because the verb returned `success:true` — KiCad can still pop a blocking error.++---++## Fusion 360 Bridge++Port: default **8773** (adom-bridge-cli registers the live port; see `adom-bridge-cli status`). Requires Fusion 360 to be installed on the user's machine.++```bash+adom-bridge-cli fusion_start+adom-bridge-cli fusion_import_step '{"path": "<host path to model.step>"}'+adom-bridge-cli fusion_export_step '{"path": "<host path to output.step>"}'+adom-bridge-cli fusion_board_info+adom-bridge-cli fusion_electron_run '{"command": "..."}'+```++---++## Extensible bridge catalog (bridges are NOT a fixed set)++Bridges are a growing ecosystem. The three above (KiCad / Fusion 360 / Puppeteer)+are **built into Adom Bridge**. Additional bridges are published to the **wiki+bridge catalog** and installed on demand — for example the **Blender bridge**+(`adom-blender-bridge`), which is NOT built in (it won't appear in `adom-bridge-cli+status` until installed). To use a catalog bridge:++- **Discover:** Bridge Manager → "Browse Bridge Catalog" → wiki `/apps?tag=hydrogen-bridge`.+- **Reserved ports:** the `8900-8999` range is set aside for 3rd-party bridges.+- **Enumerate what's actually live:** `adom-bridge-cli status` → `desktop.apps.*` lists+ every bridge ab currently knows about, with `bridgePort`, `status`, and whether+ the target app was detected. **Treat that as the source of truth** for "what+ bridges exist right now" — this skill's table lists the core ones, but new+ catalog bridges will appear in `status` without being in this table.+- **Invoke any bridge** through the `adom-bridge-cli <verb>` CLI; it routes to the+ right bridge automatically (you rarely need the port directly).++> Maintainer note: keep this skill in sync by periodically running+> `adom-bridge-cli status` against a fully-bridged machine and reconciling the table.++---++## File Transfer++```bash+# Send file from Docker to the desktop+adom-bridge-cli send_files '{"files": [{"path": "/home/adom/project/output.pdf"}]}'++# Pull file from the desktop to Docker (remotePath uses the host's native path convention)+adom-bridge-cli pull_file '{"remotePath": "<host path to data.csv>", "localPath": "/tmp/data.csv"}'+```++---++## Desktop Interaction++```bash+# Toast notification+adom-bridge-cli notify_user '{"message": "Build complete!", "duration_ms": 5000}'++# Open URL in user's browser+adom-bridge-cli desktop_open_url '{"url": "https://..."}'++# Open folder in the OS file manager+adom-bridge-cli desktop_open_folder '{"path": "<host folder path>"}'++# Execute shell command in the host's native shell (requires user approval)+adom-bridge-cli shell_execute '{"command": "<host shell command>"}'+```++---++## Screen Recording++> **Served by the embedded ab process, NOT Hydrogen's built-in bridge.** The+> `desktop_record_*` / `desktop_recorder_*` verbs only exist when the standalone+> ab (spawned `--embedded`) is connected. Verify before using:+> `adom-bridge-cli status` → `.capabilities` must include `record`. If it's absent,+> only Hydrogen's built-in bridge is up and these verbs return "unknown desktop+> command". See **hydrogen-recording** for full details.++> **Tab-vs-desktop footgun.** `desktop_record_start` records the **whole screen**+> and requires an explicit `confirmDesktopNotTabRecording:true` guard so you don't+> accidentally capture the entire desktop when you meant one tab. To record a+> single Chrome tab, use `browser_record_start` instead (CDP screencast, served by+> the Puppeteer bridge, no whole-screen capture).++```bash+# Record entire desktop (ab-served; needs the confirm guard, zero dialogs)+adom-bridge-cli desktop_record_start '{"reason": "Demo recording", "confirmDesktopNotTabRecording": true}'+adom-bridge-cli desktop_record_stop++# Record a single browser tab (CDP screencast, zero dialogs) — prefer this for one tab+adom-bridge-cli browser_record_start '{"sessionId": "default"}'+adom-bridge-cli browser_record_stop '{"sessionId": "default"}'+```++---++## Ralph Loop Pattern++```bash+# 1. Take screenshot+adom-bridge-cli desktop_screenshot_screen '{"maxWidth": 1500}'+# 2. Read the screenshot (it's saved to /screenshots/)+# 3. Analyze with Claude vision+# 4. Make changes+# 5. Take another screenshot+# 6. Repeat until done+```++---++## Browser Profiles++Hydrogen can detect all browser profiles installed on the user's machine and open+URLs in specific browsers/profiles.++**Control API endpoints**:+- `GET /browser-profiles` -- detect Chrome, Edge, Brave, Firefox, Opera profiles+- `POST /open-in-profile` -- open URL in a specific browser and profile+- `POST /open-url` -- open URL in the default browser++**Source**: `src/lib/components/BrowserProfileDialog.svelte`++---++## Cross-references++- **hydrogen-ui** -- Adom menu layout where Bridge Manager lives+- **hydrogen-networking** -- port architecture (conventional bridge ports + dynamic registration)+- **hydrogen-adom-menu** -- the API Explorer (has bridge-related endpoints)+- **hydrogen-settings** -- Hydrogen settings surface+- **hydrogen-self-screenshot** -- host screenshots, window control, and the ralph loop+- **kicad-interaction** -- foundational KiCad desktop interaction rules+- **pup** -- Puppeteer browser control via pup CLI
skills/hydrogen-demo-recording/SKILL.mdadded+176@@ -0,0 +1,176 @@+---+name: hydrogen-demo-recording+description: >+ THE recipe for recording a demo video of Hydrogen: screen-record an AI prompt+ being TYPED (visible human-jitter typing) into a Claude tab plus the AI's resulting+ output, then speed the footage 10x to 30x in video-post and lay an adom-tts voiceover+ on top, so a viewer sees exactly what using an app in Hydrogen feels like. Covers the whole+ pipeline end to end: driving Hydrogen's control API (in-workspace OR from a remote container+ via adom-bridge-cli hd_api), the high-fps native recorder, multi-tab multi-prompt demos,+ getting the mp4 out (streamed binary, never base64), and the post-production handoff.+ Trigger words: demo video, record a demo, ah demo, demo recording, record the typing,+ screen record ah, record ai prompt, app demo, demo pipeline, speedup demo, tts overlay+ demo, show what the app feels like, hydrogen-demo-recording.+---++# hydrogen-demo-recording: record an Hydrogen demo video, end to end++The canonical Adom demo: the viewer watches an AI prompt get TYPED into Hydrogen+Desktop, watches the AI do the work, and hears a narrator explain it, all in a tight+sped-up clip. This skill is the full pipeline. It exists because every piece is easy+to get slightly wrong and the pieces live in four different tools.++The shape of every demo:++1. Start Hydrogen's native high-fps recorder (no picker, no sharing banner).+2. Type the prompt into a Claude tab with VISIBLE typing (the sexy part) and submit.+3. Let the AI's output stream on camera.+4. Stop the recorder, collect the mp4.+5. Post-production: speed up 10x to 30x (video-post), overlay adom-tts narration.++## Step 0: pick your calling transport++Everything below is Hydrogen control-API calls. Two contexts:++**Inside the Hydrogen workspace** (the WSL distro): the live base URL is in a file, never an+env var:++```bash+CTRL=$(cat ~/.adom/hydrogen-control-url)+curl -s -X POST "$CTRL/claude/inject" -H 'Content-Type: application/json' -d '{...}'+```++**From a remote container** (hw, cloud): go through the adom-bridge-cli relay's+pass-through verb. Never curl through the relay (quoting gets mangled) and never hunt+for the port (hd_api auto-discovers it):++```bash+adom-bridge-cli hd_api '{"method":"POST","path":"/claude/inject","body":{...}}'+```++`hd_*` verbs auto-route to the desktop running Hydrogen; `desktop_*` and `pull_file` need+`--target <desktop name>` when more than one desktop is on the relay.++## Step 1: preflight (30 seconds, saves the take)++- `GET /health` answers with service `hydrogen-desktop-control` (not the SPA).+- `GET /capture/availability`: nothing else is recording; it also tells you which+ screenshot method coexists with a recording (CDP `POST /screenshot`, not the SSE path).+- `GET /recording/native/sources`: confirm the exact window name to capture.+- `GET /claude/auth-check`: Claude is signed in (a demo of a sign-in wall is not a demo).++## Step 2: start the recorder++```json+POST /recording/native/start+{"source":"self","cursor":true,"codec":"h264","maxSeconds":300,"reason":"demo take cap"}+```++- **`source:"self"` is THE way to record Hydrogen** (alias: `"hd"`). Never guess Hydrogen's window+ title: it carries the version and dev stamps, and title-guessing has recorded the+ WRONG app before (an Edge window titled "Claude"). `window:<substr>` matches other+ apps' windows; `"screen"` records the whole primary monitor.+- WGC per-window capture: high fps, background-safe, no picker, no "you are sharing+ your screen" banner.+- Overriding `maxSeconds` (default 600) REQUIRES a `reason` string, it shows in the+ UI toast if the cap fires. Omit both if the default cap is fine.+- `codec:"h264"` for web-playable output (h265 is smaller but not web-playable).+- `mic:true` only if you want live narration in the raw take; the usual pipeline adds+ TTS narration in post instead.+- Wait about 1 second after start so the first frames show the clean starting state.+- **Verify the take is ALIVE**: `GET /recording/native/status` while recording shows+ `frames` climbing within about 2 seconds. If it stays 0, the take is dead (target+ minimized or wrong window): stop now and fix, do not record 90 seconds of nothing.+ A 0-frame take errors at stop (500) instead of pretending success.++## Step 3: type the prompt(s) on camera++One call per prompt opens a NEW Claude tab, waits for its compose box, types with+human jitter, and submits:++```json+POST /claude/new-chat-and-send+{"text":"<the demo prompt>","typed":true,"submit":true,"delay_ms":35}+```++- `typed:true` is the visible typing (about `delay_ms` per char with 50 percent+ jitter). `typed:false` pastes instantly: fine for seeding, boring on camera.+- The call BLOCKS until typing completes: perfect for sequencing. If a relay call+ times out on a long prompt, the typing still finishes on Hydrogen's side. Do NOT re-fire.+ Confirm with `GET /claude/conversation-state` (turns went up), then continue.+ Keep prompts short enough to type in under about 20 seconds.+- Single-prompt demo into the CURRENT tab instead: `POST /claude/inject` with the+ same body shape.++**Multi-prompt demos** (the 5-tabs pattern): repeat the call once per prompt (each+opens its own tab), then flip through the finished answers on camera with the+BACKGROUND tab switch:++```json+POST /claude/tabs/activate {"index":0} // 0-based; or {"label":"substring"}+```++Verify each switch took with `GET /claude/tabs` (`active:true` moved). Pause a few+seconds per tab so the sped-up video gives each answer screen time.+`GET /claude/conversations` gives per-tab context_ids if you want to seed specific+tabs deterministically (`/claude/inject` with `context_index`).++## Step 4: stop and collect the mp4++```json+POST /recording/native/stop+```++The response carries `file` (relative), `fileAbsolute` (path INSIDE the WSL distro),+`fileWindows` (the `\\wsl$\...` UNC path), and `frames`. If your transport hiccups+and you lose the stop response, `GET /recording/native/status` when idle returns+`lastOutput` with the same paths, the take is recoverable.++- **In the workspace**: `fileAbsolute` is directly readable; you are done.+- **Remote container**: pull it as STREAMED BINARY, 1 MiB chunks, sha256-verified.+ Never base64 an mp4 through an exec channel:++```bash+adom-bridge-cli --target <desktop> pull_file '{"filePaths":["<fileWindows value>"],"saveTo":"<dir>"}'+```++## Step 5: post-production++- **Speedup**: the `video-post` skill owns this. The house style is 10x for demos+ where the output matters, 30x for long AI work sessions. Keep the typing segment+ readable (video-post can ramp: normal speed on the typing, fast on the waiting).+- **Narration**: synthesize with `adom-tts say` (it pronounces Adom terms correctly+ and caches repeats), then video-post mixes it as the audio track. Write narration+ that explains what the viewer is SEEING at each sped-up moment.+- **Recording choreography** (captions, panel staging, what makes a take clean) lives+ in the `demo-recording` skill; read it for anything fancier than a single-window take.++## Known hazards++- **An Hydrogen restart kills the take AND the demo tabs.** The recorder dies with the Hydrogen+ process (the unfinalized temp mp4 is lost) and reopened Claude tabs reset. Do not+ run a demo while anyone (including another AI thread) is rebuilding/relaunching Hydrogen+ on the same machine; if a take mysteriously vanished, check whether Hydrogen restarted+ mid-run (window title timestamp or /buildinfo).+- Tab state reads (`GET /claude/tabs`) are DOM reads: labels can be briefly empty+ while the editor reloads. Prefer `GET /claude/conversations` for stable+ context_ids + titles.+- Screenshot of the Claude panel: `POST /screenshot {target:"claude"}` captures the+ editor surface containing it (the panel is a nested webview with no own CDP target).++## Safety and cleanup (non-negotiable)++- These endpoints are disruptive tier and their responses carry a `_safety` block:+ you are typing into the user's REAL Claude panel (each submitted prompt SPENDS a+ real turn; a 5-prompt demo spends 5) and recording their REAL screen. That is the+ point of a demo, but only do it for a demo the user asked for.+- ALWAYS stop a recording you started, even when a step fails: stop first, then+ report. `GET /recording/native/status` tells you if one is live.+- NEVER call `/claude/tabs/close-all` to clean up: it closes the user's own tabs+ too. There is no per-tab close; leave demo tabs open and tell the user they exist.+- Delete junk takes you pulled; do not litter recordings/ with failed attempts.++## Related++[[hydrogen-api]] (transport + safety tiers), [[hydrogen-recording]] (recorder endpoint reference),+demo-recording (choreography), video-post (speedup + publish), adom-tts (narration).
skills/hydrogen-embedded-bridge/SKILL.mdadded+141@@ -0,0 +1,141 @@+---+name: hydrogen-embedded-bridge+description: How Hydrogen (ah) and Adom Bridge (ab) interact via "embedded mode". Use whenever the user asks about the system tray icon, why ab isn't visible, why two desktop apps are installed, the "Embedded · Hydrogen" footer pill, or how to make ab show up standalone. Trigger words — embedded mode, system tray, ab tray, why is adom desktop hidden, where's my tray icon, Hydrogen vs ab, both apps installed, why two installs, ab missing from tray, switch ab to standalone, ab won't show, run ab without Hydrogen, decouple ab from Hydrogen.+---++# Hydrogen ↔ ab Embedded Mode++There are two desktop apps in the Adom ecosystem: **Hydrogen (ah)** — the user-facing workspace app — and **Adom Bridge (ab)** — the bridge that talks to local apps (KiCad / Fusion 360 / Chrome / files). Hydrogen's installer silently installs ab (it fetches the latest ab from wiki.adom.inc at install time rather than carrying a copy) and runs it in **embedded mode**, where ab is invisible and Hydrogen's tray menu mirrors ab's controls.++This skill explains how the two interact so you can answer "why isn't ab in my tray?", "should I have two installs?", "why did the tray icon disappear?" and similar.++## Two modes++### Standalone ab (no Hydrogen anywhere)++How ab launches when nobody owns it:+- Tray icon visible in Windows notification area+- Main window opens on launch (unless `--start-hidden`)+- Autostart shortcut in `%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\AdomDesktop.lnk` → launches on every boot+- Registered in Add/Remove Programs (HKLM `Uninstall\AdomDesktop`)+- Auto-update polls `wiki.adom.inc/api/v1/pages/adom-bridge-cli/files/version.json` every 4h+- Footer shows the user's email + a "Sign in" / "Sign out" link++This is what ab looked like before Hydrogen existed and what it reverts to when Hydrogen vanishes.++### Embedded ab (Hydrogen owns it)++Hydrogen's installer puts ab into embedded mode by:+1. Writing `%LOCALAPPDATA%\Adom Bridge\embedded.json` marker (`{"owner":"hydrogen-desktop", ...}`)+2. Deleting ab's Desktop / Start Menu / Startup `.lnk` shortcuts so the user can't double-launch standalone ab+3. Configuring Hydrogen's own systray to mirror ab's menu (Open ab, Connect All, Disconnect All, Settings, etc.)++When Hydrogen spawns ab with `--embedded --start-hidden --relay-url ws://127.0.0.1:8765 --relay-name hydrogen-desktop`, ab detects embedded mode and:+- **Hides** its system tray (Hydrogen owns the one tray)+- **Suppresses** its autostart shortcut creation+- **Disables** its auto-updater (Hydrogen owns ab's update channel — Hydrogen installs the latest published ab at install time)+- **Hides** its main window on boot (Hydrogen's tray "Open Adom Bridge" menu item opens it on demand)+- **Skips** HKLM Uninstall registration (Hydrogen's installer offers cascade-uninstall of ab)+- Footer shows a read-only email + an "Embedded · Hydrogen" pill++Result: the user only ever sees one app (ah) in the tray + Start Menu, even though two processes (Hydrogen + ab) are running.++## How ab detects "am I embedded?" — 3-signal cascade++ab calls `embedded::detect_embedded_mode()` at boot. First match wins:++1. **CLI flag**: `--embedded` (or `--embedded-mode`) on the command line. Writes the marker file, owner defaults to `hydrogen-desktop`. **This is what Hydrogen spawns ab with.**+2. **Env var**: `ADOM_EMBEDDED=1` (or `true`). Same behavior as the flag.+3. **Marker file**: `%LOCALAPPDATA%\Adom Bridge\embedded.json` exists. ab then probes Hydrogen's **liveness beacon** on `127.0.0.1:9001` (a real port ab listens for — NOT Hydrogen's control API; Hydrogen's actual control API is **47084**):+ - If Hydrogen answers the beacon → embedded mode+ - If Hydrogen doesn't answer → ab treats the marker as stale, deletes it, falls back to standalone++If none of the three signals fire → standalone.++## Lifecycle ownership in embedded mode++Hydrogen's runtime supervisor:+- Reads Hydrogen's session token from `%APPDATA%\hydrogen-desktop\hydrogen-session.txt`+- Spawns ab detached with the embedded flags above+- Polls ab's direct API `/health` every 5s (stable port 24680 since ab 2.0.27; discovery-file first)+- If ab's health probe fails → Hydrogen respawns ab with the same args++Hydrogen's tray menu (mirrors ab's controls so the user gets all the ab verbs without seeing ab's tray):+```+Open Hydrogen+Reload Workspace+── Adom Bridge ──+Open Adom Bridge → POST 127.0.0.1:24680 desktop/window_show+Connect All → POST desktop/connect_all+Disconnect All → POST desktop/disconnect_all+Settings (Adom Bridge)→ POST desktop/window_show+─────+Quit → POST desktop/shutdown, 200ms grace, then app.exit(0)+```++Hydrogen's uninstaller PREUNINSTALL hook prompts "Also remove Adom Bridge?" → cascade-uninstalls ab on Yes.++## Runtime transitions++**ab ≥ v1.8.47** re-checks Hydrogen's liveness every 60s during runtime, not just at boot. This is the normal daily cycle for most users, not an edge case:++- Morning: user launches Hydrogen → Hydrogen spawns ab with `--embedded` → ab's tray hides, pill appears+- Evening: user quits Hydrogen → ab's next poll fails the Hydrogen probe → ab reverts to standalone → tray reappears+- Next morning: user launches Hydrogen again → ab's next poll succeeds → ab re-embeds → tray hides++The same ab process can flip mode back and forth indefinitely across an Hydrogen-quit / Hydrogen-relaunch cycle. Transitions:++| Current mode | Hydrogen probe says | What ab does |+|---|---|---|+| Standalone | dead | stay standalone (no-op) |+| Standalone | alive | → **embed**: hide tray, write marker, hide main window, show "Embedded · Hydrogen" pill |+| Embedded | dead | → **unembed**: show tray, delete marker, hide pill (main window left as-is) |+| Embedded | alive | stay embedded (refresh marker heartbeat in `last_seen`) |++Both transitions emit a `mode-changed` event so the frontend can update the footer pill in real time.++**ab ≤ v1.8.46** only checks at boot. If Hydrogen dies while ab is running, ab stays invisible in embedded mode until restart.++## Common questions++### "I don't see ab in my system tray on a Windows box with Hydrogen installed"++Expected. Hydrogen's installer deleted ab's autostart shortcut, so ab doesn't launch on boot. ab only runs when Hydrogen spawns it. Hydrogen's tray includes ab's menu items.++To verify: `tasklist | findstr adom-bridge-cli`. If ab's running, it's just hidden (per embedded mode). If not running, Hydrogen isn't either.++### "I want ab standalone — how do I unembed?"++- Quit Hydrogen+- Delete `%LOCALAPPDATA%\Adom Bridge\embedded.json`+- Launch ab via `%LOCALAPPDATA%\Adom Bridge\adom-bridge.exe`+- ab will detect no marker + no CLI flag → standalone mode → tray reappears++Or uninstall Hydrogen with "Yes, also remove Adom Bridge" → No → Hydrogen is gone, ab's marker is cleared, ab reverts to standalone on next launch. (Note: ab's autostart shortcut was deleted by Hydrogen's installer, so ab still won't auto-launch on boot until you re-run ab's installer to recreate it.)++### "Both Hydrogen and ab are installed — is that normal?"++Yes. Hydrogen's NSIS POSTINSTALL hook resolves the latest ab from wiki.adom.inc, verifies its published sha256, and silently runs that installer with `/S /NOLAUNCH`. If that can't happen (offline at install time), Hydrogen retries it on first launch. ab lives at `%LOCALAPPDATA%\Adom Bridge\`, Hydrogen at `%LOCALAPPDATA%\Hydrogen\`. Two separate exes, two separate Add/Remove Programs entries (well, only Hydrogen's is in Add/Remove if Hydrogen's installer ran the embedded-mode ab which skips HKLM register — ab ≥ v1.8.46).++### "ab's tray suddenly appeared even though Hydrogen is installed"++Hydrogen probably crashed or was closed. ab ≥ v1.8.47's runtime poll noticed Hydrogen is dead and reverted to standalone tray. The fix: relaunch Hydrogen from the Start Menu → ab's next poll detects Hydrogen → tray hides again.++### "Direct API for ab verbs"++ab listens on `127.0.0.1:24680` (stable since ab 2.0.27; legacy installs may still use 47200) for `POST /command` with `{"app":"desktop","command":"<verb>","args":{...}}`. The 7 user-visible verbs Hydrogen's tray uses:+- `window_show`, `window_hide`+- `connect_all`, `disconnect_all`+- `shutdown`+- `embedded_status` (returns `{embedded, owner, source, ...}`)+- `logout`++Port discovery order: `%USERPROFILE%\.adom\direct-api-port` (single line `host:port`, authoritative), then stable 24680, walk 24680-24689, legacy 47200-47209 last. Validate `service == "adom-bridge"` in /health before trusting a port.++## Source-of-truth references++- ab's mode detection: `adom-bridge-cli/src-tauri/src/embedded.rs:detect_embedded_mode()`+- Hydrogen's ab spawn: `hydrogen-desktop/src-tauri/crates/hydrogen-app/src/ad_supervisor.rs:spawn_ad_embedded()`+- Hydrogen's tray menu: `hydrogen-desktop/src-tauri/crates/hydrogen-app/src/tray.rs:install_tray()`+- Hydrogen's NSIS hook (embed-ab on install / offer-uninstall): `hydrogen-desktop/src-tauri/crates/hydrogen-app/installer/hydrogen-install.nsh.template`+- ab's release manifest (what Hydrogen reads at install time to find the latest ab): `wiki.adom.inc/api/v1/pages/adom-bridge-cli/files/version.json`