<feed xmlns='http://www.w3.org/2005/Atom'>
<title>sz-chrome-remote-cdp.git/skills/pi-browser-harness, branch master</title>
<subtitle>pi-browser-harness, patched to drive a Chrome on another host over CDP, with castle_cdp_search web search
</subtitle>
<id>https://git.soarez.net/sz/sz-chrome-remote-cdp.git/atom?h=master</id>
<link rel='self' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/'/>
<updated>2026-10-14T11:19:26+00:00</updated>
<entry>
<title>docs(readpage): flag SPA-shell results so models don't trust them as the page</title>
<updated>2026-10-14T11:19:26+00:00</updated>
<author>
<name>Igor Soarez</name>
<email>igor@soarez.org</email>
</author>
<published>2026-08-05T12:42:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=681ea9d0b3b89bec1ad8c57ef79ae2d4d82ef49b'/>
<id>urn:sha1:681ea9d0b3b89bec1ad8c57ef79ae2d4d82ef49b</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix: browser_download no longer hijacks the user's own downloads (#33)</title>
<updated>2026-10-11T18:39:18+00:00</updated>
<author>
<name>Uttkarsh</name>
<email>38376852+uttkarsh-26@users.noreply.github.com</email>
</author>
<published>2026-10-11T18:39:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=2601c90bc0ec54f1e6234d05112c99c458d4ae5e'/>
<id>urn:sha1:2601c90bc0ec54f1e6234d05112c99c458d4ae5e</id>
<content type='text'>
Browser.setDownloadBehavior was sent without a browserContextId, so the override applied to the
user's default context and outlived the session. browser_download now takes restore:true, tracks
the override this process set, and a clean session shutdown restores Chrome's default with a
bounded call that is skipped when the browser is already gone.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;</content>
</entry>
<entry>
<title>test: keep host-provided packages out of dependencies (#36)</title>
<updated>2026-10-11T18:10:29+00:00</updated>
<author>
<name>Uttkarsh</name>
<email>38376852+uttkarsh-26@users.noreply.github.com</email>
</author>
<published>2026-10-11T18:10:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=79526b01f4d3cf16c3cfb46313cf1179f0db40ac'/>
<id>urn:sha1:79526b01f4d3cf16c3cfb46313cf1179f0db40ac</id>
<content type='text'>
Adds a manifest guard (scripts/check-manifest.ts + test/util/manifest-test.ts) so npm run check
fails if a host-provided package such as typebox lands in dependencies, plus a daemon-startup
troubleshooting section in the skill.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;</content>
</entry>
<entry>
<title>feat: add per-tab request headers (#30)</title>
<updated>2026-09-08T18:35:42+00:00</updated>
<author>
<name>astarring</name>
<email>zouzhigang85@gmail.com</email>
</author>
<published>2026-09-08T18:35:42+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=8d7a067c8d82a592bfb3dcacf05305c39550cbc6'/>
<id>urn:sha1:8d7a067c8d82a592bfb3dcacf05305c39550cbc6</id>
<content type='text'>
Expose explicit set and clear tools so environment-routed pages can be opened without leaking header values or carrying headers across unrelated browsing.

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

Co-authored-by: zouzhigang &lt;zouzhigang@bytedance.com&gt;</content>
</entry>
<entry>
<title>feat!: remove the deep-research feature</title>
<updated>2026-08-02T13:42:46+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmail.com</email>
</author>
<published>2026-07-28T15:47:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=ea11182a0e8cb62d208b5b53a60c98c8bdef9e9a'/>
<id>urn:sha1:ea11182a0e8cb62d208b5b53a60c98c8bdef9e9a</id>
<content type='text'>
The harness ships browser tools; orchestrating a multi-agent research
workflow on top of them is the agent's job, not this extension's. Drops
the skill, the /deep-research command, and the web-search-researcher
subagent config.

browser_web_search and browser_read_page are untouched — the two tests
that covered their pure parsers move to test/domains/, where the test
glob still picks them up.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: pin the agent to a chosen browser profile (#16)</title>
<updated>2026-07-24T18:53:05+00:00</updated>
<author>
<name>Aman Kumar</name>
<email>145339995+amankumarsingh77@users.noreply.github.com</email>
</author>
<published>2026-07-24T18:53:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=6dd79f7c3bafacba54acb2840f8655fcb05318bf'/>
<id>urn:sha1:6dd79f7c3bafacba54acb2840f8655fcb05318bf</id>
<content type='text'>
* feat: pin the agent to a chosen browser profile (#15)

Harness tabs were created with a bare Target.createTarget, which places
them in Chrome's defaultBrowserContextId — and that value follows window
focus. Which profile the agent acted as therefore depended on which
browser window the user last clicked, so the same task could run as a
work account on one run and a personal account on the next.

/browser-profile lists the connected browser's profiles as "Name (email)"
and pins one to ~/.pi/agent/browser-harness.json, so the choice outlives
the session. The same picker appears on first browser_setup when nothing
is pinned; with no interactive UI, or on cancel, setup continues with a
note and the previous behavior.

Chrome offers no direct route to another profile: Target.createTarget
rejects a foreign browserContextId, and openerId does not inherit the
opener's context. The window is opened through the browser's own command
line (--profile-directory, handed to the running browser by Chromium's
ProcessSingleton) and identified by a unique file:// sentinel page, since
a bare about:blank#token argument is discarded. Further tabs come from
window.open evaluated with userGesture: true — the only CDP-reachable way
to place a tab in a non-default browser context — correlated by a unique
token so concurrent isolated tabs stay distinct. A failed handshake is
reported, never silently redirected to another profile.

All four tab-creation sites now funnel through cdp/target-factory, so
open_urls and the isolated tabs behind web_search / read_page cannot run
with a different profile's cookies than the visible tabs.

Also fixed along the way: snap Chromium is discovered, Windows uses
%LOCALAPPDATA%, browsers launched with an explicit --user-data-dir are
found, the running browser is chosen by ranking candidates against the
connected user-data-dir rather than taking the first process found, and
an installed-but-closed browser no longer reads as running.

CI runs the profile suites and a real-browser end-to-end test on ubuntu,
macOS, and Windows — profile discovery is the one part of the harness
whose behavior genuinely differs per OS.

Co-Authored-By: Claude Opus 4.8 (1M context) &lt;noreply@anthropic.com&gt;

* fix: single-flight harness window creation

Isolated tabs run concurrently (browser_read_page is registered
unserialized), so several could each find "no harness window" and create
one — two blank windows before this feature, two LAUNCHED profile windows
after it. ensureHarnessWindow now shares one in-flight creation per
client.

Sharing introduces a second hazard: freshlyCreated is a claim on the seed
tab, and if every waiter received it, they would all drive the same tab.
Only the caller that started the creation keeps the claim; the rest open
their own tab beside it.

Covered by test/manual/profile-concurrency-test.ts (five concurrent
isolated tabs, pinned and unpinned: distinct targets, one window, correct
profile), wired into CI on Linux only — the coordination is pure JS and
identical across platforms.

Co-Authored-By: Claude Opus 4.8 (1M context) &lt;noreply@anthropic.com&gt;

* fix: tilde expansion differs by purpose on Windows

CI on windows-latest caught this: join("~", "x") yields "~\x" there, and
expandTilde only handled "~/".

The two uses are not the same, so they no longer share a helper. The
agent dir stays byte-compatible with pi's own expandTildePath ("~/" only,
every platform) — being more lenient would put the pin file somewhere pi
never looks. $CHROME_USER_DATA_DIR is ours to interpret, so it accepts
"~\" as well, which is what a Windows user would type.

Co-Authored-By: Claude Opus 4.8 (1M context) &lt;noreply@anthropic.com&gt;

---------

Co-authored-by: Claude Opus 4.8 (1M context) &lt;noreply@anthropic.com&gt;</content>
</entry>
<entry>
<title>feat: add deep-research skill, /deep-research command, fix web-search-researcher</title>
<updated>2026-07-08T16:11:47+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmail.com</email>
</author>
<published>2026-07-08T16:11:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=1c12b43a674ae51a39c430ed8cfa138dbdf4dc71'/>
<id>urn:sha1:1c12b43a674ae51a39c430ed8cfa138dbdf4dc71</id>
<content type='text'>
deep-research skill fans out to isolated web-search-researcher subagents (now
using browser_web_search + browser_read_page instead of the non-existent
web_search/web_fetch), coverage-driven loop with a hard ceiling, synthesizes a
cited Markdown report. /deep-research command as explicit entry point. Docs updated.

Co-Authored-By: Claude Opus 4.8 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>release: v0.6.0 — per-tab isolation, Unix socket daemon, on-demand init (#6)</title>
<updated>2026-06-20T19:16:44+00:00</updated>
<author>
<name>Aman Kumar</name>
<email>145339995+amankumarsingh77@users.noreply.github.com</email>
</author>
<published>2026-06-20T19:16:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=da5d31af999b728c31ab0169373531cab4543f0c'/>
<id>urn:sha1:da5d31af999b728c31ab0169373531cab4543f0c</id>
<content type='text'>
* feat: Unix socket daemon with auto-reconnect for persistent Chrome CDP

Eliminates the 'Allow Remote Debugging' Chrome prompt that appeared on
every pi session by multiplexing pi instances through a single persistent
daemon process.

Key additions:
- Unix socket IPC (net.createServer + readline JSON framing)
- CdpBridge with ID multiplexer + event router
- DaemonTransport implementing CdpTransport interface
- Auto-spawn with ensureDaemon() (lazy, checks socket)

Fixes since initial implementation:
- Bridge auto-reconnects to Chrome with exponential backoff (1s-60s).
  Previously the bridge tried once at startup and permanently failed
  if Chrome wasn't ready — causing 'Chrome not connected' on every
  browser tool call.
- Daemon spawn uses project-local tsx binary instead of global --import
  flag, fixing silent spawn failure (ERR_MODULE_NOT_FOUND).
- Stale ctx crash: persistState in onOwnershipChange wrapped in
  try/catch to prevent CDP event consumer crashes.

49 test assertions across 4 test files. Zero TypeScript errors.

* feat: on-demand browser initialization

Browser daemon no longer auto-starts on session_start. Instead:
- session_start creates the client lazily but does NOT connect or spawn
  the daemon. Zero Chrome prompts for non-browser pi sessions.
- Browser tool wrapper checks for daemon socket before each call.
  Socket missing → clear error: 'Run /browser-setup first'.
  Socket exists → proceeds silently (daemon already running).
- /browser-setup is the explicit, one-time init point. It spawns
  the daemon and connects to Chrome only when the user opts in.
- SKILL.md updated with Connection Setup instructions telling agents
  to direct users to /browser-setup when socket is missing.

* fix: checkChromeRunning on macOS — match by substring not exact

ps -A -o comm= returns full executable paths on modern macOS
(e.g. /Applications/Google Chrome.app/Contents/MacOS/Google Chrome),
not the basename. The old exact-match check (browserProcesses.includes(l))
never matched, causing false 'No browser instance running' errors.
Changed to substring includes() with helper/renderer/crashpad filtering.

* feat: browser_setup as agent-callable tool

The agent can now self-recover from 'Browser harness not initialized'
errors by calling browser_setup directly — no user mediation needed.

- Extracted shared performSetup() from the slash command into setup.ts
- Created src/domains/setup.ts with ensureAlive:false to bypass the
  socket guard (this tool IS the setup, can't require itself)
- Registered browser_setup in the tool registry
- Updated SKILL.md: agent calls browser_setup directly, not ask user
- Removed stale test/manual/spawn-test.ts

* release: v0.6.0 — per-tab isolation, Unix socket daemon, on-demand init</content>
</entry>
<entry>
<title>release: v0.5.0 — browser_console tool for JS error/console diagnostics</title>
<updated>2026-05-07T07:24:12+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmal.com</email>
</author>
<published>2026-05-07T07:24:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=4052e6e6afef1dc20146765963dea7c0289ca401'/>
<id>urn:sha1:4052e6e6afef1dc20146765963dea7c0289ca401</id>
<content type='text'>
</content>
</entry>
<entry>
<title>release: v0.4.0 — accessibility snapshot, network capture, snapshot-first prompts</title>
<updated>2026-05-05T18:36:49+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmal.com</email>
</author>
<published>2026-05-05T18:36:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=589cd294931c01b3748779635d17a13dd240af19'/>
<id>urn:sha1:589cd294931c01b3748779635d17a13dd240af19</id>
<content type='text'>
Adds two new tools and pivots the agent's default workflow away from
screenshots toward structured page data.

browser_snapshot — CDP accessibility tree (roles, names, states, hierarchy)
with click coordinates @(x,y) attached to every interactive element via
DOM.getBoxModel (parallel, 1.5s aggregate budget). Pass directly to
browser_click — no screenshot round-trip. Optional includeScreenshot:true
for visual confirmation. format:"json" returns a slim structure with full
box per node.

browser_network_requests — replaces the deprecated browser_get_network_log
placeholder. Filters by urlPattern (substring or /regex/), method, status,
resource type, recency. Optional response-body capture under a 5s aggregate
budget with 50KB per-body cap. Buffer is page-scoped (cleared on tab switch),
500 records/tab, with a bufferOverflowed flag on drain.

CDP plumbing: in-process aggregator in src/cdp/network-buffer.ts wired into
the existing single-consumer event loop. Accessibility domain enabled
alongside Page/DOM/Runtime/Network on every attach.

Ctrl+O expand/collapse on three tools' renderResult — browser_snapshot,
browser_network_requests, browser_execute_js. Compact-by-default views with
keyHint("app.tools.expand") that respects user keybinding remaps.

Tool prompts pivoted snapshot-first: browser_screenshot is documented as
LAST RESORT for visual verification only; browser_snapshot is the default
for understanding pages; browser_execute_js is the default for surgical
reads. browser_click and browser_open_urls guidance follows.

SKILL.md collapsed from ~342 to ~53 lines — keeping only what isn't already
in tool prompts: the decision tree, connection rules, browser_run_script
daemon bindings.

Co-Authored-By: Claude Opus 4.7 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
