pup-bridge-macos
Public Made by Adomby adom
The pup for macOS SKILL PACK: the AI skills that teach a cloud/container AI how to drive the macOS Puppeteer (pup) bridge (pup_* verbs): the everyday `pup` skill plus focused sub-skills for windows/sessions/tabs, screenshots+recording, credentials, lanes, settings, browsers+Chrome install, vendor logins and the Adom wiki. Installs into ~/.claude/skills + ~/.codex/skills. DOCS ONLY: this is NOT the bridge runtime. The bridge itself is one signed macOS binary that Adom Bridge for macOS installs an
name: pup-browsers-and-chrome user-invocable: true description: "MAINTAINER detail, not for a user's ears: how pup picks and launches its browser, and every cold-start / readiness case. A user hears 'pup window'; the build behind it (installed Chrome, Edge, or pup's own automation build) is answered only when asked (pup-bridge#114). 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); pup_use to pin chrome/edge/cft/auto; INSTALLING real Google Chrome on an Edge-only box (pup_use install:true) including the UAC-approval-notify flow on locked-down machines; installing/prewarming Chrome for Testing; pup_readiness (READ-ONLY — the right 'is it ready / which browser' probe, NOT pup_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: pup_readiness, pup_use, pup_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: pup-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)
POLICY (2026-08-10, pup 2.0.53+): pup's driving browser is Chrome for Testing. The dated record
of why is docs/WHY-CFT.md on the wiki page — the policy has flipped twice, and the current flip is
final: branded Chrome asserts the "controlled by automated test software" banner during real
automation, and branded Chrome 137+ removed --load-extension, which the pup toolbar family needs.
This section previously opened with "pup drives the browser already on the machine"; that was the
mid-2026 policy and is REVERSED. What survives of it is the fallback ladder below, which is why a
missing or still-downloading CfT never blocks an open. On every open pup builds a candidate list
and spawn-verifies it:
- Pinned/cached default first (CfT, per policy) → installed Google Chrome → Edge → cached CfT.
Chrome and Edge count only when they are installed in
/Applicationsor~/Applications. - It launches a fresh process of that browser binary with an pup-managed
--user-data-dirdriven through pup's own extension channel (no debug port by default), never the user's signed-in profile, and a real rendered window (not headless). - 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.
- The browser that actually launched is cached as the default (persisted across bridge restarts) so it isn't re-probed each time.
- The CfT fetch (~150 MB) happens once — at prewarm, at first need, or when pinned via
pup_use {browser:"cft"}. Installed Chrome/Edge are the FALLBACK, not the destination: expect a healthy box to reportbrowserKind: chrome-for-testinginpup_readiness.
"Is it ready / which browser?" — pup_readiness (READ-ONLY)
adom-bridge-cli pup_readiness '{}'
# → {ready, browserKind:"chrome"|"edge"|"chrome-for-testing", browserSource, browserExecutablePath,
# candidates:[…the full fallthrough list…], defaultBrowser, diskFreeMb, chromeStablePhase, …}
pup_readinessis the right probe — it never triggers a download and tells you exactly which browser will be driven + the candidate list + the default.pup_statusis NOT a readiness check — it only lists open sessions.- AD-core
bridge_readinessis the platform-level "is this bridge up?" probe.
Pinning a browser — pup_use
pup auto-picks, but you can override (persists across restarts; launch still spawn-verifies + falls back):
adom-bridge-cli pup_use '{"browser":"chrome"}' # pin installed Chrome
adom-bridge-cli pup_use '{"browser":"edge"}' # pin Edge
adom-bridge-cli pup_use '{"browser":"cft"}' # install Chrome for Testing (~150 MB once) + pin it
adom-bridge-cli pup_use '{"browser":"auto"}' # back to auto-pick
Every pup_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
If the user specifically wants Chrome:
adom-bridge-cli pup_use '{"browser":"chrome","install":true}'
- Downloads Google's official
.dmg, copies Google Chrome into/Applications, then pins it. No prompt on a normal admin account. - Poll
pup_readiness:chromeStablePhasegoesinstalling → ready;browserKindflips to"chrome". pup keeps driving its current browser meanwhile, so nothing is blocked.
Installing / prewarming Chrome for Testing (the policy browser)
adom-bridge-cli pup_prewarm '{}' # fetch CfT WITHOUT opening a window, then pin it (poll readiness)
adom-bridge-cli pup_use '{"browser":"cft"}' # same, via the pin path
Worth running on ANY fresh box so the first real open skips the download (the fallback ladder covers the gap meanwhile). 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 pup_open_window response can mean
| Response | Means | Do |
|---|---|---|
ok:true / a real session |
A browser was found + launched | Proceed — the common case |
errorCode:"bridge_restarting" (stillRunning:true) |
AD ≥ 1.9.77: verb landed in the brief gap while the bridge respawns after an install/update | Poll pup_readiness until it answers, then retry the same verb — not a failure |
errorCode:"chrome_for_testing_installing" (installing:true) |
RARE — no installed Chrome or Edge, so pup is fetching CfT in the background | Poll pup_readiness until {ready:true}, then re-issue |
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 Google Chrome. 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 Google Chrome |
Always surface a verb's _hint verbatim when it reports not-ready or failure.
No runtime to provision
pup on macOS is one signed binary: no Node, no npm, nothing for you or the user to install. Adom Bridge downloads, verifies and spawns it.
The shell-approval gate (rarely relevant to pup)
Core AD verbs and pup's own pup_* verbs (plus the desktop_record_* verbs pup answers for ab-core) 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-bridge-cli --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 Adom Bridge's own gate.
Temporary pins and the toolbar (v2.0.378)
pup_use {browser:"chrome"|"edge", temporary:true}pins for a comparison or spike and expires at the next bridge boot (back to auto), so a forgotten pin can never strip the toolbar from every later launch. Pinning off CfT while the toolbar is on also returns a WARNING at pin time.- Any
pup_open_windowwhose window launched on a browser that cannot carry the Adom toolbar (branded Chrome ≥137, Edge) returns_toolbarNoticesaying so; CfT is the only toolbar-capable engine and the default policy converges onto it.
The download cache is pruned (2.0.677, pup-bridge#125)
Every build bump used to leave the previous build (~410 MB) in ~/.cache/puppeteer forever, plus headless-shell
builds and partial downloads. pup now prunes a
minute after every boot, keeping the pinned build, the newest complete build if the pinned one is missing, and
anything a running browser or the saved default uses. pup_cache_prune {dryRun:true} shows what would go.
---
name: pup-browsers-and-chrome
user-invocable: true
description: "MAINTAINER detail, not for a user's ears: how pup picks and launches its browser, and every cold-start / readiness case. A user hears 'pup window'; the build behind it (installed Chrome, Edge, or pup's own automation build) is answered only when asked (pup-bridge#114). 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); pup_use to pin chrome/edge/cft/auto; INSTALLING real Google Chrome on an Edge-only box (pup_use install:true) including the UAC-approval-notify flow on locked-down machines; installing/prewarming Chrome for Testing; pup_readiness (READ-ONLY — the right 'is it ready / which browser' probe, NOT pup_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: pup_readiness, pup_use, pup_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:** pup-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)
**POLICY (2026-08-10, pup 2.0.53+): pup's driving browser is Chrome for Testing.** The dated record
of why is `docs/WHY-CFT.md` on the wiki page — the policy has flipped twice, and the current flip is
final: branded Chrome asserts the "controlled by automated test software" banner during real
automation, and branded Chrome 137+ removed `--load-extension`, which the pup toolbar family needs.
This section previously opened with "pup drives the browser already on the machine"; that was the
mid-2026 policy and is REVERSED. What survives of it is the fallback ladder below, which is why a
missing or still-downloading CfT never blocks an open. On every open pup builds a candidate list
and **spawn-verifies** it:
1. **Pinned/cached default first (CfT, per policy) → installed Google Chrome → Edge → cached CfT.**
Chrome and Edge count only when they are installed in `/Applications` or `~/Applications`.
2. It **launches a fresh process** of that browser binary with an **pup-managed `--user-data-dir`** driven through pup's own
extension channel (no debug port by default), 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. **The CfT fetch (~150 MB) happens once** — at prewarm, at first need, or when pinned via
`pup_use {browser:"cft"}`. Installed Chrome/Edge are the FALLBACK, not the destination: expect a
healthy box to report `browserKind: chrome-for-testing` in `pup_readiness`.
## "Is it ready / which browser?" — `pup_readiness` (READ-ONLY)
```bash
adom-bridge-cli pup_readiness '{}'
# → {ready, browserKind:"chrome"|"edge"|"chrome-for-testing", browserSource, browserExecutablePath,
# candidates:[…the full fallthrough list…], defaultBrowser, diskFreeMb, chromeStablePhase, …}
```
- **`pup_readiness`** is the right probe — it never triggers a download and tells you exactly which
browser will be driven + the candidate list + the default.
- **`pup_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 — `pup_use`
pup auto-picks, but you can override (persists across restarts; launch still spawn-verifies + falls back):
```bash
adom-bridge-cli pup_use '{"browser":"chrome"}' # pin installed Chrome
adom-bridge-cli pup_use '{"browser":"edge"}' # pin Edge
adom-bridge-cli pup_use '{"browser":"cft"}' # install Chrome for Testing (~150 MB once) + pin it
adom-bridge-cli pup_use '{"browser":"auto"}' # back to auto-pick
```
Every `pup_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
If the user specifically wants Chrome:
```bash
adom-bridge-cli pup_use '{"browser":"chrome","install":true}'
```
- Downloads Google's official `.dmg`, copies Google Chrome into `/Applications`, then pins it. No
prompt on a normal admin account.
- **Poll `pup_readiness`**: `chromeStablePhase` goes `installing → ready`; `browserKind` flips to
`"chrome"`. pup keeps driving its current browser meanwhile, so nothing is blocked.
## Installing / prewarming Chrome for Testing (the policy browser)
```bash
adom-bridge-cli pup_prewarm '{}' # fetch CfT WITHOUT opening a window, then pin it (poll readiness)
adom-bridge-cli pup_use '{"browser":"cft"}' # same, via the pin path
```
Worth running on ANY fresh box so the first real open skips the download (the fallback ladder covers the gap meanwhile). **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 `pup_open_window` response can mean
| Response | Means | Do |
|---|---|---|
| `ok:true` / a real session | A browser was found + launched | Proceed — the common case |
| `errorCode:"bridge_restarting"` (`stillRunning:true`) | AD ≥ 1.9.77: verb landed in the brief gap while the bridge respawns after an install/update | Poll `pup_readiness` until it answers, then retry the same verb — not a failure |
| `errorCode:"chrome_for_testing_installing"` (`installing:true`) | RARE — no installed Chrome or Edge, so pup is fetching CfT in the background | Poll `pup_readiness` until `{ready:true}`, then re-issue |
| `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 Google Chrome. 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 Google Chrome |
**Always surface a verb's `_hint` verbatim** when it reports not-ready or failure.
## No runtime to provision
pup on macOS is one signed binary: no Node, no npm, nothing for you or the user to install. Adom
Bridge downloads, verifies and spawns it.
## The shell-approval gate (rarely relevant to pup)
Core AD verbs and pup's own `pup_*` verbs (plus the `desktop_record_*` verbs pup answers for ab-core) 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-bridge-cli --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 Adom Bridge's own gate.
## Temporary pins and the toolbar (v2.0.378)
- `pup_use {browser:"chrome"|"edge", temporary:true}` pins for a comparison or spike and **expires at
the next bridge boot** (back to auto), so a forgotten pin can never strip the toolbar from every
later launch. Pinning off CfT while the toolbar is on also returns a WARNING at pin time.
- Any `pup_open_window` whose window launched on a browser that cannot carry the Adom toolbar
(branded Chrome ≥137, Edge) returns `_toolbarNotice` saying so; CfT is the only toolbar-capable
engine and the default policy converges onto it.
## The download cache is pruned (2.0.677, pup-bridge#125)
Every build bump used to leave the previous build (~410 MB) in `~/.cache/puppeteer` forever, plus headless-shell
builds and partial downloads. pup now prunes a
minute after every boot, keeping the pinned build, the newest complete build if the pinned one is missing, and
anything a running browser or the saved default uses. `pup_cache_prune {dryRun:true}` shows what would go.