Claude in Chrome: Desktop wins native-host iteration order even when quit; Code's runtime never connects to its own bridge socket (macOS)
Environment
- macOS Darwin 24.6.0 (Apple Silicon)
- Claude Code:
2.1.126 - Chrome extension
Claude(idfcoeoabgfenejglbffodgkkbkcdhcgfn):1.0.69 - Claude Desktop:
1.5354.0(also installed on the same machine)
Summary
Two stacked bugs in the Claude-in-Chrome bridge prevent claude --chrome from ever connecting to the browser extension when Claude Desktop is also installed on the machine. Both are reproducible from a clean state.
Bug 1 — Extension's "is host alive?" check is too weak; Desktop wins iteration order even when its GUI is quit
The shared extension's service worker iterates two hardcoded native messaging hosts in this order:
[{name: "com.anthropic.claude_browser_extension", label: "Desktop"},
{name: "com.anthropic.claude_code_browser_extension", label: "Claude Code"}]
Desktop is tried first. The extension considers a host "alive" if connectNative succeeds and the host responds pong. Problem: Chrome can spawn the Desktop host binary at /Applications/Claude.app/Contents/Helpers/chrome-native-host and get a pong even when the Claude Desktop GUI is fully quit — the binary runs as a Chrome child via stdio and doesn't actually require a Desktop client on the other side. Net effect: the extension never falls through to Claude Code's host as long as Claude Desktop is installed on disk.
Repro:
- Install Claude Code and Claude Desktop on the same Mac.
- Quit Claude Desktop entirely.
- Run
claude --chromeand call anymcp__claude-in-chrome__*tool. - Observe
Browser extension is not connected. ps aux | grep chrome-native-hostshows/Applications/Claude.app/Contents/Helpers/chrome-native-hostrunning as a Chrome child — the Desktop host won.
Workaround:
mv ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_browser_extension.json{,.disabled}
Then toggle the Claude extension off/on at chrome://extensions. The next connectNative for the Desktop name fails (no manifest), and the extension falls through to Claude Code's host.
Suggested fix: the extension's liveness check should require the host to identify itself (not just answer pong), or Chrome should be told which native host to prefer when multiple match the same extension. Either change would let both products coexist on the same machine.
Bug 2 — claude --chrome runtime never connects to Code's own bridge socket
After applying the Bug 1 workaround, Claude Code's native host spawns correctly: ~/.claude/chrome/chrome-native-host execs the Code binary with --chrome-native-host, which creates a UNIX socket at /tmp/claude-mcp-browser-bridge-<user>/<PID>.sock (mode 0600, parent dir 0700). The native host process logs:
[Claude Chrome Native Host] Initializing...
[Claude Chrome Native Host] Creating socket listener: /tmp/claude-mcp-browser-bridge-<user>/<PID>.sock
[Claude Chrome Native Host] Socket server listening for connections
[Claude Chrome Native Host] Socket permissions set to 0600
But the running claude --chrome process never opens that socket. Verified:
$ lsof /tmp/claude-mcp-browser-bridge-<user>/*.sock
COMMAND PID USER FD TYPE NAME
2.1.126 49154 <user> 4u unix /tmp/claude-mcp-browser-bridge-<user>/49154.sock
Only the native host (server) holds the socket open. No claude --chrome client ever appears. MCP tool calls go straight to the onToolCallDisconnected() path and return the standard error.
Tested:
- Restarting
claude --chromeafter the socket already exists - Symlinking
/var/folders/<…>/T/claude-mcp-browser-bridge-<user>/<PID>.sock→ the/tmp/socket (in caseos.tmpdir()mismatch — bridge code references both) - Killing all orphan native hosts and re-toggling the extension to spawn a fresh one
None caused claude --chrome to connect. The bridge runtime side appears to never initiate.
Why this matters
Bug 1 alone makes most installs fail silently because Claude Desktop is widely installed alongside Claude Code. Bug 2 means even users who discover the Bug 1 workaround still can't use the Chrome MCP tools.
Diagnostic artifacts available on request
lsofoutput for the runningclaude --chromeand the native host- Strings extracted from the Code binary showing the socket-discovery path
- Extension service-worker excerpt with the host iteration array
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