Environment
- OS: Windows 11
- Shell: Git Bash (mingw64) — used internally by Claude Code CLI
- Node.js: v25.8.1
- npm: 11.8.0
- Codex CLI: 0.117.0 (installed globally via
npm install -g @openai/codex)
- Plugin version: 1.0.0
Problem
Running /codex:setup in Claude Code CLI reports:
| Component |
Status |
Detail |
| Node.js |
Available |
v25.8.1 |
| npm |
Missing |
not found |
| Codex CLI |
Not installed |
not found |
However, all three binaries are correctly installed and accessible from the same shell:
$ which node
/c/Program Files/nodejs/node
$ which npm
/c/Program Files/nodejs/npm
$ which codex
/c/Users/xyz/AppData/Roaming/npm/codex
Root Cause
binaryAvailable() in scripts/lib/process.mjs uses spawnSync(command, args) without shell: true.
On Windows, npm and codex are installed as .cmd batch file wrappers (e.g., npm.cmd, codex.cmd). Node.js spawnSync without shell: true cannot resolve .cmd extensions, returning ENOENT.
node.exe works because it is a native .exe file, which spawnSync can resolve directly without a shell.
Proof
// FAILS — ENOENT (current plugin behavior)
const r1 = spawnSync('npm', ['--version'], { encoding: 'utf8' });
// r1.error.code === 'ENOENT', r1.stdout === undefined
// WORKS — returns "11.8.0"
const r2 = spawnSync('npm', ['--version'], { encoding: 'utf8', shell: true });
// r2.error === null, r2.stdout === "11.8.0\n"
Proposed Fix
Two changes in scripts/lib/process.mjs:
1. Pass shell option through runCommand
const result = spawnSync(command, args, {
cwd: options.cwd,
env: options.env,
encoding: "utf8",
input: options.input,
- stdio: options.stdio ?? "pipe"
+ stdio: options.stdio ?? "pipe",
+ shell: options.shell ?? false
});
2. Enable shell: true on Windows in binaryAvailable
export function binaryAvailable(command, versionArgs = ["--version"], options = {}) {
+ const platformOptions = process.platform === "win32" ? { ...options, shell: true } : options;
- const result = runCommand(command, versionArgs, options);
+ const result = runCommand(command, versionArgs, platformOptions);
This is a minimal, targeted fix that only affects binary-availability checks on Windows and does not change behavior on macOS/Linux.
Impact
This bug affects all Windows users who use the Codex plugin through Claude Code CLI (which spawns Git Bash internally). /codex:setup, /codex:review, /codex:rescue, and any other command that calls getCodexAvailability() will fail.
Related
Environment
npm install -g @openai/codex)Problem
Running
/codex:setupin Claude Code CLI reports:However, all three binaries are correctly installed and accessible from the same shell:
Root Cause
binaryAvailable()inscripts/lib/process.mjsusesspawnSync(command, args)withoutshell: true.On Windows,
npmandcodexare installed as.cmdbatch file wrappers (e.g.,npm.cmd,codex.cmd). Node.jsspawnSyncwithoutshell: truecannot resolve.cmdextensions, returningENOENT.node.exeworks because it is a native.exefile, whichspawnSynccan resolve directly without a shell.Proof
Proposed Fix
Two changes in
scripts/lib/process.mjs:1. Pass
shelloption throughrunCommandconst result = spawnSync(command, args, { cwd: options.cwd, env: options.env, encoding: "utf8", input: options.input, - stdio: options.stdio ?? "pipe" + stdio: options.stdio ?? "pipe", + shell: options.shell ?? false });2. Enable
shell: trueon Windows inbinaryAvailableexport function binaryAvailable(command, versionArgs = ["--version"], options = {}) { + const platformOptions = process.platform === "win32" ? { ...options, shell: true } : options; - const result = runCommand(command, versionArgs, options); + const result = runCommand(command, versionArgs, platformOptions);This is a minimal, targeted fix that only affects binary-availability checks on Windows and does not change behavior on macOS/Linux.
Impact
This bug affects all Windows users who use the Codex plugin through Claude Code CLI (which spawns Git Bash internally).
/codex:setup,/codex:review,/codex:rescue, and any other command that callsgetCodexAvailability()will fail.Related
spawnSync+.cmdENOENT pattern on Windows