Browser backends are not propagated consistently across Desktop, CLI, and collaboration subagents

Open 💬 4 comments Opened Jul 13, 2026 by FranciscoJSBarragan
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using?

Codex Desktop / bundled Browser plugin: 26.707.51957
Codex CLI: 0.144.1

What subscription do you have?

Not included in this diagnostic.

What platform is your computer?

Darwin 25.5.0 arm64 arm

What issue are you seeing?

Browser backend availability is inconsistent across Codex Desktop, Codex CLI, and collaboration subagents.

In the same fresh Desktop session, the root agent can acquire and use the Codex in-app Browser, but a spawned collaboration subagent cannot acquire the same backend. In a standalone interactive CLI session, neither the root agent nor a spawned subagent receives any Browser backend. The Chrome skill is also mounted in the CLI, but the Chrome extension backend is absent.

Observed matrix:

| Surface | Context | Result |
| --- | --- | --- |
| Desktop | root agent | agent.browsers.get("iab") succeeds |
| Desktop | collaboration subagent | Browser is not available: iab |
| CLI | root agent | Browser is not available: iab; list() => [] |
| CLI | collaboration subagent | Browser is not available: iab; list() => [] |
| CLI | root agent, Chrome client | Browser is not available: extension; list() => [] |

The Desktop root-agent control was verified by navigating a newly created controlled tab to https://example.com/:

  • URL: https://example.com/
  • title: Example Domain
  • visible exact heading: Example Domain
  • only the test tab was closed afterward

The Desktop collaboration subagent loaded the same bundled Browser skill and initialized the client from the documented absolute plugin path, but await agent.browsers.get("iab") failed. This suggests the healthy Desktop IAB registration/session route is not propagated or rebound to child threads.

The standalone CLI tests were run in real interactive TUI sessions, not with ephemeral codex exec. Both the CLI root and child had the Browser skill and the JS runtime available, but no backend registered. A separate CLI root test initialized the bundled Chrome client and explicitly called get("extension"); it also returned an empty backend list.

What steps can reproduce the bug?

A. Desktop root versus collaboration subagent
  1. Start a fresh Codex Desktop task with the Browser plugin available.
  2. Read the bundled browser:control-in-app-browser skill and initialize its scripts/browser-client.mjs using the documented absolute path.
  3. In the root agent, run:
const rootIab = await agent.browsers.get("iab");
  1. Confirm the root agent succeeds. Create a controlled tab and navigate to https://example.com/.
  2. Spawn a collaboration subagent.
  3. In the child, initialize the same bundled client and run exactly:
await agent.browsers.get("iab");
  1. Read bootstrap-troubleshooting, then run await agent.browsers.list() once.

Actual child result:

Browser is not available: iab

The child does not receive the working parent IAB backend.

B. Standalone CLI root
  1. Launch the current CLI as an interactive TUI:
codex -a never -s read-only --no-alt-screen
  1. In the CLI root agent, load the bundled Browser skill/client.
  2. Run exactly:
await agent.browsers.get("iab")
  1. Follow documented bootstrap troubleshooting and list once.

Actual:

Browser is not available: iab
agent.browsers.list() => []
C. Standalone CLI Chrome backend
  1. In a new interactive CLI root session, load chrome:control-chrome.
  2. Initialize the Chrome plugin's bundled scripts/browser-client.mjs.
  3. Run exactly:
await agent.browsers.get("extension")
  1. Read both documented troubleshooting topics and list once.

Actual:

Browser is not available: extension
agent.browsers.list() => []

No fallback browser was used, and no files or configuration were modified.

What is the expected behavior?

  • A Desktop collaboration subagent assigned browser acceptance work should either inherit/attach to the parent task's healthy IAB backend, or receive a dedicated authorized IAB backend.
  • If standalone CLI intentionally cannot attach to Desktop IAB, the IAB skill should not be mounted as usable; it should fail immediately with an explicit surface-availability message.
  • If Chrome control is supported from CLI, a connected Chrome extension backend should register for the CLI root and its subagents. If it is not supported, the Chrome skill should not be advertised as usable there.
  • Root and child availability should be deterministic and documented.

Additional information

Related reports:

  • #20678 covers IAB/Node runtime connection and session ownership failures. A comment there describes a similar subagent session-binding mismatch.
  • #25647 covers the Browser skill being mounted in CLI when no IAB backend exists.
  • #26470 covers empty browser backend registration more generally.

This report adds a controlled four-context comparison on the same machine and current builds, plus a separate explicit Chrome-client test. It distinguishes the Desktop child-route failure from the standalone CLI's complete absence of registered backends.

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #31980

Powered by Codex Action

FranciscoJSBarragan · 1 month ago

I reviewed the suggested duplicate #31980 and its canonical issue #30545.

They overlap with only one control result in this report: standalone npm Codex 0.144.1 cannot discover the connected Chrome extension backend and returns Browser is not available: extension with agent.browsers.list() => [].

The primary reproduction here is different:

  • In the same Codex Desktop task, the root agent successfully acquires iab and navigates https://example.com/.
  • A collaboration subagent spawned from that working task loads the same Browser skill/client but fails with Browser is not available: iab.
  • The healthy parent IAB backend/session route is therefore not propagated or rebound to the child thread.

