codex app-server hardcodes SessionSource::VSCode; no --session-source flag on the umbrella subcommand
Summary
The codex app-server subcommand (in the umbrella codex binary) hardcodes the session source to SessionSource::VSCode. There is no CLI flag to override this, even though clientInfo.name is honored for the originator field. As a result, any third‑party host that embeds Codex via codex app-server --listen stdio:// produces sessions that:
- carry a faithful
originator(e.g.multica-agent-sdk), but - are also tagged
source=vscode, which the defaultthreadListallowlist treats as a normal interactive VSCode session.
These third‑party sessions then show up in Codex Desktop's recent/project history and, at high session rates, push real user chats out of the visible window.
The standalone codex-app-server binary already exposes --session-source (default vscode) and parses arbitrary values into SessionSource::Custom(...). The fix is to forward the same flag from the umbrella codex app-server subcommand.
Repro
- Start Codex via the umbrella binary the way embedders do today:
```
codex app-server --listen stdio://
clientInfo = { name: "my-agent-sdk", version: "..." }` over the JSON-RPC handshake.
Pass
- Inspect the resulting
~/.codex/sessions/.../rollout-*.jsonlsession_metaline:
``json``
{ "originator": "my-agent-sdk", "source": "vscode", ... }
- Open Codex Desktop. The third‑party session appears in the recent threads/project list, even though it was never a VSCode‑extension chat.
Root cause (confirmed against current main)
- The umbrella
codexapp-serversubcommand callsrun_main_with_transport_options(..., SessionSource::VSCode, ...)directly — the value is hardcoded, not read from a flag: codex-rs/cli/src/main.rs(AppServerCommandinvocation, ~L986)AppServerCommanddoes not declare a--session-sourcefield:codex-rs/cli/src/main.rs(AppServerCommandstruct, ~L435–477) — fields aresubcommand,strict_config,listen,remote_control,analytics_default_enabled,auth. No session source.- The standalone
codex-app-serverbinary already has the flag and parser: codex-rs/app-server/src/main.rs(~L31–37): claplong = "session-source",default = "vscode", parsed viaSessionSource::from_startup_arg.SessionSource::from_startup_argaccepts any string and folds unknown values intoSessionSource::Custom(normalized):codex-rs/protocol/src/protocol.rs(from_startup_arg).arg0‑style dispatch incodexdoes not alias toapp-server, so callingcodexunder a different basename is not a workaround:codex-rs/arg0/src/lib.rs.
Why hardcoding to vscode is load-bearing for the bug
The default threadList allowlist in rollout includes SessionSource::VSCode, which is why these sessions surface in Desktop in the first place:
- Default allowlist:
INTERACTIVE_SESSION_SOURCES = [Cli, VSCode, Custom("atlas"), Custom("chatgpt")] codex-rs/rollout/src/lib.rs(~L24–31)- Default filter when client doesn't pass
source_kinds: codex-rs/app-server/src/filters.rs(~L9–15)- Sessions whose
sourceis not in the allowlist are dropped fromthreadListresults: codex-rs/rollout/src/list.rs(~L748–754)
So if an embedder could pass --session-source my-agent-sdk, the resulting SessionSource::Custom("my-agent-sdk") would naturally fall outside the default allowlist and Desktop would correctly hide it — same convention the codebase already uses for non‑interactive sources.
Proposed fix
Mirror the standalone binary's flag on the umbrella subcommand:
- Add
--session-sourcetoAppServerCommand(codex-rs/cli/src/main.rs),default = "vscode"so existing VSCode‑extension behavior is unchanged. - Parse it with
SessionSource::from_startup_arg(same ascodex-rs/app-server/src/main.rs). - Pass the parsed
SessionSourceintorun_main_with_transport_options(...)instead of the hardcodedSessionSource::VSCode.
This is additive, opt-in, and matches the existing convention used by the standalone codex-app-server binary. No allowlist or Desktop‑side change is required: Custom(...) sources are already filtered out of the default interactive list.
Workarounds today
- Build/install the standalone
codex-app-serverbinary and pass--session-source <name>directly. Not viable for end users who only have the official@openai/codexdistribution (which ships onlycodex), and Desktop's bundledcodex-app-serverisn't onPATH.
Context
- Reported downstream as a noisy Codex Desktop history flood when Multica agents run concurrently with the Desktop app: https://github.com/multica-ai/multica/issues/2746
- Closely related symptoms from the same root: https://github.com/openai/codex/issues/23408 (mobile Projects list scraping Multica workdirs)
- The diagnosis above was first sketched by @truffle-dev in the Multica issue thread; this report confirms it against the current upstream tree and proposes the minimal fix.
4 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Not a duplicate of #23437. Same surface symptom (
source=vscode), different root causes.This issue is the
app-serversubcommand atcodex-rs/cli/src/main.rs:986constructing the session withcodex_protocol::protocol::SessionSource::VSCodehardcoded. The app-server's own session is misclassified at construction time. Fix is plumbing a source throughAppServerCommand(a--session-sourceflag, or detecting CLI invocation vs Desktop launch).#23437 is a separately-launched TUI session in a project directory getting written with
source=vscode,originator=Codex Desktop, andcwd=$HOMEaftercodex app-serverhas run. The TUI session never enters the:986codepath; its metadata is being polluted through shared state outside that file (env var, session-store, lockfile, or originator detection reading state set by the app-server). Patching:986leaves that codepath untouched.Worth keeping both open. The fixes are independent.
Sharing the fix outline per docs/contributing.md. Happy to PR it if a Codex maintainer wants it.
The umbrella
app-serversubcommand already mirrors the standalonecodex-app-serverbinary in every other respect (--listen,--remote-control,--analytics-default-enabled, strict config). Adding the same--session-sourceflag with the same defaults closes the gap. The change is 42 lines incodex-rs/cli/src/main.rs(1 import, 1 struct field, 1 destructure, 1 hardcoded-replacement, 3 unit tests), compiles clean on top ofb3ae3de40,cargo test -p codex-clipasses locally.The default stays
vscodeso first-party VSCode launches keep their current classification with no change.SessionSource::from_startup_argis the same parser the standalone binary uses (codex-rs/protocol/src/protocol.rs:2613), which already acceptscli/vscode/exec/mcp/app-serveraliases and wraps anything else asSessionSource::Custom(_), so downstream embedders get their identifier through without needing a new enum variant.Three unit tests in the existing
#[cfg(test)] mod testsblock cover default, custom, and alias normalization:This is upstream-only and leaves the separate TUI-classification-via-shared-state question on #23437 untouched.
Still reproducible in current Codex builds.
I verified
rust-v0.141.0still hardcodesSessionSource::VSCodein the umbrellacodex app-serverpath:codex-rs/cli/src/main.rs:1146codex-rs/app-server/src/lib.rs:398The standalone
codex-app-serverbinary has--session-source, but the distributedcodex app-servercommand does not expose it, so custom clients usingcodex app-server --listen stdio://still create threads withsource: "vscode".