[BUG]

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 0 comments · opened Jul 25, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude in Chrome never pairs: chromeExtension never written, extension and CLI both connected to the bridge but never introduced

Summary

Every mcp__claude-in-chrome__* tool call fails with the standard "Browser extension is not connected" message, on a machine where every precondition for pairing is verifiably satisfied. Pairing has never succeeded even once: onExtensionPaired has never fired, so the chromeExtension key has never been written to the CLI config, and the extension side has no stored bridgeDeviceId value either. Both endpoints are simultaneously connected to bridge.claudeusercontent.com; neither is ever told the other exists.

This is not a first-run / restart-ordering issue — a full clean-ordered reset was performed (details below) with no change.

Environment

  • Claude Code 2.1.220, installed as a global npm package under Homebrew (@anthropic-ai/claude-code)
  • Chrome extension 1.0.81 (MV3), installed from the Web Store
  • Google Chrome 150.0.7871.182
  • macOS 26.5.2, arm64
  • Corporate-MDM-managed Mac, but Chrome itself is not policy-managed (no com.google.Chrome managed preferences plist; verified)
  • Single Chrome profile (Default); no secondary profiles
  • Multi-account CLI setup: Claude Code is launched with CLAUDE_CONFIG_DIR="$HOME/.claude-<profile>" to separate two Claude accounts

Symptom

