macOS 26.601: Chrome plugin cannot bootstrap because node_repl/js is not exposed despite extension-host and node_repl processes running

Open 💬 2 comments Opened Jun 4, 2026 by constansino

What version of the Codex App are you using?

26.601.21317 (3511)

What platform is your computer?

macOS arm64

Related write-up

Detailed investigation notes, including command outputs and Chinese write-up:
https://aiya.de5.net/t/topic/213/1

What issue are you seeing?

The Chrome plugin cannot be used because the required node_repl/js tool is not exposed to the current model session, even though the local Chrome extension, native host, extension-host, browser-client.mjs, node_repl binary, and multiple node_repl processes all appear healthy.

This looks narrower than the usual "Chrome extension/native host not installed" case: on this machine the bridge processes are actually running, but the MCP tool is still missing from the tool manifest visible to the model.

Why this is different from nearby reports

I saw related issues such as #21618, #20579, and #25361. This reproduction differs in one important way:

  • extension-host is running.
  • Multiple node_repl processes have been started by the Codex app-server.
  • The native host manifest is correct.
  • The Codex Chrome Extension is installed and enabled.
  • browser-client.mjs exists.
  • But node_repl/js / mcp__node_repl__js is still not exposed to the session, so the Chrome skill cannot bootstrap agent.browsers.get("extension").

Observed behavior

The user explicitly invoked the Chrome plugin with [@chrome](plugin://chrome@openai-bundled) and had an already logged-in Chrome tab open. The Chrome skill instructions require bootstrapping browser control through the Node REPL js tool, typically mcp__node_repl__js.

However, the current turn's available tools did not include:

node_repl/js
mcp__node_repl__js
js
js_reset

Because of that, the assistant could not control Chrome and had to stop.

Static checks that pass

Chrome is running:

{
  "platform": "darwin",
  "running": true,
  "processes": [
    { "process_name": "Google Chrome" }
  ]
}

Codex Chrome Extension is installed and enabled:

{
  "extensionId": "hehggadaopoacecdllhhajmbjkdcmajg",
  "selectedProfileDirectory": "Default",
  "installed": true,
  "enabled": true,
  "profiles": [
    {
      "profileDirectory": "Default",
      "installed": true,
      "registered": true,
      "enabled": true,
      "selected": true,
      "versions": ["1.1.5_0"]
    }
  ]
}

Native Messaging Host manifest is correct:

{
  "manifestPath": "/Users/m/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.openai.codexextension.json",
  "expectedHostName": "com.openai.codexextension",
  "actualHostName": "com.openai.codexextension",
  "expectedExtensionId": "hehggadaopoacecdllhhajmbjkdcmajg",
  "allowedOrigins": [
    "chrome-extension://hehggadaopoacecdllhhajmbjkdcmajg/"
  ],
  "exists": true,
  "nameMatches": true,
  "hasExpectedOrigin": true,
  "correct": true,
  "problem": null
}

browser-client.mjs exists:

/Users/m/.codex/plugins/cache/openai-bundled/chrome/26.601.21317/scripts/browser-client.mjs

node_repl exists and is executable:

/Applications/Codex.app/Contents/Resources/node_repl: Mach-O 64-bit executable arm64
-rwxr-xr-x ... /Applications/Codex.app/Contents/Resources/node_repl

The config has a node_repl MCP server:

[mcp_servers.node_repl]
args = []
command = "/Applications/Codex.app/Contents/Resources/node_repl"
startup_timeout_sec = 120

[mcp_servers.node_repl.env]
NODE_REPL_NATIVE_PIPE_CONNECT_TIMEOUT_MS = "1000"
NODE_REPL_NODE_PATH = "/Applications/Codex.app/Contents/Resources/node"
NODE_REPL_TRUSTED_CODE_PATHS = "/Users/m/.codex"
BROWSER_USE_AVAILABLE_BACKENDS = "chrome,iab"
NODE_REPL_INSTRUCTIONS_USE_CASE_CHROME = "Control the Chrome browser in conjunction with the Chrome Plugin. Prefer this method of controlling Chrome over alternatives (such as Computer Use) unless the user explicitly mentions an alternative."

Runtime process evidence

extension-host is running:

/Users/m/.codex/plugins/cache/openai-bundled/chrome/latest/extension-host/macos/arm64/extension-host chrome-extension://hehggadaopoacecdllhhajmbjkdcmajg/

Multiple node_repl processes are also running, apparently launched by the Codex app-server:

/Applications/Codex.app/Contents/Resources/node_repl
/Applications/Codex.app/Contents/Resources/codex app-server --listen stdio://
/Applications/Codex.app/Contents/Resources/node_repl
/Applications/Codex.app/Contents/Resources/codex app-server --listen stdio://
...

Parent/child shape observed:

Codex app-server --analytics-default-enabled
  ├─ node_repl
  │   └─ codex app-server --listen stdio://
  ├─ node_repl
  │   └─ codex app-server --listen stdio://
  └─ ...

Expected behavior

When the Chrome plugin is explicitly invoked and the Chrome skill is loaded, Codex should expose the required JavaScript execution tool from the node_repl MCP server to the same model session, e.g.:

node_repl/js
mcp__node_repl__js

The Chrome skill should then be able to run:

const { setupBrowserRuntime } = await import("<plugin root>/scripts/browser-client.mjs");
await setupBrowserRuntime({ globals: globalThis });
globalThis.browser = await agent.browsers.get("extension");

Actual behavior

The Chrome plugin is visible/invokable, and all local bridge components appear installed or running, but the required node_repl/js tool is absent from the session's callable tool list. The skill cannot bootstrap browser control.

Suspected area

This looks like an app/app-server tool injection or session tool declaration bug:

  • app-server starts node_repl, but its tools are not included in the current model request/tool manifest.
  • Chrome skill loading does not guarantee that the node_repl MCP server's js tool is exposed in that thread.
  • Projectless threads and workspace threads may be using different tool injection paths.
  • The transition from the earlier 26.527 plugin/app version to 26.601 may have updated hashes/envs but still fails to guarantee tool exposure.

Impact

Any workflow that depends on logged-in Chrome automation breaks. The UI can show/trigger @chrome, and Chrome can be logged in and ready, but the model has no callable browser-control path.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