Adom Browser Extension
Public Made by Adomby adom
Your AI's hands in your real, signed-in browser. The Adom Browser Extension (abe) works with both Chrome and Edge: build, drive, and test web apps, and log past vendor walls, in the browser you already use - cookies, SSO, saved logins and captcha trust intact. The nbrowser_* bridge (pup's counterpart) runs in your actual logged-in profile.
name: publishing-the-bridge description: "PUBLISH skill for maintainers of the adom-browser-extension (native-browser) bridge - NOT for driving it. The exact, proven recipe to cut a release: bump versions in lockstep, build the zip, publish it as a Release ASSET (release create + upload --platform any), point the manifest url at the /download/ path (never a /files blob), push source, and land it with refresh_bridges. Covers the two-artifact split (Release zip vs skills pkg), the pkg's package.json declaring dependencies:{adom/adom-desktop:^1.9.x} (so pkg install pulls the AD CLI + core skills), the pkg shipping ONLY user skills while dev/publish skills live in the source repo (not the pkg, not files[], not user-invocable:false), the bridge.json contracts we declare (timeouts) and one we deliberately don't (detect), and the standing show-in-pup rule. Everyday users never need this."
Parent skill: adom-browser-extension. Maintainer-only skill (not user-invocable). Bridge SDK: https://wiki.adom.inc/adom/adom-desktop-bridges
Publishing the native-browser bridge
What "the bridge" actually is (3 artifacts, 3 places)
- Runtime —
bridge/(server.js + bridge.json) zipped and published as a Release asset (release create+release upload --platform any), with a manifest on/fileswhoseurlpoints at the Release/download/path. AD streams it tobridges-cache/native-browser/and spawns it. (Node runtime is source-only; AD provisions Node — see the SDK "Runtime contract".) - Skills pkg — the
skills/<name>/SKILL.mds, published viaadom-wiki pkg publish --org adom, installed into the container's~/.claude/skills+~/.codex/skills. - Discovery —
discovery_triggers+discovery_pitchonpage.json.
bridge.json contracts we declare (and one we deliberately don't)
timeouts(AD v1.9.79+): AD hard-caps every bridge verb at 60s unless you declare per-verb HTTP budgets. Ours match the bridge's owntimeoutFor()(screenshot|record|fetch_url|input_dispatch→ 120s) pluswait(blocks up to its 120s cap):verbs {wait:125, fetch_url:120, input_dispatch:120}prefixes [{screenshot:120},{record:120}],default:60, andstatusVerb:"nbrowser_status"(AD returns{stillRunning:true,statusVerb}on its own timeout → caller polls). Keep the describetimeoutSecondsinserver.jsaligned. Note: the adom-desktop CLI has its own ~30s client timeout, separate from AD's bridge budget — you can't observe a >30s verb via a bare CLI call.
detect— intentionally OMITTED.detectis for a HOST APP AD detects/gates. Native-browser drives the user's REAL browser via the extension, so the authoritative "is it usable" signal is extension-connected (nbrowser_readiness), not a browser binary on disk — and our read-only verbs are always forwarded regardless. A singlehostApp:"Google Chrome"would MISREPORT the common Edge-only machine (verified real: ADOMBASELINE runs fine on Edge with no Chrome), and Edge is universal on Windows so "browser installed" is near-zero signal. So we do NOT declaredetect.
Release the RUNTIME — the exact, proven sequence
Deps: none (core http/net), so the payload is source-only (no node_modules).
- Bump the version in THREE places, together (they drift if you don't):
bridge/bridge.jsonversion(what AD reads + reports),bridge/package.jsonversion,bridge/BRIDGE_VERSION.server.jsreadsVERSIONfrombridge.json(authoritative) so it can't drift — keep it that way. AD reads that sameversionoff your/statusJSON asliveVersion, so keep/statusaccurate.
- Build the zip with files at the ROOT (there is no
zipbinary — use Pythonzipfile): members =bridge.json,package.json,server.js,BRIDGE_VERSION,adom-favicon.png. Name itnative-browser-bridge-v<ver>.zip(as of 0.1.29 — it always WAS a zip; the old.binnaming was a scar from the retired/filesbase64 API which rejected.zip. Release assets are extension-agnostic and AD only follows the manifesturl, so no AD-side change was needed for the rename; old.binreleases stay valid at their existing URLs). - The runtime is a RELEASE ASSET, not a
/filesblob (SDK "two-artifact" rule — fusion + pup do exactly this). Cut a Release for the bridge version + upload the zip:adom-wiki release create adom/adom-browser-extension <ver> --title "native-browser bridge runtime v<ver>"adom-wiki release upload adom/adom-browser-extension <ver> native-browser-bridge-v<ver>.zip --platform anyThe download then serves anon athttps://wiki.adom.inc/download/adom/adom-browser-extension/<ver>/native-browser-bridge-v<ver>.zip(verify:curl -sI→ 200). (The pkg's own release stays 0.3.x; the bridge release is 0.0.x — separate version streams on the same page, that's expected.)
- sha256 + byte size → write
native-browser-bridge-manifest.jsonwith theurlpointing at that/download/path (NOT a/filesblob):{manifest_version:1, version, url:"https://wiki.adom.inc/download/adom/adom-browser-extension/<ver>/native-browser-bridge-v<ver>.zip", sha256, size, released_at}. - Push manifest + source as TEXT with
adom-wiki repo push adom-browser-extension --files native-browser-bridge-manifest.json bridge/bridge.json bridge/package.json bridge/server.js bridge/BRIDGE_VERSION ...(the manifest lives on/files; only the binary is off it). - Land it:
refresh_bridges {name:"native-browser"}→ verifynbrowser_readinessroutes andbridge_check_updates/bridge_listshowliveVersion==<ver>(nostaleProcess). (bridge_check_updates intermittently omits native-browser after an AD self-update — trust readiness + bridge_list.) - NEVER
repo rma runtime zip while the manifest still points at it. The old/files.binuploads are the dead anti-pattern (they piled up to 22 stale versions once) — do NOT re-add them. If any linger, migrate as a SEQUENCE: release-upload → repoint manifest → verify/download/serves → THEN delete the/filescopies. The pkg'spackage.json(the skills tarball, not the zip) declaresdependencies:{"adom/adom-desktop":"^1.9.x"}(sopkg installpulls the AD CLI + core skills the container needs) — NOT the server's npm deps (the bridge has none anyway). The zip'sbridge/package.jsonholds the server's runtime deps (none for us — corehttp/net).
Reaping is fixed (AD v1.9.76) — the old orphan trap is gone
Earlier, refresh_bridges could leave a stale PID serving old code (a node bridge doesn't lock the
cache dir, so a clean swap didn't reap). AD v1.9.76 fixed this: refresh_bridges now force-restarts
a running bridge after an update, restart_bridge {name} is a real verb (kill tracked+port-orphan +
respawn on the stable port), and bridge_check_updates surfaces liveVersion + staleProcess
directly. So: after a release, just refresh_bridges (or restart_bridge for an explicit restart) and
confirm liveVersion matches — no more digging in host.json or manual taskkill.
(bridge_pause/bridge_resume are a ROUTING gate only; they never kill the process.)
Publish the SKILLS pkg — USER skills ONLY (dev/publish live in the repo)
adom-wiki pkg publish --org adom. The pkg ships ONLY your USER skills — the ones a general Adom
user's agent needs to DRIVE the bridge. That's the pkg's whole job: a container pkg installs it to USE
you. Each is a real skills/<name>/SKILL.md with a Parent skill: first line; list every user-skill
path EXPLICITLY (no globs) in package.json files[] AND install.sh/uninstall.sh.
- DEV + PUBLISH skills do NOT go in the pkg — they live in your source REPO (this skill, and
developing-the-bridge). A developer who clones the source to EDIT the bridge gets them as repo files; the normal user never needs them. So: not infiles[], not ininstall.sh, and do NOT scope them withuser-invocable:false— that convention still SHIPS them and bloats every container install. Keep them underdev-skills/+publish-skills/in the repo (the wiki Skills page reads those folders for its Dev/Publish tabs). Open-vs-closed source is irrelevant — it only sets whether the repo is publicly readable; either way dev/publish stay in the repo, never the pkg. (adom-desktop core does exactly this: its RELEASE/WIKI_PUBLISH/SIGNING skills live only in source, never in the published pkg.) - The pkg's
package.jsondeclaresdependencies:{"adom/adom-desktop":"^1.9.x"}—pkg installresolves it npm-style, so installing our skill pkg also pulls the AD CLI + core skills the container needs to drive us. (Do NOT put the SERVER's npm deps here — those ride in the zip'sbridge/package.json.)
Discovery
Edit page.json discovery_triggers (30+ user-task phrasings, login/forms niche — pup can't do
logins) + discovery_pitch (an INSTRUCTION). Push page.json LAST (a pkg publish clobbers it and
drops the hero). Verify: adom-wiki discover preview --json "<7 real user queries>" → land top-3.
After ANY wiki change: show John in pup (standing rule)
Open the live page in a maximized pup window + shotlog + hand him the phone URL. Never just report "published."
After ANY release: prove the USER-VISIBLE result, unprompted (standing rule)
Verifying the pipeline is not verifying the feature. "The verb returned ok / the file exists / a test window rendered" is engineer-proof; the user cares what THEY will see. So after landing a release, automatically demonstrate the actual user-visible outcome on EVERY surface the change touches (e.g. a taskbar-badge change = show every browser+profile it will decorate, not one throwaway Notepad button) and put it in shotlog with the phone URL - before the user has to ask. If a live demo would touch something sensitive (a banking window, a signed-in session), don't skip the demo - build the same proof a safe way (generate from the real inputs off to the side) and say why. The user should never have to say "prove it."
---
name: publishing-the-bridge
description: "PUBLISH skill for maintainers of the adom-browser-extension (native-browser) bridge - NOT for driving it. The exact, proven recipe to cut a release: bump versions in lockstep, build the zip, publish it as a Release ASSET (release create + upload --platform any), point the manifest url at the /download/ path (never a /files blob), push source, and land it with refresh_bridges. Covers the two-artifact split (Release zip vs skills pkg), the pkg's package.json declaring dependencies:{adom/adom-desktop:^1.9.x} (so pkg install pulls the AD CLI + core skills), the pkg shipping ONLY user skills while dev/publish skills live in the source repo (not the pkg, not files[], not user-invocable:false), the bridge.json contracts we declare (timeouts) and one we deliberately don't (detect), and the standing show-in-pup rule. Everyday users never need this."
---
Parent skill: **adom-browser-extension**. Maintainer-only skill (not user-invocable). Bridge SDK:
https://wiki.adom.inc/adom/adom-desktop-bridges
# Publishing the native-browser bridge
## What "the bridge" actually is (3 artifacts, 3 places)
1. **Runtime** — `bridge/` (server.js + bridge.json) zipped and published as a **Release asset**
(`release create` + `release upload --platform any`), with a manifest on `/files` whose `url` points
at the Release `/download/` path. AD streams it to `bridges-cache/native-browser/` and spawns it.
(Node runtime is source-only; AD provisions Node — see the SDK "Runtime contract".)
2. **Skills pkg** — the `skills/<name>/SKILL.md`s, published via `adom-wiki pkg publish --org adom`,
installed into the container's `~/.claude/skills` + `~/.codex/skills`.
3. **Discovery** — `discovery_triggers` + `discovery_pitch` on `page.json`.
## bridge.json contracts we declare (and one we deliberately don't)
- **`timeouts`** (AD v1.9.79+): AD hard-caps every bridge verb at 60s unless you declare per-verb HTTP
budgets. Ours match the bridge's own `timeoutFor()` (`screenshot|record|fetch_url|input_dispatch` →
120s) plus `wait` (blocks up to its 120s cap): `verbs {wait:125, fetch_url:120, input_dispatch:120}`
+ `prefixes [{screenshot:120},{record:120}]`, `default:60`, and `statusVerb:"nbrowser_status"` (AD
returns `{stillRunning:true,statusVerb}` on its own timeout → caller polls). Keep the describe
`timeoutSeconds` in `server.js` aligned. Note: the adom-desktop **CLI has its own ~30s client
timeout**, separate from AD's bridge budget — you can't observe a >30s verb via a bare CLI call.
- **`detect` — intentionally OMITTED.** `detect` is for a HOST APP AD detects/gates. Native-browser
drives the user's REAL browser via the extension, so the authoritative "is it usable" signal is
**extension-connected** (`nbrowser_readiness`), not a browser binary on disk — and our read-only
verbs are always forwarded regardless. A single `hostApp:"Google Chrome"` would MISREPORT the common
Edge-only machine (verified real: ADOMBASELINE runs fine on Edge with no Chrome), and Edge is
universal on Windows so "browser installed" is near-zero signal. So we do NOT declare `detect`.
## Release the RUNTIME — the exact, proven sequence
Deps: none (core `http`/`net`), so the payload is source-only (no `node_modules`).
1. **Bump the version in THREE places, together** (they drift if you don't):
- `bridge/bridge.json` `version` (what AD reads + reports),
- `bridge/package.json` `version`,
- `bridge/BRIDGE_VERSION`.
`server.js` reads `VERSION` from `bridge.json` (authoritative) so it can't drift — keep it that way.
AD reads that same `version` off your `/status` JSON as `liveVersion`, so keep `/status` accurate.
2. **Build the zip with files at the ROOT** (there is no `zip` binary — use Python `zipfile`):
members = `bridge.json`, `package.json`, `server.js`, `BRIDGE_VERSION`, `adom-favicon.png`. Name it
`native-browser-bridge-v<ver>.zip` (as of 0.1.29 — it always WAS a zip; the old `.bin` naming was a
scar from the retired `/files` base64 API which rejected `.zip`. Release assets are extension-agnostic
and AD only follows the manifest `url`, so no AD-side change was needed for the rename; old `.bin`
releases stay valid at their existing URLs).
3. **The runtime is a RELEASE ASSET, not a `/files` blob** (SDK "two-artifact" rule — fusion + pup do
exactly this). Cut a Release for the bridge version + upload the zip:
- `adom-wiki release create adom/adom-browser-extension <ver> --title "native-browser bridge runtime v<ver>"`
- `adom-wiki release upload adom/adom-browser-extension <ver> native-browser-bridge-v<ver>.zip --platform any`
The download then serves anon at `https://wiki.adom.inc/download/adom/adom-browser-extension/<ver>/native-browser-bridge-v<ver>.zip` (verify: `curl -sI` → 200). (The pkg's own release stays 0.3.x; the bridge release is 0.0.x — separate version streams on the same page, that's expected.)
4. **sha256 + byte size** → write `native-browser-bridge-manifest.json` with the `url` pointing at that
**`/download/` path** (NOT a `/files` blob):
`{manifest_version:1, version, url:"https://wiki.adom.inc/download/adom/adom-browser-extension/<ver>/native-browser-bridge-v<ver>.zip", sha256, size, released_at}`.
5. **Push manifest + source as TEXT** with `adom-wiki repo push adom-browser-extension --files native-browser-bridge-manifest.json bridge/bridge.json bridge/package.json bridge/server.js bridge/BRIDGE_VERSION ...` (the manifest lives on `/files`; only the binary is off it).
6. **Land it:** `refresh_bridges {name:"native-browser"}` → verify `nbrowser_readiness` routes and
`bridge_check_updates`/`bridge_list` show `liveVersion==<ver>` (no `staleProcess`). *(bridge_check_updates
intermittently omits native-browser after an AD self-update — trust readiness + bridge_list.)*
7. **NEVER `repo rm` a runtime zip while the manifest still points at it.** The old `/files` `.bin` uploads
are the dead anti-pattern (they piled up to 22 stale versions once) — do NOT re-add them. If any linger,
migrate as a SEQUENCE: release-upload → repoint manifest → verify `/download/` serves → THEN delete the
`/files` copies. The **pkg's** `package.json` (the skills tarball, not the zip) declares
`dependencies:{"adom/adom-desktop":"^1.9.x"}` (so `pkg install` pulls the AD CLI + core skills the
container needs) — NOT the server's npm deps (the bridge has none anyway). The **zip's**
`bridge/package.json` holds the server's runtime deps (none for us — core `http`/`net`).
## Reaping is fixed (AD v1.9.76) — the old orphan trap is gone
Earlier, `refresh_bridges` could leave a stale PID serving old code (a node bridge doesn't lock the
cache dir, so a clean swap didn't reap). **AD v1.9.76 fixed this:** `refresh_bridges` now force-restarts
a running bridge after an update, `restart_bridge {name}` is a real verb (kill tracked+port-orphan +
respawn on the stable port), and `bridge_check_updates` surfaces `liveVersion` + `staleProcess`
directly. So: after a release, just `refresh_bridges` (or `restart_bridge` for an explicit restart) and
confirm `liveVersion` matches — no more digging in `host.json` or manual `taskkill`.
(`bridge_pause`/`bridge_resume` are a ROUTING gate only; they never kill the process.)
## Publish the SKILLS pkg — USER skills ONLY (dev/publish live in the repo)
`adom-wiki pkg publish --org adom`. **The pkg ships ONLY your USER skills** — the ones a general Adom
user's agent needs to DRIVE the bridge. That's the pkg's whole job: a container `pkg install`s it to USE
you. Each is a real `skills/<name>/SKILL.md` with a `Parent skill:` first line; list **every user-skill
path EXPLICITLY** (no globs) in `package.json` `files[]` AND `install.sh`/`uninstall.sh`.
- **DEV + PUBLISH skills do NOT go in the pkg — they live in your source REPO** (this skill, and
`developing-the-bridge`). A developer who clones the source to EDIT the bridge gets them as repo files;
the normal user never needs them. So: **not in `files[]`, not in `install.sh`, and do NOT scope them
with `user-invocable:false`** — that convention still SHIPS them and bloats every container install.
Keep them under `dev-skills/` + `publish-skills/` in the repo (the wiki Skills page reads those folders
for its Dev/Publish tabs). **Open-vs-closed source is irrelevant** — it only sets whether the repo is
publicly readable; either way dev/publish stay in the repo, never the pkg. (adom-desktop core does
exactly this: its RELEASE/WIKI_PUBLISH/SIGNING skills live only in source, never in the published pkg.)
- **The pkg's `package.json` declares `dependencies:{"adom/adom-desktop":"^1.9.x"}`** — `pkg install`
resolves it npm-style, so installing our skill pkg also pulls the AD CLI + core skills the container
needs to drive us. (Do NOT put the SERVER's npm deps here — those ride in the zip's `bridge/package.json`.)
## Discovery
Edit `page.json` `discovery_triggers` (30+ user-task phrasings, login/forms niche — pup can't do
logins) + `discovery_pitch` (an INSTRUCTION). Push `page.json` **LAST** (a pkg publish clobbers it and
drops the hero). Verify: `adom-wiki discover preview --json "<7 real user queries>"` → land top-3.
## After ANY wiki change: show John in pup (standing rule)
Open the live page in a maximized pup window + shotlog + hand him the phone URL. Never just report
"published."
## After ANY release: prove the USER-VISIBLE result, unprompted (standing rule)
Verifying the pipeline is not verifying the feature. "The verb returned ok / the file exists / a test
window rendered" is engineer-proof; the user cares what THEY will see. So after landing a release,
automatically demonstrate the actual user-visible outcome on EVERY surface the change touches (e.g. a
taskbar-badge change = show every browser+profile it will decorate, not one throwaway Notepad button)
and put it in shotlog with the phone URL - before the user has to ask. If a live demo would touch
something sensitive (a banking window, a signed-in session), don't skip the demo - build the same
proof a safe way (generate from the real inputs off to the side) and say why. The user should never
have to say "prove it."