app
Adom Bridge (macOS)
Public Made by Adomby adom
Adom Bridge is a small operating system for AI on your Mac: it gives an AI real hands on your native desktop, including your signed-in browser, KiCad, Fusion 360, the shell, files, windows and screenshots. It provisions its own Node and Python so bridges run without touching your setup, and it talks straight to your machine. It ships with Adom Hydrogen and installs standalone too, so if you drive your Mac with Claude Desktop or another AI, this is what gives that AI hands.
← Commit history
skills/adom-bridge-installer/SKILL.mddeleted−452@@ -1,452 +0,0 @@-name: adom-bridge-installer-description: How to invoke the Adom Bridge NSIS installer from a parent installer (especially Adom Hydrogen's setup steps) — silent install, /NOLAUNCH switch for Hydrogen-managed bundling, live progress via the structured log file at %TEMP%\adom-bridge-install.log. Use when bundling Adom Bridge inside another Windows installer, writing an install supervisor / setup-step UI, detecting Adom Bridge's installed version, or upgrading an existing Adom Bridge install programmatically.--# Adom Bridge installer integration--Adom Bridge (Adom Bridge) ships as a single NSIS installer:--```-Adom Bridge_<version>_x64-setup.exe (~4.8 MB on v1.8.45)-```--It installs to `%LOCALAPPDATA%\Adom Bridge\` — no UAC prompt, no admin needed. Tauri-2 bundled NSIS with our customisations in `src-tauri/installer-hooks.nsh`.--## Command-line surface--| Flag | Meaning |-|---|---|-| (none) | Installs silently, auto-launches `adom-bridge.exe` after install |-| `/S` | Standard NSIS silent flag — same behavior since the top-level `SilentInstall silent` directive already suppresses UI |-| `/NOLAUNCH` | **v1.8.45+** — install silently, do NOT auto-launch after install. Caller is responsible for spawning Adom Bridge with the desired flags |-| `/D=<path>` | Install destination override. Default is `$LOCALAPPDATA\Adom Bridge`. Rarely needed |-| `<uninstall.exe> /S` | Silent uninstall. The uninstaller lives at `%LOCALAPPDATA%\Adom Bridge\uninstall.exe` |--**UI behavior**: zero UI in all cases. `SilentInstall silent` is set at the top of the NSIS script, so even `setup.exe` invoked from Explorer runs without a window. No Welcome page, no progress bar, no Finish page.--**Auto-launch**: by default the installer calls `ExecShell "" "$INSTDIR\adom-bridge.exe"` at the end of POSTINSTALL. Pass `/NOLAUNCH` to suppress this. Used by Hydrogen when bundling Adom Bridge because Hydrogen wants to spawn Adom Bridge with `--embedded --start-hidden --relay-url ... --session-token ...` itself, not let Adom Bridge launch standalone first and get respawned via single-instance.--## Live progress log--The installer writes structured progress to `%TEMP%\adom-bridge-install.log` (Windows expands `%TEMP%` to the user's temp dir, typically `C:\Users\<name>\AppData\Local\Temp`). Each line is `[STAGE] message\r\n`:--```-[START] adom-bridge installer 1.8.45 starting-[PREINSTALL] Cleaning legacy desktop shortcuts-[PREINSTALL] Done. Tauri will now copy bundle files.-[POSTINSTALL] Bundle files copied. Cleaning Tauri's auto-created desktop shortcut.-[POSTINSTALL] /NOLAUNCH passed — skipping auto-launch (caller will spawn)-[DONE] adom-bridge installer complete (no-launch mode)-```--**`[START]`** opens with a truncated write (fresh log per install). **`[DONE]`** is always the final line — readers tailing the file can use that as the completion sentinel without needing to wait for the process exit.--Stage tags currently emitted:-- `[START]` — once, at the top-- `[PREINSTALL]` — Tauri's beforeBuildCommand hook ran, files about to be copied-- `[POSTINSTALL]` — files copied; Tauri's standard shortcuts created and our hook is cleaning the unwanted ones-- `[DONE]` — final line, installer about to exit--The uninstaller writes the same log with `[PREUNINSTALL]` / `[POSTUNINSTALL]` stages.--## Recipe: Hydrogen's setup-step UI tails the log--Spawn the installer with `/NOLAUNCH`, poll the log file on a 200 ms timer, surface each new line to Hydrogen's UI. When `[DONE]` shows up OR the process exits, the install is complete.--### Rust (Hydrogen's installer driver)--```rust-use std::{env, fs, path::PathBuf, process::Command, time::Duration};-use std::os::windows::process::CommandExt;-use tokio::time::sleep;--const CREATE_NO_WINDOW: u32 = 0x08000000;--async fn install_adom_bridge<F: FnMut(String)>(- installer_path: &str,- mut on_line: F,-) -> Result<(), String> {- let log_path: PathBuf = [&env::var("TEMP").map_err(|e| e.to_string())?, "adom-bridge-install.log"]- .iter()- .collect();- // Pre-clear so we don't read stale lines from a previous install.- let _ = fs::remove_file(&log_path);-- let mut child = Command::new(installer_path)- .args(["/S", "/NOLAUNCH"])- .creation_flags(CREATE_NO_WINDOW)- .spawn()- .map_err(|e| format!("spawn installer: {e}"))?;-- let mut last_pos = 0usize;- loop {- // Tail any new content- if let Ok(content) = fs::read_to_string(&log_path) {- if content.len() > last_pos {- let slice = &content[last_pos..];- if let Some(last_nl) = slice.rfind('\n') {- let consumed = &slice[..=last_nl];- for line in consumed.lines() {- on_line(line.to_string());- if line.starts_with("[DONE]") {- // Don't return yet — wait for process exit- // so we surface the actual exit code, but- // we know progress streaming is finished.- }- }- last_pos += consumed.len();- }- }- }- // Check if installer has exited- if let Some(status) = child.try_wait().map_err(|e| e.to_string())? {- return if status.success() {- Ok(())- } else {- Err(format!("installer exited with {}", status))- };- }- sleep(Duration::from_millis(200)).await;- }-}--// Caller:-// install_adom_bridge(r"C:\path\to\Adom Bridge_1.8.45_x64-setup.exe", |line| {-// hydrogen_setup_step.append_live_output(&line);-// }).await?;-```--### Bash (debugging / scripting)--```bash-# Pre-clear stale log-rm -f "$TEMP/adom-bridge-install.log" 2>/dev/null--# Spawn installer in background, tail the log-"./Adom Bridge_1.8.45_x64-setup.exe" /S /NOLAUNCH &-INSTALLER_PID=$!--# Tail until process exits OR [DONE] appears-while kill -0 $INSTALLER_PID 2>/dev/null; do- [ -f "$TEMP/adom-bridge-install.log" ] && tail -F "$TEMP/adom-bridge-install.log" &- sleep 0.2-done-wait-echo "Installer exited"-```--## Recipe: detect if Adom Bridge is already installed (and at what version)--The signed NSIS installer (`installMode: "currentUser"`) writes Adom Bridge's uninstall info to `HKCU` — no admin needed. **⚠ The key name is the product name `Adom Bridge` (WITH a space), NOT `AdomBridge`** (verified live 2026-07-03). Two history notes so you don't chase the wrong key:-- The NSIS uninstall key = the product name → `…\Uninstall\Adom Bridge` (space).-- Adom Bridge's OWN launch-time code used to ALSO write an `AdomBridge` (no-space) key to **HKLM** — that write was **DELETED in v1.9.68** (the no-UAC fix). So `AdomBridge` no longer exists anywhere; read `Adom Bridge`.--```-HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\Adom Bridge- DisplayName = "Adom Bridge"- DisplayVersion = "1.9.74"- InstallLocation = "C:\Users\<name>\AppData\Local\Adom Bridge"- UninstallString = "C:\Users\<name>\AppData\Local\Adom Bridge\uninstall.exe"- Publisher = "Adom Industries, Inc."-```--```rust-use winreg::enums::HKEY_CURRENT_USER;-use winreg::RegKey;--fn adom_bridge_installed_version() -> Option<String> {- let hkcu = RegKey::predef(HKEY_CURRENT_USER);- // NOTE the SPACE — the NSIS uninstall key is the product name "Adom Bridge".- let key = hkcu- .open_subkey(r"Software\Microsoft\Windows\CurrentVersion\Uninstall\Adom Bridge")- .ok()?;- key.get_value("DisplayVersion").ok()-}-```--Compare with `semver::Version::parse` to decide whether to skip / upgrade / leave-alone.--## Recipe: Hydrogen's setup-step ladder for embedding Adom Bridge--The full pattern Hydrogen's setup-step UI runs when embedding Adom Bridge:--```-1. Check installed version → registry read above-2. Decide:- no install → install bundled Adom Bridge- older than bundled → install bundled Adom Bridge (upgrade)- same or newer → skip install entirely-3. Run installer (silent + /NOLAUNCH) → tail log, surface to UI-4. Write embedded marker file → %LOCALAPPDATA%\Adom Bridge\embedded.json-5. Delete Adom Bridge's user-facing shortcuts → Start Menu, Desktop, Startup folder- (so user can't double-launch standalone)-6. Spawn Adom Bridge with embedded flags → adom-bridge.exe --embedded- --start-hidden- --relay-url ws://127.0.0.1:8765- --relay-name adom-hydrogen- --session-token <hd's token>-7. Poll Adom Bridge's direct API for liveness → GET http://127.0.0.1:47200/health-```--Steps 4 and 5 are also covered by Adom Bridge's installer if you pass `--embedded` at Adom Bridge's first launch (the embedded-mode detection writes the marker and Adom Bridge's autostart-upgrade routine handles its own shortcuts). Doing them in Hydrogen's installer is belt-and-suspenders.--## Bundle-resource pattern--Hydrogen's `tauri.conf.json` should include the Adom Bridge installer as a bundle resource so it ships inside Hydrogen's NSIS installer:--```json-"bundle": {- "resources": {- "resources/Adom Bridge_1.8.45_x64-setup.exe": "resources/"- }-}-```--At runtime Hydrogen finds it under its install dir at `$INSTDIR\resources\Adom Bridge_<ver>_x64-setup.exe` — pass that path to the install function above.--## Versioning + upgrade strategy--| Scenario | What Hydrogen's installer should do |-|---|---|-| No Adom Bridge installed | Install bundled version |-| Adom Bridge older than bundled | Install bundled version (upgrade) |-| Adom Bridge same as bundled | Skip install step; still spawn with embedded flags |-| Adom Bridge newer than bundled | Skip install step; spawn with embedded flags. Don't downgrade — embedded mode works for any Adom Bridge ≥ v1.8.42 |--The bundled Adom Bridge installer is the minimum supported version for the Hydrogen release. Hydrogen can spawn newer ADs without modification.--## Exit codes--NSIS returns:-- `0` — install succeeded-- `2` — user cancelled (won't happen with `SilentInstall silent` since there's no UI to cancel)-- Other — install error (rare with our hooks; typical cause is disk full or `%LOCALAPPDATA%` not writable)--Treat anything non-zero as a hard failure and surface the log file's last 20 lines to the user.--## Where the installer lives--**v1.8.115+** — the end-user binary home is the **V2 wiki blob store** (the-GitHub repo is private; GH release URLs 404 for anonymous downloads). Two-discovery surfaces, both anonymous:--**Preferred for parent installers (Hydrogen setup): the packages API.** Resolve-the latest registered version and its assets in one or two GETs — note-`?org=adom` is REQUIRED (the slug exists in multiple orgs; bare URLs 400):--```-https://wiki.adom.inc/api/v1/packages/adom-bridge/dist-tags?org=adom- → {"dist_tags":{"latest":"X.Y.Z"}}-https://wiki.adom.inc/api/v1/packages/adom-bridge/manifest?org=adom- → { version, ..., assets: { "windows-x64": { filename, url, sha256, size } } }-```--The `assets` map is server-derived from the page's blobs (sha256 computed-from the actual bytes — integrity-checkable). `assets[...].url` is-server-relative (`/blob/app/adom-bridge/<file>`); prefix the git-wiki host.--**Fallback / updater path: version.json**, V2-first with V1 fallback:--```-https://wiki.adom.inc/api/v1/pages/adom-bridge/files/version.json-https://wiki.adom.inc/api/v1/pages/adom-bridge/files/version.json-```--The V2 manifest's `windows.installer_url` / `cli.<plat>.binary_url` point at-the V2 files endpoint; V1's point at V1 static copies. **Follow the-manifest's URLs — do NOT construct binary URLs by hand.**--Network quirk: HEAD on V2 blob/file URLs may return 404 while GET works-(git-wiki #40 — fix in flight). Probe with a Range GET (`Range: bytes=0-0`,-expect 206), never bare HEAD. Asset filenames are dot-form everywhere-(`Adom.Bridge_<ver>_windows_x64-setup.exe`); V1 dot-normalized since v1.8.72.--The wiki page's `metadata.install.windows_installer` field points at the-canonical filename for the current published version. Hydrogen's release build-should fetch the latest via the V2-first pattern:--```bash-# Try V2 first, fall back to V1.-fetch_manifest() {- curl -fL --max-time 15 \- "https://wiki.adom.inc/api/v1/pages/adom-bridge/files/version.json" \- 2>/dev/null \- || curl -fL --max-time 15 \- "https://wiki.adom.inc/api/v1/pages/adom-bridge/files/version.json"-}--MANIFEST=$(fetch_manifest)-INSTALLER_URL=$(echo "$MANIFEST" | jq -r .windows.installer_url)-INSTALLER_SHA=$(echo "$MANIFEST" | jq -r .windows.installer_sha256)-# Each manifest carries a self-consistent installer_url that points at the-# SAME backend the manifest was served from — V2 manifest → V2 installer URL,-# V1 manifest → V1 installer URL. No URL mixing across backends.--curl -fL "$INSTALLER_URL" -o resources/ad-setup.exe--# Verify SHA256 before bundling — defends against partial fetches + tampering-DOWNLOAD_SHA=$(sha256sum resources/ad-setup.exe | awk '{print $1}')-[ "$DOWNLOAD_SHA" = "$INSTALLER_SHA" ] || { echo "SHA mismatch"; exit 1; }-```--The desktop Adom Bridge's built-in auto-updater (`src-tauri/src/updater.rs`) walks an-ordered `MANIFEST_URLS` list — V2 first, V1 fallback — and uses whichever-responds first. Once V2 has been the source of truth for a release cycle-without incident, V1 will be retired from the pipeline.--`version.json` also carries the SHA256 hash of the installer so Hydrogen's build-pipeline can verify the download before bundling.--## Asset naming convention (v1.8.113+)--The Adom Bridge wiki page hosts TWO distinct types of artifacts per release:--1. **Full Adom Bridge GUI installer** — the actual desktop app (Tauri window, bundled- bridges, relauncher). One per OS / architecture.-2. **CLI companion binary** — a separate executable that talks to Adom Bridge over- the relay. Used by Hydrogen's WSL2 container, cloud builds, sibling-app- installers, cron jobs. Does NOT contain Adom Bridge itself.--Both ship together at the same version (single `python scripts/bump-version.py-patch` bumps both, single `cargo tauri build` + `cargo build --release` in-`cli/` produces both, single `scripts/release-publish.sh` uploads both).--### Filename pattern--| Artifact | Wiki asset name pattern | Example (v1.8.113) |-|---|---|---|-| Full Adom Bridge GUI — Windows | `Adom.Bridge_<ver>_windows_x64-setup.exe` | `Adom.Bridge_1.8.113_windows_x64-setup.exe` |-| Full Adom Bridge GUI — macOS | `Adom.Bridge_<ver>_macos_<arch>.dmg` | `Adom.Bridge_1.8.113_macos_aarch64.dmg` (future) |-| Full Adom Bridge GUI — Linux | `Adom.Bridge_<ver>_linux_<arch>.AppImage` | `Adom.Bridge_1.8.113_linux_x86_64.AppImage` (future) |-| CLI companion — Linux | `adom-bridge-cli_<ver>_linux_<arch>` | `adom-bridge-cli_1.8.113_linux_x86_64` |-| CLI companion — macOS | `adom-bridge-cli_<ver>_macos_<arch>` | `adom-bridge-cli_1.8.113_macos_aarch64` (future) |-| CLI companion — Windows | `adom-bridge-cli_<ver>_windows_<arch>.exe` | `adom-bridge-cli_1.8.113_windows_x64.exe` (future) |--The `_cli_` token in the middle is the only signal you need to know "this is-the companion, not the app." `linux_x86_64` always means Linux x86_64,-regardless of whether the file is a GUI installer or a CLI binary.--### After install, the binary name is `adom-bridge`--The wiki asset name disambiguates at FETCH time. At INSTALL time the binary-is renamed to `adom-bridge` so the command users type doesn't change:--```bash-# Linux example — install the CLI companion-curl -fL "https://wiki.adom.inc/api/v1/pages/adom-bridge/files/adom-bridge-cli_1.8.113_linux_x86_64" \- -o /tmp/ad-sudo install -m 755 /tmp/ad /usr/local/bin/adom-bridge-adom-bridge --version-# → adom-bridge 1.8.113 (<sha>, built <ts>)-```--### Version.json `.cli` slot--The auto-update manifest (v1.8.113+) carries a typed `cli` sibling section-for the CLI binaries:--```json-{- "manifest_version": 1,- "version": "1.8.113",- "windows": { "installer_url": ".../Adom.Bridge_1.8.113_windows_x64-setup.exe", ... },- "cli": {- "linux_x86_64": {- "binary_url": ".../adom-bridge-cli_1.8.113_linux_x86_64",- "binary_filename": "adom-bridge-cli_1.8.113_linux_x86_64",- "binary_sha256": "...",- "binary_size": 8012408- }- },- "changelog_url": "...",- "minimum_required": "1.3.30"-}-```--Pre-v1.8.113 readers ignore `.cli` entirely (additive schema; no-`manifest_version` bump required). The desktop Adom Bridge's own auto-updater only-reads `.windows / .macos / .linux` for its GUI installer URL — it doesn't-touch `.cli`.--For Hydrogen / cloud / Docker-side fetchers, prefer the typed lookup:--```bash-# Best: read the URL out of the manifest (so the filename can evolve)-MANIFEST=$(fetch_manifest)-LINUX_CLI_URL=$(echo "$MANIFEST" | jq -r '.cli.linux_x86_64.binary_url')-LINUX_CLI_SHA=$(echo "$MANIFEST" | jq -r '.cli.linux_x86_64.binary_sha256')-curl -fL "$LINUX_CLI_URL" -o /tmp/ad-[ "$(sha256sum /tmp/ad | awk '{print $1}')" = "$LINUX_CLI_SHA" ] || exit 1-sudo install -m 755 /tmp/ad /usr/local/bin/adom-bridge-```--### Windows CLI is shipped with the NSIS (v1.8.114+)--Installing Adom Bridge on Windows now drops the CLI companion next to the GUI exe-and adds the install dir to the user's PATH so PowerShell / Claude Desktop /-cmd find it without configuration:--```-%LOCALAPPDATA%\Adom Bridge\adom-bridge.exe ← GUI (Windows subsystem)-%LOCALAPPDATA%\Adom Bridge\adom-bridge-cli.exe ← CLI companion (Console subsystem)-%LOCALAPPDATA%\Adom Bridge\ad-relauncher.exe ← visible self-restart helper-```--NSIS's POSTINSTALL hook prepends `%LOCALAPPDATA%\Adom Bridge` to-`HKCU\Environment\Path` (no UAC — user-level only) and broadcasts-`WM_SETTINGCHANGE` so freshly-opened shells pick up the change. Already--open shells need a re-launch (OS limitation).--After install, in a fresh PowerShell:--```powershell-adom-bridge-cli --version-# adom-bridge 1.8.114 (<sha>, built <ts>)-adom-bridge-cli status-adom-bridge-cli screenshot_window '{"title-contains":"VS Code"}'-```--The CLI auto-discovers the local Adom Bridge via direct-API probe at-`127.0.0.1:47200` — no relay needed when Adom Bridge is on the same box. ~5ms RTT-for compatible verbs; verbs in Adom Bridge's `cliRequired` list still flow through-a relay if one's running (Hydrogen's WSL2 distro typically owns the relay).--**Relay self-detect (v1.8.114+):** `adom-bridge-cli serve` checks for-another adom-bridge relay on `127.0.0.1:8766/health` before binding. If-one already answers, it prints a friendly note and exits cleanly without-starting a second relay (which would just sit idle — Adom Bridge's WS client only-attaches to the first one it finds). Pass `--force-bind` to override.--PREUNINSTALL strips the PATH entry back out and rebroadcasts so an-uninstall of Adom Bridge also gets PATH cleanup.--### Legacy alias migration window--Releases prior to v1.8.113 published the Linux CLI as `adom-bridge-linux`-(no version, no architecture). Hydrogen's WSL2 setup and a few cron-based-installers have that literal filename baked in.--To keep them working through the rename, v1.8.113 publishes BOTH names:--| Name | Status | Wiki URL (V2 / V1) |-|---|---|---|-| `adom-bridge-cli_<ver>_linux_x86_64` | **canonical, v1.8.113+** | V2 / V1 |-| `adom-bridge-linux` | **deprecated alias** — byte-identical copy | V2 / V1 |--Both files are byte-identical with the same SHA256. The legacy alias stays-through **v1.8.116**, then disappears. Migrate by then. Recommended pattern:--```bash-# Migration period (v1.8.113 → v1.8.115): try new name, fall back to alias-LINUX_CLI_URL_NEW=$(echo "$MANIFEST" | jq -r '.cli.linux_x86_64.binary_url // empty')-if [ -n "$LINUX_CLI_URL_NEW" ]; then- curl -fL "$LINUX_CLI_URL_NEW" -o /tmp/ad-else- # Falling back — likely talking to a pre-v1.8.113 manifest- curl -fL "https://wiki.adom.inc/api/v1/pages/adom-bridge/files/adom-bridge-linux" \- -o /tmp/ad-fi-```--Post-v1.8.116, the fallback branch dies; only the canonical name will exist.