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
Publish 1.8.172
6 files changed
+84−21
SKILL.md+33−3@@ -472,7 +472,7 @@ Bridges are AD's plugins (kicad, puppeteer, fusion360 ship bundled; others insta | `bridge_list` | Every installed bridge: `name`, `displayName`, `version` (what AD runs now), `source` (bundled / cache / third_party), `paused`, spawn kind, verbPrefixes. Start here. | | `bridge_check_updates` | **READ-ONLY.** Per bridge: `current` vs `latest` (wiki) + `updateAvailable`. Downloads nothing. The "what's behind?" probe. | | `refresh_bridges` | Apply updates. No args = sync ALL bridges from the wiki. `{"name":"kicad"}` = update just one. |-| `bridge_install` | Install a new third-party bridge from a wiki manifest URL (`{"manifestUrl":"…/<bridge>-bridge-manifest.json"}`). |+| `bridge_install` | Install a new third-party bridge from a wiki manifest URL (`{"manifestUrl":"…/<bridge>-bridge-manifest.json"}`). On `success:true` the **capsule appears in the AD GUI immediately** (no verb call needed; it's gray/idle until first use, then green). On `success:false` **nothing is registered and no capsule appears** — read `error` (a `read zip body`/`builder error` means the manifest's zip URL couldn't be fetched). Don't treat a parsed manifest as a completed install; confirm with `bridge_list`. The manifest `url` may be relative (resolved against the manifest's dir, v1.8.169+). | | `bridge_uninstall` | Remove a bridge (`{"name":"…"}`). Bundled ones revert to the bundled copy; third-party ones are fully removed. | | `bridge_pause` / `bridge_resume` | Flip a routing flag so a bridge's verbs fail-fast with `bridge_paused` (or resume). Does NOT kill the process. | @@ -527,8 +527,10 @@ Reference implementations: [`scripts/sample-bridges/hello-python/server.py`](../ - `send_files` -- Send files from the Docker container to the desktop. Files are base64-encoded in transit. - `filePaths`: array of absolute paths on the server - `targetApp`: "kicad", "fusion360", or "general"- - `destinationFolder`: **relative subfolder only** (e.g. `"kicad/symbols"`, `"fusion"`). The desktop app controls the base directory. **Absolute paths are rejected.**- - Returns `destinationPaths[]` with the absolute path of every saved file.+ - `dest`: **absolute** Windows path (under a safe root) to land the files exactly where you want (v1.8.148+). Prefer this when you know the target dir.+ - `destinationFolder`: **relative subfolder only** (e.g. `"kicad/symbols"`, `"fusion"`). The desktop app controls the base directory. **Absolute paths are rejected.** With neither `dest` nor `destinationFolder`, files land in the laptop's **Downloads** folder.+ - Returns `destinationPaths[]` with the absolute path of every saved file, plus (v1.8.168) `savedToDir` (the folder) and a rich `_hint`. **The files land on the LAPTOP (Windows host), not in your container** — verify with `list_dir`, pull one back with `pull_file`.+ - **`send_files` only COPIES bytes — it does NOT install or register a bridge.** Dropping bridge files with `send_files` will NOT make a capsule appear or verbs route. To add a bridge use `bridge_install '{"manifestUrl":"…/<bridge>-bridge-manifest.json"}'`, then confirm with `bridge_list`. - `pull_file` -- Pull files from the desktop to the container. - `filePaths`: array of absolute Windows paths on the desktop@@ -1416,6 +1418,34 @@ If you don't have the suffix handy, just ask the user. Or if the file you wanted - Example: `adom-desktop desktop_bring_to_front '{"titleContains": "Fusion"}'` - `desktop_set_window_state` -- Change a window's show state without bringing it to the foreground (or both, if combined with `desktop_bring_to_front`). Args: `hwnd` (int) OR `titleContains` (string), plus `state` (one of `"maximize"`, `"minimize"`, `"restore"`, `"show"`, `"hide"`). Use to ensure Fusion or KiCad windows are maximized for screenshots, or to hide noisy background windows during demos. - Example: `adom-desktop desktop_set_window_state '{"hwnd":133560,"state":"maximize"}'`++#### Real OS input — mouse + keyboard (v1.8.170+)++`desktop_click` / `desktop_double_click` / `desktop_right_click` / `desktop_hover` / `desktop_type` / `desktop_press_key` synthesize **real OS input via `SendInput`** — so they land on **`chrome://` pages and native dialogs that browser CDP (`nbrowser_*` / `browser_*`) cannot reach**. The verb names mirror the browser extension's `nbrowser_*` so the model transfers between in-page and whole-desktop driving.++- **Gated behind shell-auto-approve** (same risk class as `shell_execute` — keystrokes/clicks hit whatever is focused on the user's live machine). If it's off you get `errorCode:"input_not_approved"`; enable once with `adom-desktop shell_auto_approve '{"permanent":true}'`. Every action is written to the activity log.+- **Focus a window first** by passing `{window:"<title substring>"}` (alias `titleContains`) or `{hwnd:<int>}` — reuses `desktop_find_window`'s resolver, so input lands on the intended window, not whatever happened to be focused. Get the hwnd from `desktop_list_windows` / `desktop_find_window`.+- **Coords are physical screen pixels** — the same space as `desktop_list_windows` rects.++Verbs:+- `desktop_click {x, y, button?:"left"|"right"|"middle", double?, window?|hwnd?}` — left-click by default. `desktop_double_click` / `desktop_right_click` are wrappers; `desktop_hover` moves the cursor without clicking (reveals tooltips).+- `desktop_type {text, window?|hwnd?}` — types a literal Unicode string (`KEYEVENTF_UNICODE`, any keyboard layout).+- `desktop_press_key {keys:[...], repeat?, window?|hwnd?}` (alias `desktop_send_keys`) — chords/shortcuts. Modifiers `ctrl/alt/shift/win`; named keys `enter/tab/esc/space/backspace/delete/insert/home/end/pgup/pgdn/up/down/left/right/f1-f12`.++Canonical "navigate a browser to a URL" flow (works on `chrome://` where CDP can't):+```bash+adom-desktop desktop_press_key '{"keys":["ctrl+l"],"window":"Edge"}' # focus Edge + select the address bar+adom-desktop desktop_type '{"text":"edge://extensions","window":"Edge"}'+adom-desktop desktop_press_key '{"keys":["enter"],"window":"Edge"}'+```+For a control that isn't reachable by CDP/coords (e.g. the Reload button on `edge://extensions`, which lives in a shadow DOM), Tab-navigate to it then Enter: `desktop_press_key {"keys":["tab","tab","enter"]}`.++**Visual "Adom cursor" (v1.8.171+)** — a click-through teal cursor + a label that narrates what you're driving (trust cue; byte-faithful to the browser extension's cursor). Pure visual, *not* gated:+- `desktop_cursor {action:"show"|"move"|"hide", x, y, label}` — drive/narrate the cursor on its own ("watch me"). Returns the overlay `hwnd`.+- Or pass `cursor:true` + `label:"Clicking Reload"` on `desktop_click`/`desktop_double_click`/`desktop_right_click`/`desktop_hover` — AD glides the teal cursor to the target (narrating the label) *then* does the real click. Call `desktop_cursor {action:"hide"}` when the task is done.++(UIA named-control targeting — `desktop_find_control` / click-by-accessible-name — ships next.)+ - `desktop_flash_window` (v1.8.152+) -- Flash an **arbitrary** window's taskbar button orange (Win32 `FlashWindowEx`) as an "attention / ongoing activity" cue. Resolve the HWND with `desktop_list_windows` first. Args: `hwnd` (int) OR `titleContains` (string); `mode` (`"until_focused"` default — flashes until the user clicks the window; or `"count"`); `count` (int, `mode:"count"` only, default 3); `stop` (bool — clear an active flash). Returns `{ok, hwnd, title, mode}`. **Lightweight by design** (direct FlashWindowEx, no process spawn) so a bridge can call it after every verb. Distinct from the puppeteer bridge's `browser_alert_window`, which only flashes pup's OWN tracked windows — this flashes any window on the host. For progress + overlay-icon status, use `desktop_taskbar`. - Example: `adom-desktop desktop_flash_window '{"hwnd":133560}'` then `adom-desktop desktop_flash_window '{"hwnd":133560,"stop":true}'` to clear. - `desktop_taskbar` (v1.8.152+) -- Paint **glanceable status** on any window's taskbar button via `ITaskbarList3` (progress bar + overlay icon) + `FlashWindowEx`, so a bridge can show what the AI is doing on the **real app window it drives** (e.g. native-browser putting an "Adom is driving" badge + task progress on the Chrome/Edge button). Works on windows owned by **other processes**. Persistent COM (init once, reuse) — safe to tick progress frequently; no process spawn. Resolve the HWND via `desktop_list_windows`. Args (all channels optional; provide ≥1):
dist/linux/adom-desktop⋯ 1 unchanged line ⋯
package.json+5−3@@ -1,7 +1,8 @@ { "slug": "adom-desktop",- "version": "1.8.166",+ "version": "1.8.172", "type": "app",+ "hero": { "path": "docs/hero.png" }, "description": "Laptop bridge: file transfer, screenshots, notifications, KiCad + Fusion 360 control, real-Chrome (Puppeteer) automation, and Hydrogen Desktop proxy. One install gives Claude every desktop verb it needs.", "keywords": [ "adom-desktop",@@ -43,6 +44,7 @@ "uninstall.sh", "docs/**", "skills/**",- "dist/**"+ "dist/**",+ "version.json" ]-}+}
page.json+3−2@@ -1,6 +1,6 @@ { "slug": "adom-desktop",- "version": "1.8.166",+ "version": "1.8.172", "type": "app", "description": "Laptop bridge: file transfer, screenshots, notifications, KiCad + Fusion 360 control, real-Chrome (Puppeteer) automation, and Hydrogen Desktop proxy. One install gives Claude every desktop verb it needs.", "keywords": [@@ -43,7 +43,8 @@ "uninstall.sh", "docs/**", "skills/**",- "dist/**"+ "dist/**",+ "version.json" ], "visibility": "public", "org": "adom",
skills/adom-desktop/SKILL.md+33−3@@ -472,7 +472,7 @@ Bridges are AD's plugins (kicad, puppeteer, fusion360 ship bundled; others insta | `bridge_list` | Every installed bridge: `name`, `displayName`, `version` (what AD runs now), `source` (bundled / cache / third_party), `paused`, spawn kind, verbPrefixes. Start here. | | `bridge_check_updates` | **READ-ONLY.** Per bridge: `current` vs `latest` (wiki) + `updateAvailable`. Downloads nothing. The "what's behind?" probe. | | `refresh_bridges` | Apply updates. No args = sync ALL bridges from the wiki. `{"name":"kicad"}` = update just one. |-| `bridge_install` | Install a new third-party bridge from a wiki manifest URL (`{"manifestUrl":"…/<bridge>-bridge-manifest.json"}`). |+| `bridge_install` | Install a new third-party bridge from a wiki manifest URL (`{"manifestUrl":"…/<bridge>-bridge-manifest.json"}`). On `success:true` the **capsule appears in the AD GUI immediately** (no verb call needed; it's gray/idle until first use, then green). On `success:false` **nothing is registered and no capsule appears** — read `error` (a `read zip body`/`builder error` means the manifest's zip URL couldn't be fetched). Don't treat a parsed manifest as a completed install; confirm with `bridge_list`. The manifest `url` may be relative (resolved against the manifest's dir, v1.8.169+). | | `bridge_uninstall` | Remove a bridge (`{"name":"…"}`). Bundled ones revert to the bundled copy; third-party ones are fully removed. | | `bridge_pause` / `bridge_resume` | Flip a routing flag so a bridge's verbs fail-fast with `bridge_paused` (or resume). Does NOT kill the process. | @@ -527,8 +527,10 @@ Reference implementations: [`scripts/sample-bridges/hello-python/server.py`](../ - `send_files` -- Send files from the Docker container to the desktop. Files are base64-encoded in transit. - `filePaths`: array of absolute paths on the server - `targetApp`: "kicad", "fusion360", or "general"- - `destinationFolder`: **relative subfolder only** (e.g. `"kicad/symbols"`, `"fusion"`). The desktop app controls the base directory. **Absolute paths are rejected.**- - Returns `destinationPaths[]` with the absolute path of every saved file.+ - `dest`: **absolute** Windows path (under a safe root) to land the files exactly where you want (v1.8.148+). Prefer this when you know the target dir.+ - `destinationFolder`: **relative subfolder only** (e.g. `"kicad/symbols"`, `"fusion"`). The desktop app controls the base directory. **Absolute paths are rejected.** With neither `dest` nor `destinationFolder`, files land in the laptop's **Downloads** folder.+ - Returns `destinationPaths[]` with the absolute path of every saved file, plus (v1.8.168) `savedToDir` (the folder) and a rich `_hint`. **The files land on the LAPTOP (Windows host), not in your container** — verify with `list_dir`, pull one back with `pull_file`.+ - **`send_files` only COPIES bytes — it does NOT install or register a bridge.** Dropping bridge files with `send_files` will NOT make a capsule appear or verbs route. To add a bridge use `bridge_install '{"manifestUrl":"…/<bridge>-bridge-manifest.json"}'`, then confirm with `bridge_list`. - `pull_file` -- Pull files from the desktop to the container. - `filePaths`: array of absolute Windows paths on the desktop@@ -1416,6 +1418,34 @@ If you don't have the suffix handy, just ask the user. Or if the file you wanted - Example: `adom-desktop desktop_bring_to_front '{"titleContains": "Fusion"}'` - `desktop_set_window_state` -- Change a window's show state without bringing it to the foreground (or both, if combined with `desktop_bring_to_front`). Args: `hwnd` (int) OR `titleContains` (string), plus `state` (one of `"maximize"`, `"minimize"`, `"restore"`, `"show"`, `"hide"`). Use to ensure Fusion or KiCad windows are maximized for screenshots, or to hide noisy background windows during demos. - Example: `adom-desktop desktop_set_window_state '{"hwnd":133560,"state":"maximize"}'`++#### Real OS input — mouse + keyboard (v1.8.170+)++`desktop_click` / `desktop_double_click` / `desktop_right_click` / `desktop_hover` / `desktop_type` / `desktop_press_key` synthesize **real OS input via `SendInput`** — so they land on **`chrome://` pages and native dialogs that browser CDP (`nbrowser_*` / `browser_*`) cannot reach**. The verb names mirror the browser extension's `nbrowser_*` so the model transfers between in-page and whole-desktop driving.++- **Gated behind shell-auto-approve** (same risk class as `shell_execute` — keystrokes/clicks hit whatever is focused on the user's live machine). If it's off you get `errorCode:"input_not_approved"`; enable once with `adom-desktop shell_auto_approve '{"permanent":true}'`. Every action is written to the activity log.+- **Focus a window first** by passing `{window:"<title substring>"}` (alias `titleContains`) or `{hwnd:<int>}` — reuses `desktop_find_window`'s resolver, so input lands on the intended window, not whatever happened to be focused. Get the hwnd from `desktop_list_windows` / `desktop_find_window`.+- **Coords are physical screen pixels** — the same space as `desktop_list_windows` rects.++Verbs:+- `desktop_click {x, y, button?:"left"|"right"|"middle", double?, window?|hwnd?}` — left-click by default. `desktop_double_click` / `desktop_right_click` are wrappers; `desktop_hover` moves the cursor without clicking (reveals tooltips).+- `desktop_type {text, window?|hwnd?}` — types a literal Unicode string (`KEYEVENTF_UNICODE`, any keyboard layout).+- `desktop_press_key {keys:[...], repeat?, window?|hwnd?}` (alias `desktop_send_keys`) — chords/shortcuts. Modifiers `ctrl/alt/shift/win`; named keys `enter/tab/esc/space/backspace/delete/insert/home/end/pgup/pgdn/up/down/left/right/f1-f12`.++Canonical "navigate a browser to a URL" flow (works on `chrome://` where CDP can't):+```bash+adom-desktop desktop_press_key '{"keys":["ctrl+l"],"window":"Edge"}' # focus Edge + select the address bar+adom-desktop desktop_type '{"text":"edge://extensions","window":"Edge"}'+adom-desktop desktop_press_key '{"keys":["enter"],"window":"Edge"}'+```+For a control that isn't reachable by CDP/coords (e.g. the Reload button on `edge://extensions`, which lives in a shadow DOM), Tab-navigate to it then Enter: `desktop_press_key {"keys":["tab","tab","enter"]}`.++**Visual "Adom cursor" (v1.8.171+)** — a click-through teal cursor + a label that narrates what you're driving (trust cue; byte-faithful to the browser extension's cursor). Pure visual, *not* gated:+- `desktop_cursor {action:"show"|"move"|"hide", x, y, label}` — drive/narrate the cursor on its own ("watch me"). Returns the overlay `hwnd`.+- Or pass `cursor:true` + `label:"Clicking Reload"` on `desktop_click`/`desktop_double_click`/`desktop_right_click`/`desktop_hover` — AD glides the teal cursor to the target (narrating the label) *then* does the real click. Call `desktop_cursor {action:"hide"}` when the task is done.++(UIA named-control targeting — `desktop_find_control` / click-by-accessible-name — ships next.)+ - `desktop_flash_window` (v1.8.152+) -- Flash an **arbitrary** window's taskbar button orange (Win32 `FlashWindowEx`) as an "attention / ongoing activity" cue. Resolve the HWND with `desktop_list_windows` first. Args: `hwnd` (int) OR `titleContains` (string); `mode` (`"until_focused"` default — flashes until the user clicks the window; or `"count"`); `count` (int, `mode:"count"` only, default 3); `stop` (bool — clear an active flash). Returns `{ok, hwnd, title, mode}`. **Lightweight by design** (direct FlashWindowEx, no process spawn) so a bridge can call it after every verb. Distinct from the puppeteer bridge's `browser_alert_window`, which only flashes pup's OWN tracked windows — this flashes any window on the host. For progress + overlay-icon status, use `desktop_taskbar`. - Example: `adom-desktop desktop_flash_window '{"hwnd":133560}'` then `adom-desktop desktop_flash_window '{"hwnd":133560,"stop":true}'` to clear. - `desktop_taskbar` (v1.8.152+) -- Paint **glanceable status** on any window's taskbar button via `ITaskbarList3` (progress bar + overlay icon) + `FlashWindowEx`, so a bridge can show what the AI is doing on the **real app window it drives** (e.g. native-browser putting an "Adom is driving" badge + task progress on the Chrome/Edge button). Works on windows owned by **other processes**. Persistent COM (init once, reuse) — safe to tick progress frequently; no process spawn. Resolve the HWND via `desktop_list_windows`. Args (all channels optional; provide ≥1):
version.json+10−10@@ -1,21 +1,21 @@ { "manifest_version": 1,- "version": "1.8.146",- "released_at": "2026-06-15T21:00:00Z",+ "version": "1.8.172",+ "released_at": "2026-06-23T17:17:05Z", "windows": { "installer_url": "https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/Adom.Desktop_1.8.146_windows_x64-setup.exe", "installer_filename": "Adom.Desktop_1.8.146_windows_x64-setup.exe", "installer_sha256": "5fefbffa1bb0f44cc935f78ab3067260631787e60b698556c9a7f1b2f068d33b", "installer_size": 11080944 },- "changelog_url": "https://wiki.adom.inc/adom/adom-desktop",- "minimum_required": "1.3.30", "cli": { "linux_x86_64": {- "binary_url": "https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/adom-desktop-cli_1.8.146_linux_x86_64",- "binary_filename": "adom-desktop-cli_1.8.146_linux_x86_64",- "binary_sha256": "a7971beef1aba4088a9156eb076d7cb2cc4b3c34da3a23088e55ac1eaa4b4e16",- "binary_size": 8224080+ "binary_url": "https://wiki.adom.inc/api/v1/pages/adom-desktop/files/adom-desktop-cli_1.8.172_linux_x86_64",+ "binary_filename": "adom-desktop-cli_1.8.172_linux_x86_64",+ "binary_sha256": "68ac1df54326fb90829a4a8e081730962787e0007476df53279617f060a3e9b5",+ "binary_size": 8907088 }- }-}+ },+ "changelog_url": "https://wiki.adom.inc/adom/adom-desktop",+ "minimum_required": "1.3.30"+}