name: hd-demo-recording description: > THE recipe for recording a demo video of Hydrogen Desktop: 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 HD feels like. Covers the whole pipeline end to end: driving HD's control API (in-workspace OR from a remote container via adom-desktop 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, hd demo, demo recording, record the typing, screen record hd, record ai prompt, app demo, demo pipeline, speedup demo, tts overlay demo, show what the app feels like, hd-demo-recording.

hd-demo-recording: record an HD 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 HD'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 HD control-API calls. Two contexts:

Inside the HD workspace (the WSL distro): the live base URL is in a file, never an env var:

CTRL=$(cat ~/.adom/hd-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-desktop relay's pass-through verb. Never curl through the relay (quoting gets mangled) and never hunt for the port (hd_api auto-discovers it):

adom-desktop hd_api '{"method":"POST","path":"/claude/inject","body":{...}}'

hd_* verbs auto-route to the desktop running HD; 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

POST /recording/native/start
{"source":"self","cursor":true,"codec":"h264","maxSeconds":300,"reason":"demo take cap"}
  • source:"self" is THE way to record HD (alias: "hd"). Never guess HD'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:

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 HD'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:

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

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:
adom-desktop --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 HD restart kills the take AND the demo tabs. The recorder dies with the HD 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 HD on the same machine; if a take mysteriously vanished, check whether HD 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.

hd-api (transport + safety tiers), hd-recording (recorder endpoint reference), demo-recording (choreography), video-post (speedup + publish), adom-tts (narration).