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
v1.6.0: bind bridge server to loopback (127.0.0.1) only — kills the Windows Firewall 'allow Node' prompt (AD talks to the bridge over localhost); record firewall learning in dev skill
6 files changed
+20−10
adom-bridge-puppeteer-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "1.5.0",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.5.0/adom-bridge-puppeteer-v1.5.0.zip",- "sha256": "ca1e79057f398d7ae00bbaf3e9d3d5f80966e98acb986ec26581e4e37f741e92",- "size": 138480,+ "version": "1.6.0",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.6.0/adom-bridge-puppeteer-v1.6.0.zip",+ "sha256": "8b908d9857f1e2dd82a7c3499f73eabcf3a97bed4296919ee02416ecc6ad062d",+ "size": 138765, "verbPrefixes": [ "browser_", "desktop_recorder_",
dev-skills/pup-bridge-dev.md+5@@ -130,6 +130,11 @@ What we learned and baked into the code: showed nothing). Two consequences baked into SKILL.md: (1) prefer core/`browser_*` verbs over shell; (2) before any `shell_execute`, `notify_user` the person to approve the popup. This is a separate gate from the Windows UAC (admin elevation) — don't conflate them.+- **Windows Firewall prompt = bind loopback (fixed v1.6.0).** A hostless `server.listen(PORT)` binds ALL+ interfaces (0.0.0.0), so Windows pops "Allow Node.js through the firewall (public/private)?" on first+ listen — a THIRD scary prompt after UAC + shell-approval, and worse on a fresh portable-node path the+ firewall has never seen. Fix: `server.listen(PORT, '127.0.0.1', ...)`. AD only ever talks to the bridge+ over loopback, and loopback sockets are firewall-exempt → the prompt never appears. - **No prompt-free Node without AD.** pup is a Node process AD spawns via `node` on PATH. Getting Node onto a fresh box costs SOME prompt: the MSI (`desktop_install_node`) = a UAC; portable Node (zip→user dir→user PATH via `shell_execute`) = a shell-approval, no UAC. BOTH then need AD reopened (stale PATH). The only
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-desktop-puppeteer-bridge",- "version": "1.5.2",+ "version": "1.6.0", "type": "app", "description": "CONTAINER-SIDE install \u2014 the everyday `pup` user skill only. This pkg drops the `pup` skill (drive the browser bridge: open/close/tabs/screenshot/record, background-by-default) into ~/.claude/skills/ AND ~/.codex/skills/. It does NOT install the developer/publishing skills (pup-bridge-dev, pup-bridge-publish) \u2014 those are source-only; clone the repo (adom-wiki repo clone adom/adom-desktop-puppeteer-bridge) to get them from dev-skills/. It also does NOT contain the bridge runtime: the bridge (Node + Chrome for Testing) lives on the DESKTOP \u2014 bundled inside Adom Desktop and 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` = the pup user skill; dev skills = clone the source; the bridge = the Release zip + bundled in Adom Desktop.", "keywords": [
src/BRIDGE_VERSION+1−1@@ -1 +1 @@-1.5.0+1.6.0
src/bridge.json+2−2@@ -2,8 +2,8 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "1.5.0",- "description": "Drives a browser ALREADY on the machine — installed Chrome, else Microsoft Edge (every Windows PC ships with Edge) — launched with a FRESH isolated profile, so the common case has NO ~150 MB Chrome-for-Testing download and it never touches the user's real tabs/logins. Chrome for Testing is fetched only as a LAST RESORT if the machine has no Chromium browser at all. SPAWN-VERIFIED fallback: pup tries each detected browser (Chrome → Edge → CfT) and actually launches it, falling through to the next if one won't start (and handling browsers like Edge that relaunch onto another PID), so a corrupt/partial install never hard-fails an open. The browser that launches is cached as the default (persisted across restarts) so it isn't re-probed each time. On spawn the bridge SELF-WARMS: detects browsers + disk, and only if the box has no Chrome/Edge and no cached CfT does it background-fetch CfT so the first open is instant. browser_use pins a specific browser (chrome | edge | cft | auto); {browser:'chrome',install:true} downloads & installs REAL Google Chrome (user-scoped, no admin) on an Edge-only box. browser_readiness (READ-ONLY) reports which browser will be used + the full candidate list + the default + free disk. Every failure returns a specific errorCode + _hint (chrome_install_no_disk, chrome_download_network, chrome_install_permission, chrome_stable_not_detected, …). Launches with FULL browser permissions by default for full debug (strictPermissions:true opts out). Headful automation: open/close windows+tabs, navigate, screenshot, eval JS, record. v1.0.6+ optional native-drive: pass nativeBrowser+nativeProfile (from desktop_list_browsers) to browser_open_window to drive the user's REAL signed-in Chrome/Edge/Brave (their actual profile, org policies, device enrollment) — with the smart relaunch/consent flow (native_relaunch_required / native_cdp_blocked). The generic path (no nativeBrowser) always works.",+ "version": "1.6.0",+ "description": "Drives a browser ALREADY on the machine — installed Chrome, else Microsoft Edge (every Windows PC ships with Edge) — launched with a FRESH isolated profile, so the common case has NO ~150 MB Chrome-for-Testing download and it never touches the user's real tabs/logins. Binds its local server to LOOPBACK (127.0.0.1) only, so no Windows Firewall 'allow Node through the firewall' prompt ever pops. Chrome for Testing is fetched only as a LAST RESORT if the machine has no Chromium browser at all. SPAWN-VERIFIED fallback: pup tries each detected browser (Chrome → Edge → CfT) and actually launches it, falling through to the next if one won't start (and handling browsers like Edge that relaunch onto another PID), so a corrupt/partial install never hard-fails an open. The browser that launches is cached as the default (persisted across restarts) so it isn't re-probed each time. On spawn the bridge SELF-WARMS: detects browsers + disk, and only if the box has no Chrome/Edge and no cached CfT does it background-fetch CfT so the first open is instant. browser_use pins a specific browser (chrome | edge | cft | auto); {browser:'chrome',install:true} downloads & installs REAL Google Chrome (user-scoped, no admin) on an Edge-only box. browser_readiness (READ-ONLY) reports which browser will be used + the full candidate list + the default + free disk. Every failure returns a specific errorCode + _hint (chrome_install_no_disk, chrome_download_network, chrome_install_permission, chrome_stable_not_detected, …). Launches with FULL browser permissions by default for full debug (strictPermissions:true opts out). Headful automation: open/close windows+tabs, navigate, screenshot, eval JS, record. v1.0.6+ optional native-drive: pass nativeBrowser+nativeProfile (from desktop_list_browsers) to browser_open_window to drive the user's REAL signed-in Chrome/Edge/Brave (their actual profile, org policies, device enrollment) — with the smart relaunch/consent flow (native_relaunch_required / native_cdp_blocked). The generic path (no nativeBrowser) always works.", "homepage": "https://wiki.adom.inc/adom/adom-desktop", "author": "Adom Inc.", "license": "MIT",
src/server.js+7−2@@ -4725,8 +4725,13 @@ const server = http.createServer(async (req, res) => { server.timeout = 45_000; server.keepAliveTimeout = 30_000; -server.listen(PORT, async () => {- console.log(`Puppeteer Bridge running on http://localhost:${PORT}`);+// Bind to LOOPBACK only. AD always talks to the bridge over 127.0.0.1, so binding to+// 127.0.0.1 (not 0.0.0.0/all interfaces) keeps Windows Firewall silent — a socket that+// only listens on loopback is firewall-exempt, so the scary "Allow Node.js through the+// firewall on public/private networks?" dialog never pops on the user's desktop. (It+// used to, because a hostless listen() binds every interface.)+server.listen(PORT, '127.0.0.1', async () => {+ console.log(`Puppeteer Bridge running on http://127.0.0.1:${PORT} (loopback-only; no firewall prompt)`); console.log('Multi-session support: sessions are tabs sharing Chrome profiles via userDataDir'); console.log('Endpoints: /health, /command, /launch, /navigate, /reload, /screenshot, /screenshot.png, /errors, /eval, /wait, /status, /close'); // Self-warm: detect browsers + disk the moment the bridge spawns (right after AD