← Commit history
Update 10 file(s)
10 files changed
+158−27
dev-skills/developing-the-bridge/SKILL.md+2−2docs/DEVELOPING.md+5−5publish-skills/publishing-the-bridge/SKILL.md+7−7skills/adom-native-browser/SKILL.md+131skills/driving-sites/SKILL.md+4−4skills/driving-the-extension-demo/SKILL.md+1−1skills/driving-the-extension/SKILL.md+2−2skills/installing-the-extension/SKILL.md+2−2skills/native-browser-safety/SKILL.md+2−2skills/reading-google-messages/SKILL.md+2−2dev-skills/developing-the-bridge/SKILL.md+2−2@@ -1,8 +1,8 @@ --- name: developing-the-bridge-description: "DEVELOPER skill for maintainers of the adom-browser-extension (native-browser) bridge - NOT for driving it. Read this before editing bridge/server.js, host/native-host.js, or extension/. Covers the architecture (bridge + native-messaging host + MV3 extension, and how AD provisions Node), the #1 rule that every nbrowser_* verb must return rich _hint/_next/related/pitfalls via the VERB_META table, the verb contract, local testing, the AD-vs-bridge boundary, hard-won runtime gotchas (chrome.tabs.goBack fails on debugger-driven tabs; UIA Invoke fails on Win32 dialogs), and the safety invariants. Everyday users never need this."+description: "DEVELOPER skill for maintainers of the adom-native-browser (nb/abe) bridge - NOT for driving it. Read this before editing bridge/server.js, host/native-host.js, or extension/. Covers the architecture (bridge + native-messaging host + MV3 extension, and how AD provisions Node), the #1 rule that every nbrowser_* verb must return rich _hint/_next/related/pitfalls via the VERB_META table, the verb contract, local testing, the AD-vs-bridge boundary, hard-won runtime gotchas (chrome.tabs.goBack fails on debugger-driven tabs; UIA Invoke fails on Win32 dialogs), and the safety invariants. Everyday users never need this." ----Parent skill: **adom-browser-extension**. This is a maintainer-only skill (not user-invocable). Bridge+Parent skill: **adom-native-browser**. This is a maintainer-only skill (not user-invocable). Bridge SDK: https://wiki.adom.inc/adom/adom-desktop-bridges # Developing the native-browser bridge
docs/DEVELOPING.md+5−5@@ -6,10 +6,10 @@ public, open-source repo. ## 1. Get the source (fork it) -The extension lives as a wiki page + git repo at **[wiki.adom.inc/adom/adom-browser-extension](https://wiki.adom.inc/adom/adom-browser-extension)**.+The extension lives as a wiki page + git repo at **[wiki.adom.inc/adom/adom-native-browser](https://wiki.adom.inc/adom/adom-native-browser)**. - **Fork / propose changes upstream** — use the page's **Pull Requests** tab to propose edits back, or-- **Clone the source** — grab the repo from the **Files** tab (or `adompkg install adom/adom-browser-extension`),+- **Clone the source** — grab the repo from the **Files** tab (or `adompkg install adom/adom-native-browser`), then copy the **`extension/`** folder somewhere you can edit. The folder you load into the browser is **`extension/`** — it's the one with `manifest.json`.@@ -21,7 +21,7 @@ The folder you load into the browser is **`extension/`** — it's the one with ` 3. Click **Load unpacked** (top-left) and pick your **`extension/`** folder. ② 4. The extension loads — note its **ID**. ③ After any code edit, click the **Reload (↻)** button on its card. -+ ## 3. Load it in Edge (developer mode) @@ -32,7 +32,7 @@ Same idea, slightly different layout: 3. Click **Load unpacked** (top of the page) and pick your **`extension/`** folder. ② 4. The extension loads. ③ -+ ## 4. Or — let adom-desktop install it for you @@ -45,7 +45,7 @@ touching the one you're working in. Paste-into-Claude prompt: ```-Load my local adom-browser-extension from C:\path\to\extension into Chrome via developer mode.+Load my local adom-native-browser from C:\path\to\extension into Chrome via developer mode. ``` ## 5. The dev loop
publish-skills/publishing-the-bridge/SKILL.md+7−7@@ -1,8 +1,8 @@ --- name: publishing-the-bridge-description: "PUBLISH skill for maintainers of the adom-browser-extension (native-browser) bridge - NOT for driving it. The exact, proven recipe to cut a release: bump versions in lockstep, build the zip, publish it as a Release ASSET (release create + upload --platform any), point the manifest url at the /download/ path (never a /files blob), push source, and land it with refresh_bridges. Covers the two-artifact split (Release zip vs skills pkg), the pkg's package.json declaring dependencies:{adom/adom-desktop:^1.9.x} (so pkg install pulls the AD CLI + core skills), the pkg shipping ONLY user skills while dev/publish skills live in the source repo (not the pkg, not files[], not user-invocable:false), the bridge.json contracts we declare (timeouts) and one we deliberately don't (detect), and the standing show-in-pup rule. Everyday users never need this."+description: "PUBLISH skill for maintainers of the adom-native-browser (nb/abe) bridge - NOT for driving it. The exact, proven recipe to cut a release: bump versions in lockstep, build the zip, publish it as a Release ASSET (release create + upload --platform any), point the manifest url at the /download/ path (never a /files blob), push source, and land it with refresh_bridges. Covers the two-artifact split (Release zip vs skills pkg), the pkg's package.json declaring dependencies:{adom/adom-desktop:^1.9.x} (so pkg install pulls the AD CLI + core skills), the pkg shipping ONLY user skills while dev/publish skills live in the source repo (not the pkg, not files[], not user-invocable:false), the bridge.json contracts we declare (timeouts) and one we deliberately don't (detect), and the standing show-in-pup rule. Everyday users never need this." ----Parent skill: **adom-browser-extension**. Maintainer-only skill (not user-invocable). Bridge SDK:+Parent skill: **adom-native-browser**. Maintainer-only skill (not user-invocable). Bridge SDK: https://wiki.adom.inc/adom/adom-desktop-bridges # Publishing the native-browser bridge@@ -48,13 +48,13 @@ Deps: none (core `http`/`net`), so the payload is source-only (no `node_modules` releases stay valid at their existing URLs). 3. **The runtime is a RELEASE ASSET, not a `/files` blob** (SDK "two-artifact" rule — fusion + pup do exactly this). Cut a Release for the bridge version + upload the zip:- - `adom-wiki release create adom/adom-browser-extension <ver> --title "native-browser bridge runtime v<ver>"`- - `adom-wiki release upload adom/adom-browser-extension <ver> native-browser-bridge-v<ver>.zip --platform any`- The download then serves anon at `https://wiki.adom.inc/download/adom/adom-browser-extension/<ver>/native-browser-bridge-v<ver>.zip` (verify: `curl -sI` → 200). (The pkg's own release stays 0.3.x; the bridge release is 0.0.x — separate version streams on the same page, that's expected.)+ - `adom-wiki release create adom/adom-native-browser <ver> --title "native-browser bridge runtime v<ver>"`+ - `adom-wiki release upload adom/adom-native-browser <ver> native-browser-bridge-v<ver>.zip --platform any`+ The download then serves anon at `https://wiki.adom.inc/download/adom/adom-native-browser/<ver>/native-browser-bridge-v<ver>.zip` (verify: `curl -sI` → 200). (The pkg's own release stays 0.3.x; the bridge release is 0.0.x — separate version streams on the same page, that's expected.) 4. **sha256 + byte size** → write `native-browser-bridge-manifest.json` with the `url` pointing at that **`/download/` path** (NOT a `/files` blob):- `{manifest_version:1, version, url:"https://wiki.adom.inc/download/adom/adom-browser-extension/<ver>/native-browser-bridge-v<ver>.zip", sha256, size, released_at}`.-5. **Push manifest + source as TEXT** with `adom-wiki repo push adom-browser-extension --files native-browser-bridge-manifest.json bridge/bridge.json bridge/package.json bridge/server.js bridge/BRIDGE_VERSION ...` (the manifest lives on `/files`; only the binary is off it).+ `{manifest_version:1, version, url:"https://wiki.adom.inc/download/adom/adom-native-browser/<ver>/native-browser-bridge-v<ver>.zip", sha256, size, released_at}`.+5. **Push manifest + source as TEXT** with `adom-wiki repo push adom-native-browser --files native-browser-bridge-manifest.json bridge/bridge.json bridge/package.json bridge/server.js bridge/BRIDGE_VERSION ...` (the manifest lives on `/files`; only the binary is off it). 6. **Land it:** `refresh_bridges {name:"native-browser"}` → verify `nbrowser_readiness` routes and `bridge_check_updates`/`bridge_list` show `liveVersion==<ver>` (no `staleProcess`). *(bridge_check_updates intermittently omits native-browser after an AD self-update — trust readiness + bridge_list.)*
skills/adom-native-browser/SKILL.mdadded+131@@ -0,0 +1,131 @@+---+name: adom-native-browser+description: "MAIN skill for the Adom Native Browser Extension - the nbrowser_* bridge that drives the user's REAL, signed-in Chrome/Edge (pup's counterpart, but inside their actual logged-in profile so cookies/SSO/saved-logins/captcha all work). START HERE. Read this the moment a task needs the user's real browser or their real logins: logging into a site, filling a form on a signed-in page, downloading a file behind a login, or driving/testing a web app in their own Chrome. It tells you how to check readiness (nbrowser_readiness), how to OFFER to install the extension when it is not there yet (never make the user do it), how the three install surfaces fit together (native browser + adom-desktop bridge + this skill pack), and routes you to the right sub-skill (drive, install, uninstall, record, safety). Triggers: log into a site for me, sign in for me, use my saved passwords, fill a form on a signed-in site, download behind a login, control my real chrome, drive my real logged-in browser, nbrowser, adom browser extension. Part of the adom-native-browser."+---++# Adom Native Browser Extension (`nbrowser_*`) - start here++This is the **native-browser** bridge: it drives the user's **real, signed-in Chrome/Edge** from the+cloud, the same way `pup` drives a controlled Chromium. The difference is the whole point - it runs+**inside the user's actual profile**, so their cookies, SSO, saved logins, cards, carts and+human-trust signals all apply. It sails through **login walls and captchas** that block pup's empty+Chrome-for-Testing. When a task needs the user's *real* browser or their *real* logins, this is the+tool - not pup.++## When to reach for this (vs pup)++| The task | Tool |+|---|---|+| Log into a site, fill a form on a signed-in page, download behind a login, use saved passwords | **native-browser (this)** |+| Screenshot / scrape / test a PUBLIC page, no login needed | pup |+| Drive/test a web app the user is building, in THEIR browser with THEIR sessions | **native-browser (this)** |++If the user says "log into X for me", "sign in", "use my saved password", "fill out this form on a+site I'm logged into", "grab that file behind the login", or "drive my real Chrome" - that is this+bridge. pup cannot do it (fresh profile, no logins).++## FIRST-TIME / COLD-START - read before you panic++A fresh machine may not have the bridge or the extension yet, and the AI's default failure mode is to+declare defeat. Don't. These states are EXPECTED, and each has a move - branch on the state, not on+prose:++| You see | What it means | What you do |+|---|---|---|+| `nbrowser_readiness` errors / unknown verb | the AD bridge isn't installed in adom-desktop yet | `bridge_install {manifestUrl}` (see "three install surfaces") |+| `state:"needs-extension"` | bridge up, but the MV3 extension isn't in Chrome yet | **OFFER to install it** -> `installing-the-extension` (never make the user do it) |+| `state:"ready"` | extension connected, profile(s) listed | go drive it -> `driving-the-extension` |++## Step 0 - is it even installed yet? Check readiness FIRST++The extension is a **Level-2, proactively-offered** install: it is often NOT present until someone+asks for it. Before you try to drive anything, probe (READ-ONLY, never triggers an install):++```+adom-desktop nbrowser_readiness # THIS bridge: {ready,state,extensionConnected,profiles}+```++- `state:"ready"` (extensionConnected:true, one or more profiles) -> go drive it (**driving-the-extension**).+- `state:"needs-extension"` -> the bridge is up but the browser extension is not connected. This is+ your cue to **OFFER to install it** (next section) - do NOT silently give up, and do NOT make the+ user do it by hand.++**For a broad "what tools do I have / is it ready?" question, call the AD-level aggregate+`adom-desktop bridge_readiness` instead** - it is side-effect-free (never spawns a bridge or installs)+and reports every bridge's `state` at once. Use `nbrowser_readiness` when you specifically care about+THIS bridge; use `bridge_readiness` for the survey. Neither ever triggers work.++## The install-offer hook - suggest it exactly when the user needs a login++The best moment to install this is **the moment the user needs it** - they ask you to log into a+vendor, fill a form on an authenticated page, or pull a file behind a paywall/login. When+`nbrowser_readiness` says `needs-extension`, tell the user plainly:++> "To do that in your real signed-in browser (so your saved login works), I can install the Adom+> browser extension into your Chrome/Edge - about a minute, I drive it, you just click one Start+> button. Want me to?"++On yes, run **installing-the-extension**. Never demand the user click through `chrome://extensions`+themselves, and never ask them to type a long path - WE own that orchestration over adom-desktop's+generic OS verbs, with a single `notify_user` consent button.++## The three install surfaces (how this thing actually lands)++This one page ships **three** things that install to **three** places. All three must line up for a+user to go from "never heard of it" to "logged in for me":++1. **This skill pack -> the user's container.** These `SKILL.md` files install into the cloud+ container / WSL2 / Lima (`~/.claude/skills/`). **They surface BEFORE the extension exists** - that+ is deliberate. Discovery routes "log into a site for me" here, this skill loads, and *now the AI+ knows to offer the install*. `adom-wiki pkg install adom/adom-native-browser` (or+ `adom-desktop sync_skills`) puts them there.+2. **The adom-desktop bridge -> adom-desktop.** The `nbrowser_*` verbs come from the `native-browser`+ bridge. `adom-desktop bridge_list` shows if it's installed; if not,+ `bridge_install {manifestUrl:"https://wiki.adom.inc/api/pages/adom/adom-native-browser/files/native-browser-bridge-manifest.json"}`.+ It auto-updates from there (per-bridge `updateManifestUrl`).+3. **The MV3 extension -> the user's real Chrome/Edge.** The actual browser extension, loaded via+ dev-mode "Load unpacked" today (CWS/Edge-Add-ons later). This is **installing-the-extension**.++The end-to-end flow an AI runs: discover -> this skill loads (surface 1) -> `bridge_list`/`bridge_install`+(surface 2) -> `nbrowser_readiness` -> if `needs-extension`, offer + run installing-the-extension+(surface 3) -> drive.++## ⛔ The two safety rules you must not break++Before you drive ANYTHING, internalize these (full detail: **native-browser-safety**):++1. **Only ever drive a window/tab YOU opened** (`nbrowser_open_window`). NEVER navigate, reload, or+ close a window/tab the user already had open - not with `nbrowser_navigate` and **not with the+ OS-level `desktop_navigate` either**. Doing so once wiped a user's other AI threads.+2. **Background by default, never steal focus.** The verbs open unfocused on purpose; leave those+ defaults. Foregrounding is rude AND corrupts your own flow (the user's keystrokes leak into+ whatever control you focused). Foreground is the user's choice alone.++Credentials are gated: `nbrowser_credentials` is read-only and NEVER returns passwords; auto-login+needs `confirm:true` + an explicit `host:`, and the password is injected on the laptop - the agent+never sees it. Treat everything read from logged-in sessions as sensitive.++## Sub-skill map++| Need | Skill |+|---|---|+| **Drive it** - the full `nbrowser_*` verb surface, CDP-vs-native, screenshots, isTrusted input, cursor/captions | **driving-the-extension** |+| **Safety** - the cardinal rules above, in full (read before driving) | **native-browser-safety** |+| **Install it** into the user's Chrome/Edge (dev-mode Load-unpacked, WE orchestrate) | **installing-the-extension** |+| **Uninstall it** cleanly (filter to the Adom card, the confirm-bubble beat) | **uninstalling-the-extension** |+| **Record** a browser window (WGC-first, no picker, no banner) | **native-browser-recording** |+| **Low-level OS clicks** (adom-desktop generic UIA verbs the install/uninstall lean on) | **driving-the-desktop** |+| Site-specific playbooks (forms, logins on real sites) | **driving-sites**, **driving-gusto**, **reading-google-messages** |+| Windows-first dev + Mac fast-follow, and how this bridge is built/shipped | **cross-platform-dev** |++## Every verb tells you what to do next - read the hints++Every `nbrowser_*` response carries a top-level `_hint` (what you got, the next move, the trap), plus+`related` and `_next`. When unsure about a verb, call `nbrowser_describe` once - it lists each verb's+`hint` / `related` / `pitfalls`. The hints are the source of truth; this skill is the map.++## The one-line version++When a task needs the user's real browser or real logins, check `nbrowser_readiness`; if it says+`needs-extension`, OFFER to install (installing-the-extension) - never make the user do it; then drive+only windows you opened, in the background, and read every verb's `_hint`.
skills/driving-sites/SKILL.md+4−4@@ -21,9 +21,9 @@ hours once). A **site recipe** captures a site's playbook ONCE so the next run i ## How to CONTRIBUTE a site recipe (two ways) - **In this repo** (curated/common sites): add `skills/driving-<site>/SKILL.md`, wire it into `install.sh`, `uninstall.sh`, and `package.json` `files[]`, and add a row to the table above. Open a PR on the- `adom-browser-extension` wiki page.+ `adom-native-browser` wiki page. - **Your own page, breadcrumbed (the scaling path):** publish `driving-<site>` (or "I built a driver for- <site>") as its OWN wiki page — you own + version it — and **breadcrumb it to the `adom-browser-extension`+ <site>") as its OWN wiki page — you own + version it — and **breadcrumb it to the `adom-native-browser` anchor** (see the wiki `wiki-breadcrumbs` / `wiki-family` skills). This is exactly the wiki Family pattern: site recipes are children with independent owners/cadences. The anchor lists them; discovery routes by domain. @@ -33,9 +33,9 @@ hours once). A **site recipe** captures a site's playbook ONCE so the next run i name: driving-<site> description: Site recipe for <Site> (<domain>) with the Adom browser extension — login flow, selectors, gotchas, 2FA, logout. Match on "log into <site>", "<domain>", "open <site>". Part of the- adom-browser-extension site-recipe set (see driving-sites).+ adom-native-browser site-recipe set (see driving-sites). ----Part of the **adom-browser-extension** site-recipe set → **driving-sites**. Generic mechanics live in+Part of the **adom-native-browser** site-recipe set → **driving-sites**. Generic mechanics live in **driving-the-desktop**; this page is <Site>'s quirks only. ## ✅ Logging IN (prefer the most-background path)
skills/driving-the-extension-demo/SKILL.md+1−1@@ -13,7 +13,7 @@ capability reference (CDP-vs-native, the debug bar, xy-finding, verbs), read the **driving-the-extension** first. `SES` = a session id (a real Chrome window). `HWND` = the OS window handle (from-`desktop_find_window` / captured at `open_window`). Examples assume one Adom Desktop; add+`desktop_find_window` / captured at `open_window`). Examples assume one Bridge; add `--target <host>` if more than one is connected. ## ⭐ The golden rules for a watchable demo (learned the hard way)
skills/driving-the-extension/SKILL.md+2−2@@ -104,7 +104,7 @@ with no `bring_to_front` called. extension service worker → back`. You call `adom-desktop nbrowser_* '<json>'`. ## Targeting (READ FIRST)-If more than one Adom Desktop is on the relay (laptop **AdomLapper** + the **winvm**), every call must+If more than one Bridge is on the relay (laptop **AdomLapper** + the **winvm**), every call must name one or it errors `ambiguous_target`: ```bash adom-desktop --target AdomLapper nbrowser_status@@ -308,7 +308,7 @@ settle → ~600ms dwell (tune with `hoverDwellMs`). When in doubt for hover, **a **The gliding Adom cursor:** pass `cursor:true` + `intent:"…"` on any input verb and the gorgeous Adom cursor (teal arrow + pulsing ring + "Adom" label) glides to the target **while narrating its intention** ("Clicking the Pay button", "Hovering the card to reveal the tooltip"). Builds user trust - they always-see what the AI is doing and why. Mimics Hydrogen Desktop's cursor.+see what the AI is doing and why. Mimics Hydrogen's cursor. ### Native JS dialogs (alert / confirm / prompt) - the invisible blocker A native `alert()`/`confirm()`/`prompt()`/`beforeunload` is **not an OS window (no hwnd)** and does
skills/installing-the-extension/SKILL.md+2−2@@ -1,8 +1,8 @@ --- name: installing-the-extension-description: "How WE (this repo) install the Adom browser extension into the user's real Chrome/Edge in DEVELOPER MODE (\"Load unpacked\"), driving adom-desktop's GENERIC OS verbs. This is OUR orchestration, not an adom-desktop feature - AD only exposes primitives (desktop_navigate / desktop_find_control / desktop_ui_click / desktop_ui_set / desktop_screenshot); the recipe, hardening, and recovery live here. This is the DAY-ONE install path: Chrome Web Store / Edge Add-ons review is ~2 months out, so until then dev-mode load-unpacked is how a real user gets the extension. Use when the user says \"install the extension\", \"install it for me\", \"load the extension into my browser\", \"set up the browser extension\", \"the extension isn't loaded yet\". For the low-level click mechanics (popups, the PWA guard, uninstall/reload), see driving-the-desktop. Part of the adom-browser-extension."+description: "How WE (this repo) install the Adom browser extension into the user's real Chrome/Edge in DEVELOPER MODE (\"Load unpacked\"), driving adom-desktop's GENERIC OS verbs. This is OUR orchestration, not an adom-desktop feature - AD only exposes primitives (desktop_navigate / desktop_find_control / desktop_ui_click / desktop_ui_set / desktop_screenshot); the recipe, hardening, and recovery live here. This is the DAY-ONE install path: Chrome Web Store / Edge Add-ons review is ~2 months out, so until then dev-mode load-unpacked is how a real user gets the extension. Use when the user says \"install the extension\", \"install it for me\", \"load the extension into my browser\", \"set up the browser extension\", \"the extension isn't loaded yet\". For the low-level click mechanics (popups, the PWA guard, uninstall/reload), see driving-the-desktop. Part of the adom-native-browser." ----Part of **adom-browser-extension**. Low-level OS-driving mechanics: **driving-the-desktop**. Safety rules: **native-browser-safety**.+Part of **adom-native-browser**. Low-level OS-driving mechanics: **driving-the-desktop**. Safety rules: **native-browser-safety**. # Installing the extension (dev-mode Load unpacked) - the orchestration WE own
skills/native-browser-safety/SKILL.md+2−2@@ -1,8 +1,8 @@ --- name: native-browser-safety-description: "SAFETY rules for any agent driving the Adom browser extension (nbrowser_* verbs). This bridge drives the user's REAL, signed-in Chrome/Edge - their live tabs, forms, sessions, saved logins, and other AI threads. Read this BEFORE driving. The cardinal rule: only ever act on a window/tab YOU opened (nbrowser_open_window); NEVER navigate, reload, or close a window/tab the user already had open (this includes the OS-level desktop_navigate) - doing so destroyed a user's other Claude threads once. Also: background by default (never foreground unless asked), the CDP \"debugging\" bar, credentials/autologin are gated and never expose passwords, recording is WGC-first, and the user blocklist is hands-off. Match on: browser safety, agent browser isolation, don't touch my tabs, navigated my window, wiped my threads, never reuse a window, background by default, real browser safety, nbrowser safety, drive the real browser safely. Part of the adom-browser-extension."+description: "SAFETY rules for any agent driving the Adom browser extension (nbrowser_* verbs). This bridge drives the user's REAL, signed-in Chrome/Edge - their live tabs, forms, sessions, saved logins, and other AI threads. Read this BEFORE driving. The cardinal rule: only ever act on a window/tab YOU opened (nbrowser_open_window); NEVER navigate, reload, or close a window/tab the user already had open (this includes the OS-level desktop_navigate) - doing so destroyed a user's other Claude threads once. Also: background by default (never foreground unless asked), the CDP \"debugging\" bar, credentials/autologin are gated and never expose passwords, recording is WGC-first, and the user blocklist is hands-off. Match on: browser safety, agent browser isolation, don't touch my tabs, navigated my window, wiped my threads, never reuse a window, background by default, real browser safety, nbrowser safety, drive the real browser safely. Part of the adom-native-browser." ----Part of **adom-browser-extension**. Verb surface: **driving-the-extension**. Recording: **native-browser-recording**.+Part of **adom-native-browser**. Verb surface: **driving-the-extension**. Recording: **native-browser-recording**. # Driving the user's REAL browser safely
skills/reading-google-messages/SKILL.md+2−2@@ -1,8 +1,8 @@ --- name: reading-google-messages-description: How to find the Google Messages PWA on a Windows desktop and READ SMS out of it — most importantly, to retrieve a one-time 2FA / verification code so you can complete a text-message two-factor login fully automatically. Google Messages for web is usually installed as a taskbar PWA ("Messages - Google Messages for web"); its window renders BLANK to PrintWindow, so you read it with UIA (desktop_find_control), not a background screenshot. Match when the user says "read my texts", "get the SMS code", "what's the 2FA code", "check Google Messages", "find the verification code", "automate the SMS 2FA", or any login that texts a code. Part of the adom-browser-extension site-recipe set (see driving-sites).+description: How to find the Google Messages PWA on a Windows desktop and READ SMS out of it — most importantly, to retrieve a one-time 2FA / verification code so you can complete a text-message two-factor login fully automatically. Google Messages for web is usually installed as a taskbar PWA ("Messages - Google Messages for web"); its window renders BLANK to PrintWindow, so you read it with UIA (desktop_find_control), not a background screenshot. Match when the user says "read my texts", "get the SMS code", "what's the 2FA code", "check Google Messages", "find the verification code", "automate the SMS 2FA", or any login that texts a code. Part of the adom-native-browser site-recipe set (see driving-sites). ----Part of the **adom-browser-extension** site-recipe set → see **driving-sites**. Generic desktop/UIA+Part of the **adom-native-browser** site-recipe set → see **driving-sites**. Generic desktop/UIA mechanics live in **driving-the-desktop**; THIS page is the Google Messages PWA's quirks. **Why this exists:** lots of sites text a 6-digit code for 2FA (Gusto, banks, etc.). If the user runs