Skip to content

Windows: codex-cli install always fails — cmd.exe double-escapes the codex.cmd invocation (missing windowsVerbatimArguments) #3338

Description

@byigorduvanov

npx claude-mem@latest install --ide codex-cli fails every time on Windows, even when codex, codex.cmd, and codex.ps1 are all genuinely present and resolvable (where codex finds all three — this is not a "codex isn't installed" situation):

Installation failed: codex plugin marketplace add <path> failed with exit code 1: '\"C:\Users\<user>\AppData\Roaming\npm\codex.cmd\"' is not recognized as an internal or external command, operable program or batch file.
...
Installation Aborted: all-ides-failed

Root cause, in dist/npx-cli/index.js:

function l3(t){return`"${t.replace(/"/g,'""')}"`}
function Us(t,e,r,i=process.platform){
  let n={...i==="win32"?{windowsHide:!0}:{},...r};
  return i==="win32"&&IA.has(Cb(t).toLowerCase())
    ?{command:process.env.ComSpec??"cmd.exe",args:["/d","/s","/c",[t,...e].map(l3).join(" ")],options:n}
    :{command:t,args:[...e],options:n}
}

(IA = new Set([".cmd",".bat"]))

When the resolved codex command has a .cmd/.bat extension (the normal case for an npm-global-installed CLI on Windows — npm creates <name>, <name>.cmd, <name>.ps1, never a .exe), this manually pre-quotes the entire command line (l3 wraps each token in "...", doubling embedded quotes) and hands it to cmd.exe /d /s /c as a single args element. That's the documented-correct low-level pattern for invoking .cmd/.bat from Node on Windows — but the returned options object never sets windowsVerbatimArguments: true.

Without that flag, child_process.spawnSync (called via Nv/codexSpawn) applies its own automatic Windows argv-escaping on top of the already-quoted string, since it has no way to know the string is a pre-built, already-correct command line. That second pass of escaping corrupts it — the already-present " characters get backslash-escaped (\"), which cmd.exe does not treat as an escape sequence (backslash isn't special to cmd.exe's quote parsing), so it sees a malformed token and reports "is not recognized as an internal or external command."

Fix: add windowsVerbatimArguments: true to n in the win32 + .cmd/.bat branch of Us():

return i==="win32"&&IA.has(Cb(t).toLowerCase())
  ?{command:process.env.ComSpec??"cmd.exe",args:["/d","/s","/c",[t,...e].map(l3).join(" ")],options:{...n,windowsVerbatimArguments:!0}}
  :{command:t,args:[...e],options:n}

This is the standard, documented workaround for this exact Node-on-Windows spawn pattern (manually pre-quoting a .cmd/.bat invocation string) — without it, every Windows install of the codex-cli IDE integration fails, unconditionally.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions