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 2.0.146
6 files changed
+129−9
README.md+1@@ -281,6 +281,7 @@ page's **Files** tab. |---|---| | **pup** (`SKILL.md`) | START HERE: the mental model, when to use pup vs nb/nbe, the cold-start playbook, and the map to everything else. Addressing (your `ai-thread` name is the handle, no hwnd hunting), the credential vault, page integrity. | | **pup-settings** | The complete behavior reference: every Settings toggle and the feature behind it: taskbar identity (AUMID) + icon style + grouping, jump lists, the toolbar extension family, annotate/capture, foreground etiquette, the credential vault, in-page identity, recovery/safety. Read to know exactly what pup does on the machine and how to change any of it (`pup_configure` / the dashboard gear). |+| **pup-credentials** | How pup signs the user in AS THEM: the OS-keychain vault (auto-capture + background autofill, matched across a site's registrable domain), importing the user's own saved Chrome/Edge/Brave logins (`pup_import_browser_logins`, one consent + one UAC), and the not-pretty-but-it-works recovery of a CURRENT password from the browser's own password manager (drive it, eyeball, Windows Hello, read it) when a saved one has gone stale. | | **pup-auto-mode** | THE operating reality: Adom users run their AI in Claude Code Auto mode. How pup stays a great doppelganger inside the safety check: structured verbs pass, the risky moments become clean human pauses, and the `autoMode.allow` allowlist Hydrogen ships. | | **pup-doppelganger** | The mission and the one design rule it dictates: anything a human browser shows a HUMAN to click, pup handles silently for the AI. The tie-breaker for every feature decision. | | **pup-page-integrity** | The boundary: pup never mutates a page's own content (title, DOM) to carry pup metadata, that belongs on pup-owned surfaces (taskbar, dashboard, extension, identity tile). |
install.sh+2−1@@ -27,7 +27,8 @@ deploy_into() { install_skill pup-adom-wiki skills/pup-adom-wiki/SKILL.md install_skill pup-vendor-login skills/pup-vendor-login/SKILL.md install_skill pup-settings skills/pup-settings/SKILL.md- echo " -> $BASE (pup + 5 sub-skills)"+ install_skill pup-credentials skills/pup-credentials/SKILL.md+ echo " -> $BASE (pup + 6 sub-skills)" } echo "Installing adom-desktop-puppeteer-bridge skills:"
package.json+2−1@@ -1,6 +1,6 @@ { "slug": "pup-bridge",- "version": "2.0.145",+ "version": "2.0.146", "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": [@@ -29,6 +29,7 @@ "skills/pup-adom-wiki/SKILL.md", "skills/pup-vendor-login/SKILL.md", "skills/pup-settings/SKILL.md",+ "skills/pup-credentials/SKILL.md", "install.sh", "uninstall.sh", "README.md",
page.json+13−7@@ -4,13 +4,12 @@ "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.145",+ "version": "2.0.146", "tags": [ "skills", "pup", "puppeteer", "browser",- "ab", "adom-bridge", "bridge", "pup-bridge"@@ -88,7 +87,7 @@ "install_hint": "", "version_cmd": "" },- "readme": "# pup: the Puppeteer bridge\n\n**pup is the AI's own browser: a real, full Chrome/Edge window on the user's desktop that the AI drives\nwith complete programmatic control, but a _sandbox_.** It runs in a fresh, isolated profile that is\nnever the user's real signed-in browser, and opens in the **background by default** so it never disrupts\nthem. That trade is exactly why pup exists alongside **nb / nbe** (the native browser and its extension):\nnb/nbe drive the user's _real_ browser, their cookies, SSO, saved logins, their identity, for when a\ntask needs to BE the user. pup is the opposite trade: no borrowed identity, but **total control**, a\nreal, disposable browser the AI owns end to end (open/close windows + tabs, navigate, screenshot, eval\nJS, record). Logged out by design, it's the safe, fully-drivable default for automation, testing,\nscraping public pages, and showing wiki pages; reach for nb/nbe only when you genuinely need the user's\nreal logins. pup drives the browser **already on the machine** (installed Chrome, else Microsoft Edge;\nevery Windows PC ships Edge), so the common case needs no download.\n\n**The core goal: an AI-driven browser that can do everything it needs to for you - the best assistant\nin the world.** By default every pup window surfs on the shared durable **adom-you** profile, and every\nlogin made there enriches a shared credential store. Over time that store lets pup automatically enter\nusernames and passwords on every site it has ever seen, which is what makes a truly self-sufficient\nAI browser possible. Isolated throwaway profiles exist for the cases that need them (logged-out\ntesting, acting as another user), but they build nothing: adom-you is the default on purpose.\n\n> To drive the user's **real, signed-in** Chrome/Edge (their cookies, SSO, saved logins), that's the\n> **Adom browser extension's `nbrowser_*` verbs**, a separate bridge, not pup.\n\nCanonical page: **https://wiki.adom.inc/adom/pup-bridge**\n\n## Install vs Download, which is which (and why the version numbers differ)\n\nThe page header shows **two** things, for two different places. Most people need only the first.\n\n| On the page | What it is | Who runs it | You usually\u2026 |\n|---|---|---|---|\n| **Install**, `adom-wiki pkg install \u2026` | The **AI skill pack**, the `pup` skills that teach a cloud/container AI how to drive the bridge. Docs only, no runtime; drops into `~/.claude/skills` + `~/.codex/skills`. | your **container / cloud AI** | **run this** (or it arrives via `sync_skills`) |\n| **Download for your machine**, `adom-bridge-puppeteer-v<ver>.zip` | The **bridge runtime**, the actual Node program (browser detection + driving) that runs on the desktop. | **Bridge**, on the user's PC | **do nothing**, Bridge **auto-installs & auto-updates** it; the manual download is only for offline/manual installs |\n\n**Why two different version numbers?** They're independent artifacts. The **Install (pkg)** version bumps\nwhenever the *skills/docs* change (often). The **Download (runtime)** version bumps only when the *bridge\ncode* changes (rarely). So it's normal to see e.g. Install `v1.8.27` and Download `v1.8.20`, nothing is\nout of sync; they just version on their own clocks.\n\n*(There's also a third copy, the runtime is **bundled inside the Bridge installer** as a first-run\nseed, superseded by a newer cache copy via `updateManifestUrl`. You never touch it directly.)*\n\n## Use it\n\n```bash\n# everyday: open + screenshot. Opens in the BACKGROUND automatically, no need to lower it,\n# and it's fully drivable/screenshottable while hidden, so the user is never interrupted.\nadom-bridge-cli pup_open_window '{\"sessionId\":\"myapp-web\",\"owner\":\"myapp\",\"url\":\"http://localhost:3000\"}'\nadom-bridge-cli pup_screenshot '{\"sessionId\":\"myapp-web\"}'\n\n# readiness (use pup_readiness, NOT pup_status). On a box with Chrome or Edge this is\n# instantly {ready:true} with no download. Only a box with no Chromium at all fetches Chrome for\n# Testing in the background, poll until ready, then open.\nadom-bridge-cli pup_readiness '{}' # \u2192 {ready:true, browserKind:\"chrome\"|\"edge\"|...}\n```\n\n- **Task-prefix your `sessionId` + pass `owner`**, sessions are shared across every AI thread on the\n desktop; that lets pup protect your window from another thread navigating it away.\n- **`foreground:true` is the only way to show a window**, sizing/positioning does not foreground it.\n\nFull everyday usage (tabs, recording, window ownership, cold-start playbook) is in the `pup` skill\n(`SKILL.md`).\n\n## Window-type taskbar icons: read a pup window at a glance\n\n\n\nEvery pup window's **taskbar icon states what kind of thing it is showing**. All five share the same\ndrawing (the teal Adom tile carrying a solid browser window) and differ only in the window's\n*content*: a monochrome glyph on the 24x24 Adom house grid, per the brand icon law (single color,\nno gradients, no emoji):\n\n| Icon | Window content | Means |\n|---|---|---|\n|  | open book | **Adom wiki, public view**: logged out, what the world sees |\n|  | book + person | **Adom wiki, signed in**: the user's logged-in view (private source, drafts, owner cards) |\n|  | the Adom mark | **An Adom app**: localhost or a cloud-slug proxy URL |\n|  | globe | **The web**: any other site (ti.com, digikey, ...) |\n|  | two panes | **Mixed**: the window's tabs span more than one category |\n\n- The category is derived from **all tabs** in the window; it updates **live** (add a digikey tab\n to a wiki window and the icon flips to *mixed* within about a second).\n- The **overlay badge** riding the icon's corner is separate and sacred: it is the **active tab's\n own favicon**, so you always see which site you are looking at. In grouped-taskbar mode it shows\n window/tab counters instead.\n- The **tab title** carries the same login signal in text: a solid dot (`\u25cf Logged in`) or hollow dot\n (`\u25cb Public`) leads the title of every Adom wiki tab.\n- Under the hood, each window's identity (icon, name, Alt-Tab entry) rides a per-session Windows\n AppUserModelID that **carries the category**: the only way Win11 allows a taskbar tile to change\n live. Grouped mode instead keeps one stable, pinnable `Adom.Pup` identity.\n\n### Using pup's icons in your own tool (HD browser picker, launchers, menus)\n\nIf you are building a surface that offers \"open a pup window\" (a browser picker, a launcher tile, a\nmenu item), **use pup's real icon, not a stand-in.** The canonical, self-describing asset set lives\nin the wiki repo at [`assets/pup-icons/`](assets/pup-icons/), in three formats:\n\n- **SVG** (`pup-cat-*.svg`), scalable, the right choice for a web/Tauri picker.\n- **PNG** (`pup-cat-*-{32,48,128,256,512}.png`), raster fallback / retina.\n- **ICO** (`pup-cat-*.ico`), Windows multi-size, for taskbar/shortcut contexts (256px frame is\n PNG-compressed, per the Vista+ rule, so it never renders as a generic document).\n\n**For a launcher/picker item, use `pup-cat-default`**, the neutral teal browser-window tile. It is\nwhat a pup window's taskbar button looks like before its content is known, so the picker previews the\nreal result. The five category icons above (`wiki`, `wiki-in`, `app`, `web`, `mixed`) are for\n*showing an existing window's kind*, not for a generic \"open pup\" action.\n\nFetch any asset from the wiki without cloning:\n\n```\nhttps://wiki.adom.inc/api/v1/pages/pup-bridge/files/assets/pup-icons/pup-cat-default.svg\nhttps://wiki.adom.inc/api/v1/pages/pup-bridge/files/assets/pup-icons/manifest.json\n```\n\n[`assets/pup-icons/manifest.json`](assets/pup-icons/manifest.json) is machine-readable: it maps each\nicon id to its meaning, its glyph, and its file in every format, and names\n`recommended_for_launcher` so a tool can pick the right one programmatically. Brand rule if you ever\nredraw one: teal tile `#00b8b0` + dark-teal window body `#003d40` + a single-color teal glyph, no\ngradients, shadows, or emoji.\n\n## Real windows, one per type\n\nFull windows as pup opens them (title bar, tabs, page). Note the tab title glyphs on the wiki pair\nand the signed-in header on the second:\n\n**Adom wiki, PUBLIC** (tab: `\u25cb Public`, page header shows Login):\n\n\n\n**Adom wiki, SIGNED IN** (tab: `\u25cf Logged in`, page header shows the user's name):\n\n\n\n**An Adom app** (here: the shotlog viewer on a cloud slug URL):\n\n\n\n**The web** (ti.com):\n\n\n\n**Mixed** (a digikey tab and a wiki tab in one window):\n\n\n\n## Overlay badges: the corner of the taskbar icon\n\n\n\nThe base icon states the window TYPE; the small overlay riding its lower-right corner carries\nLIVE detail, composited exactly like this:\n\n| Overlay | When | What it tells you |\n|---|---|---|\n| the active tab's **favicon** on a dark rounded plate | split mode, page serves a favicon | which site the active tab is on, at a glance |\n| a **count badge** (white digit, dark plate) | split mode, 2+ tabs and no favicon | how many tabs the window holds |\n| the **dual counter** (dark = windows, teal = total tabs) | grouped mode | how much is stacked under the single Adom Pup button |\n\nThe overlay never carries branding or state that belongs to the base icon: it is live per-window\ndetail only, and the favicon always wins the slot when one exists.\n\n## The Adom wiki: logged-in vs public view, and the taskbar toggle\n\npup can show any Adom wiki page from **two viewpoints**, and both the AI and the user can switch:\n\n- **Public (default)**: a fresh logged-out profile: exactly what the world sees. Use it to verify\n what a publish actually exposed.\n- **Signed in**: `pup_open_window {..., wikiView:\"authed\"}` routes to a reserved persistent\n profile whose cookie jar holds the user's ~30-day SSO session. One login serves **every** AI\n thread on the machine. First use returns `wikiLoginNeeded:true`; the user signs in once, in that\n window.\n\n**The user can flip a wiki window themselves**: right-click its taskbar button: the jump list\ncarries **\"Adom wiki: switch to logged-in view\"** (or \"...switch to public view\"). Clicking it\nrelaunches that same window under the other cookie jar, brings it to the front, and shows an\non-screen caption while it works (\"Switching to the logged-in view of the Adom wiki\", then\n\"Adom wiki: now the LOGGED-IN view (Their Name)\"). The AI-side equivalent is the\n`pup_wiki_set_view` verb, which exists for that jump-list click: AI threads should pass\n`wikiView` on open instead.\n\n## One session, one OS window\n\nEvery pup session gets its **own OS window**, even when sessions share a browser profile (as all\nsigned-in wiki windows share the authed cookie jar). This is what makes per-window identity\npossible: a window's title belongs to its active tab, so windows that share sessions as tabs\ncannot be found, branded, flashed, or given jump lists individually. Sharing a profile shares the\ncookies; it never merges windows.\n\n## Recording\n\npup can record what it drives, a **single tab/window** or the **whole desktop**, straight from the\ncloud, with no HUD and no need to bring the window forward.\n\n\n\n*Above: a GIF preview of a real `pup_record` capture (\u22488.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.*\n\n### High-FPS windows: recording something the user is not looking at\n\npup windows are backgrounded by design, and Chrome throttles a window that is occluded, so\nrecording one normally yields a **1-2 fps** video. pup can disable Chrome's power-saving to keep a\nwindow painting at full rate, but a window in that mode can never idle down (three of them once\ndrained a laptop overnight, wiki issue #14).\n\nSo it is **opt-in and leased**:\n\n- **Default** is Chrome's own power behaviour. Normal windows throttle when occluded and cost\n nothing in the background. Right for driving, scraping and screenshots.\n- **`pup_open_window {highFps:true}`** renders at full rate while occluded, for background\n recording. It holds a lease (default 20 min), and **an active recording holds that lease open\n indefinitely, so a take is never cut off**. On lapse the window is *downgraded* back to normal\n power by relaunching with its tabs intact, never closed.\n- **`pup_highfps_extend {sessionId, minutes}`** negotiates more time up front.\n\n**Full details, defaults, activity signals, and rules of thumb: [RECORDING.md](RECORDING.md).**\n\n### Two recorders, pick by what you're capturing\n\n| Verb pair | Captures | How it works under the hood |\n|---|---|---|\n| **`pup_record_start` / `pup_record_stop`** | ONE pup **tab/window**, the page content | **CDP `Page.startScreencast`** (JPEG frames, up to ~50 fps) piped to **ffmpeg**, encoded to **VP9** in real time \u2192 one `.webm`. Tab-scoped at the protocol level, so it captures the exact tab even in the **background**, no `getDisplayMedia`, no picker, no foreground. |\n| **`desktop_record_start` / `desktop_record_stop`** | the WHOLE **desktop** (multiple apps, dialogs) | Screen capture via **MediaRecorder** \u2192 one `.webm`; ffmpeg remuxes it to stamp a proper Duration. |\n\n```bash\nadom-bridge-cli pup_record_start '{\"sessionId\":\"demo-web\"}' # \u2192 { recordingId }\n# ...drive the scene: navigate, click, type, scroll...\nadom-bridge-cli pup_record_stop '{\"sessionId\":\"demo-web\",\"recordingId\":\"<id>\"}' # \u2192 { path: \"...webm\" }\n```\n\n**ffmpeg** is required for recording. The bridge auto-detects it (a WinGet `Gyan.FFmpeg` install, PATH,\nor common dirs) and re-checks **lazily on `record_start`**, so if it's missing you can\n`winget install Gyan.FFmpeg` and just retry, no bridge restart. `pup_record_status` /\n`pup_record_list` (and the `desktop_record_*` equivalents) report in-flight and finished captures.\n\n### Formats, one native format, easy conversion\n\npup records to **one** format natively: **WebM (VP9)**, for both recorders. It doesn't offer a format\nswitch; instead, convert with the bundled ffmpeg when you need MP4 or GIF. Real numbers from the \u22488.6 s\ndemo above (1264\u00d7705):\n\n| Format | Codec | Size | How you get it | Best for | Watch out for |\n|---|---|---|---|---|---|\n| **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 |\n| **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 |\n| **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 |\n\n```bash\n# \u2192 MP4 (H.264, universal). The scale filter forces EVEN dimensions (H.264 rejects odd w/h \u2192 frame 0).\nffmpeg -i rec.webm -vf \"scale=trunc(iw/2)*2:trunc(ih/2)*2\" -c:v libx264 -crf 23 -pix_fmt yuv420p -movflags +faststart rec.mp4\n\n# \u2192 GIF (silent, looping inline preview). Palette pass keeps colors clean; drop fps/scale to shrink.\nffmpeg -i rec.webm -vf \"fps=12,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" rec.gif\n```\n\n**Rule of thumb:** keep **WebM** for archiving + web embeds; make an **MP4** the moment a human on Safari/\nPowerPoint/phone needs it; make a short **GIF** only for an inline auto-play preview.\n\n## Source & development\n\nThis bridge is cloud-owned here (extracted from `adom-bridge/plugins/puppeteer`, mirroring the\nkicad/fusion bridges). Bridge ships a bundled seed and auto-pulls newer versions from this page.\n\n- Clone the source: `adom-wiki repo clone adom/pup-bridge`\n- Runtime lives in `src/` (`server.js`, `chrome.js`, `bridge.json`, \u2026); the release zip is `src/` at zip-root.\n- **Maintainer skills** (`pup-bridge-dev`, `pup-bridge-publish`) are **source-only**, in `dev-skills/` +\n `publish-skills/`, not shipped in the pkg (per the Bridge SDK a pkg ships only user skills). Skill map:\n\n| Skill | Ships in pkg? | What it's for |\n|---|---|---|\n| `pup` (root SKILL.md) | \u2705 user | Start here, mental model (CDP-launched fresh process of the installed browser, rendered-but-backgrounded), when-vs-extension, quick start |\n| `pup-windows-sessions-tabs` | \u2705 user | sessionIds, window ownership (don't steal another thread's window), background-vs-foreground, many tabs in one window |\n| `pup-screenshots-recording` | \u2705 user | Screenshots (full-page/full-res) + recording; driving/verifying tricky pages (shadow DOM, nested scroll) |\n| `pup-browsers-and-chrome` | \u2705 user | Browser detection/launch, `pup_use`, installing Chrome/CfT (incl. UAC-notify), readiness, cold-start errors |\n| `pup-adom-wiki` | \u2705 user | Driving + verifying `wiki.adom.inc` pages in pup (view/screenshot/verify; the login situation) |\n| `pup-bridge-dev` / `pup-bridge-publish` | \u274c source-only | MAINTAINERS: bridge internals + the publish/release recipe (in `dev-skills/`/`publish-skills/`, not shipped) |\n- Ownership boundary: `CLAUDE.md`. Publish recipe: `PUBLISHING.md`. History: `CHANGELOG.md`.\n\n## Extend pup, add your own pup skill (third parties)\n\nBuilt a skill that drives pup for a specific job (a site-specific scraper, a visual test flow, a\ndomain widget)? You don't need write access here, surface it from this page with a **breadcrumb**:\n\n1. **Publish your skill** to your own wiki page (see the `adom-wiki` / `wiki-skillpack` skills). Make it a\n normal user skill so `pkg install` drops it into a container's `~/.claude/skills`.\n2. **Drop a breadcrumb on this page** pointing at it:\n ```bash\n adom-wiki breadcrumb post adom/pup-bridge \\\n --label \"Your skill name, one-line what it does\" \\\n --target-url \"https://wiki.adom.inc/<owner>/<your-slug>\" \\\n --category \"skill\"\n ```\n It's **pending until the page owner approves it**, then it shows in this page's **Breadcrumbs** tab.\n3. **Discovery is automatic:** an agent working with pup can list related third-party skills with\n `adom-wiki breadcrumb list adom/pup-bridge`, approved breadcrumbs are how pup finds\n community skills that build on it.\n\nKeep breadcrumbs on-topic (they genuinely extend pup / browser-driving); off-topic ones get rejected.\n\n## Related\n\n- [Bridge SDK guide](https://wiki.adom.inc/adom/adom-bridge-sdk), `bridge.json` schema, packaging, lifecycle\n- [KiCad bridge](https://wiki.adom.inc/adom/kicad-bridge) \u00b7 [Fusion 360 bridge](https://wiki.adom.inc/adom/fusion-bridge)\n- [Bridge (parent app)](https://wiki.adom.inc/adom/adom-bridge)\n\nMIT licensed.\n",+ "readme": "# pup: the Puppeteer bridge\n\n**pup is the AI's own browser: a real, full Chrome/Edge window on the user's desktop that the AI drives\nwith complete programmatic control, but a _sandbox_.** It runs in a fresh, isolated profile that is\nnever the user's real signed-in browser, and opens in the **background by default** so it never disrupts\nthem. That trade is exactly why pup exists alongside **nb / nbe** (the native browser and its extension):\nnb/nbe drive the user's _real_ browser, their cookies, SSO, saved logins, their identity, for when a\ntask needs to BE the user. pup is the opposite trade: no borrowed identity, but **total control**, a\nreal, disposable browser the AI owns end to end (open/close windows + tabs, navigate, screenshot, eval\nJS, record). Logged out by design, it's the safe, fully-drivable default for automation, testing,\nscraping public pages, and showing wiki pages; reach for nb/nbe only when you genuinely need the user's\nreal logins. pup drives the browser **already on the machine** (installed Chrome, else Microsoft Edge;\nevery Windows PC ships Edge), so the common case needs no download.\n\n**The core goal: an AI-driven browser that can do everything it needs to for you - the best assistant\nin the world.** By default every pup window surfs on the shared durable **adom-you** profile, and every\nlogin made there enriches a shared credential store. Over time that store lets pup automatically enter\nusernames and passwords on every site it has ever seen, which is what makes a truly self-sufficient\nAI browser possible. Isolated throwaway profiles exist for the cases that need them (logged-out\ntesting, acting as another user), but they build nothing: adom-you is the default on purpose.\n\n> To drive the user's **real, signed-in** Chrome/Edge (their cookies, SSO, saved logins), that's the\n> **Adom browser extension's `nbrowser_*` verbs**, a separate bridge, not pup.\n\nCanonical page: **https://wiki.adom.inc/adom/pup-bridge**\n\n## Install vs Download, which is which (and why the version numbers differ)\n\nThe page header shows **two** things, for two different places. Most people need only the first.\n\n| On the page | What it is | Who runs it | You usually… |\n|---|---|---|---|\n| **Install**, `adom-wiki pkg install …` | The **AI skill pack**, the `pup` skills that teach a cloud/container AI how to drive the bridge. Docs only, no runtime; drops into `~/.claude/skills` + `~/.codex/skills`. | your **container / cloud AI** | **run this** (or it arrives via `sync_skills`) |\n| **Download for your machine**, `adom-bridge-puppeteer-v<ver>.zip` | The **bridge runtime**, the actual Node program (browser detection + driving) that runs on the desktop. | **Bridge**, on the user's PC | **do nothing**, Bridge **auto-installs & auto-updates** it; the manual download is only for offline/manual installs |\n\n**Why two different version numbers?** They're independent artifacts. The **Install (pkg)** version bumps\nwhenever the *skills/docs* change (often). The **Download (runtime)** version bumps only when the *bridge\ncode* changes (rarely). So it's normal to see e.g. Install `v1.8.27` and Download `v1.8.20`, nothing is\nout of sync; they just version on their own clocks.\n\n*(There's also a third copy, the runtime is **bundled inside the Bridge installer** as a first-run\nseed, superseded by a newer cache copy via `updateManifestUrl`. You never touch it directly.)*\n\n## Use it\n\n```bash\n# everyday: open + screenshot. Opens in the BACKGROUND automatically, no need to lower it,\n# and it's fully drivable/screenshottable while hidden, so the user is never interrupted.\nadom-bridge-cli pup_open_window '{\"sessionId\":\"myapp-web\",\"owner\":\"myapp\",\"url\":\"http://localhost:3000\"}'\nadom-bridge-cli pup_screenshot '{\"sessionId\":\"myapp-web\"}'\n\n# readiness (use pup_readiness, NOT pup_status). On a box with Chrome or Edge this is\n# instantly {ready:true} with no download. Only a box with no Chromium at all fetches Chrome for\n# Testing in the background, poll until ready, then open.\nadom-bridge-cli pup_readiness '{}' # → {ready:true, browserKind:\"chrome\"|\"edge\"|...}\n```\n\n- **Task-prefix your `sessionId` + pass `owner`**, sessions are shared across every AI thread on the\n desktop; that lets pup protect your window from another thread navigating it away.\n- **`foreground:true` is the only way to show a window**, sizing/positioning does not foreground it.\n\nFull everyday usage (tabs, recording, window ownership, cold-start playbook) is in the `pup` skill\n(`SKILL.md`).\n\n## Window-type taskbar icons: read a pup window at a glance\n\n\n\nEvery pup window's **taskbar icon states what kind of thing it is showing**. All five share the same\ndrawing (the teal Adom tile carrying a solid browser window) and differ only in the window's\n*content*: a monochrome glyph on the 24x24 Adom house grid, per the brand icon law (single color,\nno gradients, no emoji):\n\n| Icon | Window content | Means |\n|---|---|---|\n|  | open book | **Adom wiki, public view**: logged out, what the world sees |\n|  | book + person | **Adom wiki, signed in**: the user's logged-in view (private source, drafts, owner cards) |\n|  | the Adom mark | **An Adom app**: localhost or a cloud-slug proxy URL |\n|  | globe | **The web**: any other site (ti.com, digikey, ...) |\n|  | two panes | **Mixed**: the window's tabs span more than one category |\n\n- The category is derived from **all tabs** in the window; it updates **live** (add a digikey tab\n to a wiki window and the icon flips to *mixed* within about a second).\n- The **overlay badge** riding the icon's corner is separate and sacred: it is the **active tab's\n own favicon**, so you always see which site you are looking at. In grouped-taskbar mode it shows\n window/tab counters instead.\n- The **tab title** carries the same login signal in text: a solid dot (`● Logged in`) or hollow dot\n (`○ Public`) leads the title of every Adom wiki tab.\n- Under the hood, each window's identity (icon, name, Alt-Tab entry) rides a per-session Windows\n AppUserModelID that **carries the category**: the only way Win11 allows a taskbar tile to change\n live. Grouped mode instead keeps one stable, pinnable `Adom.Pup` identity.\n\n### Using pup's icons in your own tool (HD browser picker, launchers, menus)\n\nIf you are building a surface that offers \"open a pup window\" (a browser picker, a launcher tile, a\nmenu item), **use pup's real icon, not a stand-in.** The canonical, self-describing asset set lives\nin the wiki repo at [`assets/pup-icons/`](assets/pup-icons/), in three formats:\n\n- **SVG** (`pup-cat-*.svg`), scalable, the right choice for a web/Tauri picker.\n- **PNG** (`pup-cat-*-{32,48,128,256,512}.png`), raster fallback / retina.\n- **ICO** (`pup-cat-*.ico`), Windows multi-size, for taskbar/shortcut contexts (256px frame is\n PNG-compressed, per the Vista+ rule, so it never renders as a generic document).\n\n**For a launcher/picker item, use `pup-cat-default`**, the neutral teal browser-window tile. It is\nwhat a pup window's taskbar button looks like before its content is known, so the picker previews the\nreal result. The five category icons above (`wiki`, `wiki-in`, `app`, `web`, `mixed`) are for\n*showing an existing window's kind*, not for a generic \"open pup\" action.\n\nFetch any asset from the wiki without cloning:\n\n```\nhttps://wiki.adom.inc/api/v1/pages/pup-bridge/files/assets/pup-icons/pup-cat-default.svg\nhttps://wiki.adom.inc/api/v1/pages/pup-bridge/files/assets/pup-icons/manifest.json\n```\n\n[`assets/pup-icons/manifest.json`](assets/pup-icons/manifest.json) is machine-readable: it maps each\nicon id to its meaning, its glyph, and its file in every format, and names\n`recommended_for_launcher` so a tool can pick the right one programmatically. Brand rule if you ever\nredraw one: teal tile `#00b8b0` + dark-teal window body `#003d40` + a single-color teal glyph, no\ngradients, shadows, or emoji.\n\n## Real windows, one per type\n\nFull windows as pup opens them (title bar, tabs, page). Note the tab title glyphs on the wiki pair\nand the signed-in header on the second:\n\n**Adom wiki, PUBLIC** (tab: `○ Public`, page header shows Login):\n\n\n\n**Adom wiki, SIGNED IN** (tab: `● Logged in`, page header shows the user's name):\n\n\n\n**An Adom app** (here: the shotlog viewer on a cloud slug URL):\n\n\n\n**The web** (ti.com):\n\n\n\n**Mixed** (a digikey tab and a wiki tab in one window):\n\n\n\n## Overlay badges: the corner of the taskbar icon\n\n\n\nThe base icon states the window TYPE; the small overlay riding its lower-right corner carries\nLIVE detail, composited exactly like this:\n\n| Overlay | When | What it tells you |\n|---|---|---|\n| the active tab's **favicon** on a dark rounded plate | split mode, page serves a favicon | which site the active tab is on, at a glance |\n| a **count badge** (white digit, dark plate) | split mode, 2+ tabs and no favicon | how many tabs the window holds |\n| the **dual counter** (dark = windows, teal = total tabs) | grouped mode | how much is stacked under the single Adom Pup button |\n\nThe overlay never carries branding or state that belongs to the base icon: it is live per-window\ndetail only, and the favicon always wins the slot when one exists.\n\n## The Adom wiki: logged-in vs public view, and the taskbar toggle\n\npup can show any Adom wiki page from **two viewpoints**, and both the AI and the user can switch:\n\n- **Public (default)**: a fresh logged-out profile: exactly what the world sees. Use it to verify\n what a publish actually exposed.\n- **Signed in**: `pup_open_window {..., wikiView:\"authed\"}` routes to a reserved persistent\n profile whose cookie jar holds the user's ~30-day SSO session. One login serves **every** AI\n thread on the machine. First use returns `wikiLoginNeeded:true`; the user signs in once, in that\n window.\n\n**The user can flip a wiki window themselves**: right-click its taskbar button: the jump list\ncarries **\"Adom wiki: switch to logged-in view\"** (or \"...switch to public view\"). Clicking it\nrelaunches that same window under the other cookie jar, brings it to the front, and shows an\non-screen caption while it works (\"Switching to the logged-in view of the Adom wiki\", then\n\"Adom wiki: now the LOGGED-IN view (Their Name)\"). The AI-side equivalent is the\n`pup_wiki_set_view` verb, which exists for that jump-list click: AI threads should pass\n`wikiView` on open instead.\n\n## One session, one OS window\n\nEvery pup session gets its **own OS window**, even when sessions share a browser profile (as all\nsigned-in wiki windows share the authed cookie jar). This is what makes per-window identity\npossible: a window's title belongs to its active tab, so windows that share sessions as tabs\ncannot be found, branded, flashed, or given jump lists individually. Sharing a profile shares the\ncookies; it never merges windows.\n\n## Recording\n\npup can record what it drives, a **single tab/window** or the **whole desktop**, straight from the\ncloud, with no HUD and no need to bring the window forward.\n\n\n\n*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.*\n\n### High-FPS windows: recording something the user is not looking at\n\npup windows are backgrounded by design, and Chrome throttles a window that is occluded, so\nrecording one normally yields a **1-2 fps** video. pup can disable Chrome's power-saving to keep a\nwindow painting at full rate, but a window in that mode can never idle down (three of them once\ndrained a laptop overnight, wiki issue #14).\n\nSo it is **opt-in and leased**:\n\n- **Default** is Chrome's own power behaviour. Normal windows throttle when occluded and cost\n nothing in the background. Right for driving, scraping and screenshots.\n- **`pup_open_window {highFps:true}`** renders at full rate while occluded, for background\n recording. It holds a lease (default 20 min), and **an active recording holds that lease open\n indefinitely, so a take is never cut off**. On lapse the window is *downgraded* back to normal\n power by relaunching with its tabs intact, never closed.\n- **`pup_highfps_extend {sessionId, minutes}`** negotiates more time up front.\n\n**Full details, defaults, activity signals, and rules of thumb: [RECORDING.md](RECORDING.md).**\n\n### Two recorders, pick by what you're capturing\n\n| Verb pair | Captures | How it works under the hood |\n|---|---|---|\n| **`pup_record_start` / `pup_record_stop`** | ONE pup **tab/window**, the page content | **CDP `Page.startScreencast`** (JPEG frames, up to ~50 fps) piped to **ffmpeg**, encoded to **VP9** in real time → one `.webm`. Tab-scoped at the protocol level, so it captures the exact tab even in the **background**, no `getDisplayMedia`, no picker, no foreground. |\n| **`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. |\n\n```bash\nadom-bridge-cli pup_record_start '{\"sessionId\":\"demo-web\"}' # → { recordingId }\n# ...drive the scene: navigate, click, type, scroll...\nadom-bridge-cli pup_record_stop '{\"sessionId\":\"demo-web\",\"recordingId\":\"<id>\"}' # → { path: \"...webm\" }\n```\n\n**ffmpeg** is required for recording. The bridge auto-detects it (a WinGet `Gyan.FFmpeg` install, PATH,\nor common dirs) and re-checks **lazily on `record_start`**, so if it's missing you can\n`winget install Gyan.FFmpeg` and just retry, no bridge restart. `pup_record_status` /\n`pup_record_list` (and the `desktop_record_*` equivalents) report in-flight and finished captures.\n\n### Formats, one native format, easy conversion\n\npup records to **one** format natively: **WebM (VP9)**, for both recorders. It doesn't offer a format\nswitch; instead, convert with the bundled ffmpeg when you need MP4 or GIF. Real numbers from the ≈8.6 s\ndemo above (1264×705):\n\n| Format | Codec | Size | How you get it | Best for | Watch out for |\n|---|---|---|---|---|---|\n| **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 |\n| **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 |\n| **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 |\n\n```bash\n# → MP4 (H.264, universal). The scale filter forces EVEN dimensions (H.264 rejects odd w/h → frame 0).\nffmpeg -i rec.webm -vf \"scale=trunc(iw/2)*2:trunc(ih/2)*2\" -c:v libx264 -crf 23 -pix_fmt yuv420p -movflags +faststart rec.mp4\n\n# → GIF (silent, looping inline preview). Palette pass keeps colors clean; drop fps/scale to shrink.\nffmpeg -i rec.webm -vf \"fps=12,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" rec.gif\n```\n\n**Rule of thumb:** keep **WebM** for archiving + web embeds; make an **MP4** the moment a human on Safari/\nPowerPoint/phone needs it; make a short **GIF** only for an inline auto-play preview.\n\n## Source & development\n\nThis bridge is cloud-owned here (extracted from `adom-bridge/plugins/puppeteer`, mirroring the\nkicad/fusion bridges). Bridge ships a bundled seed and auto-pulls newer versions from this page.\n\n- Clone the source: `adom-wiki repo clone adom/pup-bridge`\n- Runtime lives in `src/` (`server.js`, `chrome.js`, `bridge.json`, …); the release zip is `src/` at zip-root.\n- **Maintainer skills** (`pup-bridge-dev`, `pup-bridge-publish`) are **source-only**, in `dev-skills/` +\n `publish-skills/`, not shipped in the pkg (per the Bridge SDK a pkg ships only user skills). Skill map:\n\n| Skill | Ships in pkg? | What it's for |\n|---|---|---|\n| `pup` (root SKILL.md) | ✅ user | Start here, mental model (CDP-launched fresh process of the installed browser, rendered-but-backgrounded), when-vs-extension, quick start |\n| `pup-windows-sessions-tabs` | ✅ user | sessionIds, window ownership (don't steal another thread's window), background-vs-foreground, many tabs in one window |\n| `pup-screenshots-recording` | ✅ user | Screenshots (full-page/full-res) + recording; driving/verifying tricky pages (shadow DOM, nested scroll) |\n| `pup-browsers-and-chrome` | ✅ user | Browser detection/launch, `pup_use`, installing Chrome/CfT (incl. UAC-notify), readiness, cold-start errors |\n| `pup-adom-wiki` | ✅ user | Driving + verifying `wiki.adom.inc` pages in pup (view/screenshot/verify; the login situation) |\n| `pup-bridge-dev` / `pup-bridge-publish` | ❌ source-only | MAINTAINERS: bridge internals + the publish/release recipe (in `dev-skills/`/`publish-skills/`, not shipped) |\n- Ownership boundary: `CLAUDE.md`. Publish recipe: `PUBLISHING.md`. History: `CHANGELOG.md`.\n\n## Extend pup, add your own pup skill (third parties)\n\nBuilt a skill that drives pup for a specific job (a site-specific scraper, a visual test flow, a\ndomain widget)? You don't need write access here, surface it from this page with a **breadcrumb**:\n\n1. **Publish your skill** to your own wiki page (see the `adom-wiki` / `wiki-skillpack` skills). Make it a\n normal user skill so `pkg install` drops it into a container's `~/.claude/skills`.\n2. **Drop a breadcrumb on this page** pointing at it:\n ```bash\n adom-wiki breadcrumb post adom/pup-bridge \\\n --label \"Your skill name, one-line what it does\" \\\n --target-url \"https://wiki.adom.inc/<owner>/<your-slug>\" \\\n --category \"skill\"\n ```\n It's **pending until the page owner approves it**, then it shows in this page's **Breadcrumbs** tab.\n3. **Discovery is automatic:** an agent working with pup can list related third-party skills with\n `adom-wiki breadcrumb list adom/pup-bridge`, approved breadcrumbs are how pup finds\n community skills that build on it.\n\nKeep breadcrumbs on-topic (they genuinely extend pup / browser-driving); off-topic ones get rejected.\n\n## Related\n\n- [Bridge SDK guide](https://wiki.adom.inc/adom/adom-bridge-sdk), `bridge.json` schema, packaging, lifecycle\n- [KiCad bridge](https://wiki.adom.inc/adom/kicad-bridge) · [Fusion 360 bridge](https://wiki.adom.inc/adom/fusion-bridge)\n- [Bridge (parent app)](https://wiki.adom.inc/adom/adom-bridge)\n\nMIT licensed.\n", "author": "John Lauer <[email protected]>", "visibility": { "public": true@@ -101,15 +100,15 @@ "created_at": "2026-05-28T05:28:43.991Z", "skills": [], "author_name": "John Lauer",- "description": "The pup SKILL PACK, the AI skills that teach a cloud/container AI how to drive the Bridge Puppeteer (pup) bridge (pup_* 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, this is NOT the bridge runtime. The bridge itself (the Node program that drives the browser) runs on the DESKTOP: Bridge bundles it and auto-installs/updates it, and it's published separately on the Releases tab as adom-bridge-puppeteer-v<ver>.zip. So the pkg version (skills, bumps often) and the Release version (runtime, bumps rarely) differ on purpose. TL;DR: pkg install = the skills for your AI; the bridge = the Release zip, which Bridge manages for you.",+ "description": "The pup SKILL PACK — 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 — 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) — 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": [- "ab", "pup", "puppeteer", "browser", "adom-bridge", "bridge",- "skills"+ "skills",+ "pup-bridge" ], "files": [ "SKILL.md",@@ -117,6 +116,9 @@ "skills/pup-screenshots-recording/SKILL.md", "skills/pup-browsers-and-chrome/SKILL.md", "skills/pup-adom-wiki/SKILL.md",+ "skills/pup-vendor-login/SKILL.md",+ "skills/pup-settings/SKILL.md",+ "skills/pup-credentials/SKILL.md", "install.sh", "uninstall.sh", "README.md",@@ -129,5 +131,9 @@ "dependencies": { "adom/adom-bridge": "^2.0.0" },- "org": "adom"+ "org": "adom",+ "contributors": [+ "Kyle Bergstedt <[email protected]>",+ "Colby Knox"+ ] }
skills/pup-credentials/SKILL.mdadded+110@@ -0,0 +1,110 @@+---+name: pup-credentials+description: "How pup signs the user into sites AS THEM: pup's OS-keychain credential vault (auto-capture on login + silent autofill on return, matched across a site's whole registrable domain), importing the user's OWN saved Chrome/Edge/Brave passwords into the vault (pup_import_browser_logins — the SYSTEM-elevated decrypt behind one consent + one Windows UAC), and — when a saved password is STALE (a login that 'Fail to authenticate's) — recovering the CURRENT username+password straight from the user's browser password manager by driving it with Bridge desktop verbs, clicking the eyeball, waiting for the user's Windows Hello, and reading the revealed value. It is not pretty, but it works (proven end to end: recovered a live password, fixed a wrong username, logged into a gated CAD portal, downloaded a real library). Read before trying to log a user into any site pup does not already have a working credential for. Trigger words: pup vault, saved password, autofill login, import my passwords, import browser logins, pup_import_browser_logins, decrypt browser credentials, credential_set, pup_credentials, stale password, fail to authenticate, wrong password, recover my password, password manager, chrome://password-manager, show password eyeball, windows hello, get my username and password, log me in as me, seed adom-you logins."+---++# pup credentials — sign the user in AS THEM++pup is the user's doppelganger, so it needs to log in the way the user does. This skill is the whole+credential story: the vault, importing the user's saved logins, and the not-pretty-but-it-works way+to recover a **current** password when a stored one has gone stale. Verbs live in the `pup` bridge;+call them with `adom-bridge-cli`.++## 1. The vault (how pup remembers logins)++- **Auto-capture:** when the user (or pup) signs into a site, pup grabs the credential and stores it+ in the **OS keychain** (Windows DPAPI / macOS Keychain / Linux libsecret). Passwords are NEVER+ echoed back — `pup_credentials` lists host + username only.+- **Autofill:** on a return visit pup fills the saved login in the **background** (no Chrome+ dropdown, no foregrounding). Submitting is reason-gated (`pup_login {submit:true, submitReason}`)+ and confirms the live domain first (anti-phishing).+- **Registrable-domain matching:** a login saved on `ms.example.com` is offered on `example.com`+ and its siblings, like a browser password manager. So the host a credential was saved under does+ not have to equal the host of the page you are filling.+- **Durable:** the vault index lives in `~/.adom` (not the bridge cache), so it survives pup updates.+- Store one explicitly: `credential_set {host, username, password}`. List: `pup_credentials {}`.++## 2. Import the user's OWN saved browser logins++The fastest way to make pup able to sign in everywhere the user already can: pull their saved+Chrome/Edge/Brave passwords into the vault.++```+# preview: how many logins exist, per profile (read-only, no prompt)+adom-bridge-cli pup_import_scan {}++# import (optionally filter to specific sites). Runs the SYSTEM-elevated decrypt LOCALLY:+# the user approves ONE Adom Bridge consent dialog + ONE Windows UAC prompt on the desktop.+adom-bridge-cli pup_import_browser_logins {"hostFilter":["digikey","mouser","snapeda"]}+```++- **Why it must be pup (local), not a cloud thread:** the decrypt (`desktop_decrypt_browser_credentials`)+ is refused for relayed/cloud callers (`relay_forbidden`). Only a LOCAL component (pup, over the+ loopback) may ask, and the user's consent + UAC IS the authorization.+- Passwords are merged into the vault and the plaintext is dropped immediately; the verb returns+ COUNTS only. `hostFilter` (string or array, substring match) does a surgical import; omit to import+ everything saved.+- After importing, `pup_login` on those sites just works.++## 3. Recover a CURRENT password when a saved one is STALE (the not-pretty-but-works path)++**The tell:** pup fills + submits (`filledUsername/filledPassword/submitted` all true) but the site+says **"Fail to authenticate"** / "incorrect password". The stored secret is out of date (the user+changed it since the browser saved it), OR — a subtle one — the **username itself is wrong** (the+same site can be saved under different usernames in different profiles). Read the *source of truth*+the user already trusts: **their browser's own password manager.**++The password manager is a **`chrome://` page**, which CDP (pup, and the Adom native-browser+extension) **cannot touch** — so drive it at the OS level with Adom Bridge `desktop_*` verbs:++1. **Find the user's REAL browser window** (`desktop_list_windows`): a `Chrome_WidgetWin_1` titled+ "… - Google Chrome" / "… - Microsoft Edge" — NOT "for Testing" (those are pup's). Note the `hwnd`.+2. **Open a NEW tab** so you never disturb their work:+ `desktop_press_key {hwnd, keys:["ctrl","t"]}`.+3. **Go to the entry:**+ `desktop_navigate {hwnd, url:"chrome://password-manager/passwords/<domain>"}` (e.g.+ `.../passwords/componentsearchengine.com`). If it lands on the list, click the **"Search+ passwords"** box and `desktop_type` the domain.+4. **⚠ PROFILE + FOREGROUND, two gotchas that will waste your time:**+ - Passwords are **per Chrome PROFILE**. "No passwords found" / a blank entry means the login is+ in a DIFFERENT profile (Default, Profile 1/2, Work, Personal, plus Edge). `pup_import_scan`+ lists which profiles have saved passwords and their account emails. Ask the user which profile,+ or drive the window running it.+ - This chrome:// WebUI renders **BLANK to a background screenshot** (PrintWindow). **Foreground+ the window first** (`desktop_bring_to_front {hwnd}`) — then `desktop_screenshot_window` shows+ the real content. UIA (`desktop_find_control`) is also unreliable on it; the foregrounded+ screenshot + image-space clicks (`desktop_click {space:"image", shotId, x, y}`) is what works.+5. **Read the username shown** — it may not be what pup had. Note it.+6. **Click the eyeball** (Show password) — `desktop_click` on it in the foregrounded shot.+7. **Windows Hello.** Revealing triggers a Windows Hello / PIN prompt. **This is a HUMAN step —+ pup cannot authenticate it.** Toast/caption the user, wait, and let them approve.+8. **Read the revealed password** from the next foregrounded screenshot (it now shows as plaintext).+9. **Store it correctly** — with the RIGHT username from step 5:+ `credential_set {host:"<domain>", username:"<the shown username>", password:"<revealed>"}`.+ Then **hide it again** (click the eyeball), **close your tab** (`ctrl+w`), and restore the user's+ view (`ctrl+1`).+10. Retry `pup_login`. It works now, and the fresh credential is captured for next time.++### The realistic failure modes (all hit in practice)++- **Wrong username** was half the battle — always re-read the username from the manager, do not trust+ the imported one.+- **`ms.<site>` vs `<site>`** — saved under the account subdomain, used on the apex. Registrable-domain+ matching (section 1) handles this once the credential is stored.+- **Blank WebUI** until the window is foregrounded (section 4).+- **Windows Hello is unavoidable** — it is the one human moment; design the flow to pause for it.++## Privacy rules (non-negotiable)++- Only ever do this for the site the user asked about, on the user's own machine, at their request.+- The plaintext appears once in the reveal read. **Store it and move on — never print it, never+ repeat it in a later message, never log it.**+- Prefer, when the user would rather pup never see the plaintext: have them **log in once manually**+ (pup's capture rail grabs it fresh), or use a **"Sign in with Google/Microsoft"** SSO path+ (`pup-vendor-login`) that types no password at all.++## When NOT to need any of this++Manufacturer-direct sites (TI, ST, ams, …) and datasheets need no login at all — see+`ee-parts-sites.md`. Reach for credential recovery only when a site truly gates what the user wants+behind their own account.
uninstall.sh+1@@ -12,6 +12,7 @@ remove_from() { "$BASE/pup-adom-wiki" \ "$BASE/pup-vendor-login" \ "$BASE/pup-settings" \+ "$BASE/pup-credentials" \ "$BASE/pup-bridge-dev" "$BASE/pup-bridge-publish" echo " <- $BASE" }