Tool guide
browser tool
Open, reuse, close, and script Puppeteer tabs against headless Chromium, a CDP-attached app, or a saved Chrome profile. Tabs live in a process-global map and are reused by name across later calls and in-process subagents until closed.
How to use it
There is no separate gjc browser subcommand. Start a normal GJC session and ask the agent to use the browser tool. The agent drives three actions β open, run, and close β against named tabs.
# Launch GJC from your repo/workspace
gjc
# Then prompt the agent, e.g.
"Use the browser tool to open example.com and extract the main article text."
For static pages (articles, docs, JSON, PDFs), prefer the read tool. Reach for the browser when you need JS execution, authentication, or interactive actions.
Actions
openβ acquire or reuse a named tab (defaults to"main"). Optionalurlnavigates after the tab is ready;viewport,wait_until, anddialogs("accept"/"dismiss") tune the page. Theappfield selects the browser kind.runβ execute an async JS body withpage,browser,tab,display,assert, andwaitin scope.display(value)calls and the return value become tool output.closeβ release one tab, or every tab withall: true.kill: truealso terminates a spawned-app process tree (and only a GJC-launched Chrome profile process).
Browser kinds
- Headless (no
app) β local Chromium with stealth patches applied; a fresh page per tab. Default viewport is1365Γ768atdeviceScaleFactor 1.25. - Spawned app (
app.path) β reuses an existing CDP-enabled process for that executable when possible, otherwise spawns it with remote debugging. No stealth patches. - Connected browser (
app.cdp_url) β attaches to an existing CDP endpoint. No process ownership;closeonly disconnects. - Saved Chrome profile (
app.browser: "chrome"+path+user_data_dir+profile_directory) β automate with cookies and login state without risking the daily Chrome process.
The tab helper API
Inside run, prefer the structured tab helpers over raw Puppeteer; drop to page only when needed.
tab.goto(url, { waitUntil? }),tab.url(),tab.title()tab.observe({ includeAll?, viewportOnly? })β accessibility snapshot with stable numeric element ids;tab.id(n)resolves an id to anElementHandle.tab.click,tab.type,tab.fill,tab.press,tab.select,tab.scroll,tab.drag,tab.scrollIntoView,tab.uploadFiletab.waitFor(selector),tab.waitForUrl(pattern),tab.waitForResponse(pattern),tab.evaluate(fn, β¦args)tab.screenshot({ selector?, fullPage?, save?, silent? })β attaches an image unlesssilent;tab.extract(format = "markdown")returns Readability content.
Selectors accept CSS plus Puppeteer query handlers such as aria/Sign in, text/Continue, xpath/β¦, and pierce/β¦. After a tab.goto() or any navigation, re-run tab.observe() β prior element ids are invalidated.
Saved Chrome profile example
{
"action": "open",
"name": "work-browser",
"app": {
"browser": "chrome",
"path": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"user_data_dir": "~/Library/Application Support/Google/Chrome",
"profile_directory": "Profile 10",
"background": true,
"no_focus": true,
"target": "example.com"
}
}
- CDP binds to
127.0.0.1; never expose a logged-in profile's CDP port publicly β a CDP client has full browser-account access. - A matching already-running profile is reused only when its localhost CDP endpoint responds; a profile running normally without CDP is refused rather than killed or relaunched.
kill: trueterminates only the Chrome profile process that GJC launched.
Limits
- Tool timeout: default
30s, clamped to the browser range (max30s). - Headless first run may download Chromium into the Puppeteer cache; launch prefers a detected system Chrome, then
PUPPETEER_EXECUTABLE_PATH, then download. - Stealth patches apply to headless mode only; spawned and externally connected browsers are left untouched.
- Screenshots sent to the model are downscaled (max 1024Γ1024);
saveorbrowser.screenshotDirpersists full resolution.