name: pup-browsers-and-chrome user-invocable: true description: "How pup (Puppeteer bridge) picks and launches a browser, and every cold-start / readiness case. Covers: the installed-browser-first architecture (launches a FRESH CDP-driven process of installed Chrome → else Edge → else cached Chrome for Testing, spawn-verified with fallthrough, caches the winner as default); browser_use to pin chrome/edge/cft/auto; INSTALLING real Google Chrome on an Edge-only box (browser_use install:true) including the UAC-approval-notify flow on locked-down machines; installing/prewarming Chrome for Testing; browser_readiness (READ-ONLY — the right 'is it ready / which browser' probe, NOT browser_status); the cold-start error table (node_not_found, bridge_restarting, chrome_for_testing_installing, chrome_install_no_disk, CfT 'skipped' is not a failure); AD-managed Node provisioning (no install needed on AD >=1.9.63); and the shell-approval gate. Read on any browser-pick question, a fresh/first-run PC, an install/prewarm, a not-ready error, or a shell-approval prompt. Trigger words: browser_readiness, browser_use, browser_prewarm, chrome for testing, install chrome, chrome_for_testing_installing, node_not_found, bridge_restarting, chrome_install_no_disk, cold start pup, which browser, edge only box, UAC approve chrome, request_shell_approval, shell command approval, adom runtimes, pup not ready."

Parent skill: adom-desktop-puppeteer-bridge · See also: pup (start here), pup-windows-sessions-tabs, pup-screenshots-recording.

pup — browsers, Chrome install & cold-start

How pup picks + launches a browser (the architecture)

pup drives the browser already on the machine — it does NOT ship or require its own. On every open it builds a candidate list and spawn-verifies it:

  1. Chrome → Edge → cached Chrome for Testing (a pinned default, if set, goes first). Every Windows PC ships Edge, so there's almost always a candidate with no download.
  2. It launches a fresh process of that browser binary with an isolated --user-data-dir + a CDP --remote-debugging-port — a clean empty profile driven over the DevTools Protocol, never the user's signed-in profile, and a real rendered window (not headless).
  3. If the top pick is present but won't start (corrupt/partial install), pup falls through to the next — so an open never hard-fails on one broken browser.
  4. The browser that actually launched is cached as the default (persisted across bridge restarts) so it isn't re-probed each time.
  5. Chrome for Testing is the last resort — fetched (~150 MB) only if the box has no Chrome and no Edge and no cached CfT.

"Is it ready / which browser?" — browser_readiness (READ-ONLY)

adom-desktop browser_readiness '{}'
# → {ready, browserKind:"chrome"|"edge"|"chrome-for-testing", browserSource, browserExecutablePath,
#    candidates:[…the full fallthrough list…], defaultBrowser, diskFreeMb, chromeStablePhase, …}
  • browser_readiness is the right probe — it never triggers a download and tells you exactly which browser will be driven + the candidate list + the default.
  • browser_status is NOT a readiness check — it only lists open sessions.
  • AD-core bridge_readiness is the platform-level "is this bridge up?" probe.

Pinning a browser — browser_use

pup auto-picks, but you can override (persists across restarts; launch still spawn-verifies + falls back):

adom-desktop browser_use '{"browser":"chrome"}'   # pin installed Chrome
adom-desktop browser_use '{"browser":"edge"}'     # pin Edge
adom-desktop browser_use '{"browser":"cft"}'      # install Chrome for Testing (~150 MB once) + pin it
adom-desktop browser_use '{"browser":"auto"}'     # back to auto-pick

Every browser_open_window response also carries browser (what was driven), availableBrowsers, and defaultBrowser — surface it if the user asks which browser pup is using.

Installing real Google Chrome on an Edge-only box

If the user specifically wants Chrome:

