Hydrogen Desktop Bootstrap (apps + skills)
Public Made by Adomby adom
Layer Hydrogen Desktop's workspace onto a standard Adom workstation.
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.
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 →").
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, seehd-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.
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:
| 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 |
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.
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).
(1) 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.
adom-cli hydrogen caption show "Step 1: open the board" -p center -s large # 30s auto-expire
adom-cli hydrogen caption show "Step 2: run DRC" -d 60 -p center -s large # hold 60 SECONDS
adom-cli hydrogen caption hide # clear now
⚠️⚠️ -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
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 +
hideare identical on both (verified by firingadom-cli hydrogen captionin a cloud web-Hydrogen workspace — center/large rendered,-d 20held 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-dself-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)
- No
-d(or-d 0) → auto-expires after 30s. The right default — you do NOT need tohideit. - 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 4000now self-heals. - Newest wins: showing another caption replaces the current one;
hideclears immediately. - No "forever" via adom-cli — its
-dis an unsigned int (rejects negatives) by design. This is a feature, not a gap: adom-cli is the same binary on web-Hydrogen and HD, so "no persist via adom-cli" keeps both consistent and bounded (no abandoned captions). A persist-until-hidden escape exists ONLY on the raw HTTP endpoint ({"duration":-1}, below) — rarely needed. - No
caption statusverb (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-onlycaption statusis a possible future verb, not a current one.) -pposition:top/center/bottom(NO corners — use the desktop overlay for those).-ssize:small/medium/large.- Needs a live workspace/editor session (the server returns 409 if none).
Direct HTTP fallback — only for scripts already hitting HD's API
adom-cli is the consistent default; use HTTP only when a script talks to HD's API
directly. It's the same caption, same lifecycle — adom-cli just wraps this path with
the workspace owner/repo. The caption lives on the workspace-events server
(ADOM_HYDROGEN_URL, the proxy) — NOT the control port:
# show — duration in SECONDS, identical body/lifecycle to adom-cli
curl -s -X POST "$ADOM_HYDROGEN_URL/api/workspaces/editor/<owner>/<repo>/current/caption" \
-H 'Content-Type: application/json' \
-d '{"text":"Step 1: open the board","duration":60,"position":"center","size":"large"}'
# hide
curl -s -X POST "$ADOM_HYDROGEN_URL/api/workspaces/editor/<owner>/<repo>/current/caption" \
-d '{"hide":true}'
# 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.
adom-desktop desktop_caption '{"text":"Step 3: approve the UAC dialog →","position":"center","size":"large","duration":6000}'
Arguments
| 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:
# 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"}'
Patterns
- Walkthrough / demo callouts — drop a
centercaption per step (sameidso 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-
durationsmall caption in a corner (top-right), separateid, while you drive the rest of the screen. - Point at a thing — use normalized
x/yto 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.
Related skills
- hd-recording — captions are captured into screen recordings; record a walkthrough with live callouts
- hd-adom-desktop — AD carries the
caption/desktop_captionverb to the host; verify thecaptioncapability viaadom-desktop status adom-tts— audio narration to pair with on-screen captions (captions are visual-only)
---
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.
---
# 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 →").
> 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.
## 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:
| 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 |
**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.
> 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).
## (1) 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`.
```bash
adom-cli hydrogen caption show "Step 1: open the board" -p center -s large # 30s auto-expire
adom-cli hydrogen caption show "Step 2: run DRC" -d 60 -p center -s large # hold 60 SECONDS
adom-cli hydrogen caption hide # clear now
```
### ⚠️⚠️ `-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
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)
- **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.
- **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
HD, so "no persist via adom-cli" keeps both consistent and bounded (no abandoned
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.)
- `-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).
### Direct HTTP fallback — only for scripts already hitting HD's API
adom-cli is the consistent default; use HTTP **only** when a script talks to HD's API
directly. It's the **same caption, same lifecycle** — adom-cli just wraps this path with
the workspace owner/repo. The caption lives on the **workspace-events server**
(`ADOM_HYDROGEN_URL`, the proxy) — **NOT the control port**:
```bash
# show — duration in SECONDS, identical body/lifecycle to adom-cli
curl -s -X POST "$ADOM_HYDROGEN_URL/api/workspaces/editor/<owner>/<repo>/current/caption" \
-H 'Content-Type: application/json' \
-d '{"text":"Step 1: open the board","duration":60,"position":"center","size":"large"}'
# hide
curl -s -X POST "$ADOM_HYDROGEN_URL/api/workspaces/editor/<owner>/<repo>/current/caption" \
-d '{"hide":true}'
# 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}'
```
### Arguments
| 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"}'
```
## 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.
## 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`
- `adom-tts` — *audio* narration to pair with on-screen captions (captions are visual-only)