name: adom-google-onboarding description: "Hand-hold a brand-new ORG through standing up its OWN Google Workspace OAuth client so adom-google works for their whole team — read mail, post Google Chat on their behalf, build Slides/Sheets/Docs, search Drive. You drive the user's REAL logged-in browser (adom-desktop nbrowser_* extension; pup native-mode fallback) to Google Cloud Console, AUTO-FILL the fields (especially the error-prone redirect URI), capture the new client_id + client_secret, and wire it in RELAY mode (their secret stays 0600 on their box; Adom only lends its shared callback URL — it never sees the secret). Use when a NON-Adom org wants to get going themselves. Triggers — onboard my org/company to adom-google, set up google workspace for my team, configure google oauth for my company, get my company on adom-google, self-serve google setup, we want to use adom-google at our org, set up the google cloud project, create our oauth client. (For an Adom EMPLOYEE, skip all this — they install adom-google-adom and just run auth. This skill is for everyone else.)"

adom-google — Org Onboarding (drive the browser, auto-configure Google)

Goal: take a new org from nothing to "the AI is reading our mail, posting in Chat, and building decks" in one guided sitting. The hard part — creating a Google Cloud OAuth client — is normally a 20-field console slog. You do it FOR them: drive their real browser, auto-fill every field, pause only for the clicks Google forces a human to make. Pristine, billboard-grade setup.

The architecture you're wiring (know this cold)

  • The org creates their own Google Cloud project + OAuth client (Internal to their Workspace).
  • Their OAuth client's Authorized redirect URI = Adom's shared gateway /callback — a public, multi-tenant relay. Any org can register a one-time state over its WebSocket and get the auth code relayed back. Near-zero load; no per-org config on the gateway.
  • The org's client secret stays on the org's own container (~/.config/adom-google/provider.json, 0600) in RELAY mode (broker:false). Adom's gateway only relays the code; the org's CLI exchanges it and refreshes locally with their own secret. Adom never holds their secret.
  • Result: the org owns everything; Adom just lends a callback URL. (Adom employees use BROKER mode via adom-google-adom, where the secret lives on the gateway — different package, not this flow.)

Get the exact values FIRST (single source of truth)

adom-google onboard --org <slug> --json

Returns redirect_uri, enable_apis_url (one click → all 9 APIs), apis[], scopes_safe/full, consent (User type = Internal, app name), and console{} deep links. Every field you type comes from here — never hand-author a redirect URI or API id.

Which browser surface

You need the user's real, logged-in Google admin session. Use the extension (nbrowser_*) — it IS their everyday Chrome/Edge with their Workspace login + device enrollment already active. Pup Chrome-for-Testing has no logins; pup native-mode is the fallback if the extension is unavailable.

adom-desktop --target AdomLapper nbrowser_status     # connected? which browser?

If "not connected": the target profile has no open Chrome window — ask the user to open Chrome (any window) in the profile that's signed into their Workspace, then nbrowser_rescan. Fallback to pup: adom-desktop browser_open_window '{"sessionId":"gcp","nativeBrowser":"chrome","nativeProfile":"Default","url":"https://console.cloud.google.com"}'.

