Skip to content

nushell wrapper calls sh unconditionally, including on Windows #3944

Description

@worktrunk-bot

Surfaced by the nightly survey of templates/nushell.nu. Not reproduced — I have no Windows+nushell host in CI, so this is a code-reading finding with the evidence below rather than an observed failure.

The inconsistency

templates/nushell.nu branches on the platform for its temp-file cleanup, so Windows is clearly a platform the wrapper expects to run on:

# branches so cleanup can never abort the wrapper. `hide rm` is not an
# option: it's a parse-time keyword that leaks out of this function into
# the user's session, silently unbinding their alias.
if $nu.os-info.family == "windows" {
try { rm -f $cd_file $exec_file $stdout_file }

But two other spots in the same file call sh unconditionally:

  • L129try { ^sh -c $script; 0 }, running an --execute body.
  • L167^sh -c $"exit ($exit_code)", the exit-code propagation path, reached whenever wt exits non-zero.

L167 is the wider path of the two: it fires on any failing wt command, not just --execute.

Why it's reachable on Windows

Shell::Nushell isn't platform-gated. It's in Shell::all(), and configure_shell.rs offers it purely on Shell::Nushell.is_installed() — no Windows exclusion. So wt config shell install on a Windows box with nu on PATH writes this wrapper.

The test that covers the failure path does include nushell — test_wrapper_handles_command_failure has a #[case("nu")] — but it sits inside mod unix_tests under #[cfg(unix)], so it only ever runs where sh exists. That's consistent with the gap never having shown up in CI.

For contrast, templates/powershell.ps1 needs no POSIX shell for either job: it uses Invoke-Expression $script for exec bodies and sets $global:LASTEXITCODE for propagation.

The design question

L167 looks mechanically replaceable with something nushell-native. L129 is the harder one, and it's why this is an issue rather than a PR: --execute bodies are POSIX snippets by construction — ShellEscapeMode::Posix is documented as "the wrapper-independent default for bash, zsh, and nushell". So on Windows there may be no correct shell to hand them to, and the options (require sh, refuse to install the nu wrapper on Windows, document the limitation, or something else) are a maintainer call rather than a mechanical fix.

Happy to implement whichever direction you'd prefer.

Possibly relevant: #2860 proposes moving wt switch --execute to an argv input model. If exec bodies stop being POSIX snippets, the L129 half of this may dissolve on its own, leaving only L167 to fix.

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