<feed xmlns='http://www.w3.org/2005/Atom'>
<title>sz-chrome-remote-cdp.git/src/cdp/endpoint.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-15T06:07:58+00:00</updated>
<entry>
<title>feat(cdp): report a BU_CDP_WS pin in status, /browser-target and the prompt</title>
<updated>2026-10-15T06:07:58+00:00</updated>
<author>
<name>Igor Soarez</name>
<email>igor@soarez.org</email>
</author>
<published>2026-10-15T06:07:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=3e761274fe7b0e6be4a162e880293150ad9d9fbe'/>
<id>urn:sha1:3e761274fe7b0e6be4a162e880293150ad9d9fbe</id>
<content type='text'>
Upstream 0.11.0 made BU_CDP_WS reach the daemon, and discoverEndpoint()
returns it before the fork's target is consulted. resolveCdpTarget() did
not know about it, so /browser-status and the system prompt named the
BU_CDP_HTTP/stored/default target while the daemon dialled the pinned URL,
and /browser-target claimed to switch browsers when it could not.

resolveCdpTarget() now puts BU_CDP_WS first, as a remote target with
source "ws". /browser-target warns that it takes precedence, as it already
did for BU_CDP_HTTP. Only host:port is ever shown: the path carries the
browser id and a proxied URL may carry a token. /browser-status does not
probe a pinned URL, since /json/version answering says nothing about
whether the pinned browser id is still current.
</content>
</entry>
<entry>
<title>feat(cdp): /browser-target to switch browsers without leaving pi</title>
<updated>2026-10-14T11:19:26+00:00</updated>
<author>
<name>Igor Soarez</name>
<email>igor@soarez.org</email>
</author>
<published>2026-07-29T09:38:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=08e558753e8ef9b2aa96114981a5a1dd37357bad'/>
<id>urn:sha1:08e558753e8ef9b2aa96114981a5a1dd37357bad</id>
<content type='text'>
Switching between the shared browser and this machine's own previously meant
leaving pi and relaunching with BU_CDP_HTTP — and, less obviously, killing the
daemon first, or the switch silently did not happen.

  /browser-target                 show the current target
  /browser-target local           this machine's browser
  /browser-target default         the built-in default
  /browser-target host:port       somewhere else

Precedence becomes env &gt; stored &gt; default. The environment still wins so a
one-off `BU_CDP_HTTP=… pi` is never silently overridden by a choice made days
ago; when it is set, the command says so rather than pretending to obey.
Clearing falls back to the default rather than to local — "use the usual
browser", not "go local".

The daemon is the reason this needed more than a settings write. It is
machine-wide, resolves its target once per process, and holds the WebSocket to
the old browser, so re-reading the store would leave tool calls going to the
old browser while /browser-status reported the new one. The command therefore
replaces the process: the daemon now honours an inbound control/shutdown (the
action already existed in the protocol, previously only sent daemon→client),
and stopDaemon() asks for it and polls until the process is really gone before
ensureDaemon() respawns it against the new target. /browser-status now reads
the store too, so it cannot disagree with what the tools will do.

Persistence mirrors the profile pin: atomic temp-file-plus-rename, and every
read failure degrades to "nothing stored" so a corrupt file falls back to the
default instead of breaking browser control. It is a separate file from the
pin, so damage to one cannot cost you the other. The stored value stays in
BU_CDP_HTTP's vocabulary so there is exactly one resolution path.

62 tests: the full precedence table including the stored tier, that a bad value
is blamed on the source that set it rather than sending you hunting through
shell config, that the command only accepts values resolution can actually use,
and eight ways of damaging the store file.
</content>
</entry>
<entry>
<title>feat(cdp): default to the shared browser, and say so in /browser-status</title>
<updated>2026-10-14T11:17:59+00:00</updated>
<author>
<name>Igor Soarez</name>
<email>igor@soarez.org</email>
</author>
<published>2026-07-28T21:08:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.soarez.net/sz/sz-chrome-remote-cdp.git/commit/?id=95ff5e8eaefb35d79109f7ddfa1de5bf45a8daff'/>
<id>urn:sha1:95ff5e8eaefb35d79109f7ddfa1de5bf45a8daff</id>
<content type='text'>
Two follow-ups to BU_CDP_HTTP.

Default the endpoint. The remote host is now a built-in default
(DEFAULT_REMOTE_CDP), so nothing has to export BU_CDP_HTTP just to get the
usual setup. The variable becomes an override rather than a requirement.

Precedence is deliberately asymmetric, in src/cdp/endpoint.ts:

  BU_CDP_HTTP=host:port   that endpoint; unreachable is a hard error
  BU_CDP_HTTP=local|off   upstream behaviour, this machine's own browser
  unset                   the default, falling back to local when unreachable

An explicitly configured endpoint is an instruction, so failing to reach it must
not quietly automate a different browser - that would drive the operator's own
signed-in Chrome instead of the shared one. The built-in default is only a
preference, so a laptop away from the network still gets the local browser the
extension was originally written for.

Resolution is pure, with no I/O, so the status command can report the
configured intent without touching the network and the daemon can resolve the
same way in its own process.

/browser-status no longer reports a bare "Disconnected". The connection is lazy
- nothing dials the browser until the first browser_* tool runs - so a fresh
session always showed a red light that reads as a fault. It now distinguishes
"not connected yet, connects on first use" from "target unreachable", and names
the target with a reachability check, so the common confusion answers itself.

26 tests for the resolution table, covering the aliases, malformed values that
must be rejected rather than coerced, and that the default constant is itself
well-formed - if it ever stopped parsing, every machine would silently fall
back to local.
</content>
</entry>
</feed>
