claude-browser-bridge 4.0.0 → 4.0.2

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/bin/cli.js CHANGED
@@ -44,14 +44,25 @@ Docs: https://github.com/HimanshuKanwar2001/claude-browser-bridge
44
44
  `);
45
45
  }
46
46
 
47
- function init() {
47
+ async function init() {
48
48
  const extPath = args[args.indexOf("init") + 1] || null;
49
- const tokenPath = join(SERVER_DIR, ".bridge-token");
50
49
  const token = randomBytes(24).toString("hex");
51
-
52
- // Write server token
53
- writeFileSync(tokenPath, token + "\n");
54
- console.log(`✓ Token written to ${tokenPath}`);
50
+ const os = await import("node:os");
51
+ const home = os.homedir();
52
+
53
+ // Write to canonical path: ~/.claude/browser-bridge-token
54
+ const claudeDir = join(home, ".claude");
55
+ if (!existsSync(claudeDir)) mkdirSync(claudeDir, { recursive: true });
56
+ const canonicalPath = join(home, ".claude", "browser-bridge-token");
57
+ writeFileSync(canonicalPath, token + "\n");
58
+ console.log(`✓ Token written to ${canonicalPath}`);
59
+
60
+ // Also write to server/.bridge-token (legacy fallback)
61
+ try {
62
+ const legacyPath = join(SERVER_DIR, ".bridge-token");
63
+ writeFileSync(legacyPath, token + "\n");
64
+ console.log(`✓ Token written to ${legacyPath}`);
65
+ } catch {}
55
66
 
56
67
  // Write extension config if we can find the extension directory
57
68
  const searchPaths = [
package/gen-token.js CHANGED
@@ -1,13 +1,51 @@
1
- // Generates the shared secret used to authenticate the extension to the
2
- // bridge: writes server/.bridge-token and extension/config.js.
1
+ // Generates the shared secret used to authenticate the extension to the bridge.
2
+ // Writes to THREE locations so the token works regardless of install method:
3
+ // 1. ~/.claude/browser-bridge-token (canonical — works with global npm install)
4
+ // 2. server/.bridge-token (legacy — works with cloned repo)
5
+ // 3. extension/config.js (embedded in the Chrome extension)
6
+
3
7
  import { randomBytes } from "node:crypto";
4
- import { writeFileSync } from "node:fs";
8
+ import { writeFileSync, mkdirSync, existsSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { homedir } from "node:os";
11
+ import { fileURLToPath } from "node:url";
5
12
 
6
13
  const token = randomBytes(24).toString("hex");
7
- writeFileSync(new URL("./.bridge-token", import.meta.url), token + "\n");
8
- writeFileSync(
9
- new URL("../extension/config.js", import.meta.url),
10
- `// Generated by server/gen-token.js keep out of version control.\nconst BRIDGE_TOKEN = ${JSON.stringify(token)};\n`
11
- );
12
- console.log("Wrote server/.bridge-token and extension/config.js");
13
- console.log("Reload the extension in chrome://extensions to pick up the new token.");
14
+
15
+ // 1. Write to ~/.claude/browser-bridge-token (canonical path)
16
+ const claudeDir = join(homedir(), ".claude");
17
+ if (!existsSync(claudeDir)) mkdirSync(claudeDir, { recursive: true });
18
+ const canonicalPath = join(claudeDir, "browser-bridge-token");
19
+ writeFileSync(canonicalPath, token + "\n");
20
+ console.log(`✓ Token written to ${canonicalPath}`);
21
+
22
+ // 2. Write to server/.bridge-token (legacy, for local repo use)
23
+ try {
24
+ writeFileSync(new URL("./.bridge-token", import.meta.url), token + "\n");
25
+ console.log("✓ Token written to server/.bridge-token");
26
+ } catch {
27
+ // May fail if running from global install (read-only node_modules)
28
+ }
29
+
30
+ // 3. Write extension/config.js (search multiple locations)
31
+ const searchPaths = [
32
+ new URL("../extension/config.js", import.meta.url).pathname,
33
+ join(process.cwd(), "extension", "config.js"),
34
+ ];
35
+ let extensionWritten = false;
36
+ for (const p of searchPaths) {
37
+ try {
38
+ if (existsSync(join(p, "..", "manifest.json"))) {
39
+ writeFileSync(p, `// Generated by gen-token.js — keep out of version control.\nconst BRIDGE_TOKEN = ${JSON.stringify(token)};\n`);
40
+ console.log(`✓ Extension config written to ${p}`);
41
+ extensionWritten = true;
42
+ break;
43
+ }
44
+ } catch {}
45
+ }
46
+ if (!extensionWritten) {
47
+ console.log(`⚠ Extension directory not found — create extension/config.js manually:`);
48
+ console.log(` const BRIDGE_TOKEN = "${token}";`);
49
+ }
50
+
51
+ console.log("\n✓ Token generated. Reload the extension in chrome://extensions to apply.");
package/index.js CHANGED
@@ -6,7 +6,9 @@
6
6
  // "owns" the bridge; later sessions detect EADDRINUSE and relay their tool
