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
direct-api-SKILL.md+16−16@@ -16,7 +16,7 @@ Shipped in adom-desktop v1.8.25+. Requires the adom-desktop GUI to be running on | You are… | Use | |---|---| | A sibling Tauri app on the same Windows machine as adom-desktop, calling sync verbs like `server_add`, `bridge_list`, `hd_status`, `desktop_screenshot_window` | **Direct API.** One HTTP round-trip, ~5 ms, no process spawn. |-| Inside Adom Hydrogen's local Docker container, using the `adom-desktop` CLI | **Just use the CLI.** As of v1.8.27 it auto-detects the direct API at `host.docker.internal:47200` on every invocation and routes there transparently. Zero config in HD's container. The verb returns identical JSON to the cross-machine path. |+| Inside Adom Hydrogen's local Docker container, using the `adom-desktop` CLI | **Just use the CLI.** As of v1.8.27 it auto-detects the direct API at `host.docker.internal:47200` on every invocation and routes there transparently. Zero config in Hydrogen's container. The verb returns identical JSON to the cross-machine path. | | On the Windows host, running the `adom-desktop.exe` CLI directly | **Same — just use the CLI.** Auto-detects `127.0.0.1:47200` and routes through the direct API. ~60 ms warm per call vs ~150 ms for the relay path. | | Docker / Linux / cross-machine caller | The CLI `adom-desktop <verb>` (probe fails, falls through to the wss proxy → relay → GUI WS path — same behavior as v1.8.26 and earlier). | | A sibling app needing `pull_file`, `send_files`, or `shell_execute` | Spawn the CLI binary. The direct API refuses these with `errorCode:"cli_required"`. The CLI itself handles the fallback automatically when called. |@@ -173,7 +173,7 @@ The CLI dispatcher honors `args.timeout` the same way, so the two paths stay sym ## What the user sees in the GUI Activity Log -Each `POST /command` call shows up in adom-desktop's Activity Log panel with a `direct:47200` badge (the port-explicit "server name" the dispatcher attaches to direct-API calls) plus the verb's normal event tag (`desktop`, `kicad`, `hd`, etc.). This is visually distinct from the `localhost` badge attached to WS-relay traffic going through the localhost dev server at `ws://localhost:8865`.+Each `POST /command` call shows up in adom-desktop's Activity Log panel with a `direct:47200` badge (the port-explicit "server name" the dispatcher attaches to direct-API calls) plus the verb's normal event tag (`desktop`, `kicad`, `hydrogen`, etc.). This is visually distinct from the `localhost` badge attached to WS-relay traffic going through the localhost dev server at `ws://localhost:8865`. At startup, a single `direct-api` event-tagged entry says "direct-api listening on http://127.0.0.1:47200 (loopback-only). Sibling apps can POST /command without spawning the CLI." If the bind ever fails (port taken), the user sees a corresponding error entry — no silent failure. @@ -185,9 +185,9 @@ At startup, a single `direct-api` event-tagged entry says "direct-api listening ## Reference integration: Adom Hydrogen startup -This is the canonical pattern HD uses to register its container relay with adom-desktop at boot.+This is the canonical pattern Hydrogen uses to register its container relay with adom-desktop at boot. -### Rust (HD's `src-tauri/src/lib.rs` or equivalent)+### Rust (Hydrogen's `src-tauri/src/lib.rs` or equivalent) ```rust use serde_json::json;@@ -214,7 +214,7 @@ async fn register_with_adom_desktop(workspace_name: &str, relay_url: &str) -> Re if !healthy { // adom-desktop not running. Either tell the user to launch it, // or shell out to the CLI as the legacy fallback. Don't block- // HD startup.+ // Hydrogen startup. log::warn!("adom-desktop not reachable on 127.0.0.1:47200 — relay will not be auto-registered"); return Ok(()); }@@ -250,7 +250,7 @@ async fn register_with_adom_desktop(workspace_name: &str, relay_url: &str) -> Re } ``` -### TypeScript (HD's frontend, if it ever calls directly)+### TypeScript (Hydrogen's frontend, if it ever calls directly) ```typescript async function registerWithAdomDesktop(name: string, url: string): Promise<boolean> {@@ -285,24 +285,24 @@ curl -X POST http://127.0.0.1:47200/command \ If adom-desktop has already exited, the connection refuses — that's fine, the server entry is stale either way. Treat shutdown registration cleanup as best-effort. -## Embedded-mode integration (HD bundling AD, v1.8.42+)+## Embedded-mode integration (Hydrogen bundling AD, v1.8.42+) -When HD bundles AD, the direct API is the channel for HD's tray menu items and runtime control. HD spawns AD with `--embedded --start-hidden --relay-url ... --session-token ...`, then drives it via these direct-API calls:+When Hydrogen bundles AD, the direct API is the channel for Hydrogen's tray menu items and runtime control. Hydrogen spawns AD with `--embedded --start-hidden --relay-url ... --session-token ...`, then drives it via these direct-API calls: -| HD action | direct-API envelope |+| Hydrogen action | direct-API envelope | |---|---| | "Open Adom Desktop" tray menu item | `{app:"desktop", command:"window_show"}` | | Hide AD's window again | `{app:"desktop", command:"window_hide"}` | | "Connect All" / "Disconnect All" tray items | `{app:"desktop", command:"connect_all"}` / `disconnect_all` |-| HD's "Quit" menu (cascade-stops AD) | `{app:"desktop", command:"shutdown"}` |-| HD sign-out propagation | `{app:"desktop", command:"logout"}` |+| Hydrogen's "Quit" menu (cascade-stops AD) | `{app:"desktop", command:"shutdown"}` |+| Hydrogen sign-out propagation | `{app:"desktop", command:"logout"}` | | Introspect embedded state | `{app:"desktop", command:"embedded_status"}` | | Force permanent shell auto-approve | `{app:"desktop", command:"set_shell_auto_approve", args:{permanent:true}}` | -`embedded_status` returns `{embedded, owner, source, pendingRelayUrl, pendingRelayName, startHidden, markerPath, markerExists}` — useful for HD's tray to know whether AD already booted embedded or it's running standalone.+`embedded_status` returns `{embedded, owner, source, pendingRelayUrl, pendingRelayName, startHidden, markerPath, markerExists}` — useful for Hydrogen's tray to know whether AD already booted embedded or it's running standalone. ```typescript-// HD's tray-click handler — example+// Hydrogen's tray-click handler — example async function openAdomDesktop() { await fetch('http://127.0.0.1:47200/command', { method: 'POST',@@ -312,7 +312,7 @@ async function openAdomDesktop() { } ``` -Note: HD typically calls `set_shell_auto_approve {permanent: true}` only as a recovery path — AD already defaults to permanent at embedded boot. Use it when toggling user-controlled preferences (e.g. an HD setting like "Auto-approve AD shell commands ON/OFF").+Note: Hydrogen typically calls `set_shell_auto_approve {permanent: true}` only as a recovery path — AD already defaults to permanent at embedded boot. Use it when toggling user-controlled preferences (e.g. an Hydrogen setting like "Auto-approve AD shell commands ON/OFF"). ## What about verbs not in the directApi list? @@ -328,7 +328,7 @@ The `cliRequired` array in `GET /status` lists the verbs that need the CLI binar | `kicad` | **stripped** — drop the `kicad_` prefix | `kicad_open_board` → `{app:"kicad", command:"open_board"}` | | `fusion360` | **stripped** — drop the `fusion_` prefix | `fusion_start` → `{app:"fusion360", command:"launch"}` (note: also the verb name shifts internally) | | `browser` | **kept** — pup bridge dispatches on the full name | `browser_open_window` → `{app:"browser", command:"browser_open_window"}` |-| `hd` | **stripped** — drop the `hd_` prefix | `hd_status` → `{app:"hd", command:"status"}` |+| `hydrogen` | **stripped** — drop the `hd_` prefix | `hd_status` → `{app:"hydrogen", command:"status"}` | | `dynamic` | full verb name with third-party bridge prefix preserved | (dispatcher routes by prefix) | Common direct-safe verb groups:@@ -336,7 +336,7 @@ Common direct-safe verb groups: | Namespace | Examples | Notes | |---|---|---| | `desktop` | `server_add`, `server_remove`, `server_list`, `bridge_list`, `bridge_install`, `bridge_pause`, `bridge_resume`, `desktop_list_windows`, `desktop_screenshot_window`, `desktop_open_url`, `set_shell_auto_approve` | All sync, no prefix stripping. |-| `hd` | `status`, `eval`, `log`, `screenshot`, `build`, `build_frontend`, `build_rust`, `build_status`, `build_log`, `build_tail`, `launch`, `stop`, `restart` | `build*` returns instantly with `{pid, logPath}`; poll `build_status` or `build_tail` for progress. |+| `hydrogen` | `status`, `eval`, `log`, `screenshot`, `build`, `build_frontend`, `build_rust`, `build_status`, `build_log`, `build_tail`, `launch`, `stop`, `restart` | `build*` returns instantly with `{pid, logPath}`; poll `build_status` or `build_tail` for progress. | | `kicad` | `list_versions`, `open_board`, `open_schematic`, `run_drc`, `lint_board`, `install_symbol`, ... | Multi-version-aware. | | `fusion360` | `launch`, `export_step`, `walk_cloud_tree`, `window_info`, `get_app_state`, ... | 50+ verbs. | | `browser` | `browser_open_window`, `browser_navigate`, `browser_screenshot`, `browser_eval`, `browser_click`, `browser_record_start` | Per-tab. **Keep the prefix.** |