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
Publish 1.1.1
4 files changed
+111−6
SKILL.md+51−2@@ -65,6 +65,26 @@ adom-desktop browser_reload '{"sessionId":"myapp"}' **These are Bash commands, not MCP tools.** Always pass `sessionId` — `'{}'` targets the *active* session, which may not be the one you mean. +## Background by default — don't disrupt the user++**Pup is the AI's workspace, not the user's. Keep its windows OUT of the user's way unless they asked to watch.**++- After opening/driving a window for automation (screenshot, eval, scrape, a debug loop), call+ **`browser_lower_os_window`** to send it to the back so it doesn't sit on top of what the user is doing.+- **Never** call `browser_raise_os_window` (foreground) unless the user must SEE it — a recording, a demo,+ or a finished result you're explicitly showing them.+- Use **`browser_alert_window`** (flashes the taskbar) for a non-intrusive "it's ready / done" nudge+ instead of stealing focus.+- For long-running dashboards the user WILL look at, opening a dedicated pup window is fine — but still+ don't keep re-raising it on every update; flash the taskbar instead.++```bash+adom-desktop browser_open_window '{"sessionId":"job","profile":"job","url":"<url>"}'+adom-desktop browser_lower_os_window '{"sessionId":"job"}' # get it off the user's screen; keep driving headlessly+# ...screenshot / eval / navigate as needed (works while lowered)...+adom-desktop browser_alert_window '{"sessionId":"job"}' # non-intrusive "done" when you want their attention+```+ ## Core verbs | Command | Description | Key args |@@ -79,11 +99,40 @@ session, which may not be the one you mean. | `browser_errors` | Console/page errors | `sessionId` | | `browser_status` | All sessions + chrome readiness | none | | `browser_reload` | Reload + clear error log | `sessionId` |-| `browser_close_window` | Close one session (destructive) | `sessionId` |-| `browser_alert_window` | Flash the taskbar (non-intrusive) | `sessionId` |+| `browser_open_tab` / `browser_switch_tab` / `browser_close_tab` / `browser_list_tabs` | Tabs within one session/window | `sessionId`, `tabId?` |+| `browser_record_start` / `browser_record_stop` | Record a video of a window/tab | `sessionId` |+| `browser_lower_os_window` | Send the window to the back (keep it off the user's screen) | `sessionId` |+| `browser_raise_os_window` / `browser_focus_window` | Bring to foreground (use sparingly — only to show the user) | `sessionId` |+| `browser_close_window` | Close one session + its window (destructive) | `sessionId` |+| `browser_alert_window` | Flash the taskbar (non-intrusive attention) | `sessionId` |+| `browser_close` | Close ALL sessions | none | Run `adom-desktop browser_describe '{}'` for the full machine-readable verb catalog. +## Tabs management++One session = one Chrome window that can hold many tabs (one taskbar icon). Use tabs (not extra+windows) for multi-URL work — see "One window, many tabs" below. `browser_open_tab` returns a `tabId`;+pass it to `browser_switch_tab` / `browser_close_tab` / `browser_screenshot` / `browser_eval`+(`tabId` optional — omit to target the active tab). Closing the last tab closes the window.++## Recording windows++Two recorders — pick by what you're capturing:++- **`browser_record_start` / `browser_record_stop`** — records ONE pup tab/window (the page content).+ Best for "record my app" / a feature walkthrough. Returns the saved video path on stop.+- **`desktop_record_start` / `desktop_record_stop`** — records the WHOLE desktop (multiple apps,+ KiCad/Fusion, OS dialogs). Use when the capture spans more than the pup window.++```bash+adom-desktop browser_raise_os_window '{"sessionId":"demo"}' # for a recording, DO bring it forward+adom-desktop browser_record_start '{"sessionId":"demo"}'+# ...drive the scene...+adom-desktop browser_record_stop '{"sessionId":"demo"}' # → { path: "...webm" }+adom-desktop browser_lower_os_window '{"sessionId":"demo"}' # tuck it away again when done+```+ ## Don't double-open windows - New session entirely → `browser_open_window`.
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-desktop-puppeteer-bridge",- "version": "1.1.0",+ "version": "1.1.1", "type": "app", "description": "CONTAINER-SIDE install — Claude skills only. This pkg drops the skills that teach a cloud AI to drive the pup browser bridge (the `pup` user skill + the `pup-bridge-dev` developer skill) into ~/.claude/skills/. It does NOT contain the bridge runtime. The bridge itself (Node + Chrome for Testing, the code that actually drives a browser) lives on the DESKTOP: it ships bundled inside Adom Desktop and is published here on the Releases tab as adom-bridge-puppeteer-v<ver>.zip, which Adom Desktop streams into its bridges-cache. TL;DR: `pkg install` = skills for the container; the bridge = the Release zip + bundled in Adom Desktop.", "keywords": ["pup", "puppeteer", "browser", "adom-desktop", "bridge", "skills"],
page.json+34−3@@ -4,8 +4,15 @@ "slug": "adom-desktop-puppeteer-bridge", "title": "Adom Desktop - Puppeteer Bridge", "brief": "The Adom Desktop Puppeteer (pup) bridge — drive Chrome for Testing (or the user's real Chrome/Edge/Brave) from the cloud: open/screenshot/eval/record, with cold-start self-heal that auto-installs Chrome for Testing on a fresh PC. Two artifacts: the Releases zip is the bridge runtime (also bundled in Adom Desktop); the pkg installs the container-side Claude skills.",- "version": "1.1.0",- "tags": [],+ "version": "1.1.1",+ "tags": [+ "skills",+ "pup",+ "puppeteer",+ "browser",+ "adom-desktop",+ "bridge"+ ], "license": "MIT", "discovery_triggers": [ "pup",@@ -99,5 +106,29 @@ "created_at": "2026-05-28T05:28:43.991Z", "updated_at": "2026-06-16T12:43:19.735Z", "skills": [],- "author_name": "John Lauer"+ "author_name": "John Lauer",+ "description": "CONTAINER-SIDE install — Claude skills only. This pkg drops the skills that teach a cloud AI to drive the pup browser bridge (the `pup` user skill + the `pup-bridge-dev` developer skill) into ~/.claude/skills/. It does NOT contain the bridge runtime. The bridge itself (Node + Chrome for Testing, the code that actually drives a browser) lives on the DESKTOP: it ships bundled inside Adom Desktop and is published here on the Releases tab as adom-bridge-puppeteer-v<ver>.zip, which Adom Desktop streams into its bridges-cache. TL;DR: `pkg install` = skills for the container; the bridge = the Release zip + bundled in Adom Desktop.",+ "keywords": [+ "pup",+ "puppeteer",+ "browser",+ "adom-desktop",+ "bridge",+ "skills"+ ],+ "files": [+ "SKILL.md",+ "skills/**",+ "skills/pup-bridge-dev/SKILL.md",+ "install.sh",+ "uninstall.sh",+ "README.md",+ "package.json"+ ],+ "dependencies": {},+ "scripts": {+ "install": "./install.sh",+ "uninstall": "./uninstall.sh"+ },+ "org": "adom" }
skills/pup-bridge-dev/SKILL.md+25@@ -24,6 +24,31 @@ A user installs TWO different things from this one page. They are not the same: So: **the pkg is skills (container). The bridge is the zip (desktop) + the bundled seed.** Keep the pkg description saying exactly that, or people think the tarball contains the bridge — it does not. +## How pup reaches a container — auto-discovery → auto-install → verbs++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`+ (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 browser_*` verbs.+ AD routes `browser_*` 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+ cold-start self-heal (chrome.js) installs Chrome for Testing on first `browser_open_window`.++**Two install paths, keep BOTH healthy:**+- **Discovery path (above)** — works once `discovery_triggers` include the user phrases (done) + the+ 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+ `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.+ ## Repo layout - `src/` — the runnable bridge (what the release zip contains, at zip-root). `server.js`, `chrome.js`,