# Adom Desktop — Verb Reference

This is the map of every verb a caller can invoke against Adom Desktop (AD). Callers are cloud AIs (via the relay), Hydrogen Desktop and other sibling apps (via the loopback direct API), bridges (delegating back into AD), and humans at the CLI.

> **This file is the map, not the spec.** The authoritative per-verb argument list and exact return shape live in `adom-desktop help <verb>` and in each verb's own `_hint` (which AD returns on bad/missing args, echoing the arg schema). `GET /commands` on the direct API and `adom-desktop help` are the *live* discovery surfaces — this document is generated from the CLI help-map (`cli/src/commands.rs`) and can lag a release.

## How to invoke

There are three transports; all three dispatch through the same code (`commands::handle_command`) and return the same JSON (same `success`/`ok`/`error` keys, same `_hint` fields).

| Transport | Who uses it | Shape |
|---|---|---|
| **CLI** | Humans; cloud AIs on a Docker container | `adom-desktop <verb> '<json args>'` — e.g. `adom-desktop desktop_screenshot_screen`, `adom-desktop kicad_open_board '{"filePath":"C:/x.kicad_pcb"}'` |
| **Direct API** (loopback) | HD + sibling Tauri apps on the same box | `POST http://127.0.0.1:47200/command` with `{command, args, target?}` — loopback-only, can't be reached off-box |
| **Relay** (WebSocket) | Cloud AIs reaching a Windows laptop cross-machine | The CLI's `desktop_command` path over `wss://…/proxy/8765/` |

### The `{app, command, args}` envelope

Every dispatch carries an optional `app` namespace, a `command` (the verb), and `args`.

- **`app` is OPTIONAL as of v1.9.84** — it's inferred from the command: `kicad_*`→`kicad`, `fusion_*`→`fusion360`, `browser_*`→`browser`, `hd_*`→`hd`, `aps_*`→`aps`, any installed bridge's prefix→`dynamic`, otherwise `desktop`. Pass `app` explicitly only to override the inference.
- **Desktop verbs**: the `desktop_` prefix is optional (`desktop_taskbar` == `taskbar`).
- **Bundled-bridge verbs** carry their prefix on the CLI (`kicad_*`, `fusion_*`, `browser_*`). Internally the direct API strips kicad/fusion prefixes but keeps browser's — the CLI verb name is what you use.
- **Third-party bridge verbs** route via `{app:"dynamic", command:"<full verb>"}` — see `bridge_list` for what's installed.

### Multi-AD targeting (`--target`)

One relay can hold several ADs (a laptop + an Azure VM …). Address one with the global flag **`--target <name>`** (case-insensitive; matches the AD's `clientName`, else hostname): `adom-desktop --target azurevm desktop_screenshot_screen`. `--target all` fans out to every connected AD and returns `{broadcast:true, results:{<name>:<result>}, summary}`. `ADOM_TARGET=<name>` sets a default (the flag wins). If **multiple** ADs are connected and you don't pass `--target`, the call fails with `error:"ambiguous_target"` + the connected names (it never guesses). Run `adom-desktop targets` to list names. On the direct API, `target` is a body field, and `notify_user`/`targets`/`ping` are reachable as top-level verbs (v1.9.84). `X-Adom-Bridge-Token` on a direct-API call is **attribution only** (badges the call "bridge" in the Activity Log) — never an approval gate.

### Approval gating (relay callers only)

Verbs that execute an arbitrary exe / write / delete / drive input / touch the registry are **gated for RELAY (cloud-AI) callers** — allowed only with a human "auto-approve shell" grant. HD and other loopback/local callers are trusted by transport and never gated. The Tier-2 gated set: `shell_execute`, `run_script`, the `wsl_*` exec verbs, `launch_process`, `write_file`, `delete_file`, `registry_set`, `registry_delete`, `process_kill`, and the SendInput/UIA action verbs (`desktop_click`, `desktop_type`, `desktop_ui_*` action verbs, …). Read verbs (`list_dir`, `read_file`, `registry_get`, `process_list`, `net_stats`, `desktop_ui_tree`, …) stay ungated.

---

## Connectivity & status

| Verb | What it does | Key args |
|---|---|---|
| `ping` | Round-trip connectivity test (5s). Run this first to verify the desktop link. | `message` (optional, echoed) |
| `status` | Connected clients, capabilities, and app-installation status (kicad/fusion/browser installed+running). Includes a `wsl` block (count + wedged flag). | — |
| `targets` | List the ADs connected to this relay so you can address one by `--target`. | — |
| `health` | Is the relay server's HTTP API reachable. | — |
| `timeouts` | The per-verb HTTP timeout registry: which long verbs get which budget + the `statusVerb` to poll. Every verb response also carries `timeoutSeconds`. | — |
| `kick_all` | Force-disconnect all WS clients (they auto-reconnect in ~5s). | — |
| `setup_desktop` | Generate installer URL + server-config JSON for first-time desktop setup. | — |

## Connection & servers

| Verb | What it does | Key args |
|---|---|---|
| `server_add` | Register a relay server connection (upsert by `name`); connects immediately by default. The programmatic form of the GUI Quick-Add box. | `name`*, `url`*, `authToken`, `autoConnect` |
| `server_remove` | Disconnect (if connected) + delete a server entry by name. Idempotent. | `name`* |
| `server_list` | The persisted server list with live connection status. | — |
| `desktop_connect_all` | Trigger "Connect All" for every enabled server entry. | — |
| `desktop_disconnect_all` | Drop every live WS connection (entries stay in config). | — |
| `register_container` | Register THIS cloud Docker container in the user's Adom Cloud profile so their laptop AD auto-discovers + connects after sign-in. Runs cloud-side only. | `name`*, `url`*, `id`, `auth_token`, `auto_connect`, `enabled` |
| `direct_api` | *Informational (not a verb)* — describes the loopback `http://127.0.0.1:47200` HTTP listener. | — |

## AD window & lifecycle

| Verb | What it does | Key args |
|---|---|---|
| `desktop_window_show` | Show + focus AD's main window (HD's tray "Open Adom Desktop"). | — |
| `desktop_window_hide` | Hide AD's main window; app keeps running. | — |
| `desktop_shutdown` | Graceful AD exit — stop bridges then exit (~500ms after the response). | — |
| `desktop_logout` | Clear AD's cached Adom Cloud session. | — |
| `desktop_embedded_status` | Is AD running embedded under HD; how it entered (`launch-flag` vs `runtime-adopt`). | — |
| `desktop_embedded_enter` | Runtime-adopt: switch a running standalone AD into embedded mode. | — |
| `desktop_embedded_release` | Revert to standalone (AD keeps running). | — |
| `relaunch_self` | Visible self-restart for dev iter — spawns `ad-relauncher.exe` (stop→deploy→launch→verify). | `sourceExe`, `destExe`, `port`, `noAutoStart` |
| `relauncher_status` | Poll the ad-relauncher's per-step progress + HOST/SANDBOX banner state. | — |

## Notifications

| Verb | What it does | Key args |
|---|---|---|
| `notify_user` | Native Windows toast (Adom logo). Rich types: progress bar, sticky reminder, action buttons that round-trip + foreground AD on click. | `title`*, `body`*, `level`, `scenario`, `buttons`, `actions`, `progress`, `inputs`, `id` |
| `notify_response` | Poll which toast button the user clicked, by correlation `id`. `{pending:true}` until they click. | `id`* |

## Desktop control (windows, files, registry, processes, input)

### Windows

| Verb | What it does | Key args |
|---|---|---|
| `desktop_list_windows` | Enumerate visible windows with HWNDs, titles, rects, and `z` (0 = topmost). | — |
| `desktop_find_window` | Resolve a window's hwnd by title/class in Z-order (best = topmost). | `titleContains`, `className` |
| `desktop_bring_to_front` | Bring a window to the foreground. | `hwnd`/`titleContains`, `state` |
| `desktop_set_window_state` | maximize / minimize / restore / show / hide without necessarily foregrounding. | `hwnd`/`titleContains`, `state`* |
| `desktop_set_window_bounds` | Move + resize a window to exact physical-pixel bounds (DPI-aware). | `hwnd`*, `x`*, `y`*, `w`*, `h`*, `restore` |
| `desktop_flash_window` | Flash a window's taskbar button (orange attention cue). | `hwnd`/`titleContains`, `mode`, `count`, `stop` |
| `desktop_taskbar` | Paint status on any window's taskbar button: progress bar + overlay badge + flash. | `hwnd`/`titleContains`, `flash`, `progress`, `overlay` |
| `desktop_set_window_identity` | Make any window present itself as a named app (AppUserModelID + icon + display name), so taskbar / Alt-Tab / hover / pins read your app, not the process that owns the HWND. Pass `relaunchCommand` to also brand the jump-list header row (ignored without it) and define what a taskbar pin launches. | `hwnd`/`titleContains`/`cacheKey`, `appId`*, `iconPath`, `displayName`, `relaunchCommand` |
| `desktop_register_app_identity` | Register that `appId` with Windows so it resolves to a name + icon (HKCU key + Start Menu shortcut; `shortcut:false` = registry-only, for transient per-session appIds — Alt-Tab resolves, no Start Menu entry). | `appId`*, `displayName`*, `iconPath`*, `shortcut`, `target`, `args`, `shortcutName` |
| `desktop_unregister_app_identity` | Remove a registration (registry key + any shortcut carrying the AUMID). Idempotent; unknown appId is a no-op ok. | `appId`* |
| `desktop_set_window_jumplist` | Native jump-list tasks on a taskbar button's right-click menu (per-AUMID, so per-session appIds get per-window menus). `tasks:[]` clears. | `appId`*, `tasks`* |
| `desktop_screenshot_window` | Capture a window by HWND (full + Claude-safe PNG). Also captures the window's OWNED popups as a `screenshots[]` array + a `coordMap` for zero-math image-space clicks. | `hwnd`*, `resizeMax` |
| `desktop_screenshot_screen` | Capture the whole desktop (all monitors); full + safe PNG + coordMap. | — |
| `desktop_show_ui` | Stage an in-window AD UI element (settings / build_info / …) so it can be screenshotted. | `target`*, `show` |
| `desktop_caption` | Large always-on-top click-through text overlay on the desktop (narration / demo labels). Auto-expires. | `text`, `id`, `position`, `size`, `duration`, `persist`, `action` |
| `desktop_cursor` | Show / glide / hide the teal "Adom cursor" overlay glyph (pure visual, ungated). | `action`, `x`, `y`, `label`, `ttlMs`, `persist` |

### Files, folders, browsers on the desktop

| Verb | What it does | Key args |
|---|---|---|
| `desktop_open_folder` | Open a file/folder in Windows Explorer. | `path`* |
| `desktop_open_url` | Open a URL in the user's NATIVE default browser (their logged-in Edge/Chrome/Firefox/Brave). Hand-off-to-human path — Claude can't drive it after. | `url`*, `browser`, `profile` |
| `desktop_list_browsers` | Catalog every installed native browser + its profiles + signed-in account (gaia). | — |
| `desktop_list_files` | List files in a dir matching a glob, optionally filtered by mtime. No shell. | `path`*, `glob`, `modifiedSince` |
| `desktop_watch_files` | Block until a file matching the glob appears (or timeout). The wait-for-download primitive. | `path`*, `glob`, `since`, `timeoutMs`, `pollMs` |
| `desktop_pull_glob` | list/watch → pull_file each match to a container path, in one call. | `path`*, `glob`, `since`, `saveTo`*, `wait`, `timeoutMs`, `pollMs` |
| `desktop_install_node` | Unattended Node.js LTS install via winget. Trigger on `browser_*` → `node_not_found`. | — |
| `desktop_install_kicad` | Unattended KiCad install via winget (~700 MB). Trigger on `kicad_not_installed`. | — |

### Synthetic OS input (SendInput — foreground; gated)

These are REAL OS input — they land on `chrome://` pages + native dialogs that browser CDP can't reach. Foreground (AD focuses the target first). Coords are physical screen pixels, or image-space via `space:"image"` + `shotId` from a screenshot's coordMap.

| Verb | What it does | Key args |
|---|---|---|
| `desktop_click` | Real OS left-click. | `x`*, `y`*, `space`, `shotId`, `button`, `double`, `window`/`hwnd`, `cursor`, `label` |
| `desktop_double_click` | Real OS double-click. | `x`*, `y`*, `window`/`hwnd` |
| `desktop_right_click` | Real OS right-click (opens context menus). | `x`*, `y`*, `window`/`hwnd` |
| `desktop_hover` | Move the real cursor without clicking (reveals tooltips). | `x`*, `y`*, `window` |
| `desktop_type` | Type a literal Unicode string into the focused control. | `text`*, `window`/`hwnd` |
| `desktop_press_key` | Send keyboard chords/shortcuts (`["ctrl+l"]`, `["ctrl","w"]`, sequences). | `keys`*, `repeat`, `window`/`hwnd` |
| `desktop_clipboard_set` | Put text on the clipboard in the background (native). | `text`*, `returnPrior` |
| `desktop_clipboard_get` | Read the clipboard text in the background. | — |

## UI Automation (background — no focus steal)

UIA drives a window's controls PROGRAMMATICALLY (Invoke / SetValue / Toggle) with **no foreground, no focus steal, no cursor move**. Chromium/Edge expose their a11y tree, so `chrome://`/`edge://` buttons are reachable by accessible name. Every verb returns a `foreground` block (`{predicted, observed (measured), raised, pathTaken, reason}`) so you know before+after whether a call stole the screen. Read verbs are ungated; action verbs are gated (they fall back to a foregrounding SendInput click only when a control exposes no pattern). Shared selector: `{hwnd|window}` + `{name|contains|automationId|role|nth}` + `scope:"window"|"popups"|"subtree:<automationId>"`.

| Verb | What it does | Key args |
|---|---|---|
| `desktop_ui_tree` | READ: dump the accessibility subtree under a window (the "see the whole controllable surface" verb). | `window`/`hwnd`, `scope`, `maxDepth`, `roleFilter`, `nameContains`, `maxNodes` |
| `desktop_ui_from_point` | READ: the control under a pixel (screen or image space). | `x`*, `y`*, `space`, `shotId` |
| `desktop_find_control` | READ: find the best single control by name/id/role + report if it's background-actionable + its screen rect. | `window`/`hwnd`, `name`/`contains`/`automationId`, `role`, `scope` |
| `desktop_find_controls` | READ: ALL controls matching the selector (array, with `nth` indices). | `window`/`hwnd`, selector, `scope`, `maxResults` |
| `desktop_ui_text` | READ: text of a document/edit control (TextPattern). | selector, `range` |
| `desktop_ui_get` | READ: a control's value/state — Value, ToggleState, RangeValue, selected, ExpandState. | selector |
| `desktop_ui_grid_get` | READ: GridPattern dims + a cell. | selector, `row`, `col` |
| `desktop_ui_click` | Invoke a control by accessible name (background). | `window`/`hwnd`, `name`/`contains`, `role`, `scope` |
| `desktop_ui_set` | SetValue on a text field by name; optional focus-neutral `submit` (Enter + restore prior foreground). | `window`/`hwnd`, `name`/`contains`, `text`*, `submit`, `noRaise`, `scope` |
| `desktop_ui_toggle` | Toggle a checkbox/switch (TogglePattern), or set to a state. | selector, `state` |
| `desktop_ui_expand` | Expand/collapse a tree node or combobox. | selector, `action` |
| `desktop_ui_select` | Select a list item / tab / radio (SelectionItemPattern). | selector, `action` |
| `desktop_ui_scroll` | Scroll a region, or bring an item into view. | selector, `dir`, `amount` |
| `desktop_ui_set_range` | Set a slider/spinner value (RangeValuePattern). | selector, `value`* |
| `desktop_ui_focus` | SetFocus to a control (often raises the window — check `foreground.raised`). | selector |
| `desktop_ui_window` | Window ops via WindowPattern/TransformPattern: minimize/maximize/restore/close/move/resize. | `window`/`hwnd`, `action`*, `x`,`y`,`w`,`h` |
| `desktop_navigate` | Open a URL in a browser window's active tab FOCUS-NEUTRALLY (omnibox SetValue + commit + restore prior foreground). Honest `navigated` signal. | `window`/`hwnd`, `url`*, `noRaise` |
| `desktop_ui_capabilities` | READ: the foreground-hint TABLE for every UIA verb — consult before acting to know if a call steals the screen. | — |
| `desktop_ui_selftest` | Write the capability table; with `{confirm:true, window}` empirically measures foreground against a throwaway control. | `confirm`, `window`/`hwnd` |
| `desktop_ui_watch` | Subscribe to a UIA event stream (focus / window-opened / invoke / …), get a `watchId`. React instead of poll. | `event`*, `window`/`hwnd`, `properties` |
| `desktop_ui_events` | DRAIN buffered UIA events past `sinceSeq` (poll cursor); lists active watches. | `sinceSeq`, `watchId`, `max` |
| `desktop_ui_unwatch` | Stop one watch or all. | `watchId`* |

