aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FORK.md141
1 files changed, 141 insertions, 0 deletions
diff --git a/FORK.md b/FORK.md
new file mode 100644
index 0000000..cf10ecc
--- /dev/null
+++ b/FORK.md
@@ -0,0 +1,141 @@
+# Fork notes
+
+A fork of [tianrendong/pi-chrome](https://github.com/tianrendong/pi-chrome) that
+lets pi on **other machines** drive one signed-in browser. It adds a remote mode
+to the pi extension and a standalone broker for the browser's host. Without
+`PI_CHROME_REMOTE` set, it behaves exactly like upstream.
+
+Not published to npm and not proposed upstream.
+
+```
+origin https://git.soarez.net/sz/pi-chrome.git
+upstream https://github.com/tianrendong/pi-chrome.git
+```
+
+## Why the patch exists
+
+Upstream only works on the machine running the browser:
+
+- the companion extension long-polls a bridge at `127.0.0.1:17318`, hardcoded
+ in `browser-extension/service_worker.js`;
+- that bridge lives inside whichever pi session started first on the machine,
+ and goes away when that session exits;
+- a pi session on another host cannot join it. `PI_CHROME_BRIDGE_HOST` set to a
+ remote address makes `listen()` fail with `EADDRNOTAVAIL`, and only
+ `EADDRINUSE` switches a session into client mode, so the session fails at
+ startup.
+
+Upstream tried a standalone daemon in 0.16–0.17 (`docs/DESIGN-0.17-daemon.md` in
+the v0.17.3 tag) and then dropped it; main is back on the 0.15 line. This fork
+is based on main.
+
+## What the fork changes
+
+**`broker/broker.mjs`** runs on the browser's host in place of upstream's
+in-session bridge. It speaks upstream's HTTP contract to the extension, so the
+extension is loaded exactly as shipped. Node builtins only, no install step. It
+has two listeners:
+
+| listener | address | routes |
+|---|---|---|
+| extension | `127.0.0.1:17318` | `/next`, `/result`, `/status`, `/command` |
+| peer | `PI_CHROME_BROKER_PEER_HOST`, same port | `/command`, `/status` |
+
+Keeping `/next` and `/result` off the peer listener means nothing on the network
+can drain the extension's queue or forge results. `/command` needs a bearer
+token on both listeners, because the browser is signed into real accounts. Bind
+the peer listener to an address on a network you trust (a VPN, say), never to
+`0.0.0.0`.
+
+| Broker setting | Effect |
+|---|---|
+| `PI_CHROME_BROKER_PORT` | both listeners' port; default `17318`, which the extension expects |
+| `PI_CHROME_BROKER_PEER_HOST` | the peer listener's address; unset, there is no peer listener |
+| `PI_CHROME_TOKEN` | the bearer token |
+| `PI_CHROME_TOKEN_COMMAND` | a command whose output is the token, for a secret store |
+
+**`extensions/chrome-profile-bridge/index.ts`**: every change is marked
+`FORK:`.
+
+| Setting | Effect |
+|---|---|
+| `PI_CHROME_REMOTE` unset, or `local` (also `off`, `none`, `0`, `no`, `localhost`) | upstream behaviour |
+| `PI_CHROME_REMOTE=host:port` | the broker there |
+| `PI_CHROME_TOKEN`, `PI_CHROME_TOKEN_COMMAND` | the bearer token, as for the broker; read on first use |
+| `PI_CHROME_AUTHORIZE=indefinite` (or `30m`, `45`…) | skip `/chrome authorize`: every session starts authorized |
+| `PI_CHROME_REMOTE_LABEL` | how the prompt names the browser; default "the user's own browser on *host*" |
+| `PI_CHROME_REMOTE_SSH` | the ssh target the prompt gives for file transfer; default the broker's host |
+| `PI_CHROME_OTHER_BROWSER_TOOLS` | another browser's tools (e.g. `browser_*`), for the prompt to route between |
+
+In remote mode the session never binds a port and never promotes itself to
+bridge. If the broker is unreachable the tools fail. They do not silently drive
+some other browser on this machine.
+
+The system prompt gains a `pi-chrome-remote` section beside upstream's
+`chrome-profile-bridge` primer, present while `chrome_*` is authorized. It is
+added by a `before_agent_start` handler of its own, so upstream's handler stays
+as shipped. It says `chrome_*` drives
+a signed-in browser on another host, and, when another browser's tools are
+named, to keep this one for tasks that need the user's sessions. It also covers
+moving files: uploads are staged on the browser's host with scp, downloads land
+in its `~/Downloads`, and screenshots are already local. `chrome_upload_file`
+refuses relative paths in remote mode, because the browser opens them on its own
+host.
+
+Pi sessions on different hosts each get their own automation window. The
+extension keys windows by pi session id, which is globally unique. Background
+mode, which is upstream's default, keeps them from focusing the browser or
+switching its tabs.
+
+## MCP clients
+
+[pi-chrome-mcp](https://git.soarez.net/sz/pi-chrome-mcp.git) serves these
+tools to Claude Code, Claude Desktop and other MCP clients. Point its
+`PI_CHROME_PATH` at this fork's `index.ts` to use remote mode.
+
+## Setup
+
+On the browser's host:
+
+1. Clone this repository somewhere it will stay. The browser disables an
+ unpacked extension whose folder goes missing, so not a package manager's
+ cache that it may replace.
+2. Load the extension once: `chrome://extensions` (or `brave://extensions`) ->
+ Developer mode -> Load unpacked ->
+ `extensions/chrome-profile-bridge/browser-extension`.
+3. Run `node broker/broker.mjs` under a supervisor (launchd, systemd), with
+ `PI_CHROME_BROKER_PEER_HOST` and a token set. No pi session on that machine
+ may be running stock pi-chrome, which would take the port first.
+
+On every other machine, install the fork as a pi package and set
+`PI_CHROME_REMOTE=<browser host>:17318` and the token.
+
+## Taking upstream releases
+
+```
+git fetch upstream
+git rebase upstream/main
+git push --force-with-lease origin master
+```
+
+Then update the broker's checkout, restart it, and reload the extension in the
+browser. `/chrome doctor` reports a version mismatch until you do.
+
+Expect conflicts in the places marked `FORK:` in `index.ts`: the bridge class's
+bind, forward and status code (including `connectionStatus`, whose `/status`
+fetch carries the token), `session_start`, the remote prompt-section handler
+just ahead of upstream's primer, doctor, and `chrome_upload_file`. If upstream changes the extension↔bridge HTTP contract
+(`/next`, `/result`, the `x-pi-chrome-version` header), port the change to
+`broker/broker.mjs`. Its request handling is a line-by-line port of the server
+half of `ChromeProfileBridge`.
+
+## Verifying
+
+`/chrome doctor` in a pi session should report "using the pi-chrome broker at
+http://*host*:17318" and a connected extension. From outside pi:
+
+```
+curl -s -H "Authorization: Bearer $PI_CHROME_TOKEN" http://<host>:17318/status
+```
+
+`connected: true` with a recent `lastSeenAt` means the extension is polling.