Git marketplace refresh starts a full clone per concurrent `codex exec` process
Summary
When a Git-sourced marketplace is enabled, concurrent codex exec launches each start their own full Git clone of the same marketplace into a separate marketplace-upgrade-* staging directory.
This happened before the agent prompt was processed. A workload that spawned many short-lived, read-only codex exec --json processes amplified the behavior into dozens of concurrent HTTPS connections and several gigabytes of duplicate temporary data.
The update/materialization itself may reasonably use a staging directory for atomic replacement. The problem is that concurrent processes do not appear to share a refresh result or coordinate with a cross-process lock, and unchanged revisions are not cheaply rejected before the full clone.
Environment
- macOS on Apple Silicon
- Codex Desktop 26.721.81911, using its embedded Codex CLI
- Git-sourced marketplace configured in
~/.codex/config.toml:
[marketplaces.compound-engineering-plugin]
source_type = "git"
source = "https://github.com/EveryInc/compound-engineering-plugin.git"
ref = "main"
[plugins."compound-engineering@compound-engineering-plugin"]
enabled = true
The installed marketplace metadata had a persisted last_revision, and the on-disk marketplace clone was already present under ~/.codex/.tmp/marketplaces/compound-engineering-plugin.
Observed behavior
Each child process independently ran the equivalent of:
git clone https://github.com/EveryInc/compound-engineering-plugin.git \
~/.codex/.tmp/marketplaces/.staging/marketplace-upgrade-<random>
Observed during one incident:
- approximately 50 concurrent
git cloneprocesses / 47 active GitHub HTTPS connections - all clones targeted the same repository and
mainref ~/.codex/.tmp/marketplaces/.stagingreached about 4.3 GB- hundreds of
marketplace-upgrade-*directories accumulated while the parent workload was still launching newcodex execprocesses
After the parent workload stopped, the remaining clone children were orphaned (PPID 1) and needed manual termination before the temporary directories could be cleaned safely.
Expected behavior
For each configured Git marketplace:
- Use a lightweight ref check (for example
git ls-remote) and compare it with the stored revision before downloading the marketplace payload. - When the ref is unchanged, reuse the existing local materialization with no full clone.
- When an update is required, use a per-marketplace cross-process lock / single-flight refresh so one process performs the staging download and other concurrent CLI launches wait for or reuse its result.
- Keep the existing atomic staging-and-swap behavior only for the one actual update.
This is especially important because codex exec is commonly launched programmatically and in parallel by test runners or orchestration tools.
Why this matters
A single accidental parallel workload can multiply one marketplace refresh into tens of identical full repository downloads, saturating bandwidth and consuming gigabytes of disk. The behavior is independent of whether the agent run itself is read-only.
Related issues
- #35401 reports repeated plugin-catalog refreshes/writes without TTL or content comparison. This report is specifically about the Git marketplace upgrade/materialization path and concurrent full clones.
- #19382 reports repeated marketplace manifest work during normal turn/subagent setup.
- #23902 notes that Git-sourced marketplaces use a separate
marketplace_upgraderefresh path.
I can provide sanitized process listings and staging-directory measurements if useful.
1 Comment
Confirming the same cross-process/full-clone behavior through an Orca integration path, with the parent/child lifecycle captured live on macOS.
~/.codex/.tmp/marketplaces/.staging/marketplace-upgrade-*directories, approximately 150 GBOrca periodically spawns this short-lived process for its usage status bar:
It initializes JSON-RPC, sends
account/rateLimits/read, and terminates the app-server as soon as the response arrives. Codex startup has already launched marketplace auto-upgrade on a background thread. The childgit clone ... marketplace-upgrade-XXXXXXthen survives with PPID 1, while the process owning the RustTempDiris gone; activation/config revision persistence and cleanup never run. The next quota poll sees the old revision and repeats the clone.A foreground
codex plugin marketplace upgrade <name> --jsoncompleted successfully, aligned the live checkout/config/install metadata with remote HEAD, and a controlled short-livedapp-server -> account/rateLimits/read -> terminatetest then produced zero new staging directories. This confirms that the repeated full clone was caused by the interrupted startup upgrade rather than marketplace contents.Detailed Orca-side report and process tree: https://github.com/stablyai/orca/issues/7725#issuecomment-5185784338
This path reinforces the need for a cross-process per-marketplace lock/single-flight refresh, stale staging GC, and shutdown coordination that does not rely only on process-local
TempDirdrop.