<feed xmlns='http://www.w3.org/2005/Atom'>
<title>sz-chrome-remote-cdp.git/src/domains/setup.ts, 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-11T18:25:38+00:00</updated>
<entry>
<title>refactor: remove duplicate browser prompt instructions (#35)</title>
<updated>2026-10-11T18:25:38+00:00</updated>
<author>
<name>Patrick Barattin</name>
<email>p.barattin@gmail.com</email>
</author>
<published>2026-10-11T18:25:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=014de0ec21936a7a2fd64db9d151e73c79bb44ad'/>
<id>urn:sha1:014de0ec21936a7a2fd64db9d151e73c79bb44ad</id>
<content type='text'>
Remove browser instruction text repeated across tool descriptions, parameter schemas, tool
guidelines and the global browser prompt. Tool names, schemas, handlers and concurrency are
unchanged; shared recovery and ownership guidance is now available before and after the browser
connects, and the prompt names which tools are serialized versus observations.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;</content>
</entry>
<entry>
<title>refactor: tidy the whitespace the comment removal left behind</title>
<updated>2026-08-02T13:42:46+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmail.com</email>
</author>
<published>2026-07-28T15:04:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=a9bdbd8590801cd9c2fa0cda6203948ac19a779c'/>
<id>urn:sha1:a9bdbd8590801cd9c2fa0cda6203948ac19a779c</id>
<content type='text'>
Drops leading blank lines where a file header was removed, collapses
double blank lines, and closes the empty catch/handler blocks whose only
content had been a comment. Whitespace only.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>refactor(domains): strip comment noise</title>
<updated>2026-08-02T13:42:46+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmail.com</email>
</author>
<published>2026-07-28T15:00:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=b67faca60b21b0cf74d5c967f0f8d215ad601e93'/>
<id>urn:sha1:b67faca60b21b0cf74d5c967f0f8d215ad601e93</id>
<content type='text'>
Removes module banners, step markers, and comments restating the code.
Keeps one-line notes for safeJs's trust boundary, the select-match null
sentinels, the TUI width clamp, the single-window tab rule, the input
synthesis quirks (char events, keyCode, mousemove, focus, compositor),
the stale AX value, ignored-wrapper recursion, and isolated-tab routing.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>refactor(tools): declare concurrency in the tool definition</title>
<updated>2026-08-02T13:42:46+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmail.com</email>
</author>
<published>2026-07-27T18:31:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=5cfa7ccc8f4082db111bc0186c5fa3d44b767ad3'/>
<id>urn:sha1:5cfa7ccc8f4082db111bc0186c5fa3d44b767ad3</id>
<content type='text'>
serialized: true was applied in registry.ts, away from the tools it
describes. Now a required concurrency field on each definition, with a
test pinning the serialized set so the classes cannot drift.

The lock check defaults to taking the mutex for any class that is not
explicitly "parallel", so a definition that bypasses defineBrowserTool at
runtime fails safe rather than racing on shared CDP state.

The test script gains --conditions=import: pi-coding-agent publishes no
"require" condition, so importing any tool definition from a CJS-loaded
test could not resolve it.

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>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>
</feed>
