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
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "pup-bridge",- "version": "2.0.316",+ "version": "2.0.317", "type": "app", "description": "The pup SKILL PACK \u2014 the AI skills that teach a cloud/container AI how to drive the Adom Desktop Puppeteer (pup) bridge (browser_* verbs): the everyday `pup` skill plus focused sub-skills for windows/sessions/tabs, screenshots+recording, browsers+Chrome install, and driving the Adom wiki. Installs into ~/.claude/skills + ~/.codex/skills. DOCS ONLY \u2014 this is NOT the bridge runtime. The bridge itself (the Node program that drives the browser) runs on the DESKTOP: Adom Desktop bundles it and auto-installs/updates it, and it's published separately on the Releases tab as adom-bridge-puppeteer-v<ver>.zip. The pkg version is kept in lockstep with the Release version so the page's max version row always carries BOTH a pkg tarball (skills) and a runtime zip (bridge) \u2014 a skills-only or runtime-only bump on the top row breaks constraint installs. TL;DR: pkg install = the skills for your AI; the bridge = the Release zip, which Adom Desktop manages for you.", "keywords": [
page.json+1−1@@ -4,7 +4,7 @@ "slug": "pup-bridge", "title": "Pup - Puppeteer Bridge", "brief": "pup is the AI's own browser: a real, full Chrome on the user's desktop that the AI fully controls (a sandbox, not the user's signed-in browser). Rides Bridge; pup_* verbs open windows and tabs, navigate, screenshot, and eval JS.",- "version": "2.0.316",+ "version": "2.0.317", "tags": [ "skills", "pup",
tools/pup-dashboard+39−45@@ -334,69 +334,63 @@ load(); setInterval(load,15000); // ── demo ──────────────────────────────────────────────────────────────────────────────────────── async function runDemo() {- // The dock-card showcase (John: "shouldn't your pup demo be a bit cooler? show off your- // annotation feature, your jump lists, how cool your icons are"). The user CLICKED Run the demo,- // so the finale may come to their screen: the raise is captioned with exactly that reason.+ // The dock-card showcase. v2.0.317 (John: "you lost me in that demo. i had no idea what was going+ // on... show non-stop ab captions step by step, take over the cursor so i see you moving"): the+ // narration lives ON THE DESKTOP now. Every act announces itself with an on-screen caption BEFORE+ // it happens (duration scaled to reading speed), the foreground act glides the visible Adom cursor+ // with intent labels, and the drawing is slow enough to watch. The console lines mirror the+ // captions for the record; the show itself is on screen. const lines = []; const sid = 'pup-dock-demo'; const sleep = (ms) => new Promise(r => setTimeout(r, ms)); const tgt = await resolveTarget();+ const cap = async (text) => {+ const ms = Math.min(12000, Math.max(2500, 900 + text.trim().split(/\s+/).length * 350));+ await ab('desktop_caption', { text, duration: ms, id: 'pup-demo', position: 'bottom', size: 'medium' }, 8000, tgt.name);+ lines.push(' [caption] ' + text);+ return ms;+ };+ const capWait = async (text, extra) => { const ms = await cap(text); await sleep(ms + (extra || 0)); }; - lines.push('1. Opening a window in the BACKGROUND. pup births it off-screen and parks it behind');- lines.push(' your work in under 50ms, so it can never steal your screen or your keystrokes.');+ lines.push('The demo narrates ON YOUR SCREEN with captions, step by step. Watch the desktop.');+ await capWait('pup demo, step 1 of 6: I am opening a browser window IN THE BACKGROUND. Watch your TASKBAR, not your screen. Nothing will pop over your work.', 500); const open = await ab('pup_open_window', { sessionId: sid, url: 'https://wiki.adom.inc/adom/pup-bridge', owner: 'pup dock demo' }, 120000, tgt.name);- if (open._err) { lines.push(' could not open: ' + open._err); return lines; }+ if (open._err) { await cap('The demo could not open a window: ' + open._err); lines.push(' could not open: ' + open._err); return lines; } lines.push(' open: ' + (open.sessionId || sid)); - lines.push('');- lines.push('2. LOOK AT YOUR TASKBAR right now. The new button is not a generic Chrome icon: it is');- lines.push(' the Adom teal tile wearing this thread\'s NAME ("pup dock demo"), with the live page');- lines.push(' favicon badged in the corner. Every AI thread gets its own named button, so your');- lines.push(' taskbar reads as a list of your threads. While the icon lands you will see a small');- lines.push(' PROGRESS BAR under the button: pup times every operation and fills the bar over how');- lines.push(' long it usually takes, instead of flashing orange at you.');- await sleep(3500);+ await capWait('Step 2: look at the NEW TASKBAR BUTTON at the bottom of your screen. It is a teal tile wearing this thread\'s name, "pup dock demo", with the page favicon badged on its corner. Every AI thread gets its own named button.', 1000);+ await capWait('The small bar FILLING UNDER that button is pup\'s progress signal: it times every operation and fills over how long it usually takes. No orange flashing.', 800); - lines.push('');- lines.push('3. Screenshot, without touching your screen: the window renders in the background and');- lines.push(' pup reads the pixels off-screen (watch the button, the progress bar runs again).');+ await capWait('Step 3: I am taking a SCREENSHOT of that background window right now. Watch the progress bar run under its button. Your screen is not touched: the page renders off-screen.', 300); const shot = await ab('pup_screenshot', { sessionId: sid }, 60000, tgt.name);- lines.push(shot._err ? ' screenshot failed: ' + shot._err : ' screenshot: ' + shot.width + 'x' + shot.height + ' (the AI can read any page without disturbing you)');+ lines.push(shot._err ? ' screenshot failed: ' + shot._err : ' screenshot: ' + shot.width + 'x' + shot.height); - lines.push('');- lines.push('4. RIGHT-CLICK that taskbar button when you get a moment: pup installs a jump list on');- lines.push(' every window: Annotate this page, Switch to logged-in/public view (wiki windows),');- lines.push(' Open pup dashboard, Move to my workspace, Close ALL Adom Pup windows.');- await sleep(2500);+ await capWait('Step 4: that button also carries a RIGHT-CLICK menu. Try it later: Annotate this page, switch wiki views, open the pup dashboard, move the page to your workspace, close all pup windows.', 500); - lines.push('');- lines.push('5. The finale: ANNOTATION, live. Bringing the window up (with the on-screen caption');- lines.push(' pup always shows before a foreground, naming who and why), then drawing on the page.');- await ab('pup_raise_os_window', { sessionId: sid, foregroundReason: 'you clicked Run the demo on the pup dashboard: watch the annotation feature draw on the page' }, 30000, tgt.name);- await sleep(1200);+ await capWait('Step 5, the finale: I am about to bring the window UP ON YOUR SCREEN to demonstrate annotation. pup always captions a foreground with who is doing it and why, like this.', 500);+ await ab('pup_raise_os_window', { sessionId: sid, foregroundReason: 'the pup demo you started: watch the annotation feature draw on this page' }, 30000, tgt.name);+ await sleep(800);+ // glide the visible Adom cursor so the eye lands where the action will be+ await ab('pup_hover', { sessionId: sid, x: 700, y: 380, intent: 'the demo is about to draw HERE', steps: 14 }, 20000, tgt.name);+ await sleep(600); const arm = await ab('pup_annotate', { sessionId: sid, tool: 'pen' }, 30000, tgt.name); if (!arm._err) {- await sleep(600);- const draw = "(async()=>{const r=document.getElementById('__pup_annotate');if(!r)return 'no overlay';const cv=r.querySelector('canvas');if(!cv)return 'no canvas';const mk=(t,x,y)=>new PointerEvent(t,{bubbles:true,cancelable:true,clientX:x,clientY:y,pointerId:1,isPrimary:true,button:0,buttons:t==='pointerup'?0:1});const cx=Math.round(innerWidth*0.35),cy=Math.round(innerHeight*0.4),rad=Math.min(140,Math.round(innerHeight*0.18));cv.dispatchEvent(mk('pointerdown',cx+rad,cy));for(let a=0.25;a<=6.55;a+=0.22){cv.dispatchEvent(mk('pointermove',cx+rad*Math.cos(a),cy+rad*Math.sin(a)));await new Promise(q=>setTimeout(q,16));}cv.dispatchEvent(mk('pointerup',cx+rad,cy));return 'drew';})()";- const drew = await ab('pup_evaluate', { sessionId: sid, expression: draw }, 30000, tgt.name);+ await cap('Drawing on the live page with the annotation pen now. Watch the red ink.');+ await sleep(400);+ const draw = "(async()=>{const r=document.getElementById('__pup_annotate');if(!r)return 'no overlay';const cv=r.querySelector('canvas');if(!cv)return 'no canvas';const mk=(t,x,y)=>new PointerEvent(t,{bubbles:true,cancelable:true,clientX:x,clientY:y,pointerId:1,isPrimary:true,button:0,buttons:t==='pointerup'?0:1});const cx=Math.round(innerWidth*0.35),cy=Math.round(innerHeight*0.4),rad=Math.min(150,Math.round(innerHeight*0.2));cv.dispatchEvent(mk('pointerdown',cx+rad,cy));for(let a=0.12;a<=6.55;a+=0.12){cv.dispatchEvent(mk('pointermove',cx+rad*Math.cos(a),cy+rad*Math.sin(a)));await new Promise(q=>setTimeout(q,55));}cv.dispatchEvent(mk('pointerup',cx+rad,cy));return 'drew';})()";+ const drew = await ab('pup_evaluate', { sessionId: sid, expression: draw }, 40000, tgt.name); const drewOk = !drew._err && String(drew.result || '') === 'drew'; if (drewOk) {- lines.push(' A red circle was just drawn on the page. On the pen-up, pup captured the marked');- lines.push(' region, put the PNG ON YOUR CLIPBOARD with a caption strip naming the thread and');- lines.push(' page (paste it into any AI chat), and showed the confirmation toast.');- } else lines.push(' annotation draw did not run: ' + (drew._err || drew.result || 'unknown'));- } else lines.push(' annotate did not arm: ' + arm._err);- await sleep(3500);+ lines.push(' drew the red circle live');+ await capWait('The pen-up CAPTURED the circled region: it is on your CLIPBOARD right now, with a caption strip naming the thread and the page. Paste it into any AI chat. The ink fades; the capture persists.', 1200);+ } else { lines.push(' annotation draw did not run: ' + (drew._err || drew.result || 'unknown')); await cap('The drawing step did not run on this page; the rest of the demo continues.'); }+ } else { lines.push(' annotate did not arm: ' + arm._err); await cap('The annotation overlay did not arm on this page; the rest of the demo continues.'); }+ await capWait('Step 6: and back to the BACKGROUND, out of your way. The window stays open. That is pup: real browser windows an AI drives without ever stealing your screen.', 300); await ab('pup_lower_os_window', { sessionId: sid }, 20000, tgt.name);+ await cap('pup demo done. Right-click the "pup dock demo" taskbar button to explore, or say: close the pup demo window.'); lines.push('');- lines.push('6. And back to the background, out of your way. The drawing fades once captured (the');- lines.push(' capture is what persists, on your clipboard). The window stays open: right-click its');- lines.push(' taskbar button to explore the jump list, or close it there (or say: close the pup');- lines.push(' demo window).');- lines.push('');- lines.push('Not shown: recording a window to video (full frame rate in the background with highFps),');- lines.push('the credential vault that signs into sites with no Chrome popups, and the gliding Adom');- lines.push('cursor that narrates what the AI is doing. Say "show me in pup" to any Adom AI.');+ lines.push('Not shown: window recording (full frame rate in the background with highFps), the');+ lines.push('credential vault that signs into sites with no Chrome popups. Say "show me in pup".'); return lines; }