Skip to content

Windows: codex doctor cannot inspect npm global root because it spawns npm instead of npm.cmd #22964

Closed

Description

@pironjulien

What happened?

On Windows, codex doctor reports that it cannot inspect the npm global root for an npm-managed Codex install:

[!!] install      npm-managed launch could not inspect npm global root
[!!] updates      npm update target could not be inspected

The redacted JSON details show the shared root cause:

npm root -g failed: program not found

But npm is available through the normal Windows npm shim:

> npm.cmd root -g
%APPDATA%\npm\node_modules

So the warning appears to be a false positive in the doctor/update-target diagnostics rather than a broken npm install.

Environment

OS: Windows x86_64
Codex CLI before update: 0.131.0-alpha.9
Codex CLI after update: 0.131.0-alpha.22
Install context: npm
Repo inspected at: openai/codex commit 326e31a

codex doctor --summary --ascii --no-color after updating to 0.131.0-alpha.22:

11 ok | 1 idle | 3 notes | 2 warn | 0 fail degraded

The warnings are both tied to npm global-root inspection.

Reproduction

On Windows with an npm-managed Codex CLI install:

npm install -g @openai/codex@alpha
codex --version
codex doctor --summary --ascii --no-color
codex doctor --json --ascii --no-color
npm.cmd root -g

Expected:

codex doctor should resolve the npm global root and compare it with CODEX_MANAGED_PACKAGE_ROOT.

Actual:

codex doctor reports npm root -g failed: program not found, while npm.cmd root -g succeeds.

Root-cause hypothesis

codex-rs/cli/src/doctor.rs currently calls:

run_command("npm", ["root", "-g"])

On Windows, npm is commonly resolved as npm.cmd. A direct process spawn can fail to resolve the bare npm command even when npm.cmd is present on PATH.

Proposed fix

Use a platform-specific npm command for the doctor npm-root probe:

#[cfg(windows)]
const NPM_COMMAND: &str = "npm.cmd";
#[cfg(not(windows))]
const NPM_COMMAND: &str = "npm";

Then call:

run_command(NPM_COMMAND, ["root", "-g"])

I validated this as a local patch in codex-rs/cli/src/doctor.rs, with platform regression tests:

#[test]
#[cfg(windows)]
fn npm_command_uses_windows_cmd_shim() {
    assert_eq!(NPM_COMMAND, "npm.cmd");
}

#[test]
#[cfg(not(windows))]
fn npm_command_uses_plain_binary_name() {
    assert_eq!(NPM_COMMAND, "npm");
}

Local verification

The patched local clone passed:

cargo test -p codex-cli npm_command -- --nocapture
cargo test -p codex-cli compare_npm_package_roots
cargo test -p codex-cli
cargo clippy --fix --tests --allow-dirty -p codex-cli

cargo test -p codex-cli result included:

11 passed
143 passed
all listed integration tests passed

I am not opening a PR because docs/contributing.md says unsolicited code contributions are currently closed, but this should be a small targeted fix if the maintainers agree with the diagnosis.

Activity

  1. added
    bugSomething isn't working
    CLIIssues related to the Codex CLI
    windows-osIssues related to Codex on Windows systems
    on May 16, 2026
  2. pironjulien commented on May 16, 2026

    @pironjulien
    Author

    For convenience, here is the exact local diff I validated:

    diff --git a/codex-rs/cli/src/doctor.rs b/codex-rs/cli/src/doctor.rs
    index a3742ba..8ff01b0 100644
    --- a/codex-rs/cli/src/doctor.rs
    +++ b/codex-rs/cli/src/doctor.rs
    @@ -105,6 +105,10 @@ const COLOR_ENV_VARS: &[&str] = &[
     const TERMINAL_DIMENSION_ENV_VARS: &[&str] = &["COLUMNS", "LINES"];
     const TERMINFO_ENV_VARS: &[&str] = &["TERMINFO", "TERMINFO_DIRS"];
     const LOCALE_ENV_VARS: &[&str] = &["LC_ALL", "LC_CTYPE", "LANG"];
    +#[cfg(windows)]
    +const NPM_COMMAND: &str = "npm.cmd";
    +#[cfg(not(windows))]
    +const NPM_COMMAND: &str = "npm";
     const REMOTE_TERMINAL_ENV_VARS: &[&str] = &[
         "SSH_TTY",
         "SSH_CONNECTION",
    @@ -884,7 +888,7 @@ fn npm_global_root_check() -> NpmRootCheck {
             return NpmRootCheck::MissingPackageRoot;
         };
     
    -    let output = match run_command("npm", ["root", "-g"]) {
    +    let output = match run_command(NPM_COMMAND, ["root", "-g"]) {
             Ok(output) => output,
             Err(err) => return NpmRootCheck::NpmUnavailable(err),
         };
    @@ -2982,6 +2986,18 @@ mod tests {
             );
         }
     
    +    #[test]
    +    #[cfg(windows)]
    +    fn npm_command_uses_windows_cmd_shim() {
    +        assert_eq!(NPM_COMMAND, "npm.cmd");
    +    }
    +
    +    #[test]
    +    #[cfg(not(windows))]
    +    fn npm_command_uses_plain_binary_name() {
    +        assert_eq!(NPM_COMMAND, "npm");
    +    }
    +
         #[test]
         fn config_overrides_from_interactive_preserves_global_options() {
             let interactive = TuiCli::parse_from([
    
  3. added a commit that references this issue on May 16, 2026
    de9c5c0
  4. added a commit that references this issue on Jun 27, 2026
    e355107
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingwindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions