Remote-started Codex thread does not receive codex_app thread-management tools

Open 💬 8 comments Opened Jun 7, 2026 by kweiberth
💡 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 (From “About Codex” dialog)?

26.602.40724

What subscription do you have?

Pro

What platform is your computer?

Darwin 25.5.0 arm64 arm

What issue are you seeing?

When starting a Codex thread remotely from my MacBook against my Mac Studio, the agent does not get access to codex_app thread-management tools like create_thread, list_threads, read_thread, etc. A thread started directly on the Mac Studio does receive those tools.

e.g.:

Remote-started thread only received:

codex_app.read_thread_terminal

Mac Studio-started thread received:

codex_app.create_thread
codex_app.fork_thread
codex_app.handoff_thread
codex_app.list_threads
codex_app.read_thread
codex_app.send_message_to_thread
codex_app.set_thread_pinned
codex_app.set_thread_archived
codex_app.set_thread_title
plus automation_update, read_thread_terminal, and workspace dependency tools

MacBook can also manage it's own threads. Remote-started threads should receive the same app/thread-management codex_app tools as equivalent local Codex App threads, or the difference should be documented/intentional.

Checked the metadata of direct vs. remote threads, and they were identical:

originator: Codex Desktop
cli_version: 0.137.0-alpha.4
source: vscode
cwd: same
model: gpt-5.5
reasoning_effort: high
same sandbox/approval mode

So this appears to be a per-thread dynamic tool manifest difference, not a model, sandbox, cwd, repo, or app-version difference.

What steps can reproduce the bug?

Prompt w/ "Please create a new Codex app thread" in two separate threads:

  • One in the Codex app directly from your primary machine
  • One in the Codex app from another machine that is remotely connected to the primary machine

What is the expected behavior?

Both threads should have the ability to create and manage Codex threads.

Additional information

_No response_

View original on GitHub ↗

8 Comments

github-actions[bot] contributor · 1 month ago

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

  • #26489
  • #25990
  • #26354

Powered by Codex Action

kweiberth · 1 month ago

I had Codex dig into both the public openai/codex repo and the installed Codex Desktop bundle. Maybe this is helpful?

In the public repo, the app-server does not synthesize codex_app dynamic tools. It only accepts the client-provided dynamicTools array on thread/start, validates it, persists it, and passes it into the thread:

  • codex-rs/app-server-protocol/src/protocol/v2/thread.rs: ThreadStartParams.dynamic_tools
  • codex-rs/app-server/src/request_processors/thread_processor.rs: dynamic_tools.unwrap_or_default(), then validate_dynamic_tools(...), then StartThreadOptions { dynamic_tools: core_dynamic_tools, ... }

So if a thread starts without create_thread, list_threads, etc., the missing tools were already absent from the Desktop/client-side thread/start.dynamicTools manifest.

I also inspected the installed Desktop app’s extracted/minified bundle. In webview/assets/app-server-dynamic-tools-DdL_KkKV.js, the thread-management tools are created by a factory that includes:

  • fork_thread
  • handoff_thread
  • create_thread
  • list_threads
  • read_thread
  • send_message_to_thread
  • set_thread_pinned
  • set_thread_archived
  • set_thread_title

But the exported dynamic-tool builder gates those tools roughly like this:

let isLocalHost = rt(hostId)
let threadToolsEnabled = featureOverrides?.[thread_tools] === true

return [
  ...isLocalHost ? [automation_update] : [],
  read_thread_terminal,
  ...isLocalHost && threadToolsEnabled ? threadManagementTools() : [],
]

And `rt(hostId)` effectively checks the Desktop shared `host_config` and returns true only when the target host is the current Desktop-local host:

```js
hostConfig.id === hostId && hostConfig.kind === "local"

That explains the observed behavior: a thread started directly on the Mac Studio passes this local-host check and gets the full codex_app thread-management tool set. A thread started from a MacBook controlling the Mac Studio has hostId for the remote Mac Studio, but the controlling Desktop context is not kind: "local" for that host, so the thread-management tools are filtered out before thread/start is sent. The only tool left is read_thread_terminal.

Suggested fix: do not gate thread-management dynamic tools solely on host_config.kind === "local". For remote/proxied hosts, include the thread-management tools when the controlling client can route/service those calls for the target host and features.thread_tools is enabled.

ThibaultCastells · 1 month ago

I’m seeing what looks like the same Remote Control / codex_app boundary, but as a runtime refusal rather than only a missing-tool manifest. Here is what Codex says about it:

From a Remote Control session, codex_app tools can be discoverable, but calls fail with local-thread guard errors, e.g.:

thread tools are only supported for local threads

I also saw the same class of failure for automation/workspace tools:

Automations are only supported for local threads.
Workspace dependency tools are only supported for local threads.

I’m intentionally omitting local paths and full thread IDs from this public report. The important shape is:

Remote Control caller
target thread visible in Desktop / local-host managed
codex_app dynamic tool is either missing or exposed but rejected as non-local

This suggests the issue is broader than automation_update. The local-only guard appears to be evaluated against the Remote Control caller host rather than the target thread/owner host. That would explain both cases:

  1. remote-started/remote-controlled threads missing codex_app tools entirely
  2. codex_app tools being exposed but then failing with “only supported for local threads”

This seems related to #26178, where set_thread_title was exposed but refused at runtime.

johnsilvavlogs · 1 month ago

Additional evidence from a recurring macOS Desktop / Remote Control occurrence on 2026-06-17.

Surface: a Codex Desktop session controlled through the remote/mobile surface for Johns-MacBook-Pro.local. The thread started without visible thread-management tools from the beginning.

Local versions/state:

  • Codex Desktop: 26.611.62324, build 4028 (matches current appcast at the time of testing)
  • macOS: 26.3 arm64
  • App-bundled CLI: codex-cli 0.140.0-alpha.19
  • Current thread row in state_5.sqlite: created 2026-06-17 15:06 BRT, cli_version=0.140.0-alpha.19, model=gpt-5.5, reasoning_effort=xhigh
  • thread_dynamic_tools rows for the affected thread: 0
  • Tool discovery for exact thread-tool names (list_threads read_thread create_thread fork_thread send_message_to_thread set_thread_title set_thread_pinned set_thread_archived handoff_thread Codex thread management) returned only unrelated Vercel toolbar/GitHub review-thread tools; no codex_app thread-management tools were exposed to the agent.

The stronger new signal is a stale Remote Control app-server version rejection in the Desktop logs. The current Desktop repeatedly tried to connect to an older remote-control host and rejected it as below the minimum app-server version:

2026-06-17T17:55:29.854Z app_server_connection.state_changed ... hostId=remote-control:env_e_6a0761... connectionError={"code":"update-required","minRequiredVersion":"0.139.0","currentVersion":"0.137.0-alpha.4"}
2026-06-17T17:55:34.379Z Current reported app-server version: currentVersion=0.137.0-alpha.4 hostId=remote-control:env_e_6a0761...
2026-06-17T17:55:34.380Z initialize_handshake_result ... outcome=failure ... errorMessage=codex-app-server-version-unsupported:0.137.0-alpha.4
2026-06-17T17:55:34.381Z Skipping reconnect after version error close ... hostId=remote-control:env_e_6a0761...

Same version-rejection pattern appeared earlier in the day as well (00:43Z, 13:40Z, 14:48Z, 17:33Z, 17:38Z, 17:55Z). The local remote_control_enrollments table only showed the newer Johns-MacBook-Pro.local enrollment, so the rejected env_e_6a0761... host looks like a stale/bootstrap Remote Control connection rather than the currently installed app bundle.

This seems to add another concrete axis to this issue: a remote-controlled thread can start with no codex_app thread-management manifest while Desktop also has a rejected stale Remote Control app-server host (0.137.0-alpha.4) below the current minimum (0.139.0). Ideally, Desktop should either ignore/prune stale below-minimum remote hosts before constructing the dynamic tool manifest, or surface a clear recoverable state instead of silently starting the agent without create_thread / list_threads / read_thread.

Local containment applied on this machine: the global npm-installed @openai/codex was also stale (0.135.0) even though the app bundle was current, so I updated the global CLI to 0.140.0. That removes one possible below-minimum app-server launch path for future sessions, but it does not repair already-started threads because their dynamic tool manifest is fixed at thread start.

Related adjacent symptom: #28080 covers the case where thread tools are exposed and then lose handlers later. This occurrence is the “missing from thread start / remote-control path” shape, so it still looks closest to this issue.

zoomerland · 29 days ago

I can add a Windows + Android reproduction that looks like the same boundary, with a tighter A/B control.

Environment:

  • Codex Desktop: OpenAI.Codex 26.616.6631.0
  • Windows package: OpenAI.Codex_26.616.6631.0_x64__2p2nqsd0c76g0
  • affected mobile-created thread metadata:
  • originator: Codex Desktop
  • source: vscode
  • cli_version: 0.142.0-alpha.6

A/B result on the same machine/account/build:

  1. Existing Desktop-created thread, later controlled from Android/mobile:

tool_search exposes codex_app.create_thread, codex_app.list_threads, codex_app.read_thread, codex_app.send_message_to_thread, codex_app.set_thread_title, codex_app.set_thread_archived, and codex_app.automation_update.

  1. Fresh thread created directly from the laptop/Desktop UI:

tool_search exposes the same codex_app thread-management tools.

  1. Fresh thread created from Android/mobile for the same Desktop host:

tool_search returns only multi_agent_v1.spawn_agent; there is no codex_app namespace and no create_thread / list_threads / automation_update.

So the differentiator does not appear to be OS, account, app version, or simply “new thread”.
It appears to be the client/path that creates the thread.

The confusing part is that the mobile-created thread still records:

  • originator: Codex Desktop
  • source: vscode

So those metadata fields are not enough to diagnose whether the thread received the local/Desktop app-level dynamic tools.

This matches the earlier local-host gating hypothesis in this issue: a mobile-created thread may be treated like a non-local/proxied creator path, so Desktop filters out thread-management codex_app tools before thread/start.dynamicTools is persisted.

Expected behavior:
If the target Desktop host can service codex_app thread-management calls, a thread created from mobile/remote control should receive the same thread tools as a Desktop-created thread. If this is intentionally unsupported, the UI/tool surface should expose a clear capability reason instead of silently returning only multi-agent tools.

zoomerland · 29 days ago

Additional confirmation from a second Windows machine:

A previously existing / Desktop-originated thread on that machine does expose the codex_app.* tools and was able to create a new mobile-visible project successfully.

So this does not appear to be only a machine-level install/version/plugin availability issue. On the same account and target host, the availability of codex_app tools appears to be per-thread / per-thread-creation-path.

Working workaround:
Use an existing Desktop-originated thread with codex_app.*, or create the controlling thread directly from Codex Desktop UI on the target machine. After that, mobile/remote can continue using that thread and the app-level tools remain available.

Failing path:
Threads created from the mobile/remote surface may start without codex_app.*; those threads cannot perform the same project/thread-management workflow.

fujiwarakasei · 20 days ago

Adding user-impact confirmation from a phone-first / desktop-continuation workflow.

The important product issue here is not only the missing tool list. A mobile-created or remote-created Codex thread can look like a normal Desktop-controlled host thread, but its tool surface can differ from a thread created directly from Desktop. That makes the same workflow behave differently depending on where the thread was born.

Current environment where this matters:

  • Codex Desktop for macOS: 26.623.70822, build 4559
  • Bundled codex-cli: 0.142.4
  • macOS/Darwin: 25.4.0 arm64
  • Primary workflow: start or steer work from phone, then continue on Desktop while expecting the same thread/project-management capabilities.

User-visible failure shape:

  • Desktop-created thread on the target host: local/Desktop app-level tools such as codex_app.create_thread, codex_app.list_threads, codex_app.read_thread, codex_app.send_message_to_thread, codex_app.set_thread_title, etc. are expected to be available.
  • Mobile/Remote-created thread for the same host: the thread can appear to control the same Desktop host, but may not receive the same local/Desktop app-level tools, or may hit local-only guards.
  • Returning to Desktop later does not necessarily repair the mental model, because the thread has already been created with a degraded or different capability surface.

Expected behavior:

If the target Desktop host can service codex_app thread-management calls, a thread created from mobile/Remote Control should receive the same thread-management tools as a Desktop-created thread. If that is intentionally unsupported, the UI/model surface should expose a clear capability reason before or at thread creation, instead of silently creating a thread that behaves differently.

The current workaround described above -- create the controlling thread directly from Desktop first, then continue from mobile -- is useful, but it defeats the phone-first use case where mobile is supposed to be a reliable control plane for the Desktop host.

AiurArtanis · 14 days ago

Hoping St.Tibo @tibo-openai fixes this bug soon, preferably bundled with a shiny new release and a fresh batch of resets.