Browser extension is not connected. Please ensure the Claude browser extension is
installed and running (https://claude.ai/chrome), and that you are logged into
claude.ai with the same account as Claude Code. ...

This is the generic branch of onToolCallDisconnected, not the account-mismatch branch — i.e. the CLI does not believe there is an account mismatch.

Reporter-supplied context

  1. Multi-account configuration, running Claude Code with CLAUDE_CONFIG_DIR="$HOME/.claude-<profile>".
  2. The claude.ai account in that config is the same account that is logged into claude.ai in Chrome.
  3. The extension is installed, activated, and works perfectly well when used directly in the browser (signed in, chats normally).
  4. There is only one Chrome profile — no multi-profile setup.
  5. Claude in Chrome is enabled in the organization's Claude Team centralized settings. Despite that, policy-limits.json is regenerated on every CLI start containing allow_remote_control: {allowed: false}. Deleting the file and relaunching recreates it with the same contents. The reporter is the organization's only admin and confirms nobody changed org settings during this investigation.

What was verified as correct

| Check | Result |
|---|---|
| Extension installed | fcoeoabgfenejglbffodgkkbkcdhcgfn v1.0.81 present in the Default profile |
| Extension enabled | disable_reasons: [], from_webstore: true, withholding_permissions: false |
| Extension permissions | nativeMessaging, tabs, debugger, scripting, <all_urls> all in active_permissions |
| Extension signed in | Yes; claude.ai storage in Chrome contains the same organization UUID the CLI is authenticated against |
| Extension bridge flag | chrome_ext_bridge_enabled: true in extension local storage |
| CLI account | Correct account, org owner, no CLAUDE_CODE_OAUTH_TOKEN set in env |
| Bridge reachable | https://bridge.claudeusercontent.comHTTP 426 Upgrade Required (correct WS handshake response) |
| CLI on the bridge | Multiple ESTABLISHED TLS connections from the CLI process to the bridge host, continuously |
| Native messaging manifest | com.anthropic.claude_code_browser_extension.json present, correct path and allowed_origins |
| Native host process | Spawned by the running Chrome, alive, listening |
| Native host socket | /tmp/claude-mcp-browser-bridge-<user>/<pid>.sock, dir 0700, socket 0600, owned by the invoking uid — passes validateSocketSecurity |
| Native host accepts connections | Yes — verified with a raw AF_UNIX connect() from a separate process |
| Proxy / filtering | No proxy env vars, no Chrome enterprise policy, no interference observed |
| Duplicate claimants | Ruled out — all other CLI sessions holding --chrome were killed |
| Extension version gate | None found in the CLI binary |
| Pairing state (CLI) | chromeExtension key absent from config — onExtensionPaired has never fired |
| Pairing state (extension) | bridgeDeviceId present as a key name with no stored value |

Clean-ordered reset performed (no change)

  1. Killed every other CLI session holding --chrome, leaving a single claimant
  2. Quit Chrome gracefully; confirmed the native host process was reaped and the socket directory removed
  3. Relaunched Chrome; confirmed a fresh native host spawned and created a new valid socket
  4. Started a new CLI session with --chrome, strictly after Chrome was up

Result: identical failure. chromeExtension still absent.

Possibly relevant code observation

In the Chrome MCP transport selection:

function SDi(e){ return e.bridgeConfig ? r4n(e) : e.getSocketPaths ? LFl(e) : J3n(e) }

createChromeContext() sets bridgeConfig unconditionally. As a result the claude-code client always takes the WebSocket bridge transport, and the socket-pool transport (getSocketPaths: kys) appears to be unreachable for this client type. The local native host socket is created, is valid, and accepts connections — but the CLI never attempts to connect to it (confirmed by lsof: the CLI process has no file descriptor pointing at the socket at any point).

If that is intentional, then the bridge is the sole pairing path and the local native host socket is inert for Claude Code — which would be useful to state explicitly, because a healthy-looking native host strongly implies a working local channel to anyone debugging this. If it is not intentional, the local fallback may be the missing recovery path here.

What would help

Some way to see why the bridge declines to introduce the two peers. Currently a failed pairing is indistinguishable from a missing extension: the same generic message is emitted whether the extension is absent, unauthenticated, or present-and-authenticated-but-unmatched. A diagnostic that reports the bridge-side view — whether a peer for this account is registered, and what identity each side presented — would make this class of failure self-service instead of requiring binary inspection.

Note on allow_remote_control

Included because it looks alarming and the reporter initially suspected it. Inspection of the CLI binary indicates every allow_remote_control gate lives in the Remote Control ([bridge:repl]) code path, and the Claude in Chrome context contains no policy check at all — so it appears to be a red herring for this issue. Flagged anyway because the key is regenerated as denied on a Team org whose admin has Claude in Chrome enabled, which is at minimum confusing, and the two features share a bridge hostname.

Minor secondary observation (low confidence, possibly unrelated)

At one point a session was observed running as claude --resume <session-id> with no --chrome flag, after the reporter believed they had started it with --chrome. This may simply have been a mistyped command rather than the flag being dropped across resume, but it is worth a look: if --chrome is not preserved when resuming a session, browser tools silently vanish mid-conversation with no indication, which makes this bug considerably harder to diagnose.

What Should Happen?

It should pair, and be able to follow instructions about chrome given in claude code instead of saying that it can't connect to chrome or has no session or that kind of things.

Error Messages/Logs

❯ tell me the url opened in the only chrome tab

I'll check your Chrome tabs.

  Called claude-in-chrome

I can't read the tab — the Claude browser extension isn't connected, so I have no visibility into Chrome at all.

To fix it:
1. Install the extension at https://claude.ai/chrome (if not already installed)
2. Make sure you're logged into claude.ai in Chrome with the same account as Claude Code
3. Restart Chrome if this is a fresh install

Once that's done, let me know and I'll grab the URL.

Steps to Reproduce

  1. Install google chrome on mac
  2. start chrome
  3. login from chrome on claude.ai with your claude teams account
  4. navigate to the organization settings, make sure claude in chrome is enabled
  5. mkdir "$HOME/.claude-foo"
  6. CLAUDE_CONFIG_DIR="$HOME/.claude-foo" claude
  7. type /login and do the complete dance to authenticate, using the same account that was used to login in chrome
  8. install the claude in chrome extension, make sure it's activated
  9. exit claude code
  10. CLAUDE_CONFIG_DIR="$HOME/.claude-foo" claude --chrome
  11. (optional) type /chrome and struggle with the various options to attempt to make it connect to chrome
  12. ask claude code what url is open in the chrome browser

It fails and complains there's no chrome or no chrome session or no connection or whatever.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.220

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