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.2.1: launch pup with FULL browser permissions by default (all granted, was denying notifications/geolocation/midi) for full debug; per-permission grant tolerates rejected descriptors; strictPermissions opts out
6 files changed
+58−20
SKILL.md+4@@ -195,3 +195,7 @@ plain "open in pup" — that's CfT. reflexively; `browser_reload` or `browser_navigate` instead. - **Surface `_hint` verbatim** when a verb reports it isn't ready or failed. - **Never broadly kill Chrome** — use `browser_close_window` for a specific session.+- **Pup launches with FULL browser permissions by default** (notifications, geolocation, camera, mic,+ midi, sensors, clipboard, wake-lock, …) so no permission prompt ever blocks a debug flow — you don't+ need to grant anything. Pass `strictPermissions:true` to `browser_open_window` only for the rare+ untrusted-site audit where you want Chromium's default prompts back.
adom-bridge-puppeteer-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "puppeteer",- "version": "1.2.0",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.2.0/adom-bridge-puppeteer-v1.2.0.zip",- "sha256": "57d27ac4bb22b9bea1138c4b8260224e14ff0e680f5a731a8356005b510bf469",- "size": 127304,+ "version": "1.2.1",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.2.1/adom-bridge-puppeteer-v1.2.1.zip",+ "sha256": "207965598b9496411a75238eb86ecaa43e5e5299061837d5749bd82a284072c6",+ "size": 127910, "verbPrefixes": [ "browser_", "desktop_recorder_",
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-desktop-puppeteer-bridge",- "version": "1.2.0",+ "version": "1.2.1", "type": "app", "description": "CONTAINER-SIDE install — 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) — 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 — 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.2.0+1.2.1
src/bridge.json+6−4@@ -2,8 +2,8 @@ "manifest_version": 1, "name": "puppeteer", "displayName": "Puppeteer (Chrome for Testing + Native)",- "version": "1.2.0",- "description": "Tier-1 cold-start (v1.2.0, for AD v1.9.47+ two-tier model): pup brings its OWN browser (Chrome for Testing), so it needs no detect-block. It declares prewarm:[chrome-for-testing] so Adom Desktop fetches Chrome in the BACKGROUND and reports readiness via bridge_readiness. The bridge server starts fine WITHOUT Chrome; browser_readiness is a READ-ONLY probe (ready = server-up AND Chrome cached; never triggers a download); browser_open returns a non-blocking {installing:true} (never blocks/crashes) until Chrome is cached; browser_prewarm is an explicit bridge-side fetch fallback. Headful browser automation. Default path drives Chrome for Testing (CfT) with managed pup profiles. v1.0.6+ optional native-drive: pass nativeBrowser+nativeProfile (from desktop_list_browsers) to browser_open_window to drive the user's REAL Chrome/Edge/Brave with the actual signed-in account + org policies + device enrollment intact. Smart flow: if the browser is CLOSED, AD launches it fresh immediately with NO prompt (nothing to disrupt) and reports back ready-to-drive (launchedFresh:true); if it's OPEN without the port, AD returns errorCode:'native_relaunch_required' so the caller asks the user, then re-call with nativeRelaunch:true. AD then closes only that browser's own PIDs cleanly (WM_CLOSE — Sessions saved; CfT bridge sessions + other Chromium left untouched) and relaunches with --restore-last-session so every tab/window comes back. If the debug port is policy-blocked (e.g. Google Workspace's RemoteDebuggingAllowed disabled — affects Chrome browser-wide, all profiles), native drive returns errorCode:'native_cdp_blocked' with a `diagnosis` plus an `alternatives` list of other installed browsers — Edge usually escapes Google management. The generic CfT path (browser_open_window with no nativeBrowser) always works as a fallback.",+ "version": "1.2.1",+ "description": "v1.2.1: Launches with FULL browser permissions by default (all granted — notifications/geolocation/camera/mic/midi/sensors/clipboard/wake-lock/…) so no permission prompt ever blocks full debug; strictPermissions:true opts out. Tier-1 cold-start (for AD v1.9.47+ two-tier model): pup brings its OWN browser (Chrome for Testing), so it needs no detect-block. It declares prewarm:[chrome-for-testing] so Adom Desktop fetches Chrome in the BACKGROUND and reports readiness via bridge_readiness. The bridge server starts fine WITHOUT Chrome; browser_readiness is a READ-ONLY probe (ready = server-up AND Chrome cached; never triggers a download); browser_open returns a non-blocking {installing:true} (never blocks/crashes) until Chrome is cached; browser_prewarm is an explicit bridge-side fetch fallback. Headful browser automation. Default path drives Chrome for Testing (CfT) with managed pup profiles. v1.0.6+ optional native-drive: pass nativeBrowser+nativeProfile (from desktop_list_browsers) to browser_open_window to drive the user's REAL Chrome/Edge/Brave with the actual signed-in account + org policies + device enrollment intact. Smart flow: if the browser is CLOSED, AD launches it fresh immediately with NO prompt (nothing to disrupt) and reports back ready-to-drive (launchedFresh:true); if it's OPEN without the port, AD returns errorCode:'native_relaunch_required' so the caller asks the user, then re-call with nativeRelaunch:true. AD then closes only that browser's own PIDs cleanly (WM_CLOSE — Sessions saved; CfT bridge sessions + other Chromium left untouched) and relaunches with --restore-last-session so every tab/window comes back. If the debug port is policy-blocked (e.g. Google Workspace's RemoteDebuggingAllowed disabled — affects Chrome browser-wide, all profiles), native drive returns errorCode:'native_cdp_blocked' with a `diagnosis` plus an `alternatives` list of other installed browsers — Edge usually escapes Google management. The generic CfT path (browser_open_window with no nativeBrowser) always works as a fallback.", "homepage": "https://github.com/adom-inc/adom-desktop", "author": "Adom Inc.", "license": "MIT",@@ -16,7 +16,9 @@ "killImageName": "node.exe" }, "prewarm": {- "assets": ["chrome-for-testing"]+ "assets": [+ "chrome-for-testing"+ ] }, "verbPrefixes": [ "browser_",@@ -77,4 +79,4 @@ "reason": "Linux port pending — same killImageName + Chrome resolution issues as macOS." } }-}+}
src/server.js+42−10@@ -1154,13 +1154,14 @@ async function closeRestoredLeftoverTabs(browser, keepPage) { // // Two CDP mechanisms together give us this: //-// 1. Browser.setPermission (per-origin permissions) — granted for-// clipboard-read/write so paste-into-input-via-eval works; DENIED-// for notifications + geolocation so prompts don't fire mid-flow.-// Per-permission so a single unknown-name failure doesn't break-// the others (the v1.4.12 Browser.grantPermissions array form-// failed on Chrome 146 because "automaticDownloads" was-// unrecognized — taking the whole grant down with it).+// 1. Browser.setPermission (per-origin permissions) — FULL DEBUG: every+// permission Chrome accepts is GRANTED (notifications, geolocation,+// camera, mic, midi, sensors, clipboard, wake-lock, …) so no permission+// prompt EVER blocks a debug flow. Per-permission so an unknown/rejected+// descriptor (e.g. clipboard-sanitized-write on some builds) only drops+// itself, never the rest (the v1.4.12 Browser.grantPermissions array form+// failed wholesale on Chrome 146 when one name was unrecognized).+// Opt-out for the rare untrusted-site case: strictPermissions:true. // // 2. Page.setDownloadBehavior — see applyDownloadBehavior below. This // is the actual mechanism for unblocking scripted downloads. The@@ -1179,13 +1180,44 @@ async function closeRestoredLeftoverTabs(browser, keepPage) { // grant down. v1.6.3 fixes by switching to Browser.setPermission per- // permission and dropping the unhelpful automaticDownloads (which we // replace with the actually-effective Page.setDownloadBehavior).+// FULL-DEBUG default: grant EVERYTHING Chrome will accept (John: always launch+// pup with full permissions for full debug). All 'granted', none denied. Applied+// per-permission below so any descriptor a given Chrome build rejects (e.g.+// clipboard-sanitized-write) only drops itself — the rest still land. Opt-out via+// strictPermissions:true on browser_open_window for an untrusted site you're auditing. const PERMISSIVE_DEFAULT_PERMISSIONS = [ { name: 'clipboard-read', setting: 'granted' }, { name: 'clipboard-write', setting: 'granted' }, { name: 'clipboard-sanitized-write', setting: 'granted' },- { name: 'notifications', setting: 'denied' },- { name: 'geolocation', setting: 'denied' },- { name: 'midi', setting: 'denied' },+ { name: 'notifications', setting: 'granted' },+ { name: 'geolocation', setting: 'granted' },+ { name: 'camera', setting: 'granted' },+ { name: 'microphone', setting: 'granted' },+ { name: 'midi', setting: 'granted' },+ { name: 'midiSysex', setting: 'granted' },+ { name: 'background-sync', setting: 'granted' },+ { name: 'background-fetch', setting: 'granted' },+ { name: 'periodic-background-sync', setting: 'granted' },+ { name: 'payment-handler', setting: 'granted' },+ { name: 'persistent-storage', setting: 'granted' },+ { name: 'durable-storage', setting: 'granted' },+ { name: 'storage-access', setting: 'granted' },+ { name: 'top-level-storage-access', setting: 'granted' },+ { name: 'idle-detection', setting: 'granted' },+ { name: 'display-capture', setting: 'granted' },+ { name: 'window-management', setting: 'granted' },+ { name: 'local-fonts', setting: 'granted' },+ { name: 'nfc', setting: 'granted' },+ { name: 'screen-wake-lock', setting: 'granted' },+ { name: 'system-wake-lock', setting: 'granted' },+ { name: 'accelerometer', setting: 'granted' },+ { name: 'gyroscope', setting: 'granted' },+ { name: 'magnetometer', setting: 'granted' },+ { name: 'ambient-light-sensor', setting: 'granted' },+ { name: 'sensors', setting: 'granted' },+ { name: 'protected-media-identifier', setting: 'granted' },+ { name: 'captured-surface-control', setting: 'granted' },+ { name: 'speaker-selection', setting: 'granted' }, ]; async function applyDefaultPermissions(browser, profileName, { strictPermissions = false } = {}) { if (strictPermissions) {