adom-desktop browser_use '{"browser":"chrome","install":true}'
  • Downloads Google's official installer and installs Chrome, then pins it. On a normal PC this is silent (user-scoped, no prompt).
  • On a locked-down box (a VM / managed device) it needs a Windows UAC. pup escalates automatically and, on AD ≥ 1.9.84, fires a native "click YES to finish installing Chrome" notification from the bridge itself — on the machine with the prompt and pinged to whatever device the user is attending (cross-AD). If the prompt expires it re-notifies with a one-tap "Approve now". All autonomous — no AI turn needed. On older AD (no bridge-notify) it raises the UAC once and returns a hint for you to relay ("go to the box and click YES"), then you re-run the verb.
  • Poll browser_readiness: chromeStablePhase goes installing → awaiting_uac (waiting on the user's click) → ready; browserKind flips to "chrome". pup keeps driving Edge meanwhile, so nothing is blocked. elevate:"auto"|true|false on the call tunes the prompt behavior.

Installing / prewarming Chrome for Testing (last resort)

adom-desktop browser_prewarm '{}'        # fetch CfT WITHOUT opening a window, then pin it (poll readiness)
adom-desktop browser_use '{"browser":"cft"}'   # same, via the pin path

Only needed on a box with no Chrome and no Edge. CfT reported as skipped is NOT a failure — on AD ≥ 1.9.76 the prewarm is conditional, so a box with a system browser skips the ~150 MB download and bridge_readiness shows the asset {present:false, skipped:true}. That's the intended installed-browser-first behavior; don't retry or report an error.

Cold-start error table — what a browser_open_window response can mean

Response Means Do
ok:true / a real session A browser was found + launched Proceed — the common case
errorCode:"node_not_found" / "could not run npm" The bridge's Node runtime isn't ready yet AD ≥ 1.9.63 provisions Node for you — check adom-desktop runtimes '{}'; if installing, wait a few seconds and retry. No user action. Known AD false-negative: if runtimes shows node ready AND browser_readiness works but other verbs still say node_not_found, it's an AD verb-gate bug — do NOT loop desktop_install_node; tell the user to update AD
errorCode:"bridge_restarting" (stillRunning:true) AD ≥ 1.9.77: verb landed in the brief gap while the bridge respawns after an install/update Poll browser_readiness until it answers, then retry the same verb — not a failure
errorCode:"chrome_for_testing_installing" (installing:true) RARE — no Chrome AND no Edge, so pup is fetching CfT in the background Poll browser_readiness until {ready:true}, then re-issue. Faster: ask the user to install Chrome/Edge (Edge ships with Windows)
errorCode:"chrome_install_no_disk" No browser + too little disk for CfT (readiness.diskFreeMb) Tell the user how much is free vs the ~800 MB needed; ask them to free space or install Edge. Do NOT retry the download
errorCode:"chrome_install_failed" / chrome_download_network / chrome_install_permission No browser AND the CfT fallback download failed Read readiness.lastError; ask the user to install Chrome or Edge

Always surface a verb's _hint verbatim when it reports not-ready or failure.

Node provisioning — you do NOTHING (AD ≥ 1.9.63)

pup is a Node process, but you no longer install Node. AD provisions the runtime itself — a system Node if on PATH, else a portable no-UAC copy it downloads to ~/.adom/adom-runtimes/ and prewarms, then spawns the bridge by absolute path. Do NOT run desktop_install_node / npm installers / ask the user to install Node. On a truly fresh box it may be installing for a few seconds after first launch — check adom-desktop runtimes '{}' ({state: absent|installing|ready|failed}) and retry once ready. (Legacy desktop_install_node — which pops a UAC — is only for AD older than 1.9.63.)

The shell-approval gate (rarely relevant to pup)

Core AD verbs and pup's own browser_* / desktop_record_* verbs run with NO desktop prompt. Only open-ended shell_execute / run_script pop AD's "Shell command needs approval" dialog — which you almost never need (prefer typed verbs). If one returns needs_approval / human_only on AD ≥ 1.9.86: run adom-desktop --target <box> request_shell_approval (re-surfaces the dialog), ask the user to click Approve/Bypass, then retry your original verb. Never call shell_auto_approve (human-only, refuses). This is AD's own gate, NOT a Windows UAC.