<feed xmlns='http://www.w3.org/2005/Atom'>
<title>sz-chrome-remote-cdp.git/src/daemon/server.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-08-02T13:42:46+00:00</updated>
<entry>
<title>refactor: daemon internals, and fix a leak the merge exposed</title>
<updated>2026-08-02T13:42:46+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmail.com</email>
</author>
<published>2026-07-28T16:38:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=b913f2d4af218ae61de7073778feb56da89a15de'/>
<id>urn:sha1:b913f2d4af218ae61de7073778feb56da89a15de</id>
<content type='text'>
IdMultiplexer and EventRouter were the only classes in src/; they are now
createIdMultiplexer/createEventRouter closures like every other factory
here. The multiplexer kept {clientId, localId} per daemon id while the
bridge kept {send, clientId, localId, timer, isAttach} under the same key
— two maps of overlapping data, and mux.resolve()'s return value was
discarded at three of four call sites. One map now holds the union.

That merge fixes a real leak: removeClient cleared the multiplexer but
never the callbacks map, so a disconnected client's timers stayed armed
and later fired a response at a socket that was gone. clearClient now
cancels them, and a test pins it.

handleRequest polled every 250ms for up to 15s per request when Chrome
was down; N queued requests now await one connect signal.

server.ts uses its own protocol's serialize/deserialize instead of
hand-rolled JSON, and broadcast no longer routes through `this` — the
only `this` in the codebase, and the one thing that breaks when the
server object is destructured.

cdp/event-queue.ts held two unrelated concerns; the request/timeout half
moves to cdp/pending-requests.ts. cdp/daemon-transport.ts is the client
half of the daemon protocol, so it moves to daemon/transport.ts.

test/daemon/ needs adding to the test glob to run at all — there was no
daemon test directory before because none of this was reachable without
live Chrome.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>refactor: delete exports and knobs that nothing calls</title>
<updated>2026-08-02T13:42:46+00:00</updated>
<author>
<name>amankumarsingh77</name>
<email>amankumarsingh7702@gmail.com</email>
</author>
<published>2026-07-28T16:17:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=aedbb88a8025851067be9f77ec406b29d65599a8'/>
<id>urn:sha1:aedbb88a8025851067be9f77ec406b29d65599a8</id>
<content type='text'>
isInternalUrl, SPECIAL_KEYS, andThen and mapErr had no callers in src or
test. BrowserState.remoteBrowserId was parsed on restore and never
written — the field that is actually read lives on DaemonStatus.

IpcServer.disconnectClient and IpcServer.clients() were unreachable, as
was EventRouter.allClients and a write-only lineCount counter.
DAEMON_STALE_SOCKET_CLEANUP was a hardcoded true with an if around it, so
the unlink now runs unconditionally.

CdpBridge.isAlive and getSessionOwner look equally dead from src/ alone,
but test/manual/bridge-test.ts drives both — they are the only seams that
suite has, so they stay.

Co-Authored-By: Claude Opus 5 (1M context) &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(daemon): 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-28T14:57:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=a2588bb315a56a8dfcd3aa8a261cdc19b160d079'/>
<id>urn:sha1:a2588bb315a56a8dfcd3aa8a261cdc19b160d079</id>
<content type='text'>
Removes module banners, section dividers, reference lists, and comments
restating the code. Keeps one-line notes for the Windows named-pipe
endpoint, the Windows unlink no-op, the do-not-unlink-on-rejection rule,
the `.cmd` shell requirement, shell-quoting of spaced paths, and the
in-place client promotion.

Co-Authored-By: Claude Opus 5 (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>
