Skip to content

fix(desktop): inherit login-shell PATH so nvm/asdf/fnm reach run_command (#1252)#1331

Merged
esengine merged 1 commit into
mainfrom
fix/desktop-login-shell-path
May 19, 2026
Merged

fix(desktop): inherit login-shell PATH so nvm/asdf/fnm reach run_command (#1252)#1331
esengine merged 1 commit into
mainfrom
fix/desktop-login-shell-path

Conversation

@esengine

Copy link
Copy Markdown
Owner

Summary

GUI launches on macOS / Linux start without running the user's shell init — .bashrc / .zshrc / profile never execute, so PATH entries injected by version managers like nvm, asdf, fnm, volta, mise are absent from the Tauri process environment. The bundled Node we spawn inherits that empty PATH, and the first run_command that tries to invoke npm ENOENTs.

Probe the user's login-shell PATH once at desktopCommand startup:

$SHELL -ilc 'printf %s "$PATH"'

with a 2-second timeout and a __REASONIX_PATH__= marker so rc files that print banners / completion notices on every interactive shell don't corrupt the output. Prepend missing entries onto process.env.PATH. The existing resolveExecutable in src/tools/shell/exec.ts reads PATH at call time, so every run_command / run_background from this point on sees the augmented PATH.

  • No-op on Windows — system PATH already reaches GUI processes there.
  • Cached after first probe so the ~hundred-ms $SHELL -ilc cost is paid exactly once.
  • Logs how many entries were merged in to stderr so the same bug is one-line-debuggable next time.

Why this and not e.g. Tauri-side env injection in Rust

Tauri's Command::new() does inherit the GUI process env, which is the problem. Whether we patch the env in Rust (before spawning Node) or in TS (after Node starts), the same $SHELL -ilc probe is needed. Doing it in TS keeps the fix localized to the Node entry, doesn't require a Rust rebuild on iteration, and the cache + log already live in the JS process.

Test plan

  • npm run verify — 232 test files / 3,254 tests pass
  • tests/desktop-login-shell-path.test.ts — 4 new tests: Windows no-op, augment no-op on Windows, timeout returns null cleanly, idempotence
  • npm run lint clean
  • npm run typecheck clean

Closes #1252

Closes #1252.

GUI launches (double-click the desktop app on macOS / Linux) start
without running the user's shell init — `.bashrc` / `.zshrc` / profile
never execute, so PATH entries injected by version managers like
nvm, asdf, fnm, volta, mise are absent from the Tauri process's
environment. The bundled Node we spawn inherits that empty PATH, and
the first `run_command` that tries to invoke `npm` ENOENTs.

Probe the user's login-shell PATH once on `desktopCommand` startup
(`$SHELL -ilc 'printf %s "$PATH"'`, 2-second timeout, framed with a
marker so rc files that print banners don't corrupt the output) and
prepend any missing entries onto `process.env.PATH`. The existing
`resolveExecutable` in `src/tools/shell/exec.ts` reads PATH at call
time, so every `run_command` / `run_background` from this point on
sees the augmented PATH.

- No-op on Windows: system PATH already reaches GUI processes.
- Cached after first probe so we pay the ~hundred-ms `$SHELL -ilc`
  startup cost exactly once.
- Stderr message announces how many entries were merged in so the
  same bug is one-line-debuggable the next time someone hits it.

Tests in `tests/desktop-login-shell-path.test.ts` cover the Windows
no-op path, idempotence on a second call, and graceful null return
on a 1ms timeout.
@esengine esengine merged commit 8355c6f into main May 19, 2026
4 checks passed
@esengine esengine deleted the fix/desktop-login-shell-path branch May 19, 2026 11:58
esengine added a commit that referenced this pull request May 20, 2026
#1331 added augmentProcessPath() in desktopCommand so the Tauri-spawned
Node could see nvm/asdf/fnm/volta/mise PATH entries — the GUI process
never runs the user's shell init. #1334 was branched before #1331 landed
and the rebase dropped the import + call without it being part of the
QQ-runtime work.

Re-add the import and the call site, no behavior change beyond restoring
the previous fix.

Co-authored-by: reasonix <reasonix@deepseek.com>
ChasLui pushed a commit to ChasLui/DeepSeek-Reasonix that referenced this pull request May 23, 2026
ChasLui pushed a commit to ChasLui/DeepSeek-Reasonix that referenced this pull request May 23, 2026
…se (esengine#1361)

esengine#1331 added augmentProcessPath() in desktopCommand so the Tauri-spawned
Node could see nvm/asdf/fnm/volta/mise PATH entries — the GUI process
never runs the user's shell init. esengine#1334 was branched before esengine#1331 landed
and the rebase dropped the import + call without it being part of the
QQ-runtime work.

Re-add the import and the call site, no behavior change beyond restoring
the previous fix.

Co-authored-by: reasonix <reasonix@deepseek.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

桌面版无法使用npm

1 participant