Skip to content

feat(env): implement vp env command for Node.js version management#524

Merged
fengmk2 merged 119 commits intomainfrom
vp-env-shims
Feb 7, 2026
Merged

feat(env): implement vp env command for Node.js version management#524
fengmk2 merged 119 commits intomainfrom
vp-env-shims

Conversation

@fengmk2
Copy link
Copy Markdown
Member

@fengmk2 fengmk2 commented Jan 31, 2026

Add shim-based Node.js version management with the following features:

  • vp env setup: Create shims (node, npm, npx) in ~/.vite-plus/bin
  • vp env doctor: Diagnostics for environment configuration
  • vp env default [VERSION]: Set/show global default Node.js version
  • vp env which <TOOL>: Show path to tool binary
  • vp env --current [--json]: Show current environment info
  • vp env --print: Print shell snippet for session

The shims intercept node/npm/npx commands and automatically resolve
the correct Node.js version based on:

  1. .node-version file
  2. package.json#engines.node
  3. package.json#devEngines.runtime
  4. User default from config
  5. Latest LTS fallback

Implementation includes:

  • Shim detection via argv[0] or VITE_PLUS_SHIM_TOOL env var
  • Resolution cache with mtime validation for fast repeated invocations
  • Platform-specific execution (execve on Unix, spawn on Windows)
  • Conflict detection for other version managers (nvm, fnm, volta, etc.)
  • Updated install.sh with shim setup and PATH configuration prompt

@fengmk2 fengmk2 self-assigned this Jan 31, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 31, 2026

Deploy Preview for viteplus-staging ready!

Name Link
🔨 Latest commit bd0a60d
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-staging/deploys/6981f43d67724600085c1454
😎 Deploy Preview https://deploy-preview-524--viteplus-staging.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown
Member Author

fengmk2 commented Jan 31, 2026

@fengmk2 fengmk2 added the test: e2e Auto run e2e tests label Feb 1, 2026
@fengmk2 fengmk2 force-pushed the vp-env-shims branch 10 times, most recently from 6e04051 to 31b2986 Compare February 2, 2026 15:22
@fengmk2 fengmk2 removed the test: e2e Auto run e2e tests label Feb 2, 2026
@fengmk2 fengmk2 force-pushed the vp-env-shims branch 6 times, most recently from a942407 to 9c1f325 Compare February 3, 2026 05:43
@fengmk2 fengmk2 marked this pull request as ready for review February 3, 2026 05:43
@fengmk2 fengmk2 added the test: e2e Auto run e2e tests label Feb 3, 2026
Comment thread CONTRIBUTING.md Outdated
@Brooooooklyn
Copy link
Copy Markdown
Member

cursor review

Scan profile files (~/.zshenv, ~/.profile) for env sourcing line before
printing IDE setup guidance. Shows green checkmark when configured,
yellow warning with fix instructions when not. Removes fragile launchctl
recommendation in favor of consistent env file sourcing.
…nstallations

Change VITE_PLUS_BYPASS from a boolean flag to a PATH-style list of bin
directories to skip. In SystemFirst mode, append the current bin_dir to
VITE_PLUS_BYPASS before exec'ing the found system tool. find_system_tool()
and find_system_node() now filter all paths listed in VITE_PLUS_BYPASS,
preventing infinite loops when two installations find each other's shims.
…stall has no args

Make the version argument optional for `vp env install`. When omitted,
resolves from .node-version, engines.node, or devEngines.runtime in the
current project. Errors with a helpful message if no project-pinned
version is found.
Move global package install/uninstall/update from `vp env install` and
`vp env uninstall` to `vp install -g`, `vp uninstall -g`, and
`vp update -g`. Remove npm global install interception from shim
dispatch. Update snap tests, doc comments, and RFC accordingly.
Add a --dry-run flag that previews what would be removed without
actually deleting anything. The flag requires -g and shows shims,
package dir, and metadata paths that would be affected.
… tests

Remove stale .node-version and package.json from the system temp
directory to prevent walk-up resolution from picking up unexpected
version configs. Also ensure shimMode is "managed" so shim dispatch
uses vite-plus managed Node.js instead of system Node.js.
Add `vp env i` as alias for `vp env install` and `vp env uni` as alias
for `vp env uninstall` for quicker command entry.
…sion override

- Add `vp env use [VERSION]` command that outputs shell-appropriate
  export/unset commands to stdout (eval'd by shell function wrapper)
- Add VITE_PLUS_NODE_VERSION env var as priority 0 in version resolution
- Add fast-path in shim cache to skip disk I/O when env var is set
- Extend env files (POSIX, fish, PowerShell) with shell function wrappers
  that intercept `vp env use` and eval its stdout
- Add -h/--help bypass in shell function wrappers to avoid eval'ing help text
- Patch env files for vp-dev binary name in install-global-cli.ts
- Add friendly error message for invalid version inputs (e.g., `vp env use d`)
- Update doctor diagnostics to report active session override
- Add snap tests for command output and shell wrapper behavior
…ist-remote`

- `vp env list` (alias `ls`): lists locally installed Node.js versions
  with current/default markers, fnm-style `* v{version}` format
- `vp env list-remote` (alias `ls-remote`): lists remote versions from
  registry with fnm-style output (v{version} per line, LTS in bright blue)
- Add `--sort asc|desc` flag to list-remote (default: asc)
- Add `SortingMethod` enum to CLI args
…t`/`vp ls` aliases

Move global package listing from `vp env` to `vp pm list -g` where
package management belongs. Add `vp list` and `vp ls` as top-level
aliases that rewrite to `vp pm list`. When `-g` is passed, the command
intercepts early (before JS runtime init) and delegates to the managed
packages listing with optional pattern filtering.
Show Package, Binaries, Node.js, and Installed fields in the same
style as the which command output.
When `vp env install` installs a version from the session override
(VITE_PLUS_NODE_VERSION), print a reminder to run `vp env use --unset`
to revert to project version resolution.
Add `#[serial]` and clear `VERSION_ENV_VAR` in 4 tests that call
`resolve_version()` without guarding against an inherited session
override (e.g. from `vp env use 24`).
…ted help

Replace custom `print_help()` with clap's `after_help` for Examples and
Global Packages sections. Both `vp env` and `vp env -h` now produce
identical output. Also switch `alias` to `visible_alias` so aliases
show in help text.
Swap the per-package block output (Package/Binaries/Node.js/Installed)
for a compact three-column table (Package, Node version, Binaries) with
dynamic column widths and bright-blue package names.
When running `vp ls` or `vp pm list` in a directory without a
package.json, catch the PackageJsonNotFound error and return success
with no output, matching `pnpm list` behavior.
doctor:
- Add section headers (Installation, Configuration, PATH, Version Resolution)
- Fixed 18-char aligned key-value columns with ✓/✗/⚠ status indicators
- Abbreviate HOME paths with ~ shorthand
- Make Conflicts and IDE Setup sections conditional (only shown on issues)
- Remove tutorial tips ("Run 'vp env on/off'")
- Dimmed remediation hints below errors/warnings
- Bold summary line (✓ All checks passed / ✗ Some issues found)
- Fix IDE integration check to match both $HOME and absolute path forms

which:
- Core tools now show Version (bright green) and Source below the path
- Global packages: show Node version instead of full path, date-only install
- Aligned 10-char padded labels with consistent indentation
- Error prefix changed from "vp:" to "error:" (red bold)
- Remove unused get_node_path() function
Write `$HOME/.vite-plus/env` instead of absolute paths like
`/Users/foo/.vite-plus/env` to shell config files. This makes the
config portable across sessions where HOME may differ (e.g.,
NFS-mounted homes, renamed user accounts).

Duplicate detection checks for both absolute and `$HOME`-relative
forms for backward compatibility with existing installs.
`detect_shell()` checked for `PSModulePath` to detect PowerShell, but
on macOS this variable can be set by Homebrew pwsh even in bash/zsh,
causing `vp env use` to output PowerShell-style commands. Gate both
`PSModulePath` and `COMSPEC` checks behind `cfg!(windows)` so
non-Windows shells default to POSIX after ruling out fish.
…hell wrapper

`vp env use` previously only output shell commands to stdout for eval.
In CI (GitHub Actions) where the shell wrapper isn't set up, the env var
was never set and subsequent shim invocations ignored the `use` command.

Now `vp env use` also writes the resolved version to
`~/.vite-plus/.session-node-version`. The shim and version resolution
code check this file after the env var but before `.node-version`, so
`vp env use` works both with and without the eval wrapper.

Resolution priority (updated):
0. VITE_PLUS_NODE_VERSION env var
1. .session-node-version file (NEW)
2. .node-version file
3. package.json#engines.node
4. package.json#devEngines.runtime
5. User default from config.json
6. Latest LTS
The session version file should only be written when the shell eval
wrapper is explicitly unavailable (e.g., CI environments). Without
this flag, `vp env use` behaves as before — outputting shell commands
for the wrapper to eval.

Usage in CI: `vp env use 20 --write-session`
Cleanup:     `vp env use --unset --write-session`
…ion flag

Replace the manual --write-session flag with automatic detection using
VITE_PLUS_ENV_USE_EVAL_ENABLE env var. Shell wrappers (POSIX, Fish,
PowerShell, cmd.exe) now set this var before calling vp, so `vp env use`
can detect whether its stdout will be eval'd. When the wrapper is absent
(CI, direct invocation), a session file is written automatically instead
of printing shell export commands to stdout.
The recursion guard (VITE_PLUS_TOOL_RECURSION) was incorrectly blocking
package binary re-invocations through the shim. Scoped the guard to core
tools only (node/npm/npx) since package binaries resolve via metadata
lookup and can't infinite-loop. Also removed the unnecessary recursion
env var set in dispatch_package_binary().
Add YYYY-MM-DD pattern to replaceUnstableOutput() so the Installed date
in `vp env which` output doesn't cause snap test diffs across days.
@fengmk2 fengmk2 merged commit 194c0dc into main Feb 7, 2026
34 of 35 checks passed
@fengmk2 fengmk2 deleted the vp-env-shims branch February 7, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test: e2e Auto run e2e tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants