Codex uses bundled pnpm instead of host toolchain

Open 💬 24 comments Opened Jun 28, 2026 by kkaatii

What version of the Codex App are you using (From “About Codex” dialog)?

26.623.42026

What subscription do you have?

Pro

What platform is your computer?

Darwin 24.6.0 arm64 arm

What issue are you seeing?

Codex is consistently failing to run my build script because that script invokes pnpm install.

As per its own diagnosis:

  • My local projects uses PNPM v10
  • Codex comes bundled with PNPM v11 in ~/.cache/codex-runtimes/codex-primary-runtime/dependencies/bin/pnpm
  • When running the build script, Codex uses the bundled one, leading to failure to resolve dependencies, whereas the build script is run fine in any local terminal

What steps can reproduce the bug?

  1. Create a pnpm v10 project with dependencies in package.json
  2. Run pnpm install in terminal to install the dependencies
  3. Create a js script

```javascript
import { spawn } from "node:child_process";

const child = spawn("pnpm", ["install"], {
cwd: process.cwd(),
stdio: ["ignore", "pipe", "pipe"],
});

child.on("close", (code) => {
process.exit(code ?? 1);
});
```

  1. Ask Codex (with pnpm v11 bundled) to run node script.mjs inside project dir

What is the expected behavior?

Codex should use my local pnpm binary, and ask for permission elevation when needed.

In fact, using this to run the build script is fine: PATH="path-to-my-local-nodejs/bin:$PATH" CI=true node script.mjs

Additional information

_No response_

View original on GitHub ↗

24 Comments

zhuscat · 2 months ago

I encountered the same problem in Codex Desktop App

cubicj · 2 months ago

I am seeing the same issue on Windows Codex Desktop.

Codex App: 26.623.8305.0
OS: Windows 11 Education x64, 10.0.26200
Project packageManager: pnpm@10.34.1
User-global pnpm: 10.34.1
Bundled Codex pnpm: 11.7.0

Inside Codex, Get-Command pnpm -All resolves the bundled runtime first:

C:\Users\<user>\.cache\codex-runtimes\codex-primary-runtime\dependencies\bin\pnpm.cmd
C:\Users\<user>\AppData\Roaming\npm\pnpm.ps1
C:\Users\<user>\AppData\Roaming\npm\pnpm.cmd

Running pnpm check uses the bundled pnpm and fails before the project script runs:

ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY
Aborted removal of modules directory due to no TTY

Explicitly calling the user-global pnpm works:

& "$env:APPDATA\npm\pnpm.cmd" check

This uses pnpm 10.34.1 and passes. pnpm test and pnpm build also pass with the user-global pnpm.

I opened #30541 before noticing this issue. I will close it as a duplicate, but leaving the Windows reproduction details here since the same bundled pnpm shadowing happens on Windows too.

RickVM · 1 month ago

Running into this as well on my mac, exactly the same diagnoses.

Javierg9n4 · 1 month ago

I am also running into this same issue since the last codex app update on my mac.

Alt-er · 1 month ago

how to solve

v-mec · 1 month ago

Having the same issue. As a workaround, I have told Codex to use Corepack with every pnpm command in agents.md.

I would expect turning off Configuration > Codex dependencies to fix this, but this only seems to affect Node itself.

shrinktofit · 1 month ago

same for me

shrinktofit · 1 month ago

Temp solution:

  1. add following config.toml:

``toml
[shell_environment_policy]
experimental_use_profile = true
``
This let agents spawning pwsh with your user pwsh profile

  1. run code $profile, put the following at head:
function isCodexAgentRun {
  return (($env:Path -split ';') -match '\\.cache\\codex-runtimes\\').Count -gt 0
}

# If current shell is boot by agent, source another profile profile
if (isCodexAgentRun) {
  . (Join-Path $PSScriptRoot 'CodexAgent_profile.ps1')
  return
}
  1. new a CodexAgent_profile.ps1 file in dir of $profile, with following content:
$pnpmGlobalBinDir = 'path-to-the-dir-of-your-pnpm'
$pnpmCmd = Join-Path $pnpmGlobalBinDir 'pnpm.cmd'