## Shell & scripts (gated for relay callers)

| Verb | What it does | Key args |
|---|---|---|
| `shell_execute` | Run a shell command on the desktop (`cmd /c` / `sh -c`). Escape hatch — prefer a structured verb when one exists. | `command`*, `cwd`, `timeoutSeconds`, `allowPopupRisk` |
| `shell_kill_all` | Kill all running shell command processes. | — |
| `shell_auto_approve` | Enable/revoke shell auto-approve. `permanent:true` = the durable Settings checkbox; `duration_secs` = session grant; `0` revokes. | `duration_secs`, `permanent` |
| `desktop_revoke_approvals` | Clear all shell auto-approve + deny pending approvals. | — |
| `run_script` | Run a script via `cmd`/`powershell`/`node`/`python`/`bash` from a plain BODY string (system verb) OR base64 (shell verb) — no inline-quoting hell. | `interpreter`*, `body`/`scriptB64`*, `args`, `cwd`, `timeoutMs`/`timeoutSeconds` |
| `launch` | Launch an exe by absolute path (verifies it exists first — no "Windows cannot find" dialog). | `path`*, `args`, `cwd`, `detached` |
| `find_exe` | Find an exe without launching (path / webdeploy glob / Start Menu .lnk / PATH). | `name`*, `searchPaths` |
| `launch_process` | Launch a detached process with an args ARRAY; returns its pid. Kill with `process_kill`. | `path`*, `args`, `env`, `cwd`, `window` |
| `watch` | Streaming wrapper for long searches (`fusion_walk_cloud_tree` / `fusion_search_cloud_files`) — emits JSON progress events. | `command`*, `args`*, `interval` |

### System file/registry/process verbs (structured — no shell quoting)

| Verb | What it does | Key args |
|---|---|---|
| `read_file` | Read a file in AD's context (utf8/base64; %VARS%/~ expand). | `path`*, `encoding` |
| `write_file` | Write a file in AD's context (parent dirs created). | `path`*, `content`*, `encoding`, `createDirs` |
| `delete_file` | Delete a file or directory (idempotent; `recursive` for non-empty dirs). | `path`*, `recursive` |
| `list_dir` | List a directory — structured entries (dirs first, then files). | `path`* |
| `registry_get` | Read a Windows registry value (plain key string). | `hive`, `key`*, `name` |
| `registry_set` | Set a registry value (creates the key path). | `hive`, `key`*, `name`, `value`*, `type` |
| `registry_delete` | Delete a value (name set) or a whole key+subtree (name omitted). | `hive`, `key`*, `name` |
| `process_list` | List processes with reliable commandLine (via CIM). | `nameFilter`, `pidFilter` |
| `process_kill` | Kill by pid (surgical) or name (all with that image); /F /T. | `pid`/`name` |
| `net_stats` | TCP/socket stats + per-pid socket counts + ephemeral-port headroom. | — |

### WSL

| Verb | What it does | Key args |
|---|---|---|
| `wsl_exec` | Execute a base64 bash script inside a WSL distro (`wsl -d <distro> -u <user> -- bash -lc …`). Sync. | `distro`*, `user`*, `scriptB64`*, `timeoutSeconds` |
| `wsl_exec_async` | Held-session async sibling for multi-minute work — spawns detached, streams to a log, returns a `jobId` instantly. | `distro`*, `user`*, `scriptB64`*, `viaRoot` |
| `wsl_job_status` | Poll an async WSL job (running/done/exitCode + `outputTail`). | `jobId`*, `tailBytes` |
| `wsl_job_list` | List in-memory async WSL jobs. | — |
| `wsl_job_kill` | Stop a running async WSL job (kills its held wsl.exe). | `jobId`* |
| `wsl_list` | List installed WSL distros (`wsl -l -v`, parsed). | — |
| `wsl_import` | Import a tarball as a NEW named WSL2 distro (async → `jobId`). | `distro`*, `installDir`*, `tarball`*, `version` |
| `wsl_export` | Export a named distro to a tarball/.vhdx (async → `jobId`). | `distro`*, `tarball`*, `vhd` |
| `wsl_unregister` | DELETE one named distro (async; refuses `Adom-Workspace`). | `distro`* |
| `wsl_recover` | Reap orphaned/runaway `wsl.exe` clients when WSL is wedged. DRY-RUN by default. | `confirm`, `sparePids` |

## Files & transfer (require the CLI)

These stream binary/base64 and are refused by the direct API (`errorCode:"cli_required"`).

| Verb | What it does | Key args |
|---|---|---|
| `send_files` | Send files from a container to the desktop (Downloads, or `dest`). Up to ~190 MB/batch. | `filePaths`*, `targetApp`, `destinationFolder`, `dest` |
| `pull_file` | Pull files from the desktop back to the container (1 MiB binary frames, sha256-verified). Honors `--target`. | `filePaths`*, `saveTo` |
| `hd_send_files` | Send files DIRECTLY into HD's WSL2 project (correct ownership + no /mnt/c cache-lag). | `filePaths`*, `subdir` |

