name: native-browser-control description: > Drive the user's REAL logged-in Chrome or Edge from the cloud via the Adom browser extension (CDP), in the background, no focus steal. Use to click/scroll/ read a page in their actual browser, upload a file, or log them in through OAuth using their existing sessions. Trigger words: nbrowser, drive my chrome, drive edge, real browser, logged-in browser, upload to a website, sign in with google, oauth login, CDP eval browser.

Native browser control (nbrowser)

nbrowser_* drives the user's real, logged-in Chrome/Edge through the adom-browser-extension over CDP. Because it's their actual browser, their cookies and logins are already there, so a JLCPCB/Autodesk/Google flow "just works" with no credentials handed over. It runs in the background (no focus steal).

Core verbs

adom-desktop nbrowser_status '{}'                                 # {ok, ext, browser:"chrome"|"edge"}
adom-desktop nbrowser_list_tabs '{}'                             # all tabs (tabId, url, windowId, active)
adom-desktop nbrowser_open_tab '{"url":"https://..."}'          # opens a DEDICATED tab, returns tabId
adom-desktop nbrowser_eval '{"tabId":"<id>","expr":"<js>"}'     # run JS in that tab (background)
adom-desktop nbrowser_screenshot '{"tabId":"<id>"}'            # page PNG as base64 (background)
adom-desktop nbrowser_navigate '{"tabId":"<id>","url":"..."}'

Chrome vs Edge, this trips everyone

nbrowser defaults to Chrome. To drive Edge, pass "browser":"edge" on EVERY verb. nbrowser_list_tabs without it shows only Chrome tabs.

adom-desktop nbrowser_list_tabs '{"browser":"edge"}'
adom-desktop nbrowser_eval '{"browser":"edge","tabId":"<id>","expr":"location.href"}'

Gotchas (each cost a real debugging session)

  • It refuses to drive PWA / installed-app tabs (e.g. a taskbar Gmail/Chat PWA) to avoid hijacking a standalone app. Open a dedicated tab with nbrowser_open_tab.
  • A first eval can return null right after opening a tab (timing). Retry; it works.
  • No frame-targeting. eval runs in the TOP frame only. Params like allFrames, frameUrl, frame are ignored (they silently return the top frame). You CANNOT reach into a cross-origin iframe (iframe.contentDocument throws / accessible:false). This is why deeply-nested webviews (the Hydrogen Claude panel) are unreachable, see hydrogen-web-control.
  • nbrowser_eval runs in the PAGE context, so JS can click, scroll, read, and set inputs, but only same-origin.

Upload a file (DataTransfer, no OS picker)

CDP can't touch the native file dialog, so inject the bytes and set the <input type=file> directly. Base64 the file, stream it into the page in <40k chunks (the CLI arg cap), then build a File and set it via DataTransfer:

# per chunk: comma operator = ONE expression (nbrowser_eval requires a single expression)
adom-desktop nbrowser_eval '{"tabId":"<id>","expr":"(window.__b += \"<chunk>\", window.__b.length)"}'
# then decode + set the input:
adom-desktop nbrowser_eval '{"tabId":"<id>","expr":"(function(){var s=atob(window.__b),u=new Uint8Array(s.length);for(var i=0;i<s.length;i++)u[i]=s.charCodeAt(i);var f=new File([u],\"board.zip\",{type:\"application/zip\"});var inp=document.querySelectorAll(\"input[type=file]\")[0];var dt=new DataTransfer();dt.items.add(f);inp.files=dt.files;inp.dispatchEvent(new Event(\"change\",{bubbles:true}));return inp.files[0].name})()"}'

The input often clears itself right after the change event (the site read the file already), that is NORMAL, don't treat the empty input as failure. Verify by screenshot.

Drive an OAuth login yourself (NEVER ask the user)

You can log the user in end to end. Proven on JLCPCB "Sign in with Google":

  1. Click the page's "Sign in with Google" button (nbrowser_eval .click()).
  2. On accounts.google.com, CDP eval WORKS (it's not blocked). Click the user's account row, then the OAuth Continue button, both via eval .click().
  3. It redirects back logged in; any file you already uploaded persists in the session.

This is one-time per site; afterwards the session stays logged in and every run is fully background. Pick the user's primary work Google account if there's a chooser. NEVER ask the user to click or log in, you can do all of it.

When CDP eval can't reach a control

If a page genuinely blocks eval on an element, screenshot the window, map the pixel, and fall back to a foregrounded OS click, see desktop-ui-control. But try eval first, it's background and doesn't disturb the user.

Related: pup-browser-control (anonymous browsers), screen-recording (recording a live drive).