MANDATORY PREFLIGHT — profiles first, then YOUR OWN window. Never the user's tabs.

  1. nbrowser_profiles (read-only) → every connected browser:email profile across Chrome AND Edge.
  2. Pick the profile whose email matches the Google account this setup is FOR (org onboarding → the Workspace admin's profile; a personal-account setup → that personal profile, e.g. chrome:[email protected]). The user almost certainly has a browser profile tied to that account — find it, never guess, and never use "whatever profile is active."
  3. nbrowser_open_window {profile:"<key>", url:"https://console.cloud.google.com", sessionId:"gcp"} → a BACKGROUND window pinned to that profile. ALL console driving happens in this window via its sessionId. A bare nbrowser_navigate (no sessionId) targets the user's ACTIVE tab — the extension (v0.0.21+) refuses it (no_target/not_owned), and it once destroyed a user's other AI threads. There is no override.
  4. Screenshot the new window and verify the top-right account matches. Wrong account = wrong project owner, the #1 way this goes sideways.

Drive loop (repeat for every step)

  1. nbrowser_navigate {sessionId:"gcp", url:"<deep link from the config>"} — always in YOUR window.
  2. nbrowser_screenshotread it (don't assume the DOM; Google Console mutates constantly).
  3. Act with trusted input: nbrowser_type {selector,text} to fill, nbrowser_click {selector} to click. Selectors are modal-aware; prefer visible text / aria-label ([aria-label="Create"], button:has-text("Enable")). If a selector misses (elementsMatched:0), screenshot again and try a coordinate click (nbrowser_input_dispatch {type:"click",x,y}) off the screenshot.
  4. nbrowser_screenshot again to confirm the result before moving on.
  5. Narrate with nbrowser_caption {text:"Step 3/6 — enabling APIs…"} so the user follows along, and desktop_bring_to_front {titleContains:"Google Cloud"} so they can watch.
  6. Shotlog every screenshot with a description and hand the user the phone URL (per the all-screenshots rule) so they can audit each step from their phone.

Always pause for the human on these (Google requires a real click; never fake it)

  • Account chooser / re-auth prompts.
  • The final Create on the OAuth client.
  • The OAuth consent screen Publish/Save if a confirm dialog appears. Show a screenshot, say exactly what to click, wait, then continue. Auto-fill everything up to these.

The six steps

1 · Project. Navigate console.project_create. Auto-fill the project name (type into the Project name field) e.g. adom-workspace. Pause for the user to click Create. Wait for the create to finish (poll screenshots / the notifications bell), then make sure the new project is the active project (project picker, top bar).

2 · Enable all nine APIs in one click. Navigate to enable_apis_url (it pre-selects all 9). Screenshot. Click Enable. This is the single biggest time-saver — one screen instead of nine. Confirm "APIs enabled."

3 · OAuth consent screen → Internal. Navigate console.consent_screen. Choose User type = Internal (critical — Internal = only their Workspace can sign in, and gives long-lived refresh tokens). Auto-fill App name (consent.app_name), user support email (their admin), developer contact (their admin). Save. (Internal apps need no verification and skip the scary "unverified app" screen.)

4 · Create the OAuth client. Navigate console.create_client. Application type = Web application. Auto-fill Name (consent.client_name). Then the load-bearing move: AUTO-FILL the Authorized redirect URI with redirect_uri from the config — paste it verbatim, never make the user type it (one wrong char = redirect_uri_mismatch later). Screenshot to prove it matches. Pause for the user to click Create.

5 · Capture the credentials. The post-create dialog shows Client ID + Client secret. Read them: nbrowser_eval to scrape the dialog text, and ALSO screenshot as a backup. Verify the client_id ends in .apps.googleusercontent.com and the secret looks like GOCSPX-…. Then store them — secret to the CLI, never echoed into chat:

adom-google onboard finish --org <slug> --client-id "<id>" --client-secret "<secret>"

This writes provider.json (0600, broker:false). The secret lives only on the user's box.

6 · Chat app config (once). Navigate console.chat_config (Chat API → Configuration). Set an app name + avatar + "Make available to … your domain." Without this, chat spaces 404s "Chat app not found." This is the one step pure-data tools skip; do it so adom-google chat works out of the box.

Authorize + verify (the payoff)

ASK the user safe vs full (use AskUserQuestion — never pick for them; safe = no "delete all" on the consent screen, the recommended default). Then:

adom-google auth            # safe   (or: adom-google auth --full)

Print the consent URL; open it in a NEW background window in the matching profile (nbrowser_open_window {profile:"<key>", url:"<consent url>", sessionId:"consent"} — never a bare nbrowser_navigate at their tabs), screenshot the consent, pause for Allow. The gateway relays the code; the CLI exchanges it locally. Then prove it works — small, real, delightful:

adom-google status                                   # mode + "Auth: relay (your secret 0600 here…)"
adom-google chat spaces                              # lists their spaces
adom-google api https://www.googleapis.com/drive/v3/about?fields=user   # "you're signed in as …"

End by showing them ONE magic moment — e.g. compose a Google Doc or post a Chat message — so the "oh, this is a game-changer" lands immediately.

Gotchas

  • Wrong Google account under the project → everything downstream is wrong. Verify in step 0.
  • redirect_uri mismatch at auth time → the client's Authorized redirect URI ≠ redirect_uri. Re-open the OAuth client, fix the field (auto-fill again), save, retry auth. This is why step 4 auto-fills.
  • Internal vs External: always Internal for an org. External forces app verification + a scary screen.
  • Extension "not connected" = no open Chrome window in the signed-in profile. Open one, nbrowser_rescan.
  • Secrets: never print the client_secret or refresh token to the transcript/logs. Pass the secret straight into onboard finish. Screenshots of the secret dialog → shotlog them privately; don't paste the secret text into chat.
  • Don't auto-click Create/Allow/Publish — Google wants a human there, and the user should see what they're approving. Auto-fill up to the button; let them press it.

Why this matters (say it to the user)

Once they're authed, their AI can read their email, post Google Chat on their behalf, compose Google Docs, build Google Sheets and Slides, and search Google Drive — all from the terminal. That's the workflow unlock teams fall in love with. You just made the painful part painless.

Related: adom-google (the CLI + full command set) · the driving-the-extension skill (nbrowser_* deep reference) · adom-gchat (attributed bot posts).