Codex mobile remote access can reuse revoked enrollment and connect to the wrong Mac
Summary
Codex mobile remote access can enter a cross-host stale state with two Macs on the same ChatGPT account/workspace:
- Mac A shows Codex mobile / remote access as connected or successfully set up.
- The iPhone ChatGPT app shows or connects to Mac B instead.
- Re-running mobile setup / scanning a new QR code on Mac A does not replace the stale enrollment.
- Codex Desktop keeps reusing a revoked remote-control client and repeatedly reconnects to the wrong remote-control host.
This makes Mac A impossible to pair from the UI even though setup appears successful.
Environment
- Codex App for macOS: 26.513.31313
- macOS: 26.5, build 25F71
- ChatGPT mobile: latest available from App Store as of 2026-05-19
- Account/workspace: same ChatGPT account and workspace on both Macs and the iPhone
- Setup: two Mac hosts, both used with Codex mobile remote access
Expected behavior
Each Mac should have an independent Codex mobile remote-control enrollment / host identity.
When setting up mobile access on Mac A:
- Mac A should generate or use an enrollment for Mac A.
- The iPhone should show Mac A as the connected host.
- If a previous enrollment is revoked, Codex should discard it and force a fresh setup.
- A stale or revoked enrollment from Mac B should not make Mac A appear connected.
Actual behavior
Mac A shows mobile access as connected / set up, but the iPhone shows the connected host as Mac B.
Mac A repeatedly tries to use a stale enrollment and wrong remote-control:<env> host. The local state had:
electron-remote-control-client-enrollmentsadded-remote-control-env-idsselected-remote-host-idremote-connection-auto-connect-by-host-idremote-projectscodex-mobile-has-connected-deviceelectron-local-remote-control-installation-id
The remote project shown on Mac A was from Mac B.
Logs
Identifiers are redacted, but the important failure pattern is:
[remote-control-websocket] remote_control_client_refresh_start_request hasExistingEnrollment=true localEnrollmentClientId=<redacted stale client id> ...
[AppServerConnection] app_server_connection.transport_connect_failed errorMessage="Remote-control client has been revoked" hostId=remote-control:<redacted stale env id> transport=websocket
[remote-connections/window-context] connect_from_config_apply_failed errorMessage="Remote-control client has been revoked" hostId=remote-control:<redacted stale env id>
This repeats on app startup and QR setup retries.
Recovery attempts
Clearing the remote-control keys from ~/.codex/.codex-global-state.json while Codex is running is not sufficient because the running app rewrites the stale state back to disk.
Clearing both ~/.codex/.codex-global-state.json and ~/.codex/.codex-global-state.json.bak while Codex is fully stopped removes the local stale state. However, there is no obvious mobile UI to remove the incorrect/stale host from the iPhone side, and the Mac UI can still present misleading connected state before cleanup.
Why this looks like a product bug
The app treats a revoked remote-control enrollment as an existing valid local enrollment (hasExistingEnrollment=true) and keeps retrying it instead of invalidating it.
The UI also appears to conflate or reuse remote-control host state between two Macs on the same account/workspace. This produces a cross-host mismatch: Mac A reports success, while the iPhone points at Mac B.
Suggested fixes
- When the relay returns
"Remote-control client has been revoked", clear the corresponding local enrollment and remote host mapping automatically. - Do not display mobile access as connected if the stored enrollment is revoked.
- Ensure
electron-local-remote-control-installation-id/ host identity cannot be cloned or reused across Macs without re-enrollment. - Add a visible "Remove this Mac / disconnect host" action in ChatGPT mobile Codex.
- Add a "Reset Codex mobile pairing" action in Codex App
Settings > Connections.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