if (Test-Path -LiteralPath $pnpmGlobalBinDir) {
  $pathParts = $env:PATH -split ';' | Where-Object {
    $_ -and ($_.TrimEnd('\') -ine $pnpmGlobalBinDir.TrimEnd('\'))
  }
  $env:PATH = (@($pnpmGlobalBinDir) + $pathParts) -join ';'
}

function Invoke-PreferredPnpm {
  if (-not (Test-Path -LiteralPath $pnpmCmd)) {
    throw "Preferred pnpm not found: $pnpmCmd"
  }

  Write-Host "<Verbose> Invoking preferred pnpm: $pnpmCmd"

  & $pnpmCmd @args
}

function pnpm {
  Invoke-PreferredPnpm @args
}

function pnpm.cmd {
  Invoke-PreferredPnpm @args
}
mdca · 1 month ago

same

drbazzz123 · 1 month ago

Confirming this is more than a cosmetic PATH mismatch.

On our Windows Codex Desktop setup, the bundled runtime pnpm is taking precedence over the project's host toolchain and this has direct operational impact on agent-driven repo workflows.

Observed behavior in our case:

  • the project is pinned to pnpm@9.15.9
  • the Codex session resolves bundled pnpm 11.7.0 from a Codex-managed runtime path under the user's profile cache (for example: ...\.cache\codex-runtimes\...\dependencies\bin\pnpm.cmd)
  • the problematic runtime path is not present in the normal user or machine PATH; it appears in the Codex session process PATH
  • the bundled pnpm triggers unexpected install / preflight behavior instead of simply running the repo command
  • it can generate repo-visible artifacts such as placeholder pnpm-workspace.yaml
  • it interferes with validation loops, hooks, and pre-push flows

The critical point is reliability: this reduces the ability of Codex agents to autonomously and safely work through normal project loops such as:

  • run checks
  • pass repo hooks
  • commit
  • push

So from an agent-workflow perspective, this is not just a version mismatch. It is a host-vs-bundled toolchain boundary bug.

The bundled runtime for Codex-internal use is understandable. The issue is that the bundled package manager/runtime leaks into user repo command execution instead of staying isolated to Codex-internal use.

We also verified that forcing the host toolchain makes the same repo checks pass normally, which further points to session-level toolchain injection rather than a project-local configuration problem.

_This problem was investigated in depth by the agent itself, and this comment is being posted by the agent via gh on behalf of the user._
BeaconSage · 1 month ago

Codex App: 26.623.70822
macOS : 15.5
command -v pnpm: /Users/<user-name>/.cache/codex-runtimes/codex-primary-runtime/dependencies/bin/pnpm

lsave · 1 month ago

encountered the same issue; even clearing .cache/codex-runtimes didn't help, as it just rebuilds itself.

goldenice · 1 month ago

I am seeing the same issue in Codex Desktop on macOS.

Additional details:

  • The “Codex dependencies” setting is disabled in the UI.
  • The local config reflects this with workspace_dependencies = false.
  • After fully restarting the Codex app, Codex still injects its bundled runtime path ahead of the user package-manager path in the agent command environment.
  • node resolves to the host nvm-managed Node, but pnpm resolves first to Codex’s bundled runtime path under ~/.cache/codex-runtimes/codex-primary-runtime/dependencies/bin/pnpm.
  • The Codex app-server parent process already contains that runtime path in PATH, so this does not appear to come from shell startup files.
  • A clean shell without the Codex-launched environment does not include that bundled runtime path.

Expected behavior:
When “Codex dependencies” is disabled, bundled package-manager binaries should not shadow the host/project toolchain for repository commands. Bundled runtime tools may still exist for Codex internals, but they should not take precedence for user repo command execution.

michaellatman · 1 month ago

Same issue here on Codex Desktop macOS. Repo pins pnpm@10.34.4, and local nvm/corepack resolves that correctly, but Codex prepends its bundled pnpm:

~/.cache/codex-runtimes/codex-primary-runtime/dependencies/bin/pnpm

That binary is pnpm@11.7.0, so scripts/Turbo child tasks that call plain pnpm use the bundled version instead of the repo-pinned one. In our case this caused repeated node_modules recreation attempts and ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY.

vmbehety · 1 month ago

hope this gets fixed soon, this week has been a nightmare to work with codex as my work enviroment uses pnpm 10 also

Amour1688 · 1 month ago

I hit the same root cause and have a fix branch prepared, but opening a PR is currently restricted to collaborators on this repository.

Compare link: https://github.com/openai/codex/compare/main...Amour1688:fix-runtime-path-precedence?expand=1

samthemagicman · 1 month ago

This has made Codex a complete nightmare, agreed.

christianheine · 1 month ago

Here's a workaround that worked for me (Mac):

# ~/.zshenv
export PATH="$HOME/.local/bin:$PATH"
mkdir -p ~/.local/bin
corepack enable --install-directory "$HOME/.local/bin"
corepack prepare pnpm@11.10.0 --activate

On my machine Codex finds its bundled pnpm runtime as 11.7.0. But if ~/.local/bin comes earlier, pnpm should resolve to the Corepack shim instead. Note: .zshenv is required, because ~/.zshrc is for interactive shells only. It should work ok with different pnpm versions across your repos, because corepack should resolve the correct version.

tofrankie · 1 month ago
I am using macOS.

I currently use nvm or fnm to manage Node versions, alongside a Node 22 installation via Homebrew; all of these are configured in ~/.zshrc (for interactive shells). However, the Codex App runs in a non-interactive mode, so it does not load ~/.zshrc.

My temporary workaround is to add the following conditional check to ~/.zshenv:

if [[ ! -o interactive ]] && [[ "$TERM" = dumb ]] && [[ "$PATH" == *"/Users/frankie/.cache/codex-runtimes/codex-primary-runtime/dependencies/bin"* ]]; then
export PATH="/usr/local/opt/node@22/bin:$PATH"
fi

With this in place, executing Node-related commands (such as npm, yarn, or pnpm) will use the binary located at /usr/local/opt/node@22/bin.

[!IMPORTANT] Of course, this isn't a perfect solution, but it works for me since none of my current projects have upgraded to pnpm v11 yet.

If this approach suits your needs, you can adjust the user directory path accordingly. You can determine the correct path by running which pnpm inside the Codex App and then substituting it into the script.

MumuTW · 1 month ago

Adding a root-cause detail that I don't think has come up yet: PATH precedence isn't the whole story. There's a second mechanism that makes the bundled pnpm ignore packageManager even once it's picked up, and fixing PATH alone won't address it.

The runtime's pnpm shim exports a flag that disables the packageManager check:

$ cat ~/.cache/codex-runtimes/codex-primary-runtime/dependencies/bin/fallback/pnpm
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export pnpm_config_pm_on_fail=ignore
exec "${SCRIPT_DIR}/../../node/bin/node" "${SCRIPT_DIR}/../../node/node_modules/pnpm/bin/pnpm.mjs" "$@"

packageManager exists precisely so that a pnpm 11 binary landing in a pnpm 10 repo self-corrects to the pinned version. pnpm_config_pm_on_fail=ignore turns that off, so it proceeds as 11 instead.

Same entrypoint, same repo (pinned to pnpm@10.24.0), the only difference being that variable:

$ pnpm_config_pm_on_fail=ignore .../node/bin/node .../node_modules/pnpm/bin/pnpm.mjs --version
11.9.0

$ .../node/bin/node .../node_modules/pnpm/bin/pnpm.mjs --version
10.24.0

So the bundled binary already resolves correctly on its own — the shim is what prevents it.

Why this matters for the fix: with the flag in place, any path that reaches this shim still silently ignores the repo's version pin, even with PATH precedence corrected. Conversely, dropping the flag makes the bundled pnpm honour packageManager on its own, which looks like a much smaller change than reordering PATH — and it restores the exact behaviour packageManager is designed to provide, rather than depending on the user having a correctly-ordered host toolchain.

Concrete damage beyond the reported failures. On pnpm 11 the pnpm field in package.json is no longer read:

[WARN] The "pnpm" field in package.json is no longer read by pnpm. The following keys were ignored:
"pnpm.overrides", "pnpm.supportedArchitectures", "pnpm.onlyBuiltDependencies", "pnpm.patchedDependencies".

It migrates those settings into a new pnpm-workspace.yaml and rewrites pnpm-lock.yaml. Both then show up as unexplained working-tree changes. I nearly committed them into upstream PRs across several worktrees before tracing where they came from. That's a quieter failure mode than ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY (which I also hit): nothing errors, the repo just silently acquires a lockfile diff and a new file.

Workaround, for anyone without corepack. env -u pnpm_config_pm_on_fail pnpm ... does not work — the shim re-exports it internally. The variable has to be cleared inside a wrapper that bypasses the shim:

# ~/.local/bin/pnpm  (must precede the runtime's bin/fallback on PATH)
#!/usr/bin/env bash
set -euo pipefail
CODEX_NODE_ROOT="${HOME}/.cache/codex-runtimes/codex-primary-runtime/dependencies/node"
unset pnpm_config_pm_on_fail
exec "${CODEX_NODE_ROOT}/bin/node" "${CODEX_NODE_ROOT}/node_modules/pnpm/bin/pnpm.mjs" "$@"

This reuses the bundled pnpm rather than requiring a host install, so it works without corepack or nvm/fnm (the corepack suggestions above assume corepack is installed; it isn't on my machine). After this, pnpm --version reports 10.24.0 in the pinned repo and pnpm install leaves the tree clean across four worktrees — no lockfile diff, no stray pnpm-workspace.yaml.

Note CI=true is still useful for non-TTY installs, for the ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY case others have reported.

Environment: macOS (Darwin arm64), Codex CLI, repo pinned to pnpm@10.24.0, bundled pnpm 11.9.0.

zakinadhif · 15 days ago

When will this get fixed? I use windows and this is a pain.

naipi11 · 9 days ago

Codex prefers its bundled pnpm over the host toolchain, and the bundled shim also sets pnpm_config_pm_on_fail=ignore, so packageManager in package.json is ignored.

Method:

  1. Check which pnpm the agent is actually running (Get-Command pnpm / which pnpm). If it resolves under ~/.cache/codex-runtimes/.../dependencies/bin/fallback, that is the bundled copy.
  2. Put your real Node/pnpm directory earlier on PATH for non-interactive shells (macOS: a ~/.zshenv guard; Windows: User PATH, then a new terminal).
  3. In the project, pin the package manager you want (packageManager plus Corepack) and tell the agent in AGENTS.md to call that exact binary, not bare pnpm.
  4. Restart the Desktop/CLI session after the PATH change.

Evidence: the fallback pnpm shim exports pnpm_config_pm_on_fail=ignore and execs the runtime's own Node+pnpm. A current Windows session can resolve pnpm.cmd from that fallback directory.

Independent community workaround; not an official OpenAI fix.

mckalexee · 6 days ago

Running into the same issue on Mac. It's wild that pnpm 10 is completely broken inside of codex and has been for 2 months with no response.

zakinadhif · 4 days ago

Perhaps they're telling us not to use pnpm 🤔