bootstrap
Adom Hydrogen (platform base)
Public Made by Adomby adom
Layer Hydrogen's workspace onto a standard Adom workstation.
← Commit history
skills/hydrogen-api/SKILL.mddeleted−837@@ -1,837 +0,0 @@-name: hydrogen-api-description: >- Complete reference for Hydrogen control API endpoints. The control- API runs on a dynamic port (find it in the Hydrogen log or via port discovery). Use- these endpoints to drive Hydrogen programmatically: manage the workspace (the WSL2 `Adom-Workspace` distro), control- Claude Code, manipulate VS Code, manage workspace tabs, run setup steps, trigger- virgin reset, and more. The COMPLETE, always-current catalog is- GET /_manifest (every route with a category + description; curated entries are- richer). The API Explorer window (Adom menu > API Explorer, or POST /api-explorer/open)- renders it with a runnable Try per endpoint. GET /test/help lists the gated /test/*- diagnostics. NEVER blind-call destructive endpoints (see the Safety section).- Trigger words: Hydrogen API, control API, Hydrogen endpoint, container exec, claude api,- iframe eval, workspace tabs, setup run-all, workspace status, reload vscode,- browser profiles, open url, virgin reset api, reboot api, diagnostics,- ad health, test window-tree, ai cursor, setup panel, screenshot mode.--# Hydrogen Control API Reference--The control API is large and grows. This file quoted "~159 endpoints" in its body and-"~200" in its own frontmatter while the router carried **274**: two stale numbers that did-not even agree with each other, in the one document whose job is to be accurate about the-API. So it no longer quotes a count at all. Don't trust a static count or list in-this file to stay exhaustive — the API is **self-documenting**, with two live-sources of truth you should hit first:--| Source | What it gives you | Where |-|---|---|---|-| `GET /_manifest` | **THE complete catalog** — every registered route (`path`, `method`, `args`, `category`, `description`, `visibility`). Curated entries carry richer descriptions; the rest are auto-generated from the router (`scripts/gen-manifest.py`), so it never drifts. **Discover here first — don't guess paths.** | `hydrogen-control/src/lib.rs` `/_manifest` arm |-| **API Explorer window** | The human face of `/_manifest`: every endpoint grouped by category tab, with a runnable **Try** + Copy URL. Open from the Adom menu, or `POST /api-explorer/open`. | Adom menu ▸ API Explorer |-| **Workspace control** (`:47083`) | A SEPARATE server (`hydrogen-proxy`), and its ~30 routes are **NOT in `/_manifest`**: `/tabs`, `/tabs/find`, `/active-tab`, `/splits`, `/swaps`, `/moves`, `/nav`, `/window-mode`, `/caption`, `/recording`, `/screenshot`, `/audio`, `/sharing`, `/notification`. This is the surface the in-container AI reaches through `adom-cli`. Enumerating `/_manifest` alone will NOT show you these. | `hydrogen-proxy/src/lib.rs` |-| `GET /test/help` | The `/test/*` diagnostics (window enumeration, UIA click, dialog classification, cascade reset). **Gated behind `HD_TEST_API_ENABLED=1`** — 404 by default (expected, not a bug). | `hydrogen-control/src/lib.rs` `/test/help` arm |--## ⛔ Safety — the API enforces this, and tells you in-band--The API itself now labels, warns about, and gates dangerous endpoints (single source of-truth: `safety.rs` in hydrogen-control). Three tiers:--- **`catastrophic`** — irreversibly destroys real user state: `/setup/virgin-reset`,- `/setup/panel/(run-virgin-reset|wipe-keep-auth)`, `/wsl/unregister` (deletes the whole- workspace distro), `/system/reboot` (reboots the- user's COMPUTER), `/config-reset`, `/claude/wipe-creds`, `*-delete`.- **Headless calls (no browser Origin header — i.e. YOU) get HTTP 409 `confirmation_required`- and NOTHING happens** until you re-call with `?confirm=1`. Only add `?confirm=1` when the- user explicitly asked for exactly that action — never to make an error go away.-- **`destructive`** — kills/restarts/re-runs real state (recoverable but real):- `/app/(restart|relaunch-frontend)`, `/reload-vscode`,- `/container(-stop|-restart)`, `/workspace/apply-updates`, `/setup/(run-all|run-step|state|- force-close|trigger|countdown)`, `/claude/tabs/close-all`, `/updater/install`.- Never call these speculatively or in a sweep.-- **`disruptive`** — the user SEES it (window opens, focus moves, typing lands in their- real chat, screen recording starts): `/hbw/open` (and `/hbw/close` to close one by label), `/api-explorer/open`, `/open-url`,- `/open-in-profile`, `/window/foreground`, `/ai-cursor/*`, `/recording/native/start`,- `/ui/toast`, `/claude/(trigger-auth|authorize-in-browser|open-with-message|inject*|send|- submit|uia-*|new-chat-and-send|type-and-submit)` (the send/submit ones SPEND a real user- turn). Run only when the user actually wants that action, and clean up after yourself.- (Calling `/claude/authorize-in-browser` blindly is how you spray OAuth windows into Edge.)--How the API tells you:-- **Before calling:** every `GET /_manifest` entry carries `safety` + `safety_note`. Check- them before you POST anything unfamiliar. Unlabeled = safe.-- **When you call:** responses from these endpoints include a `_safety` block. READ IT —- it says exactly what you just did to the user's machine.-- **The 409 gate** is your last chance to stop; it is not an error to route around.--A safe GET/POST returns within a couple seconds with a 2xx or a clean 4xx `{ok:false,...}`.-If you must probe an endpoint you're unsure about, POST an empty `{}` body and treat a-graceful validation error as "it works" — a 500 or a hang is the bug.--**Base URL:** `http://127.0.0.1:<dynamic>` — the same loopback address from inside the-workspace (WSL2 mirrored networking shares loopback with the Windows host) and on the-Windows host. The port is dynamic per launch; read the live URL from-`~/.adom/hydrogen-control-url` — see "Finding the Control Port" below.--## Finding the Control Port--The control API port is dynamic (default 47084, auto-resolves conflicts).--```bash-# From Hydrogen log-adom-bridge hd_log '{"tail":100}' | grep "control="--# From ports.json-type %APPDATA%\hydrogen-desktop\ports.json--# From inside the WSL2 workspace — USE THIS. Hydrogen writes its live control URL to a discovery-# file every launch (mirrored loopback), so you never hunt for the dynamic port:-CTRL="$(cat ~/.adom/hydrogen-control-url)"; curl -sf "$CTRL/health"--# No file access (remote tool, browser)? Probe the DISCOVERY responder: fixed candidate-# ports tried in order (a single fixed port is not bindable on every Windows box; WSL2-# mirrored networking claims ports invisibly). Take the FIRST that answers with-# service == "hydrogen-desktop-discovery"; its control_url is the live control API:-for p in 47080 48080 49180 50280; do- R=$(curl -sf --max-time 2 "http://127.0.0.1:$p/") && echo "$R" | grep -q hydrogen-desktop-discovery && break-done-```--⭐ **From the workspace, read `~/.adom/hydrogen-control-url`** (e.g. `http://127.0.0.1:<control>`) — a-file, NOT an env var (your non-interactive Bash shells don't source `.bashrc`/`profile.d`). Hydrogen-rewrites it with the live dynamic port every launch. This is the channel for the UI command bus,-the live ports map, Claude control, etc. — distinct from `adom-cli` (`ADOM_HYDROGEN_URL` → SSE),-which is unchanged for web-hydrogen parity.--## Calling gotchas (learned the hard way)--- **Never hardcode the port.** It's dynamic (47084 is only the default and it auto-resolves- conflicts). Read `~/.adom/hydrogen-control-url` from the workspace, or `GET /ports`. Hardcoding- 47084 is what makes tools show Hydrogen as "down" when it's actually up on another port.-- **Calling from a REMOTE container (hw/cloud)? Use `adom-bridge hd_api`,** the relay's- pass-through verb: `hd_api {"method":"POST","path":"/...","body":{...}}`. It auto-discovers- the port; never shell curl through the relay (quoting gets mangled). Long-blocking calls- (typed injection) can outlive the relay timeout: the work still completes on Hydrogen's side, so- verify state instead of re-firing.-- **Getting files OUT (recordings, screenshots): streamed binary, never base64.** Endpoints- return paths inside the WSL distro; a remote container pulls them with `adom-bridge- --target <desktop> pull_file {filePaths:["\\\\wsl$\\Adom-Workspace\\<path>"], saveTo:...}`- (1 MiB binary chunks, sha256-verified, no practical size limit). `/recording/native/stop`- returns the ready-made `fileWindows` UNC path. Full demo-video pipeline: the- `hydrogen-demo-recording` skill.-- **Confirm it's really the control API, not the SPA.** In dev, the frontend file server- answers 200 with HTML for *any* path — so a bare 200 doesn't prove you hit Hydrogen's API. Check- `GET /health` returns JSON with `service:"hydrogen-desktop-control"`.-- **Driving Hydrogen from a page Hydrogen serves? Use relative fetches, not Tauri IPC.** Tauri `invoke`- is unavailable on remote http origins; a same-origin `fetch('/ports')` / `fetch('/_manifest')`- works and sidesteps port discovery entirely.-- **Driving from the CLOUD over the relay:** if two Adom Bridges are connected (laptop +- a VM), `desktop_*` verbs need `--target <name>` (e.g. `AdomLapper`) or they no-route and- look empty; `nbrowser_*`/`hd_*` auto-route. PowerShell emits **CRLF** — strip `\r` before- string-comparing its output. Long calls can exceed the relay's per-call timeout — run- detached + poll a marker (see `hydrogen-cloud-relay-patterns`).--## Health & Status--| Method | Path | Description |-|---|---|---|-| GET | `/health` | Hydrogen alive check — returns `{ok, port, service}` |-| GET | `/buildinfo` | Running build git SHA + build metadata (the only trustworthy "did my build ship?" check) |-| GET | `/ports` | The 4 editable PortConfig ports (proxy, control, cdp, code_server) |-| GET | `/ports/all` | LIVE full port map — every host + WSL2 port Hydrogen has bound, with status + mirrored-mode info |--## ab-health diagnostics (`/ab/*`)--(Canonical since 1.0.47; the old `/ad/*` spellings still answer as aliases.)--These verify the **adom-bridge / relay / embedded-ab** half of Hydrogen is alive (the-bridge that connects this cloud container to Hydrogen). All GET, all return `{ok, ...}`.--| Method | Path | Description |-|---|---|---|-| GET | `/ab/health` | Overall embedded-ab health roll-up |-| GET | `/ab/process` | Is the adom-bridge process running |-| GET | `/ab/embedded` | Embedded-ab module status |-| GET | `/ab/workspace-direct` | ⭐ The **converged** check — direct path to the workspace relay (use this one) |-| GET | `/ab/relay` | Relay (WS/HTTP) reachability |-| GET | `/ab/liveness-beacon` | Liveness beacon freshness |-| GET | `/ab/direct-api` | Direct-API reachability |-| GET | `/ab/discovery-file` | Discovery file present + parseable |--## Driving Hydrogen's UI (command bus)--Open/close/toggle any Hydrogen menu, dialog, or panel — the first-class alternative to CDP clicking. See the `hydrogen-ui` skill.--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/ui/actions` | — | List every drivable UI action `{id,label,description,group}` (+ `_hints`) |-| POST | `/ui/invoke` | `{"id":"ports.open"}` | Run a UI action; returns `{ok,value}` only after the frontend ran it |-| GET | `/auth-token` | Hydrogen session token |-| GET | `/setup-status` | Overall setup completion state |-| GET | `/diagnostics/all` | Run all diagnostic checks |-| GET | `/diagnostics/{name}` | Run a single diagnostic check |--## Workspace Management--These endpoints manage the workspace: the WSL2 distro `Adom-Workspace`. The paths-keep their historical `container` spelling; there is no container.--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/container-status` | — | `runtime_available` (WSL2 usable), `workspace_installed` (distro present), workspace exists/running |-| GET | `/container-stats` | — | CPU, memory, disk usage |-| POST | `/container-restart` | — | Restart the workspace (5s timeout) |-| POST | `/container-stop` | — | Stop the workspace |-| POST | `/container-exec` | `{"command":"..."}` | Run command in the workspace as user `adom` |-| POST | `/container-delete` | — | Remove the workspace |-| GET | `/container/logs` | — | Workspace stdout/stderr |-| GET | `/container/env` | — | Workspace environment variables |-| GET | `/container/ports` | — | Forwarded port mappings |-| GET | `/container/disk` | — | Disk usage inside the workspace |-| POST | `/container/restart` | — | Alias for `/container-restart` |-| POST | `/direct/command` | `{...}` | Direct-connect command channel into the workspace |--> `GET /container-status` renamed two fields: `docker_available` → **`runtime_available`**-> and `image_pulled` → **`workspace_installed`**. Old field names are gone.--### Workspace / WSL endpoints--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/wsl/status` | — | WSL distro state (registered, running, code-server reachable) |-| GET | `/workspace/health` | — | Deep workspace health (distro + code-server + host reachability) |-| GET | `/virgin-reset-progress` | — | Live progress of an in-flight virgin reset |-| POST | `/workspace/terminal-profile` | — | Ensure the stable `Adom-Workspace` Windows Terminal profile (idempotent) |-| POST | `/workspace/terminal-profile/remove` | — | Remove the `Adom-Workspace` Windows Terminal profile(s) |-| POST | `/workspace/check-updates` | — | Check upstream for newer code-server + Claude extension; stage them |-| POST | `/workspace/apply-updates` | — | Apply staged code-server/extension updates + reload editor |--> ⛔ `POST /wsl/unregister` is **REFUSED as deprecated** — it was a headless-> destructive reset (deletes `/home/adom/project`). Use the Setup panel's Virgin-> Reset or `POST /setup/panel/run-virgin-reset` instead.--## WebView & VS Code--| Method | Path | Body | Description |-|---|---|---|---|-| POST | `/eval` | `{"js":"..."}` | JS eval in main Hydrogen webview |-| POST | `/iframe-eval` | `{"js":"...","contextIndex":N}` | JS eval in a specific iframe context (0-14) |-| POST | `/cdp-eval` | `{"expression":"..."}` | Direct Chrome DevTools Protocol eval |-| POST | `/click` | `{"x":N,"y":N}` | Click at coordinates in webview |-| POST | `/mouse-click` | `{"x":N,"y":N,"button":"left"}` | Mouse click with options |-| POST | `/query` | `{"selector":"..."}` | Query DOM elements |-| POST | `/reload-vscode` | — | Reload the VS Code iframe |-| POST | `/vscode/hide-activity-items` | — | Hide activity-bar items (persisted, overflow-proof) |-| GET | `/targets` | — | List CDP targets (all webview contexts) |-| GET | `/cdp-info` | — | CDP connection info (port, URL) |-| GET | `/devtools` | — | DevTools status |--### AI cursor (visible cursor for demos / clicking)--Distinct from `/click` and `/mouse-click` — this renders a **visible** AI cursor,-glides it, and can click. Use for demos or when the user should see where the AI clicks.--| Method | Path | Body | Description |-|---|---|---|---|-| POST | `/ai-cursor/move` | `{"x":N,"y":N}` | Move (glide) the visible AI cursor to coordinates |-| POST | `/ai-cursor/click` | `{"x":N,"y":N}` | Move the visible AI cursor there + click |-| POST | `/ai-cursor/hide` | — | Hide the visible AI cursor |--### Screenshot primitives--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/capture/viewport` | — | Capture the Hydrogen webview viewport (PNG) |-| POST | `/shot` | `{...}` | Screenshot primitive (see **hydrogen-self-screenshot** for the full workflow) |--### Port hints--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/adom-port-hints` | — | Read the workspace port-hints map |-| POST | `/adom-port-hints` | `{...}` | Write/merge the workspace port-hints map |--## Claude Code--### Status / auth state (GET)--| Method | Path | Description |-|---|---|---|-| GET | `/claude/status` | Install state, auth, active session, version |-| GET | `/claude/auth-check` | Deep auth check — file exists, token, expiry |-| GET | `/claude/auth-status` | Auth-status detail |-| GET | `/claude/auth-page-state` | Which auth screen the panel shows: `continue-in-browser` \| `subscription-button` \| `chat`; returns `oauth_url` + `at_browser_auth_gate` |-| GET | `/claude/detect-auth-failure` | Scan webview contexts for auth button/errors |-| GET | `/claude/sessions` | List active Claude sessions |--### Auth actions (POST)--| Method | Path | Body | Description |-|---|---|---|---|-| POST | `/claude/find-auth-button` | — | Find + highlight the sign-in button WITHOUT clicking (validation) |-| POST | `/claude/start-auth` | — | Find + highlight + CLICK the "Claude.ai Subscription" button to begin OAuth |-| POST | `/claude/trigger-auth` | — | Alias for start-auth |-| POST | `/claude/detect-state` | — | Detect current auth/panel state |-| POST | `/claude/authorize-in-browser` | `{"timeout_ms":N,"dry_run":B,"fresh":B,"oauth_url":"..."}` | Auto-click the "Authorize" button on the claude.ai OAuth page (unattended sign-in) |-| POST | `/claude/authorize-tab-enter` | — | Approve the Adom OAuth tab via Enter (branded picker flow) |-| POST | `/claude/inject-creds` | — | Push host backup credentials into the workspace |-| POST | `/claude/wipe-creds` | `{"backup":B}` | Wipe Claude credentials (destructive); `backup:false` keeps the host backup so reinject can restore |--### Panel / conversation control (POST unless noted)--| Method | Path | Body | Description |-|---|---|---|---|-| POST | `/claude/open` | — | Open Claude Code panel (`claude-vscode.editor.open`) |-| POST | `/claude/ensure-open` | — | Ensure the panel is open (strict readiness; recovery if not rendered) |-| POST | `/claude/open-with-message` | `{"message":"..."}` | Open + pre-fill message |-| POST | `/claude/focus` | — | Focus Claude panel |-| POST | `/claude/new-conversation` | — | Start a fresh conversation (shows sign-in panel when unauthenticated) |-| POST | `/claude/new-chat-and-send` | `{"text":"...","typed":B,"submit":B,"delay_ms":N}` | Open fresh conversation, wait for compose box, type + (default) submit |-| POST | `/claude/submit` | — | Find + click send button |-| POST | `/claude/send` | `{"message":"..."}` | Send message to Claude |-| POST | `/claude/inject` | `{"message":"..."}` | Inject text into the compose box |-| POST | `/claude/inject-message` | `{"message":"..."}` | Inject into conversation |-| POST | `/claude/type-and-submit` | `{"message":"...","delay_ms":N}` | Type char-by-char (human-paced) + submit |-| POST | `/claude/remote-control` | `{"name":"..."}` | Turn on Claude Code Remote Control (submits `/remote-control` slash command) |-| POST | `/claude/highlight-open-button` | `{"duration":N}` | Glow animation on Claude button |-| POST | `/claude/clear-open-highlight` | — | Clear the open-button highlight |--## OAuth & Auth--| Method | Path | Body | Description |-|---|---|---|---|-| POST | `/claude-auth` | — | Full PKCE OAuth flow — opens browser, sets up callback |-| GET | `/oauth/callback` | — | OAuth callback handler (receives auth code) |-| POST | `/auth/proxy` | varies | Proxy auth requests to carbon.adom.inc |-| POST | `/open-url` | `{"url":"..."}` | Open URL (triggers browser picker) |-| POST | `/start-oauth-proxy` | `{"port":N}` | Start OAuth callback proxy on a port |-| GET | `/browser-profiles` | — | List browsers + profiles with avatars |-| POST | `/open-in-profile` | `{"url":"...","browser":"...","profileDir":"..."}` | Open URL in specific browser profile |-| POST | `/browser-picker/opened` | `{...}` | Frontend reports the browser picker was opened |-| GET | `/browser-picker/last-open` | — | Last browser-picker open event |--## Setup Steps & Setup Panel--### State / trigger / step control--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/setup/state` | — | Get current setup state (`never-run` \| `in-progress` \| `complete`) |-| POST | `/setup/state` | `{"state":"..."}` | Set setup state |-| POST | `/setup/step/<id>` | `{"continue_after":B}` | ⭐ Run one step by id (forces panel visible first); `continue_after:true` runs this step + every step after it |-| POST | `/setup/force-close` | — | Force-close setup panel |-| POST | `/setup/countdown` | `{"seconds":N,"message":"..."}` | Show countdown overlay |-| GET | `/setup/trigger` | — | Read trigger file |-| DELETE | `/setup/trigger` | — | Delete trigger file |-| POST | `/config-reset` | — | Reset Hydrogen config |--> ⛔ **REFUSED as deprecated** (headless runs with no visible UI):-> `POST /setup/run-all`, `POST /setup/run-step`, `POST /setup/virgin-reset`,-> `POST /wsl/unregister`. They return a refusal pointing at the UI-visible path.-> To run steps: use `POST /setup/step/<id>` or relaunch Hydrogen to auto-run the cascade.--### Setup panel control--| Method | Path | Body | Description |-|---|---|---|---|-| POST | `/setup/panel/show` | — | Force the setup panel visible |-| POST | `/setup/panel/hide` | — | Hide the setup panel |-| POST | `/setup/panel/show-virgin-reset` | — | Show panel + expand the Virgin Reset section |-| POST | `/setup/panel/virgin/show` | — | Show the Virgin Reset section only |-| POST | `/setup/panel/virgin/hide` | — | Hide the Virgin Reset section |-| POST | `/setup/panel/set-virgin-options` | `{"options":{...}}` | Set the virgin-reset checkboxes |-| POST | `/setup/panel/run-virgin-reset` | — | ⭐ The **ONLY** allowed virgin-reset trigger — UI-visible by construction (shows panel + checkboxes + progress before deleting anything) |-| POST | `/setup/panel/wipe-keep-auth` | — | Synchronous wipe that KEEPS Adom + Claude tokens |-| POST | `/setup/screenshot-mode` | `{"enabled":B}` | Toggle per-step screenshot capture (default OFF) |-| GET | `/setup/screenshot-mode` | — | Whether per-step screenshot mode is on |--## Workspace Tabs--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/workspace/tabs` | — | List all workspace tabs |-| GET | `/workspace/tabs/find?name=X` | — | Find tab by name (404 if not found) |-| POST | `/workspace/tabs` | `{tab spec}` | Add a new tab |--## System--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/system/nonce` | — | Get nonce for authenticated reboot |-| GET | `/system/reboot-state` | — | Check reboot pending state |-| POST | `/system/reboot` | `{"nonce":"..."}` | Reboot Windows (nonce-authenticated) |-| POST | `/system/cancel-reboot` | — | Cancel pending reboot |--## App lifecycle & window--| Method | Path | Body | Description |-|---|---|---|---|-| POST | `/app/restart` | — | Restart the Hydrogen app (kills + respawns the binary) |-| POST | `/app/relaunch-frontend` | — | Relaunch the Hydrogen GUI (kill+respawn) while it is responsive |-| POST | `/window/foreground` | — | Bring the Hydrogen window to the foreground (unminimize + focus) |--## Diagnostics (`/test/*`)--Window enumeration, UIA clicking, native-dialog classification, and cascade-diagnostics. **Gated behind `HD_TEST_API_ENABLED=1`** (return 404 / "test API-disabled" otherwise). `GET /test/help` self-lists the whole cluster.--| Method | Path | Body | Description |-|---|---|---|---|-| GET | `/test/help` | — | Self-lists every `/test/*` endpoint |-| GET | `/test/window-tree` | — | Enumerate all visible top-level windows |-| POST | `/test/focus` | `{"window":"..."}` | Focus Hydrogen (`self`) or a window by title substring |-| POST | `/test/click-uia` | `{...}` | Poll UIAutomation for a Button by Name; Invoke when found |-| GET | `/test/setup-steps` | — | Raw setup-steps.json + derived summary (alias: `/test/install-steps`) |-| POST | `/test/dump-state` | `{...}` | Write a diagnostic bundle (logs, install-steps, workspace state, tasklist, window-tree) |-| POST | `/test/reset-cascade` | — | Delete install-steps.json + emit setup-reset event |-| POST | `/test/screenshot-hydrogen-window` | `{...}` | Capture Hydrogen's own window to a PNG file |-| GET | `/test/probe-dialogs` | — | Enumerate visible windows, classify against the cascade-blocker catalog (UAC, WSL2 update, MSI installer, …); returns `kind` + `is_blocking` per window |--## Key Patterns--### iframe-eval context discovery-Contexts 0-14 cover all webview frames. Context numbers shift when panels open/close.-Always scan, never hardcode. The Claude Code extension webview IS reachable through-these contexts.--```-POST /iframe-eval {"js":"document.body.innerText.substring(0,100)","contextIndex":3}-```--### container-exec-Runs as user `adom` inside the workspace. Use full paths (`/home/adom/`-not `~/`). Tilde doesn't expand through the exec chain.--```-POST /container-exec {"command":"ls /home/adom/project"}-```--### Re-run a setup step after completion-The trigger file poller STOPS when all steps are done. `POST /setup/run-all` is-**REFUSED as deprecated** — don't use it. Re-run one step by id (or relaunch Hydrogen to-auto-run the cascade):-```-POST /setup/step/<id>-```--## Complete route index--<!-- BEGIN GENERATED ROUTE INDEX -->--Every route the router exposes, 318 across 22 categories, grouped the-way the API Explorer groups them. Generated from the same table `/_manifest` serves, so it-cannot drift from the code; `scripts/check-manifest-fresh.sh` fails the build if it does.--`/_manifest` remains the richer source at runtime: it carries each route's args, its-description, and a `safety` flag (`destructive` / `disruptive`) that this flat index does not.-**Read a route's safety from `/_manifest` before calling it, not from this list.**--**AI Threads** (38)--- `GET /ai-threads`-- `POST /ai-threads/activate`-- `POST /ai-threads/close`-- `GET /ai-threads/dom-debug`-- `POST /ai-threads/dom-event`-- `GET /ai-threads/dom-events`-- `POST /ai-threads/focus`-- `GET /ai-threads/history`-- `POST /ai-threads/hook-event`-- `POST /ai-threads/inject`-- `POST /ai-threads/inspect`-- `POST /ai-threads/install`-- `GET /ai-threads/install/log`-- `POST /ai-threads/issue-inject`-- `GET /ai-threads/issue-queue`-- `GET /ai-threads/names`-- `POST /ai-threads/new`-- `POST /ai-threads/new-tui`-- `POST /ai-threads/pick`-- `GET /ai-threads/prompts`-- `POST /ai-threads/rename`-- `POST /ai-threads/reorder`-- `POST /ai-threads/repo-link`-- `GET /ai-threads/repo-links`-- `POST /ai-threads/resume`-- `POST /ai-threads/run-prompt`-- `GET /ai-threads/run-prompt/status`-- `GET /ai-threads/settings`-- `POST /ai-threads/settings`-- `GET /ai-threads/tabs`-- `POST /ai-threads/tag`-- `GET /ai-threads/tags`-- `GET /ai-threads/tools`-- `POST /ai-threads/uninstall`-- `GET /ai-threads/wait`-- `POST /ai-threads/walk`-- `GET /ai-threads/walk-report`-- `GET /ai-threads/wiki-repos`--**Adom Bridge** (19)--- `GET /ab/direct-api`-- `GET /ab/discovery-file`-- `GET /ab/embedded`-- `GET /ab/health`-- `GET /ab/liveness-beacon`-- `GET /ab/permissions`-- `POST /ab/permissions/request`-- `POST /ab/permissions/revoke`-- `GET /ab/process`-- `GET /ab/relay`-- `GET /ab/settings`-- `POST /ab/settings`-- `POST /ab/show`-- `POST /ab/toast-ack`-- `POST /ab/verb`-- `GET /ab/workspace-direct`-- `POST /direct/command`-- `GET /direct/health`-- `GET /direct/status`--**Auth & User** (7)--- `GET /auth-token`-- `GET /auth/browser-status`-- `GET /auth/proxy`-- `POST /auth/proxy`-- `DELETE /user/avatar`-- `POST /user/avatar`-- `POST /user/refresh`--**Browser & Open** (11)--- `GET /browser-picker/last-open`-- `POST /browser-picker/opened`-- `DELETE /browser-picker/prefs`-- `GET /browser-picker/prefs`-- `PUT /browser-picker/prefs`-- `GET /browser-profiles`-- `POST /open-in-profile`-- `POST /open-url`-- `GET /webview-can-embed`-- `GET /webview-proxy`-- `GET /wiki-proxy`--**Claude** (49)--- `POST /claude-auth`-- `GET /claude/auth-check`-- `GET /claude/auth-page-state`-- `GET /claude/auth-status`-- `POST /claude/authorize-in-browser`-- `POST /claude/authorize-tab-enter`-- `POST /claude/clear-open-highlight`-- `POST /claude/cli-auth/code`-- `POST /claude/cli-auth/start`-- `GET /claude/contexts`-- `GET /claude/conversation-state`-- `GET /claude/conversations`-- `POST /claude/cross-eval`-- `GET /claude/detect-auth-failure`-- `POST /claude/detect-state`-- `POST /claude/ensure-open`-- `POST /claude/find-auth-button`-- `POST /claude/focus`-- `POST /claude/highlight-open-button`-- `POST /claude/inject`-- `POST /claude/inject-creds`-- `POST /claude/inject-message`-- `POST /claude/new-chat-and-send`-- `POST /claude/new-conversation`-- `POST /claude/open`-- `POST /claude/open-with-message`-- `POST /claude/remote-control`-- `POST /claude/sample-prompt`-- `GET /claude/sample-prompts`-- `POST /claude/sample-prompts/refresh`-- `POST /claude/send`-- `GET /claude/sessions`-- `POST /claude/start-auth`-- `GET /claude/status`-- `POST /claude/submit`-- `GET /claude/tabs`-- `POST /claude/tabs/activate`-- `POST /claude/tabs/close-all`-- `POST /claude/tabs/close-empty-groups`-- `POST /claude/tabs/close-untitled`-- `POST /claude/tabs/merge-groups`-- `POST /claude/trigger-auth`-- `POST /claude/type-and-submit`-- `POST /claude/uia-authorize`-- `POST /claude/uia-scan`-- `POST /claude/wipe-creds`-- `POST /config-reset`-- `GET /oauth/callback`-- `POST /start-oauth-proxy`--**Container / Docker (legacy)** (15)--- `POST /container-delete`-- `POST /container-exec`-- `POST /container-pull-image`-- `POST /container-restart`-- `POST /container-start`-- `GET /container-stats`-- `GET /container-status`-- `POST /container-stop`-- `GET /container/disk`-- `GET /container/env`-- `GET /container/logs`-- `GET /container/ports`-- `POST /container/restart`-- `POST /image-delete`-- `POST /volume-delete`--**Dock** (6)--- `GET /dock/apps`-- `POST /dock/close`-- `POST /dock/launch`-- `POST /dock/refresh`-- `POST /dock/reset`-- `POST /dock/result`--**Editor State Machine (ESM)** (4)--- `POST /editor/audit-prompt`-- `POST /editor/bars`-- `POST /editor/normalize`-- `GET /editor/state`--**Eval & Automation** (17)--- `POST /ai-cursor/click`-- `POST /ai-cursor/hide`-- `POST /ai-cursor/move`-- `POST /cdp-eval`-- `POST /click`-- `GET /devtools`-- `POST /devtools`-- `POST /eval`-- `POST /eval-in`-- `POST /files/inject`-- `POST /iframe-eval`-- `POST /mouse-click`-- `POST /query`-- `POST /reload-vscode`-- `GET /targets`-- `POST /vscode/command`-- `POST /vscode/hide-activity-items`--**Health & Build** (17)--- `GET /_manifest`-- `POST /app/relaunch-frontend`-- `POST /app/restart`-- `GET /buildinfo`-- `GET /cdp-info`-- `GET /console`-- `GET /diagnostics`-- `GET /diagnostics/all`-- `GET /doctor`-- `POST /doctor`-- `GET /health`-- `GET /logs/tail`-- `GET /ports`-- `GET /ports/all`-- `POST /ports/check`-- `POST /ports/set`-- `POST /report/problem`--**Hydrogen Browser Window** (9)--- `GET /hbw/chrome`-- `POST /hbw/chrome-toggle`-- `POST /hbw/close`-- `POST /hbw/nav`-- `POST /hbw/open`-- `GET /hbw/state`-- `GET /hbw/tip`-- `GET /hbw/tip-state`-- `POST /hbw/tooltip`--**Other** (5)--- `POST /annotate`-- `GET /favicon.ico`-- `GET /webview/frames`-- `POST /webview/link-intercepted`-- `GET /welcome.html`--**Permissions** (3)--- `POST /permission/dismiss`-- `POST /permission/request`-- `POST /permission/resolve`--**Screenshots & Recording** (9)--- `GET /capture/availability`-- `GET /capture/viewport`-- `GET /recording/native/capabilities`-- `GET /recording/native/sources`-- `POST /recording/native/start`-- `GET /recording/native/status`-- `POST /recording/native/stop`-- `POST /screenshot`-- `POST /shot`--**Settings** (2)--- `GET /settings/external-changes`-- `POST /settings/rebroadcast`--**Setup Cascade** (25)--- `GET /setup-status`-- `POST /setup/countdown`-- `GET /setup/flags`-- `POST /setup/flags`-- `POST /setup/force-close`-- `POST /setup/panel/hide`-- `POST /setup/panel/run-virgin-reset`-- `POST /setup/panel/set-virgin-options`-- `POST /setup/panel/show`-- `POST /setup/panel/show-virgin-reset`-- `POST /setup/panel/virgin/hide`-- `POST /setup/panel/virgin/show`-- `POST /setup/panel/wipe-keep-auth`-- `POST /setup/run-all`-- `POST /setup/run-step`-- `GET /setup/screenshot-mode`-- `POST /setup/screenshot-mode`-- `GET /setup/state`-- `POST /setup/state`-- `POST /setup/step`-- `DELETE /setup/trigger`-- `GET /setup/trigger`-- `POST /setup/virgin-reset`-- `POST /virgin-reset`-- `GET /virgin-reset-progress`--**System** (6)--- `GET /adom-port-hints`-- `POST /adom-port-hints`-- `POST /system/cancel-reboot`-- `GET /system/nonce`-- `POST /system/reboot`-- `GET /system/reboot-state`--**Test & Dev** (13)--- `POST /debug/show-auth-caption`-- `POST /debug/zorder-probe`-- `POST /dev/emit-event`-- `POST /test/click-uia`-- `POST /test/dump-state`-- `POST /test/focus`-- `GET /test/help`-- `GET /test/install-steps`-- `GET /test/probe-dialogs`-- `POST /test/reset-cascade`-- `POST /test/screenshot-hd-window`-- `GET /test/setup-steps`-- `GET /test/window-tree`--**UI & Windows** (14)--- `POST /api-explorer/open`-- `POST /demo/run`-- `POST /panel-webview/fullscreen`-- `GET /panes/memory`-- `POST /panes/reload-errors`-- `POST /ui/_bus-pong`-- `POST /ui/_result`-- `POST /ui/_sync`-- `GET /ui/actions`-- `POST /ui/invoke`-- `POST /ui/toast`-- `POST /ui/toast-ack`-- `POST /window/close`-- `POST /window/foreground`--**Wake & Repair** (5)--- `POST /wake/config`-- `POST /wake/preview`-- `POST /wake/preview/hide`-- `POST /wake/simulate`-- `GET /wake/status`--**Widgets** (7)--- `GET /widgets`-- `POST /widgets/close`-- `POST /widgets/menu`-- `POST /widgets/navigate`-- `POST /widgets/open`-- `POST /widgets/refresh`-- `GET /widgets/status`--**Workspace & Updates** (37)--- `POST /migration/approved`-- `POST /migration/dismissed`-- `POST /updater/check`-- `POST /updater/install`-- `POST /updater/show-banner`-- `GET /updater/status`-- `POST /workspace/apply-updates`-- `POST /workspace/check-updates`-- `POST /workspace/exec`-- `GET /workspace/health`-- `POST /workspace/migration/approve`-- `POST /workspace/migration/decline`-- `GET /workspace/stats`-- `GET /workspace/tabs`-- `POST /workspace/tabs`-- `GET /workspace/tabs/`-- `POST /workspace/tabs/`-- `GET /workspace/tabs/find`-- `POST /workspace/terminal-profile`-- `POST /workspace/terminal-profile/remove`-- `POST /workspace/vscode-settings`-- `POST /workspaces/apply`-- `GET /workspaces/benches`-- `POST /workspaces/demo`-- `POST /workspaces/menu`-- `POST /workspaces/offer`-- `POST /workspaces/refresh`-- `POST /workspaces/reset`-- `POST /workspaces/save`-- `GET /workspaces/status`-- `POST /workspaces/unload`-- `GET /wsl/gui`-- `POST /wsl/gui`-- `GET /wsl/status`-- `POST /wsl/unregister`-- `GET /wsl/wedge`-- `POST /wsl/wedge-repair`--**Workspace control** (~30 routes, a SEPARATE server on the proxy port, absent from `/_manifest`)--Reached at `/api/workspaces/editor/<owner>/<repo>/current/...`, which the handler strips-before matching. A bare `GET /tabs` on the proxy 404s; that is correct, not a fault.--- `/tabs`-- `/tabs/find`-- `/tabs/alert`-- `/active-tab`-- `/splits`-- `/swaps`-- `/moves`-- `/nav`-- `/reload`-- `/window-mode`-- `/caption`-- `/recording`-- `/screenshot`-- `/audio`-- `/sharing`-- `/notification`-- `/probe`--<!-- END GENERATED ROUTE INDEX -->