Skip to content

macOS desktop app fails to detect Codex when login shell is Nushell #309

@ramarivera

Description

@ramarivera

Summary

On macOS, the packaged desktop app fails to detect codex when the account login shell is nushell and the app is launched from Finder.

The failure is caused by the macOS PATH bootstrap code invoking the user shell with POSIX-style arguments:

execFileSync(shell, ["-ilc", "echo -n $PATH"], ...)

That command is invalid for nu, so PATH normalization fails and later spawn("codex") reports:

Codex CLI (`codex`) is not installed or not on PATH.

This appears distinct from the existing fish-shell report in #218. Fish corrupts PATH formatting; Nushell fails earlier because the probe command itself is not valid.

Related issues:

Environment

  • macOS desktop app (/Applications/T3 Code (Alpha).app)
  • login shell: /opt/homebrew/bin/nu
  • codex installed and runnable outside T3
  • launchctl getenv PATH already includes the right entries, including ~/.local/share/mise/shims

Reproduction

  1. Set the macOS account shell to Nushell:
chsh -s /opt/homebrew/bin/nu
  1. Ensure codex is available in normal shell usage:
command -v codex
codex --version
  1. Launch T3 Code from Finder.
  2. Open the Codex provider status panel.

Actual result

The app shows:

Codex CLI (`codex`) is not installed or not on PATH.

Expected result

If codex is reachable for the user session, the desktop app should detect it correctly regardless of whether the user shell is zsh, bash, fish, or nu.

Root cause

The current macOS PATH bootstrap uses the desktop process environment shell directly:

  • apps/desktop/src/fixPath.ts
  • apps/server/src/os-jank.ts

Current logic:

const shell = process.env.SHELL ?? "/bin/zsh";
const result = execFileSync(shell, ["-ilc", "echo -n $PATH"], {
  encoding: "utf8",
  timeout: 5000,
});

For Nushell, this is not a valid command. Running the equivalent manually fails:

$ /opt/homebrew/bin/nu -ilc 'echo -n $PATH'
Error: nu::parser::unknown_flag
The `echo` command doesn't have flag `-n`.

Because the PATH probe fails, the app keeps a reduced inherited PATH and later spawn("codex") returns ENOENT / command-not-found.

Additional debugging notes

I verified all of the following on the affected machine:

  • launchctl getenv PATH contains the expected mise shim path.
  • with-env { PATH: (launchctl getenv PATH) } { ^command -v codex } resolves successfully.
  • Finder-launched T3 processes still show a reduced PATH and SHELL=/opt/homebrew/bin/nu.
  • The provider health check is ultimately calling codex --version, and that fails only because PATH bootstrap never succeeded.

Suggested fix

There are two separate robustness issues in the macOS PATH bootstrap:

  1. It assumes every shell accepts -ilc with POSIX shell command syntax.
  2. It assumes process.env.SHELL is always the right shell to probe from the packaged app.

A fix should make both codepaths more defensive:

  • apps/desktop/src/fixPath.ts
  • apps/server/src/os-jank.ts

At minimum:

  1. Stop using echo -n $PATH

    • use printf %s "$PATH"
  2. Fall back more robustly when resolving the shell

    • process.env.SHELL?.trim()
    • then os.userInfo().shell?.trim()
    • then /bin/zsh
  3. Handle non-POSIX shells explicitly

    • fish and nu should not be invoked with POSIX command text unless there is shell-specific handling
    • if the shell cannot be safely probed, keep the inherited PATH or use a macOS-specific fallback instead of silently failing

Why this matters

This is not just a Nushell feature request. The current implementation makes the packaged macOS desktop app brittle for any shell that does not accept POSIX-compatible -ilc 'echo -n $PATH' behavior.

That means the app can report a false-negative “codex not installed” state even when codex is correctly installed and visible to the user session.

🤖 This content was generated with AI assistance using GPT-5.4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions