app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
← Commit history
Fix stale post-rename references in docs: old slug adom-desktop-puppeteer-bridge -> pup-bridge, CLI adom-desktop -> adom-bridge-cli, related bridge links to new slugs
18 files changed
+170−170
CHANGELOG.md+2−2CLAUDE.md+9−9HANDOFF-TO-ADOM-DESKTOP.md+13−13HANDOFF-notify-for-bridges.md+2−2PROPOSAL-shared-runtimes.md+1−1PUBLISHING.md+8−8README.md+19−19SKILL.md+15−15dev-skills/pup-bridge-debug/SKILL.md+3−3dev-skills/pup-bridge-dev/SKILL.md+32−32dev-skills/pup-bridge-test/SKILL.md+1−1dev-skills/pup-browser-import/SKILL.md+4−4dev-skills/pup-differential-diagnosis/SKILL.md+2−2publish-skills/pup-bridge-publish/SKILL.md+23−23skills/pup-adom-wiki/SKILL.md+4−4skills/pup-browsers-and-chrome/SKILL.md+12−12skills/pup-screenshots-recording/SKILL.md+9−9skills/pup-windows-sessions-tabs/SKILL.md+11−11CHANGELOG.md+2−2@@ -1211,7 +1211,7 @@ install chrome") — no `errorCode`, no auto-install, no actionable hint. The AI - `bridge.json`: `statusVerb:"pup_readiness"` + `updateManifestUrl` so AD auto-updates from this page; new verbs registered in `verbs[]` + `pup_describe`. -**Ownership:** extracted from `adom-desktop/plugins/puppeteer` into this standalone wiki repo-(`wiki.adom.inc/adom/adom-desktop-puppeteer-bridge`), mirroring the cloud-owned kicad/fusion model.+**Ownership:** extracted from `adom-bridge/plugins/puppeteer` into this standalone wiki repo+(`wiki.adom.inc/adom/pup-bridge`), mirroring the cloud-owned kicad/fusion model. Bridge keeps a bundled SEED for first-run/offline and auto-pulls newer versions from here via `updateManifestUrl`.
CLAUDE.md+9−9@@ -1,15 +1,15 @@-# CLAUDE.md — adom-desktop-puppeteer-bridge (READ THIS, it is YOUR project)+# CLAUDE.md — pup-bridge (READ THIS, it is YOUR project) This repo is **the Puppeteer ("pup") bridge** — the canonical source of truth, published-to `wiki.adom.inc/adom/adom-desktop-puppeteer-bridge`. If you are an Adom AI touching anything pup /+to `wiki.adom.inc/adom/pup-bridge`. If you are an Adom AI touching anything pup / `pup_*` / Chrome-for-Testing, **you own and maintain this code here.** Bridge (AD) ships a bundled SEED of this bridge for first-run/offline, but the live code is THIS repo and AD auto-pulls it-via the `updateManifestUrl` in `bridge.json`. (Extracted from `adom-desktop/plugins/puppeteer` on+via the `updateManifestUrl` in `bridge.json`. (Extracted from `adom-bridge/plugins/puppeteer` on 2026-06-29, mirroring the kicad/fusion cloud-owned model.) -## You vs adom-desktop (AD) core — the boundary+## You vs adom-bridge-cli (AD) core — the boundary -- **AD core owns:** the `adom-desktop` CLI, the relay / `/command` passthrough (relays your response+- **AD core owns:** the `adom-bridge-cli` CLI, the relay / `/command` passthrough (relays your response VERBATIM incl. `_hint`/`errorCode`/`statusVerb`), bridge lifecycle (`bridge_install` / streaming this bridge into `…\bridges-cache\puppeteer`, the stable port, supervisor), `desktop_install_node`, and the `node_not_found` gate that fires BEFORE this bridge can spawn. AD also runs `npm install` in the bridge@@ -19,7 +19,7 @@ via the `updateManifestUrl` in `bridge.json`. (Extracted from `adom-desktop/plug fields on `/status`, the `pup_describe` catalog, the `pup` `SKILL.md` (+ the source-only maintainer skills in `dev-skills/`/`publish-skills/`), and the edit → publish → reinstall loop. - So: a `pup_*` verb misbehaves, a hint is missing, Chrome-for-Testing won't install, the chip lies →- it's **your code**, fix it here and republish. It is NOT an adom-desktop request. If a GENERIC AD+ it's **your code**, fix it here and republish. It is NOT an adom-bridge-cli request. If a GENERIC AD capability is missing (a new lifecycle verb, calling `pup_prewarm` on embedded first-run), file that against AD — don't re-absorb the bridge. @@ -41,7 +41,7 @@ via the `updateManifestUrl` in `bridge.json`. (Extracted from `adom-desktop/plug `install.sh` / `adom-wiki pkg`). The cold-start playbook lives here. The maintainer skills (`dev-skills/pup-bridge-dev`, `publish-skills/pup-bridge-publish`) are SOURCE-ONLY — per the Bridge SDK a pkg ships only user skills, so they stay in the repo, out of `files[]` (open-vs-closed doesn't matter).-- `package.json` (root, skillpack) — declares `dependencies:{ "adom/adom-desktop": "^1.9.x" }` so+- `package.json` (root, skillpack) — declares `dependencies:{ "adom/adom-bridge": "^1.9.x" }` so `pkg install` pulls the AD CLI + core skills. SERVER npm deps live ONLY in the Release zip's `src/package.json`. ## The publish/reinstall loop@@ -50,7 +50,7 @@ See `PUBLISHING.md` for the full recipe. Short form: edit `src/` → bump `src/B `src/bridge.json` together → build `adom-bridge-puppeteer-v<ver>.zip` from `src/` (zip-root, no top dir) → `adom-wiki release upload` the zip → point `adom-bridge-puppeteer-manifest.json` at that release URL (with the zip's real sha256/size) → `adom-wiki repo push` the manifest + changed source + SKILL.md →-`adom-desktop bridge_install {"manifestUrl": ".../files/adom-bridge-puppeteer-manifest.json","force":true}`+`adom-bridge-cli bridge_install {"manifestUrl": ".../files/adom-bridge-puppeteer-manifest.json","force":true}` to test → verify in pup. Wiki = canonical. **ALWAYS show wiki changes in pup (standing rule from John):** after ANY publish/edit to this wiki@@ -65,4 +65,4 @@ Reuse one window (`sessionId: cft` or `pup-wiki`) instead of spawning new ones; - **`sha256`/`size` in the manifest MUST match the served release asset** or `bridge_install` rejects it. - **Never hand-edit the bridges-cache or the bundled seed.** They get clobbered. Edit `src/`, publish. - **Source-only zip.** Do NOT zip node_modules (88 MB, wiki limits, native builds) — AD reconstructs it.-- Pup is **AD-owned-ish but cloud-managed from here now.** Don't republish it from the adom-desktop repo.+- Pup is **AD-owned-ish but cloud-managed from here now.** Don't republish it from the adom-bridge-cli repo.
HANDOFF-TO-ADOM-DESKTOP.md+13−13@@ -1,19 +1,19 @@-# Handoff to the adom-desktop build thread — pup is now cloud-owned+# Handoff to the adom-bridge-cli build thread — pup is now cloud-owned -Paste the block below into the adom-desktop build thread (the one that owns+Paste the block below into the adom-bridge-cli build thread (the one that owns `github.com/adom-inc/adom-desktop`). It mirrors what was done for the kicad/fusion bridges. --- -**Subject: The Puppeteer (pup) bridge moved out of adom-desktop into its own wiki repo — please treat it like kicad/fusion now.**+**Subject: The Puppeteer (pup) bridge moved out of adom-bridge-cli into its own wiki repo — please treat it like kicad/fusion now.** We took over code management of the Puppeteer bridge. It now lives at its own canonical wiki repo, exactly like the kicad and fusion bridges: -- **Canonical repo / page:** https://wiki.adom.inc/adom/adom-desktop-puppeteer-bridge+- **Canonical repo / page:** https://wiki.adom.inc/adom/pup-bridge - **Current published version:** **1.1.0** (release asset + streaming manifest are live)-- **Manifest (updateManifestUrl target):** `https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/adom-bridge-puppeteer-manifest.json`-- **Release zip:** `https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.1.0/adom-bridge-puppeteer-v1.1.0.zip` (sha256 `525eabb0350ea0eaf52a949e9b3026f5a4a035868afe9546a7478298b9539b8c`, source-only — node_modules is reconstructed by AD's `npm install` on spawn, as today)+- **Manifest (updateManifestUrl target):** `https://wiki.adom.inc/api/v1/pages/pup-bridge/files/adom-bridge-puppeteer-manifest.json`+- **Release zip:** `https://wiki.adom.inc/download/adom/pup-bridge/1.1.0/adom-bridge-puppeteer-v1.1.0.zip` (sha256 `525eabb0350ea0eaf52a949e9b3026f5a4a035868afe9546a7478298b9539b8c`, source-only — node_modules is reconstructed by AD's `npm install` on spawn, as today) **What changed in 1.1.0 (the reason for all this):** cold-start self-heal. On a fresh PC (HD bundles AD; the installer pre-installs neither Node nor Chrome for Testing), the first "open in pup" used to@@ -23,7 +23,7 @@ detects a missing Chrome for Testing, auto-installs it (programmatically via the led/summary/tooltip truthfully (yellow while installing). The `node_not_found` path you already own is unchanged and still correct. -**Please make these adom-desktop changes (all small, mirroring kicad/fusion):**+**Please make these adom-bridge-cli changes (all small, mirroring kicad/fusion):** 1. **Keep pup a pre-installed bundled SEED** (do NOT remove it from `bundle.resources`) — same as kicad/fusion/blender. Fresh installs must still ship a working pup offline.@@ -40,13 +40,13 @@ unchanged and still correct. `plugins/puppeteer/CANONICAL.md` breadcrumb pointing at the wiki repo, like the kicad/fusion seeds. 4. **Stop treating `plugins/puppeteer` as the source of truth.** Don't hand-edit it as if live and don't- `release-bridge.sh puppeteer` from the adom-desktop repo anymore (it would clobber the cloud-owned+ `release-bridge.sh puppeteer` from the adom-bridge-cli repo anymore (it would clobber the cloud-owned page). pup is now in the same bucket as kicad/fusion in `BRIDGE_OWNERSHIP.md` / `release-publish.sh` SKILLS_SRC — please add the same guard. (Also: pup's consumer SKILL now ships from the bridge's own wiki page, so drop `pup-SKILL.md` from the AD-core pkg's SKILLS_SRC to avoid a stale copy clobbering ours — same move you made for kicad/fusion.) **ALSO remove `"puppeteer"` from `AD_CORE_SKILL_BRIDGES` in `bridge_registry.rs`** so `bridge_list` reports- `skillPkg = adom/adom-desktop-puppeteer-bridge` for the puppeteer bridge — that's what makes the daily+ `skillPkg = adom/pup-bridge` for the puppeteer bridge — that's what makes the daily `sync_skills` auto-install the pup skills into every container. It's hardcoded `null` (skill-in-core) today, which is no longer true now that the skill ships from the pup page. @@ -78,13 +78,13 @@ above) → adom-desktop, but don't re-absorb the bridge. ## ALSO: the bridge-authoring docs are stale — please update them (affects EVERY new bridge author) -A new user asking "make me an adom-desktop bridge for <X>" gets pointed at: the **`adom-desktop-bridges`**+A new user asking "make me an adom-bridge-cli bridge for <X>" gets pointed at: the **`adom-bridge-sdk`** Bridge SDK guide (#1 discovery hit), the **`adom-desktop-bridge-author`** skill, and the repo's **`skills/BRIDGE_SDK.md`** (source). The RUNTIME guidance (bridge.json, verbs, health chip, rich hints, lifecycle) is good + current. But the PUBLISH/PACKAGING guidance is outdated — and in one place WRONG. These are AD-core-owned (we won't touch them, same as you don't touch pup), so please fix all three: -1. **WRONG — "zip/bin under `/files`".** `BRIDGE_SDK.md` "Publish + iterate" (and the `adom-desktop-bridges`+1. **WRONG — "zip/bin under `/files`".** `BRIDGE_SDK.md` "Publish + iterate" (and the `adom-bridge-sdk` page) tell authors the bridge zip goes on the page's `/files`. It does NOT — `/files` strips/rejects binaries. The zip is a **RELEASE asset** (`adom-wiki release create` + `release upload`); the manifest's `url` points at the release download URL with a matching `sha256`/`size`. (This is what fusion/kicad/pup@@ -108,12 +108,12 @@ These are AD-core-owned (we won't touch them, same as you don't touch pup), so p so "open my app in <X>" surfaces the page; the discover snippet is auto-generated from `discovery_triggers` + `discovery_pitch` (no separate upload step). -6. **STALE URL — the retired wiki host.** Both the `adom-desktop-bridges` page AND the+6. **STALE URL — the retired wiki host.** Both the `adom-bridge-sdk` page AND the `adom-desktop-bridge-author` skill still cite **`wiki-ufypy5dpx93o.adom.cloud`** (retired). The only host is `wiki.adom.inc`. Grep + scrub (incl. the `page.json` `readme` body). **Easiest path:** lift the content from the pup bridge's now-canonical publish playbook —-`wiki.adom.inc/adom/adom-desktop-puppeteer-bridge` → `dev-skills/pup-bridge-publish.md` (it carries all six+`wiki.adom.inc/adom/pup-bridge` → `dev-skills/pup-bridge-publish.md` (it carries all six points above, battle-tested) — and generalize the pup-specifics into the SDK guide. ---
HANDOFF-notify-for-bridges.md+2−2@@ -1,6 +1,6 @@ # Handoff to Bridge: expose ALL AD verbs to bridges via the direct-API -**From:** pup (adom-desktop-puppeteer-bridge)+**From:** pup (pup-bridge) **TL;DR:** A bridge should be able to call **any** AD verb the CLI can, through the loopback direct-API (`127.0.0.1:47200`). Today it can only reach a **subset** (`desktop_*` + other bridges' verbs). That's why pup can't fire `notify_user` to walk a@@ -75,4 +75,4 @@ pup probes `GET /commands` for `notify_user` and caches the result (`readiness.chromeStableNotifyChannel`). The moment the verb appears, pup's notify-first UAC flow activates with **zero pup release** for the local case. Cross-AD `target` is a tiny pup follow-up once the arg is finalized. Full context:-`adom/adom-desktop-puppeteer-bridge` repo.+`adom/pup-bridge` repo.
PROPOSAL-shared-runtimes.md+1−1@@ -1,6 +1,6 @@ # Proposal: AD-managed shared runtimes (portable Node + Python) for all bridges -**Status:** proposal to the adom-desktop (AD) build thread. Authored from the pup bridge after a full+**Status:** proposal to the adom-bridge-cli (AD) build thread. Authored from the pup bridge after a full cold-start debugging pass on three fresh Windows boxes (AdomLapper, AdomTestWin11 vbox, winvm Azure). **Owner of the fix:** AD core (bridge runtime provisioning + spawn). Bridges only *declare* their need.
PUBLISHING.md+8−8@@ -40,9 +40,9 @@ print("sha256:", hashlib.sha256(open(out,"rb").read()).hexdigest(), "size:", os. ## 3 — publish the zip as a RELEASE asset (preserves your sha) ```bash-adom-wiki release create adom/adom-desktop-puppeteer-bridge 1.1.1 # idempotent-adom-wiki release upload adom/adom-desktop-puppeteer-bridge 1.1.1 adom-bridge-puppeteer-v1.1.1.zip --json-# JSON gives sha256, size, download_url (/download/adom/adom-desktop-puppeteer-bridge/1.1.1/<file>)+adom-wiki release create adom/pup-bridge 1.1.1 # idempotent+adom-wiki release upload adom/pup-bridge 1.1.1 adom-bridge-puppeteer-v1.1.1.zip --json+# JSON gives sha256, size, download_url (/download/adom/pup-bridge/1.1.1/<file>) ``` ## 4 — point the manifest at the release + push it (text, git-ok)@@ -50,14 +50,14 @@ adom-wiki release upload adom/adom-desktop-puppeteer-bridge 1.1.1 adom-bridge-p `adom-bridge-puppeteer-manifest.json`: ```json { "manifest_version": 1, "name": "puppeteer", "version": "1.1.1",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.1.1/adom-bridge-puppeteer-v1.1.1.zip",+ "url": "https://wiki.adom.inc/download/adom/pup-bridge/1.1.1/adom-bridge-puppeteer-v1.1.1.zip", "sha256": "<the release asset's sha256>", "size": <bytes>, "verbPrefixes": ["pup_","desktop_recorder_","desktop_record_"], "healthEndpoint": "/status", "statusVerb": "pup_readiness", "released_at": "<UTC ISO8601>" } ``` ```bash-adom-wiki repo push adom/adom-desktop-puppeteer-bridge \+adom-wiki repo push adom/pup-bridge \ --files adom-bridge-puppeteer-manifest.json src/bridge.json src/BRIDGE_VERSION src/server.js src/chrome.js SKILL.md \ -m "v1.1.1: <what changed>" ```@@ -68,12 +68,12 @@ adom-wiki repo push adom/adom-desktop-puppeteer-bridge \ ## 5 — install into Bridge + test ```bash-adom-desktop bridge_install '{"manifestUrl":"https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/adom-bridge-puppeteer-manifest.json","force":true}'+adom-bridge-cli bridge_install '{"manifestUrl":"https://wiki.adom.inc/api/v1/pages/pup-bridge/files/adom-bridge-puppeteer-manifest.json","force":true}' # server-only change → AD reaps + respawns the bridge from the new cache on the next pup_* call.-# Then: adom-desktop pup_readiness '{}' (confirms the new verbs/code are live)+# Then: adom-bridge-cli pup_readiness '{}' (confirms the new verbs/code are live) ``` -(Multiple desktops on one relay → pass `--target <name>`; `adom-desktop targets` lists them.)+(Multiple desktops on one relay → pass `--target <name>`; `adom-bridge-cli targets` lists them.) ## Pitfall checklist
README.md+19−19@@ -15,7 +15,7 @@ testing, acting as another user), but they build nothing: adom-you is the defaul > To drive the user's **real, signed-in** Chrome/Edge (their cookies, SSO, saved logins), that's the > **Adom browser extension's `nbrowser_*` verbs** — a separate bridge, not pup. -Canonical page: **https://wiki.adom.inc/adom/adom-desktop-puppeteer-bridge**+Canonical page: **https://wiki.adom.inc/adom/pup-bridge** ## Install vs Download — which is which (and why the version numbers differ) @@ -39,13 +39,13 @@ seed, superseded by a newer cache copy via `updateManifestUrl`. You never touch ```bash # everyday: open + screenshot. Opens in the BACKGROUND automatically — no need to lower it, # and it's fully drivable/screenshottable while hidden, so the user is never interrupted.-adom-desktop pup_open_window '{"sessionId":"myapp-web","owner":"myapp","url":"http://localhost:3000"}'-adom-desktop pup_screenshot '{"sessionId":"myapp-web"}'+adom-bridge-cli pup_open_window '{"sessionId":"myapp-web","owner":"myapp","url":"http://localhost:3000"}'+adom-bridge-cli pup_screenshot '{"sessionId":"myapp-web"}' # readiness (use pup_readiness, NOT pup_status). On a box with Chrome or Edge this is # instantly {ready:true} with no download. Only a box with no Chromium at all fetches Chrome for # Testing in the background — poll until ready, then open.-adom-desktop pup_readiness '{}' # → {ready:true, browserKind:"chrome"|"edge"|...}+adom-bridge-cli pup_readiness '{}' # → {ready:true, browserKind:"chrome"|"edge"|...} ``` - **Task-prefix your `sessionId` + pass `owner`** — sessions are shared across every AI thread on the@@ -102,8 +102,8 @@ real result. The five category icons above (`wiki`, `wiki-in`, `app`, `web`, `mi Fetch any asset from the wiki without cloning: ```-https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/assets/pup-icons/pup-cat-default.svg-https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/assets/pup-icons/manifest.json+https://wiki.adom.inc/api/v1/pages/pup-bridge/files/assets/pup-icons/pup-cat-default.svg+https://wiki.adom.inc/api/v1/pages/pup-bridge/files/assets/pup-icons/manifest.json ``` [`assets/pup-icons/manifest.json`](assets/pup-icons/manifest.json) is machine-readable: it maps each@@ -185,7 +185,7 @@ cookies; it never merges windows. pup can record what it drives — a **single tab/window** or the **whole desktop** — straight from the cloud, with no HUD and no need to bring the window forward. -+ *Above: a GIF preview of a real `pup_record` capture (≈8.6 s, the tab navigating the Adom wiki, recorded in the background on a VM). The native capture is the WebM linked below — this GIF is just an inline preview.* @@ -216,9 +216,9 @@ So it is **opt-in and leased**: | **`desktop_record_start` / `desktop_record_stop`** | the WHOLE **desktop** (multiple apps, dialogs) | Screen capture via **MediaRecorder** → one `.webm`; ffmpeg remuxes it to stamp a proper Duration. | ```bash-adom-desktop pup_record_start '{"sessionId":"demo-web"}' # → { recordingId }+adom-bridge-cli pup_record_start '{"sessionId":"demo-web"}' # → { recordingId } # ...drive the scene: navigate, click, type, scroll...-adom-desktop pup_record_stop '{"sessionId":"demo-web","recordingId":"<id>"}' # → { path: "...webm" }+adom-bridge-cli pup_record_stop '{"sessionId":"demo-web","recordingId":"<id>"}' # → { path: "...webm" } ``` **ffmpeg** is required for recording. The bridge auto-detects it (a WinGet `Gyan.FFmpeg` install, PATH,@@ -234,9 +234,9 @@ demo above (1264×705): | Format | Codec | Size | How you get it | Best for | Watch out for | |---|---|---|---|---|---|-| **WebM** ([view](https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/pup-recording-demo.webm)) | VP9 | **143 KB** | pup's **native** output — no step | Chrome/Edge/Firefox, small + high quality, the source of truth | Older **Safari**, PowerPoint, and some chat apps don't accept VP9/WebM |-| **MP4** ([view](https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/pup-recording-demo.mp4)) | H.264 | **135 KB** | transcode (below) | **Universal** — Safari, iOS, PowerPoint, Slack/Teams, "send it to anyone" | H.264 needs **even width & height** — odd dims (like 705) fail at frame 0; the `scale` filter forces even |-| **GIF** ([view](https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/pup-recording-demo.gif)) | — | **192 KB** | transcode (below) | Auto-playing, looping **inline preview** in any README/chat/GitHub — no player, no click (like the one above) | No audio, capped colors, and it balloons fast at higher fps/resolution/length — keep it short + downscaled |+| **WebM** ([view](https://wiki.adom.inc/api/v1/pages/pup-bridge/files/pup-recording-demo.webm)) | VP9 | **143 KB** | pup's **native** output — no step | Chrome/Edge/Firefox, small + high quality, the source of truth | Older **Safari**, PowerPoint, and some chat apps don't accept VP9/WebM |+| **MP4** ([view](https://wiki.adom.inc/api/v1/pages/pup-bridge/files/pup-recording-demo.mp4)) | H.264 | **135 KB** | transcode (below) | **Universal** — Safari, iOS, PowerPoint, Slack/Teams, "send it to anyone" | H.264 needs **even width & height** — odd dims (like 705) fail at frame 0; the `scale` filter forces even |+| **GIF** ([view](https://wiki.adom.inc/api/v1/pages/pup-bridge/files/pup-recording-demo.gif)) | — | **192 KB** | transcode (below) | Auto-playing, looping **inline preview** in any README/chat/GitHub — no player, no click (like the one above) | No audio, capped colors, and it balloons fast at higher fps/resolution/length — keep it short + downscaled | ```bash # → MP4 (H.264 — universal). The scale filter forces EVEN dimensions (H.264 rejects odd w/h → frame 0).@@ -251,10 +251,10 @@ PowerPoint/phone needs it; make a short **GIF** only for an inline auto-play pre ## Source & development -This bridge is cloud-owned here (extracted from `adom-desktop/plugins/puppeteer`, mirroring the+This bridge is cloud-owned here (extracted from `adom-bridge/plugins/puppeteer`, mirroring the kicad/fusion bridges). Bridge ships a bundled seed and auto-pulls newer versions from this page. -- Clone the source: `adom-wiki repo clone adom/adom-desktop-puppeteer-bridge`+- Clone the source: `adom-wiki repo clone adom/pup-bridge` - Runtime lives in `src/` (`server.js`, `chrome.js`, `bridge.json`, …); the release zip is `src/` at zip-root. - **Maintainer skills** (`pup-bridge-dev`, `pup-bridge-publish`) are **source-only** — in `dev-skills/` + `publish-skills/`, not shipped in the pkg (per the Bridge SDK a pkg ships only user skills). Skill map:@@ -278,22 +278,22 @@ domain widget)? You don't need write access here — surface it from this page w normal user skill so `pkg install` drops it into a container's `~/.claude/skills`. 2. **Drop a breadcrumb on this page** pointing at it: ```bash- adom-wiki breadcrumb post adom/adom-desktop-puppeteer-bridge \+ adom-wiki breadcrumb post adom/pup-bridge \ --label "Your skill name — one-line what it does" \ --target-url "https://wiki.adom.inc/<owner>/<your-slug>" \ --category "skill" ``` It's **pending until the page owner approves it**, then it shows in this page's **Breadcrumbs** tab. 3. **Discovery is automatic:** an agent working with pup can list related third-party skills with- `adom-wiki breadcrumb list adom/adom-desktop-puppeteer-bridge` — approved breadcrumbs are how pup finds+ `adom-wiki breadcrumb list adom/pup-bridge` — approved breadcrumbs are how pup finds community skills that build on it. Keep breadcrumbs on-topic (they genuinely extend pup / browser-driving); off-topic ones get rejected. ## Related -- [Bridge SDK guide](https://wiki.adom.inc/adom/adom-desktop-bridges) — `bridge.json` schema, packaging, lifecycle-- [KiCad bridge](https://wiki.adom.inc/adom/adom-desktop-kicad-bridge) · [Fusion 360 bridge](https://wiki.adom.inc/adom/adom-desktop-fusion-bridge)-- [Bridge (parent app)](https://wiki.adom.inc/adom/adom-desktop)+- [Bridge SDK guide](https://wiki.adom.inc/adom/adom-bridge-sdk) — `bridge.json` schema, packaging, lifecycle+- [KiCad bridge](https://wiki.adom.inc/adom/kicad-bridge) · [Fusion 360 bridge](https://wiki.adom.inc/adom/fusion-bridge)+- [Bridge (parent app)](https://wiki.adom.inc/adom/adom-bridge) MIT licensed.
SKILL.md+15−15@@ -1,17 +1,17 @@ --- name: pup user-invocable: true-description: "Drive a browser on the user's desktop from the cloud — the Puppeteer 'pup' bridge (pup_* verbs via the adom-desktop CLI). pup drives the browser ALREADY on the machine in a pup-managed DURABLE profile (logins/localStorage persist and are shared across pup windows; {isolated:true} for a throwaway) (installed Chrome, else Microsoft Edge — on Windows every PC has Edge, on macOS neither is guaranteed so a download may be needed), driven over CDP, in the BACKGROUND so it never disturbs the user; NOT the user's real signed-in profile (that's the Adom extension's nbrowser_* verbs), NOT headless (a real rendered window, so screenshots/recording are true-to-life). Chrome for Testing only as a last resort. Open/close windows + tabs, navigate, screenshot, eval JS, record. This is the START-HERE skill: the mental model + when-to-use + the skill map; deeper topics route to the sub-skills. For 'is it ready' use pup_readiness (not pup_status). Trigger words: pup, puppeteer, browser window, open in pup, open my app in pup, browser screenshot, browser eval, browser reload, visual debug, headful chrome, pup_open_window, pup_screenshot, pup_readiness, pup_prewarm, chrome for testing, open in browser, pup_login, log into a site in pup, autofill password, saved login, durable profile, isolated window."+description: "Drive a browser on the user's desktop from the cloud — the Puppeteer 'pup' bridge (pup_* verbs via the adom-bridge-cli CLI). pup drives the browser ALREADY on the machine in a pup-managed DURABLE profile (logins/localStorage persist and are shared across pup windows; {isolated:true} for a throwaway) (installed Chrome, else Microsoft Edge — on Windows every PC has Edge, on macOS neither is guaranteed so a download may be needed), driven over CDP, in the BACKGROUND so it never disturbs the user; NOT the user's real signed-in profile (that's the Adom extension's nbrowser_* verbs), NOT headless (a real rendered window, so screenshots/recording are true-to-life). Chrome for Testing only as a last resort. Open/close windows + tabs, navigate, screenshot, eval JS, record. This is the START-HERE skill: the mental model + when-to-use + the skill map; deeper topics route to the sub-skills. For 'is it ready' use pup_readiness (not pup_status). Trigger words: pup, puppeteer, browser window, open in pup, open my app in pup, browser screenshot, browser eval, browser reload, visual debug, headful chrome, pup_open_window, pup_screenshot, pup_readiness, pup_prewarm, chrome for testing, open in browser, pup_login, log into a site in pup, autofill password, saved login, durable profile, isolated window." --- # Pup — browser control on the user's desktop (start here) -Drive a browser on the user's desktop from a cloud container via the `adom-desktop` CLI. Every verb is a+Drive a browser on the user's desktop from a cloud container via the `adom-bridge-cli` CLI. Every verb is a **Bash command** (NOT an MCP tool): ```bash-adom-desktop --ai-thread "<your thread>" pup_open_window '{"sessionId":"mytask-web","url":"https://example.com"}'-adom-desktop --ai-thread "<your thread>" pup_screenshot '{"sessionId":"mytask-web"}'+adom-bridge-cli --ai-thread "<your thread>" pup_open_window '{"sessionId":"mytask-web","url":"https://example.com"}'+adom-bridge-cli --ai-thread "<your thread>" pup_screenshot '{"sessionId":"mytask-web"}' ``` ## THE CORE GOAL (John's words, so everyone truly understands it)@@ -233,9 +233,9 @@ repo — not shipped here.)* ```bash # Open in the BACKGROUND (automatic — never disturbs the user), then drive it invisibly.-adom-desktop --ai-thread "<your thread>" pup_open_window '{"sessionId":"mytask-web","url":"http://localhost:3000"}'-adom-desktop --ai-thread "<your thread>" pup_eval '{"sessionId":"mytask-web","expr":"document.title"}' # verify it really loaded-adom-desktop --ai-thread "<your thread>" pup_screenshot '{"sessionId":"mytask-web"}' # true-to-life PNG+adom-bridge-cli --ai-thread "<your thread>" pup_open_window '{"sessionId":"mytask-web","url":"http://localhost:3000"}'+adom-bridge-cli --ai-thread "<your thread>" pup_eval '{"sessionId":"mytask-web","expr":"document.title"}' # verify it really loaded+adom-bridge-cli --ai-thread "<your thread>" pup_screenshot '{"sessionId":"mytask-web"}' # true-to-life PNG ``` - **Your `--ai-thread` name IS the owner** — pup owns every window by the ai-thread that opened it, so@@ -316,7 +316,7 @@ threads; pass `wikiView:"authed"|"public"` on pup_open_window instead. Details: ## Key rules (the essentials — details in the sub-skills) - **Always pass `sessionId`** on session-scoped verbs — `'{}'` targets the *active* session, which may not- be the one you mean. There is no top-level `pup` subcommand; it's `adom-desktop pup_<cmd> <json>`.+ be the one you mean. There is no top-level `pup` subcommand; it's `adom-bridge-cli pup_<cmd> <json>`. **ONE DANGEROUS EXCEPTION: `pup_close`.** There `'{}'` does NOT mean "the active session" — it means **ALL sessions, every window, across every AI thread on the machine**, immediately and without confirmation. If you want to close one window it is `pup_close_window {"sessionId":"…"}`, never@@ -341,7 +341,7 @@ threads; pass `wikiView:"authed"|"public"` on pup_open_window instead. Details: window/tab verb does), then poll `pup_list_windows` with backoff until it answers. **Do NOT spam opens** while AD says `bridge_starting` — one is enough; it's already starting. (`bridge_list` `status:"running"` is not liveness; the LED + `browser.bridgeRunning` + an actual verb reply are.)-- Full machine-readable catalog: `adom-desktop --ai-thread "<your thread>" pup_describe '{}'`.+- Full machine-readable catalog: `adom-bridge-cli --ai-thread "<your thread>" pup_describe '{}'`. ## Verify what you rendered — pup checks it FOR you (v1.9.106) @@ -370,7 +370,7 @@ when you generated or edited the content, screenshot it anyway. ## Name your thread so the user can tell your window apart -Pass `--ai-thread "<what this conversation is>"` on every `adom-desktop` call (a global flag, like+Pass `--ai-thread "<what this conversation is>"` on every `adom-bridge-cli` call (a global flag, like `--target`). A typical user runs ~20 AI threads against one desktop, so pup puts your thread name at the FRONT of the window title (visible in the taskbar hover-preview header, which truncates ~25-30 chars) and in the hover tooltip alongside the container, browser and session. That is how the user knows which@@ -381,19 +381,19 @@ it names the shell rather than you. Responses carry `_reportIssues` on failures and on your first substantive verb. Reports from real machines are the only way this bridge gets correct:-`adom-wiki issue list adom/adom-desktop-puppeteer-bridge` to check for a duplicate, then-`adom-wiki issue create adom/adom-desktop-puppeteer-bridge --title "<symptom>" --category bug-report+`adom-wiki issue list adom/pup-bridge` to check for a duplicate, then+`adom-wiki issue create adom/pup-bridge --title "<symptom>" --category bug-report --body "<what you ran, expected, got, the VERBATIM response JSON, bridge version, OS>"`.-An AD-core problem (relay, bridge lifecycle, caller identity) goes to `adom/adom-desktop` instead.+An AD-core problem (relay, bridge lifecycle, caller identity) goes to `adom/adom-bridge` instead. -## Every adom-desktop call needs `--ai-thread`+## Every adom-bridge-cli call needs `--ai-thread` AD refuses any command that does not say which AI conversation is asking (`errorCode: caller_identity_required`). It is a **global flag**, like `--target`, and it goes before the verb: ```bash-adom-desktop --ai-thread "chip-fetcher tab 3" pup_open_window '{"sessionId":"cf-web","url":"..."}'+adom-bridge-cli --ai-thread "chip-fetcher tab 3" pup_open_window '{"sessionId":"cf-web","url":"..."}' ``` Pick a name the USER would recognise for this conversation, never a UUID. It is **attribution, not
dev-skills/pup-bridge-debug/SKILL.md+3−3@@ -18,7 +18,7 @@ All are AD-**core** verbs (they do NOT route through pup, so they answer even wh | Tool | What it tells you | |---|---|-| `adom-desktop --target <box> bridge_log_read '{"name":"puppeteer","lines":40}'` | **THE tell.** The AD lifecycle log (v1.9.93). Repeated `spawned process pid … (node.exe)` with **no reap between them** = pup is **self-crashing** and AD keeps respawning it. Note the cadence. |+| `adom-bridge-cli --target <box> bridge_log_read '{"name":"puppeteer","lines":40}'` | **THE tell.** The AD lifecycle log (v1.9.93). Repeated `spawned process pid … (node.exe)` with **no reap between them** = pup is **self-crashing** and AD keeps respawning it. Note the cadence. | | The AD GUI **bridge LED** | **Accurate liveness.** Dim = the pup process is not actively serving. Green = a verb spawned it and it's alive. | | `status` → `browser.bridgeRunning` | Corroborates the LED. `false` = pup not serving. | | `bridge_check_updates` → `liveVersion` / `staleProcess` | Version truth: `liveVersion` reads the RUNNING process's `/status`; `staleProcess:true` = running old code. |@@ -137,7 +137,7 @@ caption is REPLACED by the result caption rather than stacking). ## §AD verb works from the CLI but NOT from pup (direct-API verb subset, found v1.9.10) -**Symptom:** an AD verb (e.g. `desktop_caption`) works perfectly when tested via `adom-desktop <verb>`+**Symptom:** an AD verb (e.g. `desktop_caption`) works perfectly when tested via `adom-bridge-cli <verb>` from the container, but pup's `chrome.adCommand('<verb>', …)` silently does nothing. **Cause: the two paths hit DIFFERENT surfaces.** The container CLI goes through the **relay** (full verb set). pup's loopback `chrome.adCommand` hits AD's **direct API** (`~/.adom/direct-api-port`, e.g. `:62521`),@@ -774,7 +774,7 @@ Rules: disappears. A second right-click works and stays. Reproduces on EVERY pup window, every time, from a clean slate. The list CONTENT is correct when shown, and the tasks run. -**Status: not fixed. Tracked on `adom/adom-desktop#40`** (AD owns `desktop_set_window_identity` and the+**Status: not fixed. Tracked on `adom/adom-bridge#40`** (AD owns `desktop_set_window_identity` and the shell interaction). Four separate pup-side fixes were attempted and all failed. Before you "fix" this, read the eliminations — three of them cost a release each, and two of them I announced as fixes before verifying, which was wrong.
dev-skills/pup-bridge-dev/SKILL.md+32−32@@ -1,14 +1,14 @@ --- name: pup-bridge-dev-description: "DEVELOPER skill for building, publishing, and maintaining the Puppeteer (pup) bridge. NOT needed by general users — they want the `pup` skill. Read this when editing the bridge code, cutting a new version, publishing to the wiki, wiring the cold-start Chrome-for-Testing self-heal, or understanding the pkg-vs-release-vs-bundled artifact model. Trigger words: pup bridge dev, publish pup bridge, build puppeteer bridge, bridge_install pup, adom-desktop-puppeteer-bridge, cold-start self-heal, pup_readiness internals, pup release, pup manifest, ship pup bridge."+description: "DEVELOPER skill for building, publishing, and maintaining the Puppeteer (pup) bridge. NOT needed by general users — they want the `pup` skill. Read this when editing the bridge code, cutting a new version, publishing to the wiki, wiring the cold-start Chrome-for-Testing self-heal, or understanding the pkg-vs-release-vs-bundled artifact model. Trigger words: pup bridge dev, publish pup bridge, build puppeteer bridge, bridge_install pup, pup-bridge, cold-start self-heal, pup_readiness internals, pup release, pup manifest, ship pup bridge." --- -Parent skill: **adom-desktop-puppeteer-bridge**+Parent skill: **pup-bridge** # pup-bridge-dev — building & shipping the Puppeteer bridge The canonical source of truth for the pup bridge is **this wiki repo**-(`wiki.adom.inc/adom/adom-desktop-puppeteer-bridge`), extracted from `adom-desktop/plugins/puppeteer`+(`wiki.adom.inc/adom/pup-bridge`), extracted from `adom-bridge/plugins/puppeteer` on 2026-06-29 to be cloud-owned like the kicad/fusion bridges. Read `CLAUDE.md` (ownership boundary) and `PUBLISHING.md` (step-by-step recipe) in this repo alongside this skill. @@ -51,7 +51,7 @@ A user installs TWO different things from this one page. They are not the same: | Artifact | What it is | Who installs it | How | |---|---|---|---|-| **pkg tarball** (Packages tab) | the **container-side Claude skills** (`SKILL.md` + `skills/*`) — docs that teach the cloud AI how to drive pup. **No bridge runtime.** | a cloud **container** | `adom-wiki pkg install adom/adom-desktop-puppeteer-bridge`, or auto via AD's `sync_skills` |+| **pkg tarball** (Packages tab) | the **container-side Claude skills** (`SKILL.md` + `skills/*`) — docs that teach the cloud AI how to drive pup. **No bridge runtime.** | a cloud **container** | `adom-wiki pkg install adom/pup-bridge`, or auto via AD's `sync_skills` | | **release zip** (Releases tab) | the **bridge RUNTIME** (`server.js`, `chrome.js`, `bridge.json`, node deps reconstructed on spawn) — the code that actually drives Chrome on the desktop | **Bridge**, streamed into `bridges-cache\puppeteer` | `bridge_install {manifestUrl}` / `refresh_bridges` (via `updateManifestUrl`) | | **bundled seed** (inside the AD installer) | a copy of the same runtime, shipped in the NSIS for first-run/offline | every AD install | ships with Bridge; superseded by a newer cache copy (cache-over-bundled, numeric version) | @@ -65,10 +65,10 @@ The full chain when a user on a fresh container says *"open my app in pup"*: 1. **Discovery.** The wiki's `discover` index (fed by this page's `discovery_triggers` — which now lead with `pup`, `open in pup`, `open my app in pup`, screenshot/record/tabs) matches the phrase. The container's regenerated `adom-wiki-discover` skill surfaces this page, so the AI proposes it.-2. **Auto-install the pkg.** The AI runs `adom-wiki skills install adom/adom-desktop-puppeteer-bridge`+2. **Auto-install the pkg.** The AI runs `adom-wiki skills install adom/pup-bridge` (a.k.a. `pkg install`). That extracts the tarball and runs `install.sh`, which drops `SKILL.md` + `skills/*` into **both `~/.claude/skills/` and `~/.codex/skills/`**. The `pup` skill is now loaded.-3. **The skill calls the bridge.** `pup`'s SKILL.md tells the AI to run `adom-desktop pup_*` verbs.+3. **The skill calls the bridge.** `pup`'s SKILL.md tells the AI to run `adom-bridge-cli pup_*` verbs. AD routes `pup_*` to the puppeteer bridge. 4. **The bridge runtime.** It's already on the desktop: AD ships pup as a **bundled seed** (and supersedes it from this page's release zip via `updateManifestUrl` / `bridge_install`). On a truly fresh PC the@@ -79,7 +79,7 @@ The full chain when a user on a fresh container says *"open my app in pup"*: discover index is regenerated. This is the "user said pup → AI installs the skill" path. - **AD `sync_skills` path** — AD's daily `maybe_background_skill_sync` reads `bridge_list` → each bridge's `skillPkg` → `pkg install`s it into the container. For pup this requires AD to report- `skillPkg = adom/adom-desktop-puppeteer-bridge` for the `puppeteer` bridge. **Today AD hardcodes it to+ `skillPkg = adom/pup-bridge` for the `puppeteer` bridge. **Today AD hardcodes it to `null`** (`AD_CORE_SKILL_BRIDGES = ["puppeteer"]` in `bridge_registry.rs`, from when pup's skill lived in the AD-core pkg). That must be removed now that the skill ships from this page — it's in the AD handoff. @@ -124,7 +124,7 @@ degraded path exists). Contract: - `src/` — the runnable bridge (what the release zip contains, at zip-root). `server.js`, `chrome.js`, `credential_vault.js`, `bridge.json`, `BRIDGE_VERSION`, node `package.json`/`package-lock.json`, html/icons.-- `SKILL.md` (root) — the **user** skill (`name: pup`). Deployed to `~/.claude/skills/adom-desktop-puppeteer-bridge/`.+- `SKILL.md` (root) — the **user** skill (`name: pup`). Deployed to `~/.claude/skills/pup-bridge/`. - `dev-skills/pup-bridge-dev/SKILL.md` — THIS dev skill. `publish-skills/pup-bridge-publish/SKILL.md` — the publish recipe. Per the Bridge SDK, a pkg ships ONLY user skills, so these are **source-only**: in the repo (read via `repo clone` / Files tab), NOT in `package.json files[]`, NOT installed by@@ -206,7 +206,7 @@ What we learned and baked into the code: **AD ≥ 1.9.86 addendum:** every gate-hit now auto-surfaces the in-window approval dialog + toast + taskbar flash on the target box (1.9.84 briefly regressed to a silent `human_only` refusal with NO prompt — bricked shell on headless/RDP boxes). On `needs_approval`/`human_only`: run- `adom-desktop --target <box> request_shell_approval` (re-surfaces the dialog + foregrounds AD;+ `adom-bridge-cli --target <box> request_shell_approval` (re-surfaces the dialog + foregrounds AD; surfaces only, never grants), have the human click Approve/Bypass, then RETRY the original verb. Never call `shell_auto_approve` — it's human-only and refuses by design. - **Windows Firewall prompt = bind loopback (fixed v1.6.0).** A hostless `server.listen(PORT)` binds ALL@@ -253,7 +253,7 @@ What we learned and baked into the code: reading the third saw pre-update text. When auditing against a doc, verify the EXACT file you read; when publishing multi-copy docs, push and verify every copy. -## Cross-repo issues — file an AD-core bug on adom/adom-desktop, NOT on your own page (John, 2026-07-24)+## Cross-repo issues — file an AD-core bug on adom/adom-bridge, NOT on your own page (John, 2026-07-24) You depend MASSIVELY on AD-core (it spawns you, provisions your Node runtime, relays your verbs, installs you), so you will hit AD bugs constantly during pup dev. This is common enough that getting the@@ -262,34 +262,34 @@ DESTINATION right is its own discipline. The rule, verified with a live mistake: **An issue lives on the issue list of the repo that OWNS the code that must change.** - A pup bug (a `pup_*` verb, a hint, the CfT self-heal, the status chip) is YOURS: fix it here, or- track it on the pup page (`adom/adom-desktop-puppeteer-bridge`).+ track it on the pup page (`adom/pup-bridge`). - An AD-CORE gap (a lifecycle verb, spawn / provision / bind behavior, `preserve_client_deps`, the relay dropping a response field, the stdout capture, `bridge_log_read`, a manifest field AD must honor) goes- on **`adom/adom-desktop`'s issue list**, NOT the pup page. The AD-core thread watches its OWN page and+ on **`adom/adom-bridge`'s issue list**, NOT the pup page. The AD-core thread watches its OWN page and does NOT read pup's issues. An AD ask on the pup page is a note to yourself that nobody who can fix it will ever see. - A wiki or CLI bug goes on `adom/wiki`. A sibling bridge bug goes on that bridge's page. **The live mistake (2026-07-24):** three AD-core lifecycle asks (npm-install-on-lockfile-change, stdout log rotation, `bridge_log_read` interleaving) were filed as pup issue #18 (a self-note), then-moved to `adom/adom-desktop#28`. The Bridge-SDK template ask went to `adom/adom-desktop#29`. Precedent-that adom/adom-desktop IS the right home for pup->AD asks: AD #26/#27 (CfT), #16 (window-verb+moved to `adom/adom-bridge#28`. The Bridge-SDK template ask went to `adom/adom-bridge#29`. Precedent+that adom/adom-bridge IS the right home for pup->AD asks: AD #26/#27 (CfT), #16 (window-verb interception), #3/#20/#21 (Bridge SDK). **How:** ```bash-adom-wiki issue list adom/adom-desktop # FIRST: skim for a dup, comment instead of re-filing-adom-wiki issue create adom/adom-desktop \+adom-wiki issue list adom/adom-bridge # FIRST: skim for a dup, comment instead of re-filing+adom-wiki issue create adom/adom-bridge \ --title "<verb or subsystem>: <the gap in one line>" \ --category bug-report \ --body "$(cat writeup.md)" # what you hit live + date + AD version + root cause + ask # close/comment take the GLOBAL discussion id (the "id" field), NOT the per-page "number":-# adom-wiki issue close <globalId> --comment "moved to adom/adom-desktop#N"+# adom-wiki issue close <globalId> --comment "moved to adom/adom-bridge#N" ``` Separate what is AD-core's from what is yours IN the body, so the two are never conflated. After filing, read the AD-core reply on that thread (it may change your plan, e.g. "fixed in AD X.Y, bump your pin"): that issue is the cross-repo channel, keep the loop closed there. See the CLAUDE.md-"You vs adom-desktop (AD) core" boundary for capability-vs-policy calls.+"You vs adom-bridge-cli (AD) core" boundary for capability-vs-policy calls. ## ⛔ THE IRON LAW OF WINDOW PLACEMENT (John, verbatim, 2026-07-31 — the ~100th time he has had to say it) @@ -744,7 +744,7 @@ downloads-and-restarts in one step for the UPDATE path; `restart_bridge` is the launch dedup (#1); AD's 30s relay timeout + the dim LED just made a pup bug VISIBLE. Own it. **4. The ~60s respawn LOOP (crash-poison session file, fixed v1.9.6 — the deeper root cause).** The-AD build thread read the lifecycle log (`adom-desktop bridge_log_read {name:"puppeteer"}`) and saw+AD build thread read the lifecycle log (`adom-bridge-cli bridge_log_read {name:"puppeteer"}`) and saw pup being **spawned every ~60s with no reap** — i.e. the process was dying on its OWN and AD's supervisor kept respawning it, even while idle. Cause: `recoverSessions()` runs on every boot and reconnects to Chromes named in `~/.adom/pup-sessions/*.json`. If a recovery op crashes pup@@ -827,9 +827,9 @@ Full recipe in `PUBLISHING.md`. The load-bearing rules: ## Testing a new version on a real desktop ```bash-adom-desktop targets # multiple desktops → --target <name> is required-adom-desktop --target <name> bridge_install '{"manifestUrl":"https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/adom-bridge-puppeteer-manifest.json","force":true}'-adom-desktop --target <name> pup_readiness '{}' # proves the new code is live+adom-bridge-cli targets # multiple desktops → --target <name> is required+adom-bridge-cli --target <name> bridge_install '{"manifestUrl":"https://wiki.adom.inc/api/v1/pages/pup-bridge/files/adom-bridge-puppeteer-manifest.json","force":true}'+adom-bridge-cli --target <name> pup_readiness '{}' # proves the new code is live ``` - **No Node on the box** → `pup_*` returns `node_not_found` before the bridge spawns (AD core; correct).@@ -842,8 +842,8 @@ adom-desktop --target <name> pup_readiness '{}' # proves the new code is live ## Don't -- Don't edit `adom-desktop/plugins/puppeteer` as if it's live, and don't `release-bridge.sh puppeteer`- from the adom-desktop repo — that clobbers this cloud-owned page.+- Don't edit `adom-bridge/plugins/puppeteer` as if it's live, and don't `release-bridge.sh puppeteer`+ from the adom-bridge-cli repo — that clobbers this cloud-owned page. - Don't ship the bridge runtime in the pkg tarball or the skills in the release zip. Two artifacts, two homes. - Don't install 'stable' Chrome — pin to puppeteer's expected buildId (`chrome.js` does this). @@ -924,7 +924,7 @@ saw CfT show the same dialog, and launch flags became the real fix (they apply t too). What was left for CfT was **version determinism** and **a clean binary we fully control**. Weighed against the costs — a build that goes stale (fleet was 6 majors behind on 146 while stable was 152), a fragile ~150 MB download, and the fleet dep-bump needed to move it (blocked by AD `preserve_client_deps`,-adom/adom-desktop#28) — those advantages matter mainly for a MANAGED/enterprise fleet with policy-bound+adom/adom-bridge#28) — those advantages matter mainly for a MANAGED/enterprise fleet with policy-bound Chrome. For the Adom individual user base (unmanaged Chrome, Edge always present), native-first wins: no download, always the user's current battle-tested build, and every taskbar icon/identity override works on it identically (OS-window level, browser-agnostic — verified: John's box drove native Chrome 150 fully@@ -1067,7 +1067,7 @@ Caught by Kyle 2026-07-24: pup's published **skills package was 17 releases behi version after 1.9.74 returns **404** at `/api/v1/packages/adom/<slug>/<ver>/tarball` — those are release tags, not packages. So `pkg install` silently resolved to the **1.9.74** tarball: stale docs, and a published `install.sh` that wrote the start-here skill to-`~/.claude/skills/adom-desktop-puppeteer-bridge/` while its own `SKILL.md` declares `name: pup` — a+`~/.claude/skills/pup-bridge/` while its own `SKILL.md` declares `name: pup` — a slug that contradicts its frontmatter, its trigger words, and every cross-reference in the sub-skills. **The trap:** `release create` + `release upload` ships the RUNTIME. It does nothing for the SKILLS@@ -1091,7 +1091,7 @@ versions, concurrent agents, a Mac, a stalled download. So pup ASKS for reports, in the place the AI actually reads (the SDK's first principle: the caller reads your OUTPUT, never your on-disk skill). `_reportIssues` carries the repo slug, the exact `adom-wiki issue list` / `issue create` commands, and what evidence to include (verbatim response JSON +-bridge version + OS). It also routes AD-core problems to `adom/adom-desktop` so reports land on the repo+bridge version + OS). It also routes AD-core problems to `adom/adom-bridge` so reports land on the repo that owns the code. Opt out: `pup_configure {reportIssues:"off"}`. **Throttling is the whole design.** A line on every response trains the caller to skip the field; a line@@ -1133,7 +1133,7 @@ DURABLY that breaks.** Measured all three forms on this container: | form | works? | scope | |---|---|---|-| `ADOM_AI_THREAD="<name>" adom-desktop …` (prefix, no export) | yes | that ONE process — leaks nothing |+| `ADOM_AI_THREAD="<name>" adom-bridge-cli …` (prefix, no export) | yes | that ONE process — leaks nothing | | a bare call right after that prefix | refused | confirms the prefix is scoped | | `export` then N calls inside ONE shell invocation | yes, all N | that invocation only | | `'{"caller":{"aiThread":"<name>"}}'` or flat `'{"aiThread":"<name>"}'` in args | yes | that call |@@ -1162,7 +1162,7 @@ persistent multi-thread container the natural way to satisfy that is a profile e never executed. If an env var you set in a profile appears to have no effect, check that guard before anything else. - **Verify a config change took effect in a FRESH shell, don't assume the write was the fix.** I claimed- the profile fix worked; one `echo` of the variable proved it hadn't. Reported as adom/adom-desktop#37,+ the profile fix worked; one `echo` of the variable proved it hadn't. Reported as adom/adom-bridge#37, asking for a global `--ai-thread` flag so the CORRECT mechanism is also the ergonomic one. ## Shipping behavior means shipping DOCS: skills, then pkg, then release (John, 2026-07-25)@@ -1218,9 +1218,9 @@ observation exercises identity registration, the window stamp, the jump list and single shot, and it is the cheapest possible regression net for this bridge: ```bash-adom-desktop --target <box> --ai-thread "<you>" pup_open_window '{"sessionId":"smoke","url":"https://example.com"}'-adom-desktop --target <box> --ai-thread "<you>" bridge_log_read '{"name":"puppeteer","lines":40}' # expect "stamped appId=", NOT "stamp FAILED"-adom-desktop --target <box> --ai-thread "<you>" desktop_find_window '{"titleContains":"session: smoke"}' # rect.left must NOT be ~-32768+adom-bridge-cli --target <box> --ai-thread "<you>" pup_open_window '{"sessionId":"smoke","url":"https://example.com"}'+adom-bridge-cli --target <box> --ai-thread "<you>" bridge_log_read '{"name":"puppeteer","lines":40}' # expect "stamped appId=", NOT "stamp FAILED"+adom-bridge-cli --target <box> --ai-thread "<you>" desktop_find_window '{"titleContains":"session: smoke"}' # rect.left must NOT be ~-32768 ``` `stamp FAILED` in the log and a `rect.left` of -32768 are the two tells. Both are one call away and both
dev-skills/pup-bridge-test/SKILL.md+1−1@@ -67,7 +67,7 @@ Rules that apply to EVERY scenario (each one was paid for): have grown unless a new operation ran. Target boilerplate: `T="pup bridge maintenance"` and every call is-`adom-desktop --target AdomLapper --ai-thread "<thread>" <verb> '<json>'`.+`adom-bridge-cli --target AdomLapper --ai-thread "<thread>" <verb> '<json>'`. ## 1. Smoke (after every ship) Open (no sessionId, thread-identified) → eval `1+1` → screenshot → close.
dev-skills/pup-browser-import/SKILL.md+4−4@@ -8,7 +8,7 @@ description: How to import a user's existing Chrome logins (passwords, cookies/s ## ✅ NOW LIVE (2026-08-04) — AD shipped the decrypt helper The elevated decrypt (the whole blocker below) landed in **Bridge v1.9.220** as-**`desktop_decrypt_pup_credentials`** (this was adom/adom-desktop #51). The pup side is wired:+**`desktop_decrypt_pup_credentials`** (this was adom/adom-bridge #51). The pup side is wired: the dashboard Settings → "Import logins from Chrome / Edge" picker (from `pup_import_scan`) → Import button → `import-run` action → `chrome.adCommand('desktop_decrypt_pup_credentials', …)` → `credentialVault.mergeImportedCredentials(rows)`.@@ -16,7 +16,7 @@ Import button → `import-run` action → `chrome.adCommand('desktop_decrypt_pup **THE ONE RULE THAT MATTERS: call it LOCALLY, never over the relay.** It is a loopback/bridge-only verb. `chrome.adCommand` already routes over AD's **direct API** (127.0.0.1:47200 from `~/.adom/direct-api-port`), which is the correct local path — so calling it from the bridge is right.-A relayed/cloud call (e.g. `adom-desktop --target … desktop_decrypt_pup_credentials` from the+A relayed/cloud call (e.g. `adom-bridge-cli --target … desktop_decrypt_pup_credentials` from the container) is REFUSED with `errorCode: relay_forbidden` and pops NO UAC. AD fires its OWN consent dialog (names the caller) + a UAC prompt — that UAC **is** the user's permission for the decrypt. @@ -64,7 +64,7 @@ key a normal user process can unwrap. Instead: ### Measured reality on John's Chrome 150 (2026-08-03) -Probed via `adom-desktop shell_execute` (PowerShell + the desktop's Python, which parsed the actual+Probed via `adom-bridge-cli shell_execute` (PowerShell + the desktop's Python, which parsed the actual `Login Data` SQLite): - `chrome_version = 150.0.7871.187`@@ -149,7 +149,7 @@ ONCE, decrypt EVERY profile with it. (blocked by the managed-profile device policy — see below). Never write a plaintext CSV/file. Decrypt in memory, hand to the vault, zero the buffers. 5. **DECISION 3 (locked) — ownership:** the elevated SYSTEM decrypt helper is **AD-core** (file- against adom/adom-desktop); pup owns discovery-surfacing, the merge, the vault, and the UX.+ against adom/adom-bridge); pup owns discovery-surfacing, the merge, the vault, and the UX. 6. **Cookies: attempt, but treat failure as normal.** Same SYSTEM helper can try each profile's `Cookies` store (`Network\Cookies`, `v20`, same per-browser master key). On a managed profile expect the "device security policy" refusal - surface it honestly per-item (Codex-style), do not fail the
dev-skills/pup-differential-diagnosis/SKILL.md+2−2@@ -57,9 +57,9 @@ overlap (a migration, a batch, an audit loop). So the real repro is **concurrent ```bash # fire N heavy opens at once, then poll the bridge the whole time — it must stay responsive-for n in 1 2 3 4; do ( adom-desktop --target <host> --ai-thread stress pup_open_window \+for n in 1 2 3 4; do ( adom-bridge-cli --target <host> --ai-thread stress pup_open_window \ "{\"sessionId\":\"stress-$n\",\"url\":\"<heavy url>?s=$n\"}" & ); done-for i in $(seq 1 10); do adom-desktop --target <host> pup_readiness '{"reason":"probe"}'; sleep 3; done+for i in $(seq 1 10); do adom-bridge-cli --target <host> pup_readiness '{"reason":"probe"}'; sleep 3; done ``` If the probes stay `ready` through the load, the bridge is healthy under it. A `DROP` / `error sending
publish-skills/pup-bridge-publish/SKILL.md+23−23@@ -1,13 +1,13 @@ --- name: pup-bridge-publish-description: "DEVELOPER skill — the exact, battle-tested recipe for publishing a new version of the Puppeteer (pup) bridge to wiki.adom.inc, plus every gotcha hit live. NOT for general users. Read before cutting a release: which artifact goes where (pkg=skills, release=bridge zip), version-lockstep, the `files` allowlist, keeping the tarball lean (NO zip / NO src / NO heroes / NO node deps), the pkg ships ONLY the pup USER skill (dev/publish skills are source-only in dev-skills/ + publish-skills/, never in the pkg — open-vs-closed source doesn't matter), the skillpack package.json declaring dependencies:{ adom/adom-desktop } to pull the AD CLI + core skills, deploying skills to .claude AND .codex, scrubbing stale retired-wiki (wiki-ufypy5dpx93o.adom.cloud) URLs, user-first discovery triggers, sha matching, and verify steps. Trigger words: publish pup bridge, ship pup bridge, release pup, pkg publish, repo push, adom-wiki release, bridge manifest, pup version bump, no zip in tarball, dev skill source only, scrub old wiki url, codex skills, discovery triggers, adom-desktop-puppeteer-bridge publish."+description: "DEVELOPER skill — the exact, battle-tested recipe for publishing a new version of the Puppeteer (pup) bridge to wiki.adom.inc, plus every gotcha hit live. NOT for general users. Read before cutting a release: which artifact goes where (pkg=skills, release=bridge zip), version-lockstep, the `files` allowlist, keeping the tarball lean (NO zip / NO src / NO heroes / NO node deps), the pkg ships ONLY the pup USER skill (dev/publish skills are source-only in dev-skills/ + publish-skills/, never in the pkg — open-vs-closed source doesn't matter), the skillpack package.json declaring dependencies:{ adom/adom-bridge } to pull the AD CLI + core skills, deploying skills to .claude AND .codex, scrubbing stale retired-wiki (wiki-ufypy5dpx93o.adom.cloud) URLs, user-first discovery triggers, sha matching, and verify steps. Trigger words: publish pup bridge, ship pup bridge, release pup, pkg publish, repo push, adom-wiki release, bridge manifest, pup version bump, no zip in tarball, dev skill source only, scrub old wiki url, codex skills, discovery triggers, pup-bridge publish." --- -Parent skill: **adom-desktop-puppeteer-bridge**+Parent skill: **pup-bridge** # pup-bridge-publish — shipping a new pup bridge version -The pup bridge is cloud-owned at `wiki.adom.inc/adom/adom-desktop-puppeteer-bridge`. This is the+The pup bridge is cloud-owned at `wiki.adom.inc/adom/pup-bridge`. This is the step-by-step ship recipe + the traps that cost real time. Companion: `pup-bridge-dev` (architecture / ownership), `PUBLISHING.md` (terse recipe), `CLAUDE.md` (ownership boundary). @@ -40,7 +40,7 @@ sed -i 's/"version": "1.1.0"/"version": "1.1.1"/' src/bridge.json # bridge ru sed -i 's/"version": "1.1.0"/"version": "1.1.1"/' package.json # adompkg descriptor (the pkg) ``` `src/BRIDGE_VERSION` and `src/bridge.json` MUST match (AD uses BRIDGE_VERSION to detect a stale running-process). Keep the number **above** the seed in `adom-desktop/plugins/puppeteer` so cache-over-bundled wins.+process). Keep the number **above** the seed in `adom-bridge/plugins/puppeteer` so cache-over-bundled wins. ### 2. Build the bridge zip (source-only, `src/` at zip ROOT — no top-level dir) @@ -62,10 +62,10 @@ print("sha256:", hashlib.sha256(open(out,"rb").read()).hexdigest(), "size:", os. ### 3. Publish the zip as a Release (releases PRESERVE your sha) ```bash-adom-wiki release create adom/adom-desktop-puppeteer-bridge 1.1.1 --title "..." --changelog "<≥2 words>"-adom-wiki release upload adom/adom-desktop-puppeteer-bridge 1.1.1 adom-bridge-puppeteer-v1.1.1.zip --json+adom-wiki release create adom/pup-bridge 1.1.1 --title "..." --changelog "<≥2 words>"+adom-wiki release upload adom/pup-bridge 1.1.1 adom-bridge-puppeteer-v1.1.1.zip --json # the response's assets[].sha256/size are what the manifest MUST carry. Then VERIFY the PUBLIC url:-curl -sL https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.1.1/adom-bridge-puppeteer-v1.1.1.zip | sha256sum+curl -sL https://wiki.adom.inc/download/adom/pup-bridge/1.1.1/adom-bridge-puppeteer-v1.1.1.zip | sha256sum ``` ### 4. Point the manifest at the release + push it (git repo)@@ -74,7 +74,7 @@ Edit `adom-bridge-puppeteer-manifest.json` → `version`, `url` (the release dow `size` (from step 3 — **must match the served asset or `bridge_install` rejects it**). Then: ```bash-adom-wiki repo push adom/adom-desktop-puppeteer-bridge \+adom-wiki repo push adom/pup-bridge \ --files adom-bridge-puppeteer-manifest.json src/bridge.json src/BRIDGE_VERSION src/server.js src/chrome.js \ -m "v1.1.1: <what changed>" ```@@ -85,7 +85,7 @@ adom-wiki repo push adom/adom-desktop-puppeteer-bridge \ adom-wiki pkg pack # ALWAYS pack + inspect BEFORE publish tar tzf *.tgz # confirm: SKILL.md + skills/*/SKILL.md + install.sh, and NOTHING heavy adom-wiki pkg publish --org adom --version 1.1.1-adom-wiki pkg notes adom/[email protected] -m "Container skills: <what changed>"+adom-wiki pkg notes adom/[email protected] -m "Container skills: <what changed>" ``` The pkg description lives in the root **`package.json`** `description` — keep it explicit that this is@@ -137,7 +137,7 @@ the output and grep for `"status": "ok"`; do not print "installed" unless it's t **GATE 3 — the version ON DISK, not what install claimed.** ```bash-adom-desktop --target <name> shell_execute '{"command":"cmd /c type \"%LOCALAPPDATA%\\Bridge\\bridges-cache\\puppeteer\\BRIDGE_VERSION\"", "reason":"…"}'+adom-bridge-cli --target <name> shell_execute '{"command":"cmd /c type \"%LOCALAPPDATA%\\Bridge\\bridges-cache\\puppeteer\\BRIDGE_VERSION\"", "reason":"…"}' ``` (Use `cmd /c type`, not `powershell -File` — a damaged PS profile on some boxes drops `-File` to an interactive banner and burns the timeout.)@@ -151,9 +151,9 @@ npm-install-on-lockfile-change — filed in AD_REQUEST_bridge_staleness.md.) ```bash # manifest serves at the updateManifestUrl path (necessary, NOT sufficient — see Gate 1):-curl -s https://wiki.adom.inc/api/v1/pages/adom-desktop-puppeteer-bridge/files/adom-bridge-puppeteer-manifest.json | jq .sha256-adom-desktop --target <name> bridge_install '{"manifestUrl":".../files/adom-bridge-puppeteer-manifest.json","force":true}'-adom-desktop --target <name> pup_readiness '{}'+curl -s https://wiki.adom.inc/api/v1/pages/pup-bridge/files/adom-bridge-puppeteer-manifest.json | jq .sha256+adom-bridge-cli --target <name> bridge_install '{"manifestUrl":".../files/adom-bridge-puppeteer-manifest.json","force":true}'+adom-bridge-cli --target <name> pup_readiness '{}' # render the page in pup + READ the screenshot (curl 200 is NOT verification). Confirm version + Skills tab. ``` @@ -173,18 +173,18 @@ The Bridge SDK ("Where every file lives", corrected 2026-07-06) is authoritative **The pkg's `package.json` DECLARES its dependency on AD** so `pkg install` pulls the AD CLI + core skills into the container: ```jsonc-"dependencies": { "adom/adom-desktop": "^1.9.x" } // pkg dep — pulls the AD CLI + core skills+"dependencies": { "adom/adom-bridge": "^1.9.x" } // pkg dep — pulls the AD CLI + core skills ``` This is the ONE dependency the skillpack package.json carries. Your SERVER's npm deps (`puppeteer`, …) live ONLY in the Release zip's `src/package.json`, never here. **Verify after `adom-wiki pkg pack`:** `shipped 1 user skill(s)`; `tar tzf *.tgz` shows exactly `SKILL.md`, `install.sh`, `uninstall.sh`, `README.md`, `package.json` — **no `skills/`, no `dev-skills/`,-no `*.zip`, no `src/`, no `*.png`**; and `package.json` has `dependencies: { "adom/adom-desktop": … }`.+no `*.zip`, no `src/`, no `*.png`**; and `package.json` has `dependencies: { "adom/adom-bridge": … }`. History (so nobody re-thrashes this — it flipped 3×): the pkg ships ONLY the `pup` user skill; dev + publish are source-only in `dev-skills/`/`publish-skills/`; the skillpack `package.json` declares the-`adom/adom-desktop` dep. Settled 1.8.23 (2026-07-06) on the maintainer's corrected guidance.+`adom/adom-bridge` dep. Settled 1.8.23 (2026-07-06) on the maintainer's corrected guidance. ## Keep the pkg tarball LEAN — NO zip, NO src/, NO heroes @@ -193,7 +193,7 @@ hero PNGs, `node_modules`, or the dev/publish skills. Guards: the `package.json` (`SKILL.md`, `install.sh`, `uninstall.sh`, `README.md`, `package.json`) **plus** `.gitignore` (`*.zip`, `*.png`, `*.bundle`, `*.tgz`, the old `*-source.tar.gz`). **ALWAYS** `adom-wiki pkg pack` then `tar tzf *.tgz` and confirm: **no `*.zip`, no `src/`, no `*.png`, no `skills/`, no `dev-skills/`;-`shipped 1 user skill(s)`; and `package.json` has `dependencies: { "adom/adom-desktop": … }`**. ~12 KB is+`shipped 1 user skill(s)`; and `package.json` has `dependencies: { "adom/adom-bridge": … }`**. ~12 KB is right (one SKILL.md + scripts); MEGABYTES means a binary/`src/` leaked in (it was 16 MB before the guards). `rm -f *.tgz` after. @@ -218,7 +218,7 @@ Fix every hit (README + the `page.json` `readme` body are the usual culprits), t entity (not just local): ```bash-curl -s https://wiki.adom.inc/api/pages/adom/adom-desktop-puppeteer-bridge | grep -c wiki-ufypy5dpx93o # want 0+curl -s https://wiki.adom.inc/api/pages/adom/pup-bridge | grep -c wiki-ufypy5dpx93o # want 0 ``` Also `repo rm` any stale source-mirror artifacts left on the page (old `*-source.tar.gz` / `*.bundle`).@@ -229,8 +229,8 @@ Also `repo rm` any stale source-mirror artifacts left on the page (old `*-source - **Page:** `https://wiki.adom.inc/adom/<slug>` - **File (served, anon):** `https://wiki.adom.inc/api/v1/pages/<slug>/files/<name>` - **Release download:** `https://wiki.adom.inc/download/adom/<slug>/<ver>/<file>`-- **Sibling pages:** `/adom/adom-desktop-bridges`, `/adom/adom-desktop-kicad-bridge`,- `/adom/adom-desktop-fusion-bridge`, `/adom/adom-desktop`+- **Sibling pages:** `/adom/adom-bridge-sdk`, `/adom/kicad-bridge`,+ `/adom/fusion-bridge`, `/adom/adom-bridge` ## Discovery triggers — lead with everyday USER phrases @@ -260,7 +260,7 @@ bespoke `start_pup_bridge` npm-installs only the BUNDLED copy; the cache copy ge ## Final step of EVERY publish — show it in pup (standing rule) After any release/repo-push/pkg-publish, refresh the LIVE wiki page in a pup window the user can-see (`pup_navigate` the existing session to `https://wiki.adom.inc/adom/adom-desktop-puppeteer-bridge?v=<ver>`,+see (`pup_navigate` the existing session to `https://wiki.adom.inc/adom/pup-bridge?v=<ver>`, cache-busted), screenshot it, and hand over the link. Never report "published" without showing it. ## Binary/hero pushes: `ok:true, commit:null` = the server honored the repo .gitignore@@ -312,7 +312,7 @@ skills. A release does NOT ship skills. `adom-wiki pkg update` reported `STALE_INSTALL: the registry no longer resolves it` and skipped pup entirely. Nothing in the release pipeline noticed, because the release half was perfect. - Verify, do not assume:- `curl -s -o /dev/null -w "%{http_code}" https://wiki.adom.inc/api/v1/packages/adom/adom-desktop-puppeteer-bridge/<VER>/tarball`+ `curl -s -o /dev/null -w "%{http_code}" https://wiki.adom.inc/api/v1/packages/adom/pup-bridge/<VER>/tarball` must be **200**. `ship.sh` GATE 2b now checks this and warns, but the warning only helps if you read it. **3. THEN THE RELEASE ZIP + MANIFEST** (the existing recipe: bump BRIDGE_VERSION + bridge.json → build →@@ -326,5 +326,5 @@ and pkg you already published. ```bash grep -ciE '<new concept>' SKILL.md # 0 = the skill is stale, go back to step 1 python3 -c "import json;print(json.load(open('package.json'))['version'])" # must equal the release-curl -s -o /dev/null -w '%{http_code}\n' https://wiki.adom.inc/api/v1/packages/adom/adom-desktop-puppeteer-bridge/$(cat src/BRIDGE_VERSION)/tarball+curl -s -o /dev/null -w '%{http_code}\n' https://wiki.adom.inc/api/v1/packages/adom/pup-bridge/$(cat src/BRIDGE_VERSION)/tarball ```
skills/pup-adom-wiki/SKILL.md+4−4@@ -4,7 +4,7 @@ user-invocable: true description: "Driving the Adom wiki (wiki.adom.inc) inside a pup window — the common case of loading, viewing, and VERIFYING wiki pages with the pup_* verbs. Use when the user says show me the wiki / open my wiki page in pup / verify my page rendered / check the hero/version/download card / does my published page look right. Covers: pup shows the RENDERED page (use the adom-wiki CLI for API tasks like publish/search/releases — NOT pup); wiki pages are component-heavy with nested scroll, so use the shadow-DOM-survey + scroll-the-element techniques; and the LOGIN situation — every pup window shares ONE durable profile (v1.9.162), so once the user signs into the wiki once it stays logged in everywhere; wikiView:"public" is the explicit logged-OUT view for publish-visibility checks. Trigger words: adom wiki, wiki.adom.inc, show me the wiki, open the wiki in pup, open my wiki page, verify my wiki page, check my hero, wiki version chip, download card, wiki page rendered, is my page live, wiki login pup, log into the wiki." --- -**Parent skill:** adom-desktop-puppeteer-bridge · See also: `pup` (start here), `pup-screenshots-recording` (the tricky-pages techniques), the `adom-wiki` skill (the CLI for API work).+**Parent skill:** pup-bridge · See also: `pup` (start here), `pup-screenshots-recording` (the tricky-pages techniques), the `adom-wiki` skill (the CLI for API work). # pup — driving the Adom wiki @@ -23,9 +23,9 @@ download card is correct. This skill is the wiki-specific playbook. ```bash # Verify a page you just published (own the window, task-prefix the id):-adom-desktop pup_open_window '{"sessionId":"wiki-mypage","owner":"mypage","url":"https://wiki.adom.inc/adom/my-slug?v=1.2.3"}'-adom-desktop pup_eval '{"sessionId":"wiki-mypage","expr":"document.title"}' # confirm it loaded-adom-desktop pup_screenshot '{"sessionId":"wiki-mypage"}' # read it — did the hero/version render?+adom-bridge-cli pup_open_window '{"sessionId":"wiki-mypage","owner":"mypage","url":"https://wiki.adom.inc/adom/my-slug?v=1.2.3"}'+adom-bridge-cli pup_eval '{"sessionId":"wiki-mypage","expr":"document.title"}' # confirm it loaded+adom-bridge-cli pup_screenshot '{"sessionId":"wiki-mypage"}' # read it — did the hero/version render? ``` Reuse **one** window per page (stable `sessionId` like `wiki-<slug>`) so re-publishes refresh the same
skills/pup-browsers-and-chrome/SKILL.md+12−12@@ -4,7 +4,7 @@ user-invocable: true description: "How pup (Puppeteer bridge) picks and launches a browser, and every cold-start / readiness case. Covers: the installed-browser-first architecture (launches a FRESH CDP-driven process of installed Chrome → else Edge → else cached Chrome for Testing, spawn-verified with fallthrough, caches the winner as default); pup_use to pin chrome/edge/cft/auto; INSTALLING real Google Chrome on an Edge-only box (pup_use install:true) including the UAC-approval-notify flow on locked-down machines; installing/prewarming Chrome for Testing; pup_readiness (READ-ONLY — the right 'is it ready / which browser' probe, NOT pup_status); the cold-start error table (node_not_found, bridge_restarting, chrome_for_testing_installing, chrome_install_no_disk, CfT 'skipped' is not a failure); AD-managed Node provisioning (no install needed on AD >=1.9.63); and the shell-approval gate. Read on any browser-pick question, a fresh/first-run PC, an install/prewarm, a not-ready error, or a shell-approval prompt. Trigger words: pup_readiness, pup_use, pup_prewarm, chrome for testing, install chrome, chrome_for_testing_installing, node_not_found, bridge_restarting, chrome_install_no_disk, cold start pup, which browser, edge only box, UAC approve chrome, request_shell_approval, shell command approval, adom runtimes, pup not ready." --- -**Parent skill:** adom-desktop-puppeteer-bridge · See also: `pup` (start here), `pup-windows-sessions-tabs`, `pup-screenshots-recording`.+**Parent skill:** pup-bridge · See also: `pup` (start here), `pup-windows-sessions-tabs`, `pup-screenshots-recording`. # pup — browsers, Chrome install & cold-start @@ -28,7 +28,7 @@ builds a candidate list and **spawn-verifies** it: ## "Is it ready / which browser?" — `pup_readiness` (READ-ONLY) ```bash-adom-desktop pup_readiness '{}'+adom-bridge-cli pup_readiness '{}' # → {ready, browserKind:"chrome"|"edge"|"chrome-for-testing", browserSource, browserExecutablePath, # candidates:[…the full fallthrough list…], defaultBrowser, diskFreeMb, chromeStablePhase, …} ```@@ -43,10 +43,10 @@ adom-desktop pup_readiness '{}' pup auto-picks, but you can override (persists across restarts; launch still spawn-verifies + falls back): ```bash-adom-desktop pup_use '{"browser":"chrome"}' # pin installed Chrome-adom-desktop pup_use '{"browser":"edge"}' # pin Edge-adom-desktop pup_use '{"browser":"cft"}' # install Chrome for Testing (~150 MB once) + pin it-adom-desktop pup_use '{"browser":"auto"}' # back to auto-pick+adom-bridge-cli pup_use '{"browser":"chrome"}' # pin installed Chrome+adom-bridge-cli pup_use '{"browser":"edge"}' # pin Edge+adom-bridge-cli pup_use '{"browser":"cft"}' # install Chrome for Testing (~150 MB once) + pin it+adom-bridge-cli pup_use '{"browser":"auto"}' # back to auto-pick ``` Every `pup_open_window` response also carries `browser` (what was driven), `availableBrowsers`, and@@ -57,7 +57,7 @@ Every `pup_open_window` response also carries `browser` (what was driven), `avai If the user specifically wants Chrome: ```bash-adom-desktop pup_use '{"browser":"chrome","install":true}'+adom-bridge-cli pup_use '{"browser":"chrome","install":true}' ``` - Downloads Google's official installer and installs Chrome, then pins it. **On a normal PC this is@@ -75,8 +75,8 @@ adom-desktop pup_use '{"browser":"chrome","install":true}' ## Installing / prewarming Chrome for Testing (last resort) ```bash-adom-desktop pup_prewarm '{}' # fetch CfT WITHOUT opening a window, then pin it (poll readiness)-adom-desktop pup_use '{"browser":"cft"}' # same, via the pin path+adom-bridge-cli pup_prewarm '{}' # fetch CfT WITHOUT opening a window, then pin it (poll readiness)+adom-bridge-cli pup_use '{"browser":"cft"}' # same, via the pin path ``` Only needed on a box with no Chrome and no Edge. **CfT reported as `skipped` is NOT a failure** — on AD@@ -89,7 +89,7 @@ installed-browser-first behavior; don't retry or report an error. | Response | Means | Do | |---|---|---| | `ok:true` / a real session | A browser was found + launched | Proceed — the common case |-| `errorCode:"node_not_found"` / "could not run npm" | The bridge's Node runtime isn't ready yet | **AD ≥ 1.9.63 provisions Node for you** — check `adom-desktop runtimes '{}'`; if `installing`, wait a few seconds and **retry**. No user action. **Known AD false-negative:** if `runtimes` shows node `ready` AND `pup_readiness` works but other verbs still say `node_not_found`, it's an AD verb-gate bug — do NOT loop `desktop_install_node`; tell the user to update AD |+| `errorCode:"node_not_found"` / "could not run npm" | The bridge's Node runtime isn't ready yet | **AD ≥ 1.9.63 provisions Node for you** — check `adom-bridge-cli runtimes '{}'`; if `installing`, wait a few seconds and **retry**. No user action. **Known AD false-negative:** if `runtimes` shows node `ready` AND `pup_readiness` works but other verbs still say `node_not_found`, it's an AD verb-gate bug — do NOT loop `desktop_install_node`; tell the user to update AD | | `errorCode:"bridge_restarting"` (`stillRunning:true`) | AD ≥ 1.9.77: verb landed in the brief gap while the bridge respawns after an install/update | Poll `pup_readiness` until it answers, then retry the same verb — not a failure | | `errorCode:"chrome_for_testing_installing"` (`installing:true`) | RARE — no Chrome AND no Edge, so pup is fetching CfT in the background | Poll `pup_readiness` until `{ready:true}`, then re-issue. Faster: ask the user to install Chrome/Edge (Edge ships with Windows) | | `errorCode:"chrome_install_no_disk"` | No browser + too little disk for CfT (`readiness.diskFreeMb`) | Tell the user how much is free vs the ~800 MB needed; ask them to free space or install Edge. Do NOT retry the download |@@ -103,7 +103,7 @@ pup is a Node process, but **you no longer install Node.** AD provisions the run if on PATH, else a portable **no-UAC** copy it downloads to `~/.adom/adom-runtimes/` and prewarms, then spawns the bridge by absolute path. Do NOT run `desktop_install_node` / npm installers / ask the user to install Node. On a truly fresh box it may be `installing` for a few seconds after first launch — check-`adom-desktop runtimes '{}'` (`{state: absent|installing|ready|failed}`) and retry once `ready`. (Legacy+`adom-bridge-cli runtimes '{}'` (`{state: absent|installing|ready|failed}`) and retry once `ready`. (Legacy `desktop_install_node` — which pops a UAC — is only for AD older than 1.9.63.) ## The shell-approval gate (rarely relevant to pup)@@ -111,6 +111,6 @@ install Node. On a truly fresh box it may be `installing` for a few seconds afte Core AD verbs and pup's own `pup_*` / `desktop_record_*` verbs run with **NO desktop prompt**. Only open-ended `shell_execute` / `run_script` pop AD's "Shell command needs approval" dialog — which you almost never need (prefer typed verbs). If one returns `needs_approval` / `human_only` on **AD ≥ 1.9.86**:-run `adom-desktop --target <box> request_shell_approval` (re-surfaces the dialog), ask the user to click+run `adom-bridge-cli --target <box> request_shell_approval` (re-surfaces the dialog), ask the user to click Approve/Bypass, then **retry your original verb**. Never call `shell_auto_approve` (human-only, refuses). This is AD's own gate, NOT a Windows UAC.
skills/pup-screenshots-recording/SKILL.md+9−9@@ -4,7 +4,7 @@ user-invocable: true description: "Capturing pup (Puppeteer bridge) windows: SCREENSHOTS (pup_screenshot — lossless PNG, full-page vs viewport, full-resolution via pup_screenshot_full_res, and how to actually READ the image) and RECORDING (pup_record_start/stop records ONE pup tab/window's page content to a video; desktop_record_start/stop records the WHOLE desktop across apps). Covers framing a window at an exact size for a clean shot WITHOUT foregrounding it, and why pup shots are true-to-life (real rendered window, not headless). Read when screenshotting a page, capturing full-page vs above-the-fold, recording a demo/walkthrough of an app, or choosing the window-recorder vs the desktop-recorder. Trigger words: pup_screenshot, pup_screenshot_full_res, full page screenshot, screenshot the page, read the screenshot, pup_record_start, pup_record_stop, desktop_record_start, desktop_record_stop, record my app, record a demo, screen recording, walkthrough video, pup screenshot, pup recording." --- -**Parent skill:** adom-desktop-puppeteer-bridge · See also: `pup` (start here), `pup-windows-sessions-tabs`, `pup-browsers-and-chrome`.+**Parent skill:** pup-bridge · See also: `pup` (start here), `pup-windows-sessions-tabs`, `pup-browsers-and-chrome`. # pup — screenshots & recording @@ -16,9 +16,9 @@ without disturbing the user. ## Screenshots ```bash-adom-desktop pup_screenshot '{"sessionId":"mytask-web"}' # viewport, lossless PNG-adom-desktop pup_screenshot '{"sessionId":"mytask-web","fullPage":true}' # entire scrollable page-adom-desktop pup_screenshot '{"sessionId":"mytask-web","tabId":"tab-2"}' # a specific tab+adom-bridge-cli pup_screenshot '{"sessionId":"mytask-web"}' # viewport, lossless PNG+adom-bridge-cli pup_screenshot '{"sessionId":"mytask-web","fullPage":true}' # entire scrollable page+adom-bridge-cli pup_screenshot '{"sessionId":"mytask-web","tabId":"tab-2"}' # a specific tab ``` - Returns a **PNG saved on the container** (the machine running the CLI) — the response gives you the path.@@ -48,11 +48,11 @@ adom-desktop pup_screenshot '{"sessionId":"mytask-web","tabId":"tab-2"}' # a spe ```bash # Recording a pup window the user will watch → DO bring it forward first-adom-desktop pup_raise_os_window '{"sessionId":"demo-web"}'-adom-desktop pup_record_start '{"sessionId":"demo-web"}'+adom-bridge-cli pup_raise_os_window '{"sessionId":"demo-web"}'+adom-bridge-cli pup_record_start '{"sessionId":"demo-web"}' # ...drive the scene: navigate, click, type, scroll...-adom-desktop pup_record_stop '{"sessionId":"demo-web"}' # → { path: "...webm" }-adom-desktop pup_lower_os_window '{"sessionId":"demo-web"}' # tuck it away again when done+adom-bridge-cli pup_record_stop '{"sessionId":"demo-web"}' # → { path: "...webm" }+adom-bridge-cli pup_lower_os_window '{"sessionId":"demo-web"}' # tuck it away again when done ``` - `pup_record_stop` returns the saved video **path**. Recording status/list verbs:@@ -87,7 +87,7 @@ all of it** — reach for these instead of hand-rolling evals: pierce shadow roots directly — no hand-rolled walk: ```bash-adom-desktop pup_eval '{"sessionId":"...","expr":"$$deep(\"a[href]\").length"}' # counts across shadow roots+adom-bridge-cli pup_eval '{"sessionId":"...","expr":"$$deep(\"a[href]\").length"}' # counts across shadow roots ``` **Still verify by DOM, then by eye.** To count cards/links/rows, count in `pup_eval` by document-Y
skills/pup-windows-sessions-tabs/SKILL.md+11−11@@ -4,7 +4,7 @@ user-invocable: true description: "pup (Puppeteer bridge) windows, sessions, and tabs: how sessionIds work and why to task-prefix them, WINDOW OWNERSHIP so you never steal another AI thread's window (owner + session_owned_by_another_thread + takeover), the BACKGROUND-by-default rule (foreground:true is the only way to show a window; sizing/positioning does NOT foreground), running MANY TABS in one window instead of many windows, switching/listing/closing sessions and tabs, and verifying what you actually opened. Read when opening/reusing pup windows, managing tabs, deciding background vs foreground, or seeing errorCode session_owned_by_another_thread. Trigger words: pup sessionId, pup_open_window owner, session_owned_by_another_thread, takeover window, pup background, foreground:true, pup_open_tab, pup_switch_tab, pup_list_tabs, pup_switch_window, pup_list_windows, pup_close_window, pup tabs, many tabs one window, don't steal window, pup_lower_os_window, pup_raise_os_window, pup_alert_window." --- -**Parent skill:** adom-desktop-puppeteer-bridge · See also: `pup` (start here), `pup-screenshots-recording`, `pup-browsers-and-chrome`.+**Parent skill:** pup-bridge · See also: `pup` (start here), `pup-screenshots-recording`, `pup-browsers-and-chrome`. # pup — windows, sessions & tabs @@ -41,9 +41,9 @@ If you `pup_open_window` a sessionId that already exists **with a new url**, pup ```bash # right — owned, task-prefixed-adom-desktop pup_open_window '{"sessionId":"wikifix-preview","owner":"wikifix","url":"<url>"}'+adom-bridge-cli pup_open_window '{"sessionId":"wikifix-preview","owner":"wikifix","url":"<url>"}' # wrong — generic + anonymous: may hijack another thread's window (pup reprimands you in _hint)-adom-desktop pup_open_window '{"sessionId":"wiki","url":"<url>"}'+adom-bridge-cli pup_open_window '{"sessionId":"wiki","url":"<url>"}' ``` ## Background by default — pup NEVER pops onto the user's screen unless asked@@ -90,10 +90,10 @@ track of WHICH one you just changed. pup handles both, automatically: ```bash # default: background — drive it invisibly, user never sees a thing-adom-desktop pup_open_window '{"sessionId":"job-web","owner":"job","url":"<url>"}'-adom-desktop pup_screenshot '{"sessionId":"job-web"}'+adom-bridge-cli pup_open_window '{"sessionId":"job-web","owner":"job","url":"<url>"}'+adom-bridge-cli pup_screenshot '{"sessionId":"job-web"}' # only if the user asked to SEE it:-adom-desktop pup_open_window '{"sessionId":"demo-web","owner":"demo","url":"<url>","foreground":true}'+adom-bridge-cli pup_open_window '{"sessionId":"demo-web","owner":"demo","url":"<url>","foreground":true}' ``` ## Taskbar look — split vs grouped (user preference, `pup_configure`)@@ -115,11 +115,11 @@ For a vendor fetch / multi-doc review, put the URLs in **tabs of one window** (o separate windows: ```bash-adom-desktop pup_open_window '{"sessionId":"task-web","owner":"task","url":"https://first.example.com"}'-adom-desktop pup_open_tab '{"sessionId":"task-web","url":"https://second.example.com"}' # → { tabId: "tab-2", tabCount: 2 }-adom-desktop pup_switch_tab '{"sessionId":"task-web","tabId":"tab-2"}'-adom-desktop pup_screenshot '{"sessionId":"task-web","tabId":"tab-2"}' # tabId optional — omit for the active tab-adom-desktop pup_close_tab '{"sessionId":"task-web","tabId":"tab-2"}'+adom-bridge-cli pup_open_window '{"sessionId":"task-web","owner":"task","url":"https://first.example.com"}'+adom-bridge-cli pup_open_tab '{"sessionId":"task-web","url":"https://second.example.com"}' # → { tabId: "tab-2", tabCount: 2 }+adom-bridge-cli pup_switch_tab '{"sessionId":"task-web","tabId":"tab-2"}'+adom-bridge-cli pup_screenshot '{"sessionId":"task-web","tabId":"tab-2"}' # tabId optional — omit for the active tab+adom-bridge-cli pup_close_tab '{"sessionId":"task-web","tabId":"tab-2"}' ``` - `pup_open_tab` returns `{tabId, tabCount, activeTabId}`; pass the `tabId` to