pi-chrome 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # pi-chrome
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/pi-chrome.svg)](https://www.npmjs.com/package/pi-chrome)
4
+
3
5
  Control the Chrome profile you already use from Pi.
4
6
 
5
7
  `pi-chrome` gives Pi agents browser tools for your **real Chrome windows, tabs, and authenticated sessions**. It uses a companion Chrome extension instead of the Chrome DevTools Protocol (CDP), so it does not launch a throwaway debug browser profile and does not require re-signing into the apps you already have open.
@@ -9,8 +11,8 @@ Multiple Pi sessions can use Chrome at the same time. The first Pi session start
9
11
  ## Why try it?
10
12
 
11
13
  - **Uses your existing Chrome profile** — works with the Chrome windows/tabs you are already using, including logged-in GitHub, admin dashboards, local apps, and internal tools.
14
+ - **Background by default** — agents can inspect, navigate, click, type, and snapshot without bringing Chrome to the foreground or interrupting whatever you are doing. Toggle for the whole session with `/chrome-foreground`, or pass `foreground: true` on a single tool call.
12
15
  - **Full browser automation toolkit for Pi** — list/create/activate/close tabs, snapshot pages with usable CSS selectors, navigate, evaluate JavaScript, click, type, press keys, wait for page state, and capture screenshots.
13
- - **Background by default** — agents can inspect, navigate, click, type, and snapshot without bringing Chrome to the foreground or interrupting whatever you are doing. Toggle for the whole session with `/chrome-foreground` (useful for demos, pair-driving, debugging) or pass `foreground: true` on a single tool call.
14
16
  - **Built-in setup and agent guidance** — `/chrome-onboard` walks users through installing the companion extension, `/chrome-status` checks connectivity, screenshots save to disk, and the prompt primer tells agents to inspect with `chrome_snapshot` before acting and avoid destructive actions unless explicitly requested.
15
17
 
16
18
  ## Install
@@ -25,6 +27,10 @@ For local development from a checkout:
25
27
  pi install ./pi-chrome
26
28
  ```
27
29
 
30
+ ### Why an unpacked Chrome extension?
31
+
32
+ The Chrome Web Store does not allow extensions that talk to a local bridge controlled by another tool, so `pi-chrome` ships its companion as an unpacked extension you load yourself. The source is small, MIT-licensed, and lives in `extensions/chrome-profile-bridge/browser-extension/` next to this README — read it before loading.
33
+
28
34
  ## First-time setup
29
35
 
30
36
  In Pi, run:
@@ -57,20 +63,68 @@ Performing Chrome bridge health check
57
63
  Chrome profile bridge connected (ID: <chrome-extension-id>)
58
64
  ```
59
65
 
60
- ## Quick demo prompt
66
+ ## Foreground control
67
+
68
+ By default, `chrome_*` tools act silently in the background — your editor or terminal keeps focus and Chrome does not pop up. This lets agents work alongside you without interrupting whatever you are doing.
61
69
 
62
- After setup, try this in Pi:
70
+ When you want to watch the agent (demos, pair-driving, debugging), turn foreground on for the whole Pi session:
71
+
72
+ ```text
73
+ /chrome-foreground # toggle
74
+ /chrome-foreground on # explicit
75
+ /chrome-foreground off # explicit
76
+ ```
77
+
78
+ For a single tool call, the agent can pass `foreground: true` directly. The per-call value always wins over the session toggle.
79
+
80
+ ## Quick demo prompts
81
+
82
+ After setup, try one of these in Pi:
83
+
84
+ Background inspection (no Chrome interruption):
85
+
86
+ ```text
87
+ Inspect my active GitHub tab in the background with chrome_snapshot and summarize the PR state without focusing Chrome.
88
+ ```
89
+
90
+ Existing authenticated tab:
63
91
 
64
92
  ```text
65
93
  Use chrome_tab list to find my existing GitHub tab, chrome_snapshot it, then summarize the visible PR state. Do not click anything yet.
66
94
  ```
67
95
 
68
- Or for a local web app repro:
96
+ Local web app repro with screenshot:
69
97
 
70
98
  ```text
71
99
  Use chrome_tab list to find my localhost app, inspect it with chrome_snapshot, navigate through the bug repro flow, and save a screenshot when you reach the broken state.
72
100
  ```
73
101
 
102
+ ## Recipes
103
+
104
+ Copy-paste these into Pi after setup. Each one uses tabs you already have open and accounts you are already signed into.
105
+
106
+ - **PR triage:** "Use chrome_tab list to find my GitHub notifications tab, snapshot it, and summarize PRs needing my review."
107
+ - **Linear standup:** "Open my Linear current cycle in the active tab, snapshot it, and write me a 5-bullet standup."
108
+ - **Bug repro with evidence:** "Open the staging app I'm already signed into, reproduce <bug>, and save a screenshot of each step under ./repro/."
109
+ - **Form auto-fill (no submit):** "Open <vendor> portal, fill the new-vendor form from this JSON, but stop before submit."
110
+ - **Admin cross-check:** "Across my Stripe / Postmark / our admin tabs, find any user where state disagrees."
111
+ - **Local dev visual diff:** "Snapshot localhost:3000 and the staging URL of the same page; tell me what's visually different."
112
+ - **Auth-only data pull:** "Open my analytics dashboard tab and chrome_evaluate to extract today's KPIs from the page state."
113
+
114
+ Screenshots save under `.pi/chrome-screenshots/` by default, which composes nicely with PR demo workflows.
115
+
116
+ ## Diagnostics
117
+
118
+ - `/chrome-status` — quick health check; reports the connected Chrome extension ID and version.
119
+ - `/chrome-doctor` — deeper diagnosis with one-line fixes for common setup failures (extension not loaded, bridge owner stale after `pi update`, version mismatch between pi-chrome and the loaded Chrome extension).
120
+
121
+ If the Chrome extension you have loaded is older than `pi-chrome` on disk, `/chrome-doctor` will tell you to reload it from `chrome://extensions`.
122
+
123
+ ## Compose with
124
+
125
+ - **pi-qq** — ask side questions about what the agent saw in Chrome without polluting the main transcript: `/qq summarize what the active GitHub tab shows`.
126
+ - **PR demo skills** (such as `ios-pr-agent` / `ios-demo-record` workflows) — `chrome_screenshot` writes to `.pi/chrome-screenshots/` so you can attach images to PR descriptions or demo bundles.
127
+
74
128
  ## Tools
75
129
 
76
130
  The package registers these Pi tools:
@@ -88,7 +142,8 @@ The package registers these Pi tools:
88
142
 
89
143
  These tools are especially useful for authenticated web app debugging, repro flows, admin workflows, visual checks, and inspecting local development pages without rebuilding login state.
90
144
 
91
- ## How it works
145
+ <details>
146
+ <summary><strong>How it works (technical details)</strong></summary>
92
147
 
93
148
  Pi starts a local bridge on `127.0.0.1:17318`. The companion Chrome extension, installed in your normal Chrome profile, polls that local bridge for commands and executes them using Chrome extension APIs.
94
149
 
@@ -96,6 +151,8 @@ If another Pi session is already running the bridge, additional Pi sessions auto
96
151
 
97
152
  This is intentionally different from CDP-based tools: the browser extension lives inside the profile you already use, so Pi can interact with existing tabs and authenticated page state.
98
153
 
154
+ </details>
155
+
99
156
  ## Security model
100
157
 
101
158
  The companion Chrome extension runs in the Chrome profile where you install it and has broad tab/scripting permissions. Only install it from a package source you trust.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Pi Existing Chrome Profile Bridge",
4
- "version": "0.1.0",
4
+ "version": "0.4.0",
5
5
  "description": "Lets Pi control tabs in this existing Chrome profile via a local bridge at 127.0.0.1.",
6
6
  "permissions": ["tabs", "scripting", "storage", "activeTab", "alarms"],
7
7
  "host_permissions": ["<all_urls>", "http://127.0.0.1:17318/*"],
@@ -80,7 +80,12 @@ function sleep(ms) {
80
80
  async function dispatch(action, params) {
81
81
  switch (action) {
82
82
  case "tab.version":
83
- return { extensionId: chrome.runtime.id, bridgeUrl: BRIDGE_URL, userAgent: navigator.userAgent };
83
+ return {
84
+ extensionId: chrome.runtime.id,
85
+ extensionVersion: chrome.runtime.getManifest().version,
86
+ bridgeUrl: BRIDGE_URL,
87
+ userAgent: navigator.userAgent,
88
+ };
84
89
  case "tab.list":
85
90
  return (await chrome.tabs.query({})).map(formatTab);
86
91
  case "tab.new": {
@@ -46,6 +46,7 @@ type BridgeResult = {
46
46
  error?: string;
47
47
  };
48
48
 
49
+ const PI_CHROME_VERSION = "0.4.0";
49
50
  const DEFAULT_HOST = process.env.PI_CHROME_BRIDGE_HOST ?? "127.0.0.1";
50
51
  const DEFAULT_PORT = Number(process.env.PI_CHROME_BRIDGE_PORT ?? "17318");
51
52
  const DEFAULT_TIMEOUT_MS = 30_000;
@@ -351,19 +352,50 @@ If chrome_* tools time out, ask the user to run /chrome-onboard, then load the b
351
352
  handler: async (_args, ctx) => {
352
353
  ctx.ui.notify("Performing Chrome bridge health check", "info");
353
354
  try {
354
- const version = (await bridge.send("tab.version", {}, 35_000)) as { extensionId?: string };
355
- ctx.ui.notify(
356
- version.extensionId
357
- ? `Chrome profile bridge connected (ID: ${version.extensionId})`
358
- : "Chrome profile bridge connected",
359
- "info",
360
- );
355
+ const version = (await bridge.send("tab.version", {}, 35_000)) as { extensionId?: string; extensionVersion?: string };
356
+ const suffix = [version.extensionId ? `ID: ${version.extensionId}` : null, version.extensionVersion ? `ext v${version.extensionVersion}` : null]
357
+ .filter(Boolean)
358
+ .join(", ");
359
+ ctx.ui.notify(suffix ? `Chrome profile bridge connected (${suffix})` : "Chrome profile bridge connected", "info");
361
360
  } catch (error) {
362
361
  ctx.ui.notify(`Chrome bridge health check failed: ${(error as Error).message}`, "warning");
363
362
  }
364
363
  },
365
364
  });
366
365
 
366
+ pi.registerCommand("chrome-doctor", {
367
+ description:
368
+ "Diagnose Chrome bridge setup. Checks the local bridge, the companion Chrome extension, and reports a one-line fix for common failures.",
369
+ handler: async (_args, ctx) => {
370
+ const lines: string[] = [`pi-chrome v${PI_CHROME_VERSION}`];
371
+ const status = bridge.status();
372
+ lines.push(`• Local bridge: mode=${status.mode}, url=${status.url}`);
373
+ try {
374
+ const version = (await bridge.send("tab.version", {}, 8_000)) as {
375
+ extensionId?: string;
376
+ extensionVersion?: string;
377
+ };
378
+ if (version.extensionId)
379
+ lines.push(`✓ Companion Chrome extension responding (ID: ${version.extensionId}, ext v${version.extensionVersion ?? "unknown"})`);
380
+ else lines.push("✓ Companion Chrome extension responding (no extension ID reported)");
381
+ if (version.extensionVersion && version.extensionVersion !== PI_CHROME_VERSION) {
382
+ lines.push(
383
+ `⚠ Extension version (${version.extensionVersion}) differs from pi-chrome (${PI_CHROME_VERSION}). Reload "Pi Existing Chrome Profile Bridge" in chrome://extensions to pick up the latest service worker.`,
384
+ );
385
+ }
386
+ } catch (error) {
387
+ const message = (error as Error).message;
388
+ lines.push(`✗ Companion Chrome extension not responding: ${message}`);
389
+ if (message.includes("older pi-chrome without multi-session")) {
390
+ lines.push(" Fix: restart the Pi session that owns the bridge (it was started on an older pi-chrome).");
391
+ } else {
392
+ lines.push(" Fix: run /chrome-onboard, then load the bundled browser-extension folder in chrome://extensions and keep that Chrome window open.");
393
+ }
394
+ }
395
+ ctx.ui.notify(lines.join("\n"), "info");
396
+ },
397
+ });
398
+
367
399
  pi.registerCommand("chrome-foreground", {
368
400
  description:
369
401
  "Toggle whether chrome_* tools bring Chrome to the foreground. Foreground ON: you can watch the agent work in your browser, useful for demos, pair-driving, and debugging — tradeoff: Chrome pops up and steals focus, interrupting whatever app you were using. Foreground OFF (default): chrome_* tools act silently in the background, so your editor/terminal keeps focus and your workflow is not interrupted. Pass `on` / `off` to set explicitly, or no argument to toggle.",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-chrome",
3
- "version": "0.3.1",
4
- "description": "Control your existing authenticated Chrome profile from one or more Pi sessions with tabs, snapshots, clicks, typing, JS evaluation, waits, and screenshots. Background-by-default so Chrome stops popping up when agents act.",
3
+ "version": "0.4.0",
4
+ "description": "Control your existing authenticated Chrome profile from Pi with tabs, snapshots, clicks, typing, JS evaluation, waits, and screenshots \u2014 background by default.",
5
5
  "keywords": [
6
6
  "pi-package",
7
7
  "pi-extension",