## Bridges — lifecycle & management

| Verb | What it does | Key args |
|---|---|---|
| `bridge_list` | List every installed bridge (bundled + third-party): version, source, ports, verb prefixes, `skillPkg`/`installSkill`. | — |
| `bridge_info` | Rich detail for ONE bridge (alias `bridge_detail`) + `logTail`, resolved ports, full verb list, `manifestUrl`. | `name`* |
| `bridge_readiness` | READ-ONLY readiness probe across every bridge — "what EDA tools do I have / are they ready" (never spawns/installs). | — |
| `bridge_check_updates` | READ-ONLY: current-vs-wiki-latest version per bridge + whether an update is available. | — |
| `bridge_install` | Install a bridge from a wiki manifest URL (download + sha256-verify + unzip into cache). | `manifestUrl`* |
| `bridge_uninstall` | Remove a bridge from the cache (bundled ones revert to the bundled fallback). | `name`* |
| `bridge_pause` / `bridge_resume` | Flip a bridge's routing flag off/on (process not killed). | `name`* |
| `bridge_stop_all` / `bridge_start_all` | Global bridge kill-switch off / on. | — |
| `bridge_kill` | Kill all of one bridge's tracked processes (re-spawns on next routed verb). | `name`* |
| `restart_bridge` | Kill + respawn a bridge in one call, from the current cache, on the same stable port. | `name`* |
| `bridge_log_read` | Read / stream a bridge's startup+runtime log (`tail -f` via `sinceOffset`). | `name`*, `tailLines`, `sinceOffset`, `maxBytes` |
| `refresh_bridges` | Force an immediate wiki sync of the bridge cache (one bridge or all). | `name` |
| `refresh_heroes` | Force-refresh only the bridge ART cache (hero images + wiki meta). | `name` |
| `sync_skills` | Reconcile the container's `~/.claude/skills/` with the connected desktop's bridges (installs each bridge's skill pkg). | — |
| `runtimes` | READ-ONLY: AD-managed portable runtime (Node/Python) status. | — |

## KiCad (`kicad_*`)

Forwarded to the KiCad bridge. Multiple KiCad versions coexist — every `open_*` accepts an optional `kicadVersion` (default = newest).

| Verb | What it does | Key args |
|---|---|---|
| `kicad_list_versions` | List installed KiCad versions with paths. | — |
| `kicad_open_board` | Open a `.kicad_pcb` in the PCB editor. | `filePath`*, `kicadVersion` |
| `kicad_open_schematic` | Open a `.kicad_sch` in the schematic editor. | `filePath`*, `kicadVersion` |
| `kicad_open_symbol_editor` | Open the Symbol Editor. | `symbolName`, `libraryName`, `kicadVersion` |
| `kicad_open_footprint_editor` | Open the Footprint Editor. | `footprintName`, `libraryName`, `kicadVersion` |
| `kicad_open_3d_viewer` | Open the 3D viewer (board or footprint). | `editor`, `kicadVersion` |
| `kicad_close_symbol_editor` / `kicad_close_footprint_editor` / `kicad_close_3d_viewer` | Close that sub-editor window. | — |
| `kicad_close` | Close all KiCad windows. | — |
| `kicad_install_library` | Install a symbol/footprint library into a version's lib table. | `libraryPath`*, `libraryType`*, `libraryName`, `kicadVersion` |
| `kicad_install_symbol` | Decode a base64 symbol, install it as a library, open the editor. | `fileName`*, `fileContent`*, `kicadVersion` |
| `kicad_run_drc` | Headless Design Rule Check on a PCB via kicad-cli (structured JSON). | `filePath`*, `kicadVersion` |
| `kicad_run_erc` | Headless Electrical Rule Check on a schematic. | `filePath`* |
| `kicad_lint_board` | Pre-flight lint a `.kicad_pcb` (file-format + DRC + schematic-parity + tiered hint). Use before opening. | `filePath`*, `schematicParity` |
| `kicad_lint_schematic` | Pre-flight lint a `.kicad_sch` (file-format + ERC). Use before opening. | `filePath`* |
| `kicad_lint_library` | Validate a library file/dir before install (S-expression parse; detects outdated formats). | `libraryPath`* |
| `kicad_format_upgrade` | Upgrade a KiCad file to the current format (mutates in place). | `filePath`*, `kind`, `force` |
| `kicad_fix_keyboard` | Release stuck modifier keys + unlock foreground focus. | — |
| `kicad_window_info` | List all KiCad windows with HWNDs + rects. | — |
| `kicad_screenshot_all` | Screenshot all KiCad windows in one shot (array). | — |
| `kicad_send_key` | Send a keystroke / modifier combo to a KiCad window. | `key`*, `hwnd` |
| `kicad_click` | Click at coordinates (relative 0.0–1.0 by default). | `hwnd`*, `x`*, `y`*, `relative` |
| `kicad_bridge_status` | Enumerate running KiCad processes that have the reverse-bridge plugin loaded. | `exeName`, `pid`, `pruneStale` |
| `kicad_bridge_call` | Generic RPC passthrough into the in-KiCad plugin (board graph, exports, library nav, DRC trigger, net topology). | `exeName`*, `method`*, `params`, `timeout`, `pid` |
| `kicad_install_plugin` | (Re)deploy the reverse-bridge plugin to every detected KiCad version. | `force` |
| `kicad_open_editors` | Cross-process inventory of every open KiCad editor frame (via the bridge, not screen scraping). | — |

## Fusion 360 (`fusion_*`) + APS (`aps_*`)

Two-tier: the bridge handles launch/detection; the AdomBridge add-in handles exports/queries inside Fusion. Workflow: `fusion_start` → open a file → work → `fusion_close`.

### Lifecycle & documents

| Verb | What it does | Key args |
|---|---|---|
| `fusion_start` | First-class Fusion startup (glob-discover, verify, launch, wait for add-in, dismiss blocking dialogs). Idempotent. | `timeoutSeconds`, `dismissBlockingDialogs` |
| `fusion_dismiss_blocking_dialogs` | Escape every known blocking/picker modal until the add-in is responsive. Call on `fusion_addin_not_responding`. | `maxAttempts`, `extraPatterns` |
| `fusion_close_window` | Close a specific Fusion dialog by WM_CLOSE. | `hwnd`* |
| `fusion_close` | Close Fusion gracefully. | — |
| `fusion_get_app_state` | Open documents, active workspace, Electronics status. (The `statusVerb` to poll on timeouts.) | — |
| `fusion_document_info` | Open document tabs + cloud metadata for the active doc. | — |
| `fusion_activate_document` | Switch to an open document tab by name/type. | `name`, `documentType` |
| `fusion_close_document` | Close a document without the save dialog. | `name`, `save` |
| `fusion_close_all_documents` | Close all open documents. | `saveChanges` |

### 3D CAD

| Verb | What it does | Key args |
|---|---|---|
| `fusion_import_step` | Import STEP/STL/IGES/SAT/OBJ/F3D into Fusion. | `filePath`* |
| `fusion_export_step` / `_stl` / `_3mf` / `_f3d` / `_usdz` / `_iges` / `_sat` | Export the active 3D design in that format. (Some formats — fbx/dxf/dwg/obj/skp — are dialog-only and unavailable via API; the verb notes the substitute.) | `outputPath`* |
| `fusion_get_design_info` | Active design metadata (bodies, components). | — |
| `fusion_get_parameters` / `fusion_set_parameter` | List / modify user parameters. | (`set`: `name`*, `value`*) |
| `fusion_take_screenshot` | Capture the viewport as PNG with camera-orientation control (render API). | `outputPath`*, `width`, `height`, `orientation` |

### Electronics (EAGLE-in-Fusion)

| Verb | What it does | Key args |
|---|---|---|
| `fusion_open_lbr` / `fusion_open_schematic` / `fusion_open_board` | Open a `.lbr` / `.sch` / `.brd` in the matching editor. | `filePath`* |
| `fusion_open_electronics` | Check whether the Electronics workspace is active. | — |
| `fusion_show_3d_board` / `fusion_show_2d_board` | Switch between 3D PCB view and 2D board layout. | — |
| `fusion_electron_run` | Execute an EAGLE command (WINDOW FIT, RATSNEST, DRC …). Fire-and-forget. | `command`* |
| `fusion_execute_text_command` | Low-level `app.executeTextCommand()`. | `command`* |
| `fusion_board_info` | Structured board data: components, nets, traces, DRC violations. | — |
| `fusion_export_source` | Export the active electronics doc as native `.fsch`/`.fbrd`/`.flbr`. | `outputPath`* |
| `fusion_export_eagle_source` | Export as plain EAGLE `.sch`/`.brd` XML. | `outputPath`* |
| `fusion_export_lbr` | Export a library as a `.scr` script. | `outputPath` |
| `fusion_import_electronics` | Import a native `.fsch`/`.fbrd`/`.flbr` as a new local project. | `filePath`* |
| `fusion_list_text_commands` | List available EAGLE text commands in context. | — |

### Cloud files + APS

| Verb | What it does | Key args |
|---|---|---|
| `fusion_save_to_cloud` | Save the active document to the Fusion cloud. | `name`*, `projectName`, `folderPath`, `description` |
| `fusion_list_cloud_projects` | List cloud projects in the user's hub. | — |
| `fusion_list_cloud_files` | List files + subfolders in a cloud project/folder. | `projectName`, `folderPath` |
| `fusion_create_cloud_folder` | Create a folder (idempotent). | `folderName`*, `projectName`, `parentPath` |
| `fusion_walk_cloud_tree` | BFS-walk a cloud folder tree → flat folders + files with paths. | `projectName`, `folderPath`, `maxDepth`, `maxFolders`, `extensions`, `nameContains`, `includeFiles` |
| `fusion_search_cloud_files` | Folder-walking cloud search by name substring (slow — Autodesk API limitation). Prefer `aps_search`. | `query`*, `projectName`, `folderPath`, `recursive`, `maxDepth`, `maxFolders`, `maxResults`, … |
| `fusion_check_recovery` | Check whether a cloud file has crash-recovery data (before opening). | `fileName`*, `projectName`, `folderPath` |
| `fusion_open_cloud_file` | Open a cloud file by name (stops if recovery exists → specify `recovery`). | `fileName`*, `projectName`, `folderPath`, `recovery` |
| `fusion_export_cloud_file` | Export the active doc to a local file (step/stl/f3d/…). | `outputPath`*, `format` |
| `fusion_delete_cloud_file` | Delete a cloud file (must not be open). | `fileName`*, `projectName`, `folderPath` |
| `aps_search` | FAST indexed cloud search via Autodesk Platform Services (server-side index; works with Fusion closed). | `query`*, `projectName`, `projectId`, `hubId` |
| `aps_status` | Is native APS search available (configured + signedIn)? Call first to pick aps vs folder-walk. | — |
| `aps_auth` | Interactive Autodesk sign-in (system browser, PKCE OAuth; one-time). | — |
| `aps_hubs` / `aps_projects` | List APS hubs (teams) / projects in a hub. | (`projects`: `hubId`) |

### Recovery, manufacturing, UI

| Verb | What it does | Key args |
|---|---|---|
| `fusion_dismiss_recovery` / `fusion_relocate_recovery` | Dismiss recovery dialogs / relocate recovery files to `~/.adom/recovery/`. | — |
| `fusion_detect_layers` | Auto-detect PCB copper layer count (2/4) via ULP + CAM. | — |
| `fusion_set_design_rules` | Apply Adom/JLCPCB `.edru` design rules (auto 2/4 layer). | `action`, `layers`, `outputPath` |
| `fusion_export_gerbers` | Export Gerber + Excellon drill as a fab-ready ZIP. | `outputDir`, `boardName`, `layers` |
| `fusion_export_bom` | Export the BOM as CSV (grouped by value+package). | `outputPath`, `grouped` |
| `fusion_export_cpl` | Export the pick-and-place / CPL as CSV. | `outputPath`, `side` |
| `fusion_export_board_image` | Export a PNG with layer presets (top_copper, assembly_top, fabrication…). | `outputPath`, `dpi`, `preset`, `layers`, `monochrome`, `listPresets` |
| `fusion_window_info` | Main window HWND/title/rect + all Qt dialogs. | — |
| `fusion_screenshot_fusion` | Screenshot the main window or a specific dialog. | `hwnd` |
| `fusion_screenshot_all` | Screenshot the main window + list all dialogs. | — |
| `fusion_click_fusion` | Click at coordinates in the window or a dialog (relative 0.0–1.0). | `x`*, `y`*, `relative`, `hwnd` |
| `fusion_send_key` | Send keyboard input to Fusion or a dialog (enter/escape/tab dismisses most). | `key`*, `hwnd` |

## Browser / Puppeteer (`browser_*`)

Drives PUPPETEER-controlled Chrome for Testing (isolated profile, no saved logins) — Claude drives it programmatically. (Contrast `desktop_open_url`, which opens the user's real logged-in browser for a human.) Auto-starts the bridge on first `browser_*` call.

| Verb | What it does | Key args |
|---|---|---|
| `browser_open_window` | Open a Chrome window at a URL (full-capability mode: scripted downloads + clipboard granted). | `sessionId`*, `url`*, `profile`*, `freshProfile`, `strictPermissions`, `downloadPath` |
| `browser_close_window` | Close a session's Chrome window (all its tabs). | `sessionId`* |
| `browser_navigate` | Navigate a tab to a new URL. | `sessionId`, `url`*, `tabId` |
| `browser_eval` | Evaluate JavaScript in page context. | `sessionId`, `expr`*, `tabId` |
| `browser_input_dispatch` | Dispatch TRUSTED input via CDP (`isTrusted=true`) — use when a click "lands but does nothing". | `type`*, `selector`/`x`/`y`, `text`, `key`, `sessionId`, `tabId`, … |
| `browser_fetch_url` | Fetch a URL with the session's cookies, raw bytes (bypasses Chrome's PDF-viewer wrapper). | `url`*, `sessionId`, `tabId`, `method`, `headers`, `body`, `saveTo`, `desktopSaveTo` |
| `browser_errors` | Console errors + failed network requests (optionally per-tab). | `sessionId`, `clear`, `tabId` |
| `browser_reload` | Reload the page + clear the error log. | `sessionId`, `tabId` |
| `browser_status` | All sessions: URLs, error counts, alive status. | — |
| `browser_close` | Close one session (with `sessionId`) or ALL sessions (no arg); bridge stays up. | `sessionId` |
| `browser_wait` | Wait for content to settle. | `ms` |
| `browser_list_windows` | List all open browser sessions with URLs + titles. | — |
| `browser_rescan` | Recover orphaned Chrome windows whose CDP socket dropped. | `adoptOrphans` |
| `browser_switch_window` | Switch the bridge's active session. | `sessionId`* |
| `browser_focus_window` | Bring a session's tab to front WITHIN Chrome (not the OS window). | `sessionId`* |
| `browser_raise_os_window` | Raise the OS window above all apps (do before recording so Chrome doesn't throttle). | `sessionId`* |
| `browser_lower_os_window` | Minimize the OS window hosting a session. | `sessionId`* |
| `browser_alert_window` | Flash the Chrome window's taskbar icon (no foreground steal). | `sessionId`* |
| `browser_open_tab` | Add a tab to an existing session (same Chrome window). | `sessionId`*, `url`* |
| `browser_switch_tab` | Make a specific tab the active one. | `sessionId`*, `tabId`* |
| `browser_close_tab` | Close one tab; the session + other tabs remain. | `sessionId`*, `tabId`* |
| `browser_list_tabs` | List all tabs incl. auto-tracked popups (`opener`/`openerTabId`). | `sessionId`* |
| `browser_screenshot` | Lossless PNG, auto-resized ≤1568px — safe to Read into Claude. | `sessionId`, `fullPage`, `maxWidth`, `tabId` |
| `browser_screenshot_full_res` | Full-resolution PNG (NO resize) — save/export only, do NOT Read. | `sessionId`, `fullPage`, `tabId` |
| `browser_record_start` | Record a tab (CDP screencast → single VP9 .webm). Raise the OS window first. | `sessionId`*, `tabId`, `fps`, `quality`, `maxDurationMs` |
| `browser_record_stop` | Stop a tab recording; muxes synchronously → a finished .webm. | `sessionId`, `recordingId`* |
| `browser_record_status` | Active tab recordings with live capture stats. | `sessionId` |
| `browser_record_list` | Completed recording .webm files on disk. | — |
| `credential_set` | Store HTTP Basic Auth creds for a host pattern (password → OS keychain). | `host`*, `username`*, `password`* |
| `credential_list` | List stored host patterns + usernames (never passwords). | — |
| `credential_delete` | Remove a credential entry by exact host pattern. | `host`* |

### Desktop recording (whole-screen / native window)

| Verb | What it does | Key args |
|---|---|---|
| `desktop_recorder_open` | Open the whole-desktop recorder HUD without starting a clip. | `reason`* |
| `desktop_record_start` | Start a WHOLE-DESKTOP recording (every pixel) via getDisplayMedia. Requires an explicit confirm. | `reason`*, `confirmDesktopNotTabRecording`*, `monitor`, `fps`, `audio`, … |
| `desktop_record_stop` | Stop the active desktop clip. | `recordingId` |
| `desktop_record_status` | HUD + active-clip status. | — |
| `desktop_record_list` | Completed desktop recordings on disk. | — |
| `desktop_recorder_close` | Close the HUD (ends the session). | — |
| `desktop_list_monitors` | List available monitors. | — |
| `desktop_record_window_start` | Native single-window recording via Windows Graphics Capture (no picker/banner, background-capturable). | `hwnd`/`titleContains`, `fps`, `codec` |
| `desktop_record_window_stop` | Finalize a WGC window recording → MP4 path. | `recordingId`* |
| `desktop_record_window_status` | Status of a WGC window recording. | `recordingId`* |

## Hydrogen Desktop (`hd_*`)

Built-in proxy handlers to HD's local control API (port discovered from `ports.json`, never hardcoded). When HD isn't running, these return a clean `{ok:false, error:"HD not running"}`.

| Verb | What it does | Key args |
|---|---|---|
| `hd_status` | Composed + relayed snapshot: `processPresent` / `controlApiReachable` / `embedded` (three orthogonal signals, churn-honest) + SHAs + narrative. | — |
| `hd_api` | Generic HTTP pass-through to any HD control endpoint (auto-discovers the port). | `method`, `path`*, `body`, `port` |
| `hd_log` | Tail HD's log file from disk (works even when HD is down). | `tail` |
| `hd_open_url` | Open a URL in a specific browser profile via HD's endpoint. | `url`*, `browser`, `profileDir` |
| `hd_browser_profiles` | Enumerate browsers + profiles HD detects. | — |
| `hd_screenshot` | Capture the HD window as a lossless PNG. | — |
| `hd_build` | Full HD rebuild (async: git pull → pnpm → cargo). Returns `{pid, logPath}`. | `show`, `lingerSecs` |
| `hd_build_frontend` / `hd_build_rust` | Frontend-only / Rust-only HD build (async). | `show`, `lingerSecs` |
| `hd_build_status` | Sync build-state probe (compiledCrates, relinkOnly, exeChanged, exeLocked+holderPids …). | — |
| `hd_build_log` / `hd_build_tail` | Full build log / streaming tail (`offset`→`newOffset`). | (`tail`: `offset`) |
| `hd_launch` | Start HD's debug binary detached (guards: build_in_progress / build_failed / already_running). | `killExisting` |
| `hd_stop` | Kill hydrogen-desktop.exe (`wasRunning` distinguishes killed vs nothing-to-do). | — |
| `hd_restart` | Stop + launch in one call. | — |
| `hd_ship` | Atomic "rebuild from the exact SHA I pushed + relaunch + verify it's running". | `expectSha`*, `clean` |
| `hd_shot` | Capture a named HD region (titlebar/vscode/setup-panel/…) → full + safe PNG, auto-pulled. | `region`*, `resizeMax`, `format` |

*Moved to the internal hd-dev build (public AD refuses with `verb_moved_to_hd_dev`, use `hd_api` as the workaround): `hd_eval`, `hd_iframe_eval`, `hd_reload_vscode`, `hd_container_exec`.*

## Tunnels & remote display

| Verb | What it does | Key args |
|---|---|---|
| `tunnel` | Generic TCP-over-the-relay tunneling — grouped verb: `open` \| `close` \| `list` \| `check` \| `rdp`. Both legs resolve to one `--target` machine + are verified before `ok`. | subcommand, `to`, `target`, `local`, `tunnelId`, `size`/`monitor`/`width`/`height` |
| `rdp` | Back-compat alias for `tunnel rdp`: open a verified tunnel + launch mstsc, sized to the laptop's real screen. | `to`*, `target`, `local`, `size`, `monitor`, `width`, `height` |
| `tunnel_close` | Alias for `tunnel close`: tear down a tunnel / one conn / all. | `tunnelId`/`local`/`connId`/`all` |
| `tunnel_list` | Alias for `tunnel list`: live tunnels with relay+desktop reconciliation; flags leaks. | — |
| `tunnel_check` | Alias for `tunnel check`: per-leg health (names the unhealthy leg). | `tunnelId`/`local` |
| `display` | This desktop's monitor geometry — bounds, work area, per-monitor DPI/scale, primary, virtual box. Powers display-aware RDP sizing. | — |

---

*Generated from `cli/src/commands.rs` (`list_commands()`) and `src-tauri/src/screenshot.rs` (`DESKTOP_COMMANDS`). For the authoritative arg schema + return shape of any verb, run `adom-desktop help <verb>` or read the `_hint` AD returns when you call it with bad args. `GET http://127.0.0.1:47200/commands` lists the machine-readable surface (desktop + bridge verbs) live.*
