openai / openai/codex

[macOS][regression] `codex_app` MCP override makes `CODEX_APP_SERVER_USE_LOCAL_DAEMON=1` unreachable

Open
#41,014 5 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server bug mcp
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

After updating ChatGPT Desktop, the existing managed local App Server path no longer works in a normal Desktop startup.

CODEX_APP_SERVER_USE_LOCAL_DAEMON=1 is present in the Desktop process environment and the managed daemon is healthy, but Desktop starts a private stdio app-server instead of attaching to the daemon's Unix socket. If another local client is already using the same thread through the managed daemon, Desktop then shows:

This is open in another app
Close it there to continue here.

This appears to be a startup-logic regression caused by the new app-managed codex_app MCP override.

Environment

  • ChatGPT Desktop: 26.820.60940 (build 7119)
  • Bundled Codex: codex-cli 0.150.0-alpha.8
  • Standalone managed Codex/App Server: 0.149.1
  • Bundled codex-app-tools plugin: 0.1.3
  • macOS: 26.5.2 (25F84)
  • Architecture: Apple Silicon / arm64

Managed daemon status before launching Desktop:

{
  "status": "running",
  "backend": "pid",
  "managedCodexVersion": "0.149.1",
  "socketPath": "$CODEX_HOME/app-server-control/app-server-control.sock",
  "cliVersion": "0.150.0-alpha.8",
  "appServerVersion": "0.149.1"
}

Previously working behavior

Before the Desktop update, this setup worked:

ChatGPT Desktop ────────┐
                        ├─ managed app-server --listen unix://
local sidecar/client ───┘

Both clients connected to the same Unix socket and could observe/continue the same live thread.

This is the same shared-daemon topology documented in #31991.

Steps to reproduce

  1. Install the standalone Codex package.

  2. Start the managed App Server:

    codex app-server daemon bootstrap
    
  3. Ensure the Desktop process receives:

    launchctl setenv CODEX_APP_SERVER_USE_LOCAL_DAEMON 1
    
  4. Fully quit and restart ChatGPT Desktop.

  5. Connect a second local client to $CODEX_HOME/app-server-control/app-server-control.sock.

  6. Open or continue a thread through that client.

  7. Open the same thread in ChatGPT Desktop.

Actual behavior

Desktop does not attach to the managed daemon. It uses a private stdio app-server, so the system has two app-server processes with separate writer ownership:

ChatGPT Desktop ── private app-server --listen stdio://
local client ───── managed app-server --listen unix://

Opening the managed-daemon thread in Desktop produces the active-writer / “open in another app” conflict.

Fully quitting Desktop releases its private writer, but that defeats the shared-client workflow.

Diagnostic evidence

Inspection of the packaged Desktop startup logic shows that the managed-daemon branch is selected only when all of the following are true, including:

configOverrides.length === 0 &&
process.env.CODEX_APP_SERVER_USE_LOCAL_DAEMON === "1"

The same startup now creates the Codex app-tools native pipe, sets CODEX_APP_TOOLS_PIPE_PATH, reads the bundled codex-app-tools/desktop-mcp.json, and returns a request-level override for:

mcp_servers.codex_app

Therefore, on a healthy normal Desktop startup:

codex_app native pipe starts
  → mcp_servers.codex_app override is non-empty
  → configOverrides.length !== 0
  → managed-daemon branch is skipped
  → private stdio app-server is spawned

The daemon version gate is not the blocker: the packaged minimum is older than 0.149.1, so this execution path is rejected before daemon version selection matters.

The current Desktop process environment was also checked:

CODEX_APP_SERVER_USE_LOCAL_DAEMON=set
CODEX_APP_TOOLS_PIPE_PATH=set
CODEX_CLI_PATH=unset
CODEX_APP_SERVER_FORCE_CLI=unset
CODEX_APP_SERVER_WS_URL=unset

Expected behavior

If CODEX_APP_SERVER_USE_LOCAL_DAEMON=1 is set and a compatible daemon is healthy, Desktop should attach to it.

At minimum, one of these should be supported:

  1. Give the explicit local-daemon setting precedence and disable Desktop-only app tools with a clear warning.
  2. Provide a supported setting to disable the app-managed codex_app MCP injection.
  3. Make the codex_app tools client/session-scoped so they do not require a process-wide app-server config override.
  4. Support per-connection config overlays on the managed daemon.

Why this is distinct from a generic writer-lock issue

The writer conflict is the visible symptom. The earlier transport-selection decision is the regression: an automatically injected Desktop MCP override makes the existing local-daemon branch unreachable during normal startup.

Related reports cover the individual symptoms, but not this combined cause:

  • #31991 — previously working Desktop + managed App Server topology
  • #37403 — Desktop/CLI/Remote thread gets already has an active writer after update
  • #40157 — standalone app-server/Remote → Desktop produces “opened in another app”
  • #40860 — Desktop injects mcp_servers.codex_app even when absent from user config
  • #40819 — request-level codex_app config overrides file-level configuration

Additional note

I understand that CODEX_APP_SERVER_USE_LOCAL_DAEMON is undocumented. However, the current Desktop bundle still contains the environment-variable check, daemon discovery/version gate, and Unix-socket transport path. The automatic codex_app override now prevents that retained path from being selected.

No thread IDs, usernames, repository names, or private paths are included.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Inspect the packaged Desktop startup logic described in the report, especially the configOverrides check, CODEX_APP_SERVER_USE_LOCAL_DAEMON path, and codex_app injection; reproduce with daemon bootstrap and the launchctl environment setup. Done means a compatible healthy daemon is selected despite the injected override, preserving the shared Unix-socket workflow or providing a clearly supported disablement path.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos
Domain
backend, desktop, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.