Skip to content

macOS: automation Chrome shares bundle id with daily Chrome; CHROME_WS_BROWSER not honored in MCP path #40

Description

@YoungYo

Summary

On macOS, chrome-process.js (the code path used by the MCP use_browser tool) always launches the literal /Applications/Google Chrome.app binary — the same bundle the user's everyday browser uses. When automation Chrome instances pile up (see below), macOS's per-bundle "app is running" tracking gets hijacked: clicking the Dock icon / Spotlight-launching "Google Chrome" just activates one of the tool's headless/windowless automation instances instead of opening a real window. To the user this looks exactly like "my browser won't start."

Root cause, in two parts

1. CHROME_WS_BROWSER is documented but not honored in the MCP path.

README.md / COMMANDLINE-USAGE.md document CHROME_WS_BROWSER as overriding auto-detection, and the standalone chrome-ws CLI does read it (chrome-ws:316):

const chromePath = process.env.CHROME_WS_BROWSER || paths.find(p => existsSync(p));

But skills/browsing/lib/chrome-process.js — which is what mcp/dist/index.js actually requires at runtime (require(join(__dirname, "../../skills/browsing/chrome-ws-lib.js"))chrome-process.js) — never reads it at all. The env var silently does nothing for anyone using the MCP tool (as opposed to the CLI).

2. No way to point automation at a separate Chrome bundle, so it collides with the daily browser.

Because the hardcoded darwin path list only ever contains the main Google Chrome.app, every automation instance (any of superpowers-chrome, -2, -3, ... profiles) shares bundle id com.google.Chrome with the user's regular browser. Combined with instances that never get cleaned up across crashed/closed Claude Code sessions (I found 6 live automation Chrome processes across 4 different profile dirs, one running since 3 days prior, plus 4 separate MCP server node processes going back a week — all still holding old in-memory code via require() caching), the result is that macOS Launch Services considers "Google Chrome" perpetually running, and normal launch attempts just re-activate a headless/invisible instance.

Suggested fix

Minimal patch to skills/browsing/lib/chrome-process.js — honor CHROME_WS_BROWSER (bringing it in line with the CLI and the docs), and prefer a dedicated automation-only Chrome build when present so day-to-day Chrome is never touched by default:

     // --- Step 3: Find Chrome binary ---
     const chromePaths = {
       darwin: [
+        `${os.homedir()}/Library/Caches/superpowers/chrome-for-testing/current`,
         '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
         '/Applications/Chromium.app/Contents/MacOS/Chromium'
       ],
       ...
     };

     const platform = os.platform();
     const paths = chromePaths[platform] || [];

-    let chromePath = null;
-    for (const path of paths) {
-      if (existsSync(path)) {
-        chromePath = path;
-        break;
-      }
+    let chromePath = process.env.CHROME_WS_BROWSER;
+    if (chromePath && !existsSync(chromePath)) chromePath = null;
+    if (!chromePath) {
+      for (const path of paths) {
+        if (existsSync(path)) {
+          chromePath = path;
+          break;
+        }
+      }
     }

(chrome-for-testing/current being a symlink the user/installer points at a @puppeteer/browsers-installed "Google Chrome for Testing.app", which has its own distinct bundle id and therefore never collides with the daily browser's running-app state.)

I've verified this resolution logic in isolation — it correctly prefers the dedicated build when present and falls back to the shared Google Chrome.app otherwise, with no behavior change for anyone who hasn't installed a separate build.

Secondary issue: process leakage across sessions

Separately (and probably deserving its own issue if useful): I found MCP server node processes and their spawned Chrome instances still alive from sessions started 3-7 days earlier, all under different auto-incremented profile names (superpowers-chrome, -2, -3, -4...). Nothing appears to reap these when a Claude Code session ends unexpectedly (vs. a clean chrome-ws kill/shutdown). Over time this silently accumulates background Chrome processes and — per the above — increasingly masks the user's real browser. Happy to file separately if that's preferred.

Environment

  • superpowers-chrome 3.0.2 (same code present on main as of this writing)
  • macOS, Apple Silicon

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions