app
Adom Bridge
Public Made by Adomby adom
Adom Bridge unleashes your AI onto your full PC: full power, full safety. The AI breaks out of the container it runs in and onto your real machine, managing and running your entire laptop as you: launch apps, move files, drive any window, control KiCad, Fusion 360 or your real signed-in browser. Works with any AI, cloud or local (Claude Desktop, Claude Code, Codex), no Hydrogen required. Bridge and its bridges are an operating system for AI, with managed Node and Python runtimes, and a human-onl
← Commit history
verbs-hd.md+38−38@@ -4,11 +4,11 @@ Build, ship, screenshot, and drive the embedded Adom Hydrogen. _Part of the [Adom Desktop verb reference](VERB-REFERENCE.md). Invoke as `adom-desktop <verb> '<json>'`._ -> **Note:** v1.8.15+: hd_* verbs proxy to Adom Hydrogen's local API on 127.0.0.1:9001. HD is a sibling Tauri v2 app that runs alongside adom-desktop on the user's machine. These are built-in proxy handlers (NOT a separate bridge process) — when HD isn't running, hd_status returns {ok:false, error:'HD not running'} cleanly instead of crashing.+> **Note:** v1.8.15+: hd_* verbs proxy to Adom Hydrogen's local API on 127.0.0.1:9001. Hydrogen is a sibling Tauri v2 app that runs alongside adom-desktop on the user's machine. These are built-in proxy handlers (NOT a separate bridge process) — when Hydrogen isn't running, hd_status returns {ok:false, error:'Hydrogen not running'} cleanly instead of crashing. ### `hd_api` -Generic HTTP pass-through to HD's control API. The canonical way to call ANY HD endpoint from a script/AI without shelling out to curl (which the relay mangles). Auto-discovers HD's control port from %APPDATA%/adom-hydrogen/ports.json (key 'control'); falls back to 47084. Public-build denylist refuses destructive paths (e.g. /wsl/unregister, /setup/virgin-reset) — use the hd-dev internal build for those.+Generic HTTP pass-through to Hydrogen's control API. The canonical way to call ANY Hydrogen endpoint from a script/AI without shelling out to curl (which the relay mangles). Auto-discovers Hydrogen's control port from %APPDATA%/adom-hydrogen/ports.json (key 'control'); falls back to 47084. Public-build denylist refuses destructive paths (e.g. /wsl/unregister, /setup/virgin-reset) — use the hd-dev internal build for those. **Args:** - `body` — optional object — JSON body for POST/PUT/PATCH. Passed through verbatim (no escaping).@@ -16,21 +16,21 @@ Generic HTTP pass-through to HD's control API. The canonical way to call ANY HD - `path` — required string starting with '/' — e.g. '/setup/run-step', '/wsl/status', '/claude/start-auth' - `port` — optional int — override discovered port; for testing -**Returns:** {success:bool, ok:bool, status:int, body:any, method:str, path:str, port:int} — `body` is the parsed JSON HD returned (or a string if non-JSON)+**Returns:** {success:bool, ok:bool, status:int, body:any, method:str, path:str, port:int} — `body` is the parsed JSON Hydrogen returned (or a string if non-JSON) **Example:** `adom-desktop hd_api '{"method":"POST","path":"/setup/run-step","body":{"id":"welcome"}}'` ### `hd_browser_profiles` -Enumerate browsers + profiles HD detects on the user's machine (GET /browser-profiles). Use the returned profileDir values when calling hd_open_url.+Enumerate browsers + profiles Hydrogen detects on the user's machine (GET /browser-profiles). Use the returned profileDir values when calling hd_open_url. -**Returns:** HD's /browser-profiles response — typically {browsers:[{name, profiles:[{dir, name, gaia?}, ...]}]}+**Returns:** Hydrogen's /browser-profiles response — typically {browsers:[{name, profiles:[{dir, name, gaia?}, ...]}]} ### `hd_build` -Full HD rebuild (async): git pull → pnpm build → cargo build (debug). Returns immediately with {pid, logPath}; the build runs detached so the relay's 30s HTTP timeout doesn't kill it. Each step appends to %TEMP%\hd-build.log (overwritten at start); the script writes BUILD_OK or BUILD_FAILED:<reason> as its final line so callers can detect completion without scraping tool-specific output. v1.8.16+.+Full Hydrogen rebuild (async): git pull → pnpm build → cargo build (debug). Returns immediately with {pid, logPath}; the build runs detached so the relay's 30s HTTP timeout doesn't kill it. Each step appends to %TEMP%\hd-build.log (overwritten at start); the script writes BUILD_OK or BUILD_FAILED:<reason> as its final line so callers can detect completion without scraping tool-specific output. v1.8.16+. **Args:** - `lingerSecs` — optional int (default 30 when show=true, 0 when show=false) — v1.8.23+. After the build's final BUILD_OK/BUILD_FAILED line, the visible window stays open for this many seconds before auto-closing. 30s default lets the user read the error; pass 0 to close immediately; pass a larger number for more reading time. Capped at 3600s. Ignored entirely when show=false (no window to linger).@@ -43,7 +43,7 @@ Full HD rebuild (async): git pull → pnpm build → cargo build (debug). Return ### `hd_build_frontend` -Frontend-only HD build (async): `pnpm build` from the repo root. Same log/PID/sentinel conventions as hd_build. Use when only Svelte/TypeScript changed and the Rust binary is unchanged — much faster than a full build.+Frontend-only Hydrogen build (async): `pnpm build` from the repo root. Same log/PID/sentinel conventions as hd_build. Use when only Svelte/TypeScript changed and the Rust binary is unchanged — much faster than a full build. **Args:** - `lingerSecs` — optional int (default 30 when show=true) — see hd_build for details. v1.8.23+.@@ -63,7 +63,7 @@ Return the FULL build log from %TEMP%\hd-build.log. Use this after hd_build_stat ### `hd_build_rust` -Rust-only HD build (async): `cargo build` from src-tauri/. Same log/PID/sentinel conventions as hd_build. Use when only Rust code changed (no frontend changes). v1.8.52+: dispatch response also carries builtSha + exeMtimeBefore + exeSizeBefore (captured at spawn time into %TEMP%\hd-build-meta.json) so the subsequent hd_build_status / hd_launch don't need a separate git rev-parse + stat call.+Rust-only Hydrogen build (async): `cargo build` from src-tauri/. Same log/PID/sentinel conventions as hd_build. Use when only Rust code changed (no frontend changes). v1.8.52+: dispatch response also carries builtSha + exeMtimeBefore + exeSizeBefore (captured at spawn time into %TEMP%\hd-build-meta.json) so the subsequent hd_build_status / hd_launch don't need a separate git rev-parse + stat call. **Args:** - `lingerSecs` — optional int (default 30 when show=true) — see hd_build for details. v1.8.23+.@@ -76,11 +76,11 @@ Rust-only HD build (async): `cargo build` from src-tauri/. Same log/PID/sentinel ### `hd_build_status` -Synchronous build-state probe. v1.8.52+ enriched: returns compiledCrates (parsed from 'Compiling X' lines so you KNOW your crate recompiled vs cargo found nothing to do — eliminates the most common stale-relink trap), relinkOnly (true when succeeded but compiledCrates is empty), exeMtimeBefore/After + exeSizeBefore/After + exeChanged (proves the binary actually got rewritten), exeLocked + holderPids (when cargo failed because adom-hydrogen.exe is held by another process — most often a still-running HD instance), builtSha (the SHA hd_build_rust / hd_build was dispatched at — compare to /buildinfo.build_sha after launch), elapsedSecs (from dispatch to now). State machine: no log → idle; log present without sentinel + PID alive → building; log ends with BUILD_OK → succeeded; log ends with BUILD_FAILED → failed; log present without sentinel + PID dead → treated as failed (orphaned). v1.8.16+.+Synchronous build-state probe. v1.8.52+ enriched: returns compiledCrates (parsed from 'Compiling X' lines so you KNOW your crate recompiled vs cargo found nothing to do — eliminates the most common stale-relink trap), relinkOnly (true when succeeded but compiledCrates is empty), exeMtimeBefore/After + exeSizeBefore/After + exeChanged (proves the binary actually got rewritten), exeLocked + holderPids (when cargo failed because adom-hydrogen.exe is held by another process — most often a still-running Hydrogen instance), builtSha (the SHA hd_build_rust / hd_build was dispatched at — compare to /buildinfo.build_sha after launch), elapsedSecs (from dispatch to now). State machine: no log → idle; log present without sentinel + PID alive → building; log ends with BUILD_OK → succeeded; log ends with BUILD_FAILED → failed; log present without sentinel + PID dead → treated as failed (orphaned). v1.8.16+. **Returns:** {ok:bool, building:bool, succeeded:bool, failed:bool, lastLines:[string] (last ~40 lines of stderr), logPath:string, pid:int (cargo PID or 0), pidAlive:bool, failureReason:string (when failed:true — e.g. 'compile_error', 'exe_locked', 'orphaned_no_sentinel'), compiledCrates:[string] (names parsed from 'Compiling X v...' lines — EMPTY means relink-only, your code didn't actually rebuild), relinkOnly:bool (true iff succeeded:true && compiledCrates empty), exeChanged:bool (mtime OR size after differs from before — definitive proof a fresh binary was written), exeMtimeBefore:int (unix seconds), exeMtimeAfter:int (unix seconds), exeSizeBefore:int (bytes), exeSizeAfter:int (bytes), exeLocked:bool (true when build failed because adom-hydrogen.exe was held by another PID), holderPids:[int] (the PIDs holding the exe — taskkill these), builtSha:string|null (the git SHA hd_build was dispatched at — compare to /buildinfo.build_sha after launch), elapsedSecs:int, flavor:string ('rust'|'frontend'|'full'), _hint:string} -**Note:** **relinkOnly:true on success is the #1 trap to look for** — your push didn't actually change the binary because cargo found nothing to recompile. Usually means your source changes weren't pulled, or you changed a file the workspace doesn't track. Use hd_ship with clean:true to force a fresh build. **exeLocked:true on failure** plus holderPids tells you exactly which PID to taskkill; or just use hd_ship which kills HD before building.+**Note:** **relinkOnly:true on success is the #1 trap to look for** — your push didn't actually change the binary because cargo found nothing to recompile. Usually means your source changes weren't pulled, or you changed a file the workspace doesn't track. Use hd_ship with clean:true to force a fresh build. **exeLocked:true on failure** plus holderPids tells you exactly which PID to taskkill; or just use hd_ship which kills Hydrogen before building. ### `hd_build_tail`@@ -97,50 +97,50 @@ Streaming tail of the build log. Pass offset=0 on first call; the response inclu ### `hd_container_exec` -[MOVED to hd-dev in v1.8.72] Run a command inside HD's Docker container. Public Adom Desktop refuses with verb_moved_to_hd_dev. Workaround: hd_api '{"method":"POST","path":"/container-exec","body":{"command":"..."}}'.+[MOVED to hd-dev in v1.8.72] Run a command inside Hydrogen's Docker container. Public Adom Desktop refuses with verb_moved_to_hd_dev. Workaround: hd_api '{"method":"POST","path":"/container-exec","body":{"command":"..."}}'. **Args:** - `command` — required string -**Returns:** Public build: refusal payload. hd-dev internal build: HD's /container-exec response.+**Returns:** Public build: refusal payload. hd-dev internal build: Hydrogen's /container-exec response. ### `hd_eval` -[MOVED to hd-dev in v1.8.72] Evaluate JS in HD's main webview. Public Adom Desktop returns {error:'verb_moved_to_hd_dev'} with a _hint pointing at the internal build. Workaround: hd_api '{"method":"POST","path":"/eval","body":{"js":"..."}}'.+[MOVED to hd-dev in v1.8.72] Evaluate JS in Hydrogen's main webview. Public Adom Desktop returns {error:'verb_moved_to_hd_dev'} with a _hint pointing at the internal build. Workaround: hd_api '{"method":"POST","path":"/eval","body":{"js":"..."}}'. **Args:** - `js` — required string — JS expression or statement -**Returns:** Public build: refusal payload. hd-dev internal build: HD's /eval response.+**Returns:** Public build: refusal payload. hd-dev internal build: Hydrogen's /eval response. ### `hd_iframe_eval` -[MOVED to hd-dev in v1.8.72] Evaluate JS inside HD's code-server iframe via CDP. Public Adom Desktop refuses with verb_moved_to_hd_dev. Workaround: hd_api '{"method":"POST","path":"/iframe-eval","body":{"js":"..."}}'.+[MOVED to hd-dev in v1.8.72] Evaluate JS inside Hydrogen's code-server iframe via CDP. Public Adom Desktop refuses with verb_moved_to_hd_dev. Workaround: hd_api '{"method":"POST","path":"/iframe-eval","body":{"js":"..."}}'. **Args:** - `contextIndex` — optional int - `js` — required string -**Returns:** Public build: refusal payload. hd-dev internal build: HD's /iframe-eval response.+**Returns:** Public build: refusal payload. hd-dev internal build: Hydrogen's /iframe-eval response. ### `hd_launch` -Start HD's debug binary detached. v1.8.52+ returns structured launch state so you NEVER mistake 'attached to a stale running process' for 'launched fresh code'. Three guards refuse the launch: (1) build_in_progress — a hd_build/hd_build_frontend/hd_build_rust is still running; (2) build_failed — last build ended with BUILD_FAILED; (3) already_running — adom-hydrogen.exe is in the process list. The already_running guard can be overridden with `killExisting:true` (taskkills the existing instance then spawns fresh; killedFirst=true in the response). On success, sleeps briefly then reports HD's actual PID (looked up via tasklist) since the cmd-wrapper PID is gone immediately. v1.8.16+.+Start Hydrogen's debug binary detached. v1.8.52+ returns structured launch state so you NEVER mistake 'attached to a stale running process' for 'launched fresh code'. Three guards refuse the launch: (1) build_in_progress — a hd_build/hd_build_frontend/hd_build_rust is still running; (2) build_failed — last build ended with BUILD_FAILED; (3) already_running — adom-hydrogen.exe is in the process list. The already_running guard can be overridden with `killExisting:true` (taskkills the existing instance then spawns fresh; killedFirst=true in the response). On success, sleeps briefly then reports Hydrogen's actual PID (looked up via tasklist) since the cmd-wrapper PID is gone immediately. v1.8.16+. **Args:**- - `killExisting` — optional bool (default false). When false and HD is already running, refuse with reason=already_running so the caller doesn't accidentally attach to a stale process. When true, taskkill the existing instance with a 600ms grace period before launching fresh; killedFirst=true in the response.+ - `killExisting` — optional bool (default false). When false and Hydrogen is already running, refuse with reason=already_running so the caller doesn't accidentally attach to a stale process. When true, taskkill the existing instance with a 600ms grace period before launching fresh; killedFirst=true in the response. -**Returns:** On launch: {ok:true, launched:true, wasAlreadyRunning:bool, pid:int (HD's actual PID, not the cmd-wrapper), killedFirst:bool (true iff killExisting was honored), exePath:string, builtSha:string|null (the SHA the binary was built at — compare to /buildinfo.build_sha to confirm fresh code), _hint}. On refusal: {ok:false, launched:false, wasAlreadyRunning:bool, pid:int|null, killedFirst:false, reason:string, _hint}. reason ∈ {'build_in_progress' (a hd_build/hd_build_rust/hd_build_frontend is still running — wait for hd_build_status.building:false), 'build_failed' (last build ended with BUILD_FAILED — fix and retry hd_build), 'already_running' (HD is up — pass killExisting:true to force-kill+relaunch, or use hd_restart), 'binary_missing' (target/debug/adom-hydrogen.exe not on disk — run hd_build first)}.+**Returns:** On launch: {ok:true, launched:true, wasAlreadyRunning:bool, pid:int (Hydrogen's actual PID, not the cmd-wrapper), killedFirst:bool (true iff killExisting was honored), exePath:string, builtSha:string|null (the SHA the binary was built at — compare to /buildinfo.build_sha to confirm fresh code), _hint}. On refusal: {ok:false, launched:false, wasAlreadyRunning:bool, pid:int|null, killedFirst:false, reason:string, _hint}. reason ∈ {'build_in_progress' (a hd_build/hd_build_rust/hd_build_frontend is still running — wait for hd_build_status.building:false), 'build_failed' (last build ended with BUILD_FAILED — fix and retry hd_build), 'already_running' (Hydrogen is up — pass killExisting:true to force-kill+relaunch, or use hd_restart), 'binary_missing' (target/debug/adom-hydrogen.exe not on disk — run hd_build first)}. **Note:** **The launched + wasAlreadyRunning + killedFirst combination is the proof you need** — `launched:true, wasAlreadyRunning:false, killedFirst:false` means truly fresh code is running; any other combination requires you to think about whether your changes actually took effect. builtSha is included so you can immediately compare to /buildinfo.build_sha without a separate call. ### `hd_log` -Read the tail of HD's log file at %APPDATA%\adom-hydrogen\adom-hydrogen.log. Doesn't require HD to be running — reads the file directly from disk. Use this when HD seems stuck or has crashed to see what it said last.+Read the tail of Hydrogen's log file at %APPDATA%\adom-hydrogen\adom-hydrogen.log. Doesn't require Hydrogen to be running — reads the file directly from disk. Use this when Hydrogen seems stuck or has crashed to see what it said last. **Args:** - `tail` — optional int (default 30) — number of trailing lines to return@@ -150,26 +150,26 @@ Read the tail of HD's log file at %APPDATA%\adom-hydrogen\adom-hydrogen.log. Doe ### `hd_open_url` -Open a URL in a specific browser profile via HD's /open-in-profile endpoint. HD knows which browsers + profiles are installed (see hd_browser_profiles) and dispatches to the right one with the right --profile-directory / -P flag.+Open a URL in a specific browser profile via Hydrogen's /open-in-profile endpoint. Hydrogen knows which browsers + profiles are installed (see hd_browser_profiles) and dispatches to the right one with the right --profile-directory / -P flag. **Args:** - `browser` — optional (default 'chrome') — 'chrome', 'edge', 'firefox', 'brave' - `profileDir` — optional (default 'Default') — profile directory name from hd_browser_profiles - `url` — required string -**Returns:** HD's /open-in-profile response (typically {ok, pid, profile})+**Returns:** Hydrogen's /open-in-profile response (typically {ok, pid, profile}) ### `hd_reload_vscode` -[MOVED to hd-dev in v1.8.72] Reload the VS Code iframe inside HD. Public Adom Desktop refuses with verb_moved_to_hd_dev. Workaround: hd_api '{"method":"POST","path":"/reload-vscode"}' (allowed by the public denylist).+[MOVED to hd-dev in v1.8.72] Reload the VS Code iframe inside Hydrogen. Public Adom Desktop refuses with verb_moved_to_hd_dev. Workaround: hd_api '{"method":"POST","path":"/reload-vscode"}' (allowed by the public denylist). -**Returns:** Public build: refusal payload. hd-dev internal build: HD's /reload-vscode response.+**Returns:** Public build: refusal payload. hd-dev internal build: Hydrogen's /reload-vscode response. ### `hd_restart` -Stop + launch in one call. Same guards as hd_launch (build_in_progress / build_failed / binary_missing all refuse). If HD is running it's taskkilled with a 600ms grace period before relaunch to release the exe lock. v1.8.16+.+Stop + launch in one call. Same guards as hd_launch (build_in_progress / build_failed / binary_missing all refuse). If Hydrogen is running it's taskkilled with a 600ms grace period before relaunch to release the exe lock. v1.8.16+. **Returns:** {ok, killedPid?, pid, exePath, _hint} @@ -182,25 +182,25 @@ Capture the Adom Hydrogen window as a lossless PNG. Finds the window by title (' **Returns:** {success, savedTo, sizeKB, hwnd, data:{image (base64), format:'png', encoding, sizeBytes}} -**Note:** Requires HD to be running AND its window to be visible (PrintWindow can't capture a hidden window). If HD isn't found, returns 'Adom Hydrogen window not found' — verify HD is up via hd_status.+**Note:** Requires Hydrogen to be running AND its window to be visible (PrintWindow can't capture a hidden window). If Hydrogen isn't found, returns 'Adom Hydrogen window not found' — verify Hydrogen is up via hd_status. ### `hd_send_files` -Send local files DIRECTLY into Adom Hydrogen's WSL2 project. Relays the bytes to HD's control API, which writes them (as adom) into <project>/<subdir> (default 'downloads', created on first use). Lands in the WSL2 ext4 filesystem so the AI sees them IMMEDIATELY — avoids the plain send_files path (→ Windows Downloads → /mnt/c mount) whose ~5s WSL2 listing-cache makes freshly-dropped files look missing. HD owns the write (it knows its container/bind-mount layout + runs as adom), so ownership + visibility are correct. Requires HD running (hd_launch) and an HD build exposing POST /files/inject.+Send local files DIRECTLY into Adom Hydrogen's WSL2 project. Relays the bytes to Hydrogen's control API, which writes them (as adom) into <project>/<subdir> (default 'downloads', created on first use). Lands in the WSL2 ext4 filesystem so the AI sees them IMMEDIATELY — avoids the plain send_files path (→ Windows Downloads → /mnt/c mount) whose ~5s WSL2 listing-cache makes freshly-dropped files look missing. Hydrogen owns the write (it knows its container/bind-mount layout + runs as adom), so ownership + visibility are correct. Requires Hydrogen running (hd_launch) and an Hydrogen build exposing POST /files/inject. **Args:** - `filePaths` — required array of absolute local file paths to send (same as send_files)- - `subdir` — optional string (default 'downloads') — subfolder under HD's project dir to write into; sits alongside the project's screenshots/ folder+ - `subdir` — optional string (default 'downloads') — subfolder under Hydrogen's project dir to write into; sits alongside the project's screenshots/ folder -**Returns:** send_files-style result: {success:bool, filesReceived:int, destinationPaths:[ '<project>/<subdir>/<name>', ... ], error}. destinationPaths are the WSL2 paths HD actually wrote, so the AI can find them straight away. HD down or endpoint missing → success:false + a clear error.+**Returns:** send_files-style result: {success:bool, filesReceived:int, destinationPaths:[ '<project>/<subdir>/<name>', ... ], error}. destinationPaths are the WSL2 paths Hydrogen actually wrote, so the AI can find them straight away. Hydrogen down or endpoint missing → success:false + a clear error. -**Note:** Use this instead of send_files whenever the destination is HD's WSL2 project (it's the cure for the /mnt/c cache-lag 'file isn't there' confusion).+**Note:** Use this instead of send_files whenever the destination is Hydrogen's WSL2 project (it's the cure for the /mnt/c cache-lag 'file isn't there' confusion). ### `hd_ship` -v1.8.49+: atomic 'rebuild from the exact SHA I just pushed + relaunch + verify it's actually running' sequence. v1.8.57+ adds three guardrails BEFORE doing destructive work: (a) expectSha pre-validation — `git fetch origin main` then `git cat-file -t <sha>` must be `commit` and `git merge-base --is-ancestor <sha> origin/main` must succeed; (b) global build lock at `%TEMP%\hd-build.lock` — refuses immediately if another hd_build_*/hd_ship is in flight (no queue); (c) single-flight lifecycle mutex — refuses if hd_launch/hd_stop/hd_restart/hd_ship is already running. Pipeline after guards pass: (1) taskkill HD + poll until zero (frees exe lock); (2) git fetch + reset --hard origin/main + assert HEAD == expectSha; (3) optional cargo clean; (4) cargo build; (5) launch + poll http://127.0.0.1:47084/buildinfo until SHA matches.+v1.8.49+: atomic 'rebuild from the exact SHA I just pushed + relaunch + verify it's actually running' sequence. v1.8.57+ adds three guardrails BEFORE doing destructive work: (a) expectSha pre-validation — `git fetch origin main` then `git cat-file -t <sha>` must be `commit` and `git merge-base --is-ancestor <sha> origin/main` must succeed; (b) global build lock at `%TEMP%\hd-build.lock` — refuses immediately if another hd_build_*/hd_ship is in flight (no queue); (c) single-flight lifecycle mutex — refuses if hd_launch/hd_stop/hd_restart/hd_ship is already running. Pipeline after guards pass: (1) taskkill Hydrogen + poll until zero (frees exe lock); (2) git fetch + reset --hard origin/main + assert HEAD == expectSha; (3) optional cargo clean; (4) cargo build; (5) launch + poll http://127.0.0.1:47084/buildinfo until SHA matches. **Args:** - `clean` — optional bool, default false. true forces `cargo clean -p adom-hydrogen` before build to defeat the stale-relink trap — use when build said 'Finished' but the running SHA doesn't match expectSha on a prior hd_ship attempt.@@ -208,30 +208,30 @@ v1.8.49+: atomic 'rebuild from the exact SHA I just pushed + relaunch + verify i **Returns:** On success: {ok:true, builtSha (== expectSha), runningSha (== expectSha per /buildinfo), compiled:bool, elapsedSecs, _hint}. On pipeline failure: {ok:false, failedAt: 'args'|'kill'|'git'|'clean'|'build'|'launch'|'verify', error, builtSha|null, runningSha|null, compiled|null, elapsedSecs, _hint}. On v1.8.57+ guard refusal: {ok:false, refused:true, failedAt: 'sha_validate'|'git_fetch'|'lock'|'lifecycle_lock', error, narrative, _youProbablyMeant|_next}. Hallucinated SHA → 'sha_validate' + _youProbablyMeant tells you what real SHAs look like. Lock held → 'lock' + holderPid/holderVerb/elapsedSec tells you who's holding it. -**Note:** Long-running: cold cargo build can take 2-3 min. CLI WS timeout is 12 min — call as a single sync invocation and wait. v1.8.57+: arg validation, SHA validation, and lock acquisition all happen BEFORE any destructive action — if you get `refused:true` at the top, the running HD was not touched. `compiled:false` on success means cargo found nothing to recompile (either cached or HEAD didn't actually change). The verify step requires HD to expose http://127.0.0.1:47084/buildinfo returning JSON with `build_sha` (or `buildSha` or `sha`).+**Note:** Long-running: cold cargo build can take 2-3 min. CLI WS timeout is 12 min — call as a single sync invocation and wait. v1.8.57+: arg validation, SHA validation, and lock acquisition all happen BEFORE any destructive action — if you get `refused:true` at the top, the running Hydrogen was not touched. `compiled:false` on success means cargo found nothing to recompile (either cached or HEAD didn't actually change). The verify step requires Hydrogen to expose http://127.0.0.1:47084/buildinfo returning JSON with `build_sha` (or `buildSha` or `sha`). ### `hd_shot` -v1.8.54+: Capture a named region of Adom Hydrogen, produce BOTH a full-res PNG and a Claude-safe-resized copy, and return rich metadata so the AI never has to chain screenshot→pull→convert→crop→resize→Read manually. Regions are deterministic (no AI-supplied pixel coords) — they resolve via HD window bounds + CDP element rects queried through HD's /eval endpoint. Each shot is self-identifying: it includes the running build's SHA + local build time read from HD's /buildinfo so you can confirm you're looking at the build you expect before trusting what you see. v1.8.61+ universal screenshot delivery contract: the CLI auto-pulls BOTH PNGs to /tmp/ad-shots/<basename>, verifies each landed + is non-empty, and enriches the response with `localFullPath` + `localSafePath` + `localFullExists` + `localSafeExists` + `fullBytes` + `safeBytes` + `source:'hd_shot'` + `narrative` telling you which path to Read for analysis (the safe one).+v1.8.54+: Capture a named region of Adom Hydrogen, produce BOTH a full-res PNG and a Claude-safe-resized copy, and return rich metadata so the AI never has to chain screenshot→pull→convert→crop→resize→Read manually. Regions are deterministic (no AI-supplied pixel coords) — they resolve via Hydrogen window bounds + CDP element rects queried through Hydrogen's /eval endpoint. Each shot is self-identifying: it includes the running build's SHA + local build time read from Hydrogen's /buildinfo so you can confirm you're looking at the build you expect before trusting what you see. v1.8.61+ universal screenshot delivery contract: the CLI auto-pulls BOTH PNGs to /tmp/ad-shots/<basename>, verifies each landed + is non-empty, and enriches the response with `localFullPath` + `localSafePath` + `localFullExists` + `localSafeExists` + `fullBytes` + `safeBytes` + `source:'hd_shot'` + `narrative` telling you which path to Read for analysis (the safe one). **Args:** - `format` — optional string, default 'png' (only PNG supported in v1).- - `region` — REQUIRED string. One of: 'full' (whole HD window), 'titlebar' (top ~40px strip — build SHA / timestamp readout), 'vscode' (VS Code iframe pane via CDP element rect), 'setup-panel' (Setup Steps panel via .setup-panel or .setup-panel-output), 'wiki' (wiki/browser tab pane), 'claude' (Claude Code panel). If unknown, response is {ok:false, error, knownRegions:[...]}.+ - `region` — REQUIRED string. One of: 'full' (whole Hydrogen window), 'titlebar' (top ~40px strip — build SHA / timestamp readout), 'vscode' (VS Code iframe pane via CDP element rect), 'setup-panel' (Setup Steps panel via .setup-panel or .setup-panel-output), 'wiki' (wiki/browser tab pane), 'claude' (Claude Code panel). If unknown, response is {ok:false, error, knownRegions:[...]}. - `resizeMax` — optional int, default 1400. Longest side of the safe-resized copy. Use lower (≈800) if you want to fit more shots in one Claude turn; higher (1568) for max fidelity. **Returns:** {ok, region, fullPath, safePath, fullSize:[w,h], safeSize:[w,h], clipRect:[x,y,w,h], capturedAtLocal, runningBuildSha, runningBuildLocal, hdWindowFound:bool, regionFound:bool, windowOuter:[w,h], capturedSize:[w,h], _hints:{pull, fullForArchive, staleWindow, regionMiss}} -**Note:** Always pull_file the SAFE path and Read THAT — it's already sized for Claude's image analysis. The FULL path is meant for shotlog / disk archival, NOT direct Read (may exceed Claude's per-image budget). **regionFound:false** when the element rect wasn't in HD's DOM — the panel/iframe may not be mounted yet, OR HD's markup changed and region_selectors() in hd_bridge.rs is out of date. Either way, the shot is still produced (falls back to the full window) so you have something to look at. **runningBuildSha** can be null if HD's /buildinfo isn't exposed yet — same SHA HD's launch path uses, so you can compare to hd_launch's builtSha. All child spawns use CREATE_NO_WINDOW (no cmd flashes). v1.8.54+.+**Note:** Always pull_file the SAFE path and Read THAT — it's already sized for Claude's image analysis. The FULL path is meant for shotlog / disk archival, NOT direct Read (may exceed Claude's per-image budget). **regionFound:false** when the element rect wasn't in Hydrogen's DOM — the panel/iframe may not be mounted yet, OR Hydrogen's markup changed and region_selectors() in hd_bridge.rs is out of date. Either way, the shot is still produced (falls back to the full window) so you have something to look at. **runningBuildSha** can be null if Hydrogen's /buildinfo isn't exposed yet — same SHA Hydrogen's launch path uses, so you can compare to hd_launch's builtSha. All child spawns use CREATE_NO_WINDOW (no cmd flashes). v1.8.54+. ### `hd_status` -v1.8.58+ COMPOSED + RELAYED snapshot of HD's state; v1.8.129+ churn-honest. AD owns host/process/repo facts; HD owns runtime state (relayed verbatim from HD's control API, port discovered from %APPDATA%/adom-hydrogen/ports.json key 'control', fallback 47084 — NOT a hardcoded port). v1.8.129 reports THREE orthogonal signals instead of one boolean so you can reason about HD's constant build-relaunch churn: processPresent (adom-hydrogen.exe exists, sampled with retry to ride the ~1s kill→respawn gap), controlApiReachable (control port actually listening), and embedded (AD's OWN mode — answers 'is AD embedded under HD?'). `running` = processPresent||controlApiReachable.+v1.8.58+ COMPOSED + RELAYED snapshot of Hydrogen's state; v1.8.129+ churn-honest. AD owns host/process/repo facts; Hydrogen owns runtime state (relayed verbatim from Hydrogen's control API, port discovered from %APPDATA%/adom-hydrogen/ports.json key 'control', fallback 47084 — NOT a hardcoded port). v1.8.129 reports THREE orthogonal signals instead of one boolean so you can reason about Hydrogen's constant build-relaunch churn: processPresent (adom-hydrogen.exe exists, sampled with retry to ride the ~1s kill→respawn gap), controlApiReachable (control port actually listening), and embedded (AD's OWN mode — answers 'is AD embedded under Hydrogen?'). `running` = processPresent||controlApiReachable. -**Returns:** {ok:true, running:bool (process||control), processPresent:bool, controlApiReachable:bool, controlPort:int (the dynamically-discovered port), embedded:bool (AD's own mode), embeddedOwner:string|null, embeddedVia:string|null ('LaunchFlag'|'RuntimeAdopt'), laptopHeadSha:string, originMainSha:string, shaMatchesOrigin:bool, runningSha:string|null, workspaceHealth:object|null (HD's /workspace/health relayed verbatim), buildinfo:object|null (HD's /buildinfo relayed verbatim), narrative:string (honest about up-serving vs up-churning vs down, plus AD's embedded mode), _next:string}+**Returns:** {ok:true, running:bool (process||control), processPresent:bool, controlApiReachable:bool, controlPort:int (the dynamically-discovered port), embedded:bool (AD's own mode), embeddedOwner:string|null, embeddedVia:string|null ('LaunchFlag'|'RuntimeAdopt'), laptopHeadSha:string, originMainSha:string, shaMatchesOrigin:bool, runningSha:string|null, workspaceHealth:object|null (Hydrogen's /workspace/health relayed verbatim), buildinfo:object|null (Hydrogen's /buildinfo relayed verbatim), narrative:string (honest about up-serving vs up-churning vs down, plus AD's embedded mode), _next:string} -**Note:** v1.8.129 fixes the misleading 'HD is NOT running' that fired when a single tasklist snapshot landed mid-relaunch. If you see running:true + controlApiReachable:false, HD is mid-build/relaunch — retry in a few seconds, don't treat it as down. Use this as the entry point for 'what's HD's state?' — it tells you which downstream verb to run next (hd_ship, hd_launch, hd_shot, etc.).+**Note:** v1.8.129 fixes the misleading 'Hydrogen is NOT running' that fired when a single tasklist snapshot landed mid-relaunch. If you see running:true + controlApiReachable:false, Hydrogen is mid-build/relaunch — retry in a few seconds, don't treat it as down. Use this as the entry point for 'what's Hydrogen's state?' — it tells you which downstream verb to run next (hd_ship, hd_launch, hd_shot, etc.). ### `hd_stop`