# Why pup drives Chrome for Testing

Policy as of 2026-08-10 (pup 2.0.53+): **pup's driving browser is Chrome for Testing (CfT), not
branded Chrome or Edge.** This page is the technical record of why, because the policy has flipped
twice and the reasons deserve to outlive the people who remember them.

A short history: early pup was CfT-based. In mid-2026 the default flipped to "drive the browser
already on the machine" to make first runs instant (no ~160 MB download when a perfectly good
Chrome or Edge is already installed). Running that way in production surfaced the problems below,
and on 2026-08-10 the policy flipped back to CfT for good.

## 1. The automation banner you cannot turn off

The moment pup does real automation in branded Chrome, moving a synthetic cursor, filling a login
form, assisting with a captcha, Chrome asserts the infobar: **"Chrome is being controlled by
automated test software."** It blips in and out as automation starts and stops, reflowing the
viewport each time, and it is deliberately hard to suppress in the branded build: the classic
trick (stripping `--enable-automation` from the launch args) changes input and focus semantics,
and newer branded builds re-assert automation indicators when DevTools attaches regardless. Users
watched the banner flicker over their windows all day. CfT is the build Google ships FOR
automation: the banner is not fighting you there, and suppressing chrome-level test UI is
supported behavior rather than an arms race.

## 2. Extensions: branded Chrome closed every silent path (the forcing reason)

Branded Chrome 137 (mid-2025) **removed the `--load-extension` flag** specifically to stop
software from silently side-loading extensions. We verified the fallout live on branded 148
(2026-08-10), trying every route to auto-install the Adom Pup toolbar:

- The CDP replacement (`Extensions.loadUnpacked`) requires a `--remote-debugging-pipe` launch,
  which is incompatible with pup's detached-launch architecture (pup windows deliberately outlive
  the bridge process and are re-adopted over the port), **and** the install turned out to be
  session-scoped anyway: it does not persist into the profile.
- Driving `chrome://extensions` plus the native folder dialog works but puts a file dialog on the
  user's screen. Horrific, vetoed.
- The remaining branded paths are all user-visible or worse: a Web Store click per profile, or an
  enterprise force-install policy that brands the browser "managed by your organization".

CfT still honors `--load-extension`. So on CfT the toolbar is simply a **launch argument**: every
profile launch carries it, every window is born with the toolbar pinned, and there is no install
step in existence. This capability gap alone justifies the policy.

## 3. Version determinism

CfT is pinned to the exact build puppeteer expects (matched buildId) and **has no auto-updater**.
Branded Chrome updates itself underneath running profiles on Google's schedule, which means CDP
behavior can drift mid-session, and two pup windows opened an hour apart can be driving different
browser versions. Deterministic versions are what make pup's ralph tests reproducible and make a
CDP bug a fixable fact instead of a moving target. pup owns CfT's update cadence via its own
self-heal (src/chrome.js), which is exactly where that control belongs.

## 4. None of the consumer chrome

No first-run bubbles, no default-browser nagging, no profile-import prompts, no sign-in and sync
pressure, and no Finch field-trial experiments silently flipping browser behavior per machine.
Branded Chrome runs server-assigned experiments; CfT gives every machine the same browser.

## 5. Isolation from the user's own browser

A different binary means a different process tree: the user's real Chrome can update, crash, or be
closed without touching a single pup window, and pup's taskbar identity never tangles with their
browsing. Profiles were always pup-owned; CfT extends the separation to the binary itself.

## Known trade-offs, stated honestly

- **First-run download** (~160 MB) on machines without CfT cached. pup has detected, installed,
  and repaired CfT by itself since long before this policy (readiness self-heal).
- The window title and Task Manager say **"Google Chrome for Testing"**. The rendered window is
  otherwise identical.
- **No Widevine DRM**: protected video (streaming services) will not play in pup. Driving those is
  an nb/nbe job anyway, with the user's real browser and identity.
- Users who explicitly pin branded Chrome (`pup_use {browser:"chrome"}`) keep everything working
  except the toolbar extension and infobar suppression; pup tells them why when it matters.

## What did NOT change with the switch

Profiles, cookies, and logins live in pup's own userDataDirs, independent of the driving binary.
Repinning from branded Chrome to CfT changed nothing about the shared adom-you credential store,
window ownership, taskbar identity, or recovery; the same profile simply renders under the
automation build.