#31980/#30545 do not cover collaboration subagents or the Desktop root-versus-child IAB availability mismatch. The CLI Chrome result is included only as a comparison/control and should be tracked under #30545. The standalone CLI IAB-skill-without-backend behavior is already related to #25647.

I am keeping this issue open for the Desktop collaboration-subagent IAB propagation failure. If maintainers prefer, the title/body can be narrowed to that specific regression while retaining the CLI results only as diagnostic context.

rufusclaw1234 · 1 month ago

Additional deterministic macOS CLI → Desktop handoff evidence

I reproduced this on 2026-07-16 with:

  • macOS 26.5.2 (25F84), arm64
  • ChatGPT/Codex app 26.707.91948 (build 5440)
  • Codex CLI 0.144.5
  • bundled Browser plugin 26.707.91948

This narrows the standalone interactive CLI failure: the Desktop handoff reaches the correct visible thread and ChatGPT publishes a live Browser socket, but the supported Browser client still finds no IAB backend matching the CLI session.

Reproduction

  1. Start a brand-new interactive Codex CLI session.
  2. Confirm that nodeRepl.requestMeta["x-codex-turn-metadata"].session_id, thread_id, and the rollout session_meta.session_id are the same UUID.
  3. After the session is fully initialized, run:

``sh
/usr/bin/open -a /Applications/ChatGPT.app \
'codex://threads/<the-current-cli-session-id>'
``

  1. ChatGPT visibly switches to the exact CLI thread (the transcript matches).
  2. At the handoff, a new /tmp/codex-browser-use/*.sock appears and is owned by the live ChatGPT process.
  3. Initialize the bundled Browser client through the documented mcp__node_repl__js path and run:

``js
await agent.browsers.get("iab")
``

Actual:

``text
Browser is not available: iab
``

  1. Follow bootstrap-troubleshooting and run the supported fresh scan:

``js
await agent.browsers.list()
``

Actual:

``js
[]
``

  1. Repeat the app-targeted deep link after the CLI session has been active for several minutes. ChatGPT still opens the correct thread, but the fresh backend scan remains [].

Diagnostic significance

This rules out stale Launch Services routing and a one-shot empty-client cache as explanations for this reproduction. The app handoff works and a live socket exists, but all IAB candidates are removed before the Browser surface is exposed to the CLI.

The current bundled client filters IAB candidates by comparing the backend's metadata.codexSessionId with the current Codex session identity. The observed behavior is therefore consistent with the Desktop socket being published under a different session/route identity even though the UI opens the correct persisted thread. This appears to be the same session-ownership failure class discussed in #20678, now demonstrated specifically across an exact interactive CLI → Desktop deep-link handoff.

Expected: opening the exact persisted CLI thread in Desktop should publish or rebind an IAB backend whose session identity matches that CLI thread, allowing get("iab") and list() to succeed.

I did not bypass the trusted Browser client boundary or attempt raw socket control.

sh58702e · 8 days ago

Deterministic root vs subagent IAB session-scoping evidence — Desktop 26.814.41407

I reproduced the collaboration-subagent case on macOS with ChatGPT/Codex Desktop and the bundled Browser plugin both at 26.814.41407.

Observed metadata relationship:

  • The root turn owns a working iab; agent.browsers.list() returns one IAB registered to the root Codex session.
  • A spawned collaboration subagent has a distinct child thread_id.
  • Its trusted turn metadata still carries the same root session_id, identifies the root as parent_thread_id, and marks thread_source as subagent.
  • In that child, the documented fresh Browser setup returns agent.browsers.list() => [], and get("iab") fails with Browser is not available: iab.

The bundled browser-service behavior explains the deterministic mismatch: for a subagent it derives the IAB discovery/session key from the child thread_id, then filters IAB candidates by exact equality with each backend's metadata.codexSessionId. The available IAB is registered to the shared root session, so it is removed before claimTab() can be used. Fresh setup does not change the result.

This is not a plugin-version, enabled-backend, or stale-client mismatch. I did not patch config, trusted services, bundled files, or raw browser sockets.

A security-preserving fix would separate:

  • browser ownership: trusted root session_id;
  • caller attribution: child thread_id and turn_id.

An authorized child belonging to the same trusted root session should discover that root session's IAB, while unrelated sessions, missing metadata, and malformed metadata continue to fail closed.

Suggested regression matrix:

  1. Root metadata + matching root IAB → visible.
  2. Child metadata + same root session_id + distinct child thread_id → same IAB visible.
  3. Unrelated root session_id → IAB absent.
  4. Missing or malformed trusted metadata → fail closed.
  5. Explicit IAB request → never fall back to Chrome.
  6. Child command → root browser ownership retained, child thread/turn attribution retained.
  7. claimTab() and later-turn handoff continue to work only inside the owning root session.

As a local workflow mitigation, I am separating root-only Browser evidence capture from subagent implementation, with a frozen manifest/SHA handoff and no concurrent writers. That mitigates blocked work but does not fix child IAB discovery.