7
7
  // calls through the owner. If the owner exits, a relay takes over the port.
8
8
 
9
- import { readFileSync } from "node:fs";
9
+ import { readFileSync, existsSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { homedir } from "node:os";
10
12
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
11
13
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
14
  import {
@@ -17,20 +19,32 @@ import WebSocket, { WebSocketServer } from "ws";
17
19
 
18
20
  const PORT = Number(process.env.BRIDGE_PORT) || 8787;
19
21
 
20
- // F2 FIX: Re-read token on every auth attempt so `init` token regeneration
21
- // takes effect without restarting the server.
22
- const TOKEN_PATH = new URL("./.bridge-token", import.meta.url);
22
+ // Token resolution: check multiple locations so it works whether the server
23
+ // runs from a global npm install, npx, or the cloned repo.
24
+ const TOKEN_LOCATIONS = [
25
+ process.env.BRIDGE_TOKEN_PATH, // explicit override
26
+ join(homedir(), ".claude", "browser-bridge-token"), // canonical home path
27
+ new URL("./.bridge-token", import.meta.url).pathname, // relative to server file (repo install)
28
+ join(process.cwd(), "server", ".bridge-token"), // cwd/server/ (cloned repo)
29
+ join(process.cwd(), ".bridge-token"), // cwd root
30
+ ].filter(Boolean);
31
+
23
32
  function readToken() {
24
- try {
25
- return readFileSync(TOKEN_PATH, "utf8").trim();
26
- } catch {
27
- return null;
33
+ // Also check env var directly
34
+ if (process.env.BRIDGE_TOKEN) return process.env.BRIDGE_TOKEN;
35
+ for (const p of TOKEN_LOCATIONS) {
36
+ try {
37
+ const t = readFileSync(p, "utf8").trim();
38
+ if (t) return t;
39
+ } catch {}
28
40
  }
41
+ return null;
29
42
  }
30
43
  if (!readToken()) {
31
44
  console.error(
32
- "[bridge] WARNING: server/.bridge-token is missing run `claude-browser-bridge init` " +
33
- "or `node gen-token.js`. Refusing all extension connections until then."
45
+ "[bridge] WARNING: auth token not found. Run `claude-browser-bridge init` " +
46
+ "or `node gen-token.js`. Searched:\n" +
47
+ TOKEN_LOCATIONS.map(p => " - " + p).join("\n")
34
48
  );
35
49
  }
36
50
 
@@ -220,15 +234,17 @@ establish();
220
234
  const HELP_TOOL = {
221
235
  name: "browser_bridge_help",
222
236
  description:
223
- "Returns the complete usage guide for all 57 browser-bridge tools. Call this ONCE at the start of any session where you need to use browser tools, to learn the optimal workflows and avoid slow anti-patterns.",
237
+ "Returns the complete usage guide for all 65 browser-bridge tools. Call this ONCE at the start of any session where you need to use browser tools, to learn the optimal workflows and avoid slow anti-patterns.",
224
238
  inputSchema: { type: "object", properties: {} },
225
239
  };
226
240
 
227
- const HELP_TEXT = `# Claude Browser Bridge — 58 Tools
241
+ const HELP_TEXT = `# Claude Browser Bridge — 65 Tools
228
242
 
229
243
  ## WHICH TOOL FIRST? (decision tree)
230
244
  - Investigating a bug → diagnose (gives snapshot + errors + network + API responses in ONE call)
231
245
  - Fixing CSS/visual → batch([screenshot, get_styles({selector:".target"}), get_html({selector:".target"})])
246
+ - Debugging image layers/z-index → batch([get_element_rect({selector:".container", include_children:true}), annotate({annotations:[...]})])
247
+ - Checking pixel colors on images → inspect_pixel({selector:"img", x:50, y:50, percent:true})
232
248
  - Performance check → batch([performance_trace, get_load_timeline, heap_snapshot_summary])
233
249
  - Accessibility audit → batch([get_accessibility_tree, check_contrast({selector:".text"})])
234
250
  - Reading page content → eval (specific data) or get_page_text (all text)
@@ -274,7 +290,19 @@ Regression Testing:
274
290
  Before/After Comparison:
275
291
  screenshot (save dataUrl) → make changes → visual_diff({before_dataUrl:"..."})
276
292
 
277
- ## ALL 58 TOOLS BY CATEGORY:
293
+ Image/Layer Debugging:
294
+ annotate({annotations:[{selector:".base",label:"Base",color:"red"},{selector:".overlay",label:"Overlay",color:"blue"}]}) → screenshot → clear_annotations
295
+ inspect_pixel({selector:".garment-img", x:50, y:30, percent:true}) → check if transparent or opaque
296
+ get_element_rect({selector:".container", include_children:true}) → see all child positions + z-indexes
297
+ capture_canvas({selector:".composer"}) → flatten all stacked images into one PNG
298
+
299
+ Cross-Product Comparison:
300
+ new_tab({url:"product-A"}) → new_tab({url:"product-B"}) → compare_tabs({tab_id_1:A, tab_id_2:B})
301
+
302
+ State Management Testing:
303
+ set_storage({key:"cache", action:"remove"}) → reload → verify fresh state
304
+
305
+ ## ALL 65 TOOLS BY CATEGORY:
278
306
  Core: diagnose, batch, select_tab, snapshot, eval, screenshot, full_page_screenshot, get_page_text, get_html, get_page_info, browser_bridge_help
279
307
  Interaction: click, fill, hover, scroll, press_key, select_option, upload_file, highlight_element
280
308
  Navigation: navigate, new_tab, close_tab, go_back, go_forward, reload, list_tabs, wait_for
@@ -284,6 +312,8 @@ Accessibility: get_accessibility_tree, check_contrast
284
312
  Emulation: emulate_device, network_throttle, set_geolocation, toggle_dark_mode
285
313
  Testing: visual_diff, inject_css, mock_network, record_actions, replay_actions, handle_dialog
286
314
  Productivity: save_form_profile, load_form_profile, save_tab_session, restore_tab_session, edit_cookie, export_pdf
315
+ Visual Debugging: inspect_pixel, get_element_rect, compare_tabs, annotate, clear_annotations, capture_canvas
316
+ Storage: set_storage
287
317
  `;
288
318
 
289
319
  const BATCH_TOOL = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-browser-bridge",
3
- "version": "4.0.0",
4
- "description": "Connect your live Chrome tabs to Claude Code — 57 tools for debugging, performance, accessibility, device emulation, and browser automation.",
3
+ "version": "4.0.2",
4
+ "description": "Connect your live Chrome tabs to Claude Code — 65 tools for debugging, performance, accessibility, visual inspection, and browser automation.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "claude-browser-bridge": "./bin/cli.js"