Universal NVM (unvm)
A universal node.js version manager for Windows (no admin) and Unix.
-
Install is simple with a PowerShell script on Windows, or a bash script on Unix.
-
No admin required on Windows to install or use.
-
A linked system wide version that can be changed any time.
-
Change to any version independently in a terminal any time.
Table Of Contents
Installing Universal NVM on Windows using PowerShell
You don't need admin rights to install or use, only the permission to execute PowerShell scripts.
To install, start a Windows PowerShell and copy and the scripts below into the shell terminal and press enter:
cd $Env:USERPROFILE;
Invoke-WebRequest https://raw.githubusercontent.com/jchip/universal-nvm/v1.11.1/install.ps1 -OutFile install.ps1;
.\install.ps1;
del install.ps1
Tested on Windows 10 and 11.
Default Location: Installs to $Env:USERPROFILE\.unvm (e.g., C:\Users\YourName\.unvm)
Custom Location: Use the -nvmhome parameter:
.\install.ps1 -nvmhome C:\custom-location
Or set $Env:NVM_HOME before running the script. If neither is set, a Directory Browser dialog will open to choose a location.
$Env:NVM_HOME="C:\custom-location"
Troubleshooting
Running scripts disabled
If you get the error:
install.ps1 cannot be loaded because running scripts is disabled on this system.
Then you need to set execution policy for PowerShell to RemoteSigned with the command:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
See this StackOverflow question for details.
You need to keep this policy if you want to use nvm in PowerShell to switch node.js versions.
No PowerShell - Manual Install
If for some reason you absolutely can't have PowerShell or permission to install from it, then you can try to manually install following these steps:
- Download the package zip file from https://github.com/jchip/universal-nvm/archive/v1.11.1/.zip
- Extract this file to your home directory. You will get a new directory
universal-nvm-1.11.1.
- Rename it to
nvm, for example: C:\Users\<username>\nvm
- Download the zipfile https://nodejs.org/dist/v20.12.1/node-v20.12.1-win-x64.zip
- Extract this file to
C:\Users\<username>\nvm. You will get a new directory node-v20.12.1-win-x64
- Move
node.exe from that directory into C:\Users\<username>\nvm
- (optional) You can delete the directory after if you want.
- Open
RegEdit.exe, in HKEY_CURRENT_USER/Environment
- Add the following entries
NVM_HOME -> C:\Users\<username>\nvm
NVM_LINK -> C:\Users\<username>\nvm\nodejs\bin
- Append the following to the entry
Path
;C:\Users\<username>\nvm\bin;C:\users\<username>\nvm\nodejs\bin
- Open Command Prompt, and run
nvm install lts, note the version installed, and then nvm link <version>.
Make sure to replace <username> above with your actual user name.
Using Git Bash on Windows
If you want to use Universal NVM with Git Bash after installing on Windows via PowerShell:
Now you can use nvm commands in Git Bash just like on Unix systems.
Installing Universal NVM on Unix
To install, using cURL and the install script:
curl -o- https://raw.githubusercontent.com/jchip/universal-nvm/v1.11.1/install.sh | bash
or wget:
wget -qO- https://raw.githubusercontent.com/jchip/universal-nvm/v1.11.1/install.sh | bash
Default Location: ~/.unvm
Custom Location: Set NVM_HOME before running the install script:
export NVM_HOME=~/custom-location
Shell Initialization on Unix
The Universal NVM installation automatically updates your shell profile files to initialize nvm. The behavior differs between zsh and bash:
Zsh (macOS default)
For zsh users, the installer updates both .zshenv and .zshrc:
.zshenv: Sourced for ALL shells (interactive and non-interactive)
.zshrc: Sourced for interactive shells only
This means:
- ✅ Terminal sessions have nvm available
- ✅ Non-interactive scripts have nvm available
- ✅ GUI applications (like VS Code) have nvm available (when combined with
nvx --install-to-user)
Bash
For bash users, the installer updates .bashrc or .bash_profile:
.bash_profile: Sourced for login shells (macOS default)
.bashrc: Sourced for interactive non-login shells (Linux default)
- Non-interactive shells: NOT sourced by default
This means:
- ✅ Terminal sessions have nvm available
- ❌ Non-interactive bash scripts do NOT have nvm by default
Using nvm in bash scripts:
If you need nvm in a bash script, you have three options:
-
Source the profile explicitly in your script:
#!/bin/bash
source ~/.bashrc
node --version
-
Use a login shell with the shebang:
#!/bin/bash -l
node --version
-
Set BASH_ENV to automatically source a file for non-interactive shells:
export BASH_ENV=~/.bashrc
You can add this to your .bash_profile to make it permanent, but be aware this will affect all bash scripts system-wide.
Note: This is standard bash behavior by design - non-interactive shells have a minimal environment for performance and predictability.
Using PowerShell 7 on macOS/Linux
Universal NVM supports PowerShell 7 (pwsh) on macOS and Linux. If you have PowerShell 7 installed, you can use the PowerShell scripts directly on Unix systems.
Installing PowerShell 7:
On macOS (using Homebrew):
brew install --cask powershell
On Linux, follow the official PowerShell installation guide.
Using nvm in PowerShell on macOS/Linux:
After installing Universal NVM (via bash/zsh), you can use the PowerShell scripts:
# Set up NVM_HOME
$Env:NVM_HOME = "$HOME/.unvm"
# Add nvm function to your PowerShell profile
function nvm {
& "$Env:NVM_HOME/bin/nvm.ps1" @args
}
# Use nvm commands
nvm --version
nvm ls
nvm install lts
nvm use 20
Enable auto-use in PowerShell:
PowerShell on macOS/Linux supports the same auto-use functionality as Windows:
# Enable auto-use (adds to $PROFILE)
nvm auto-use enable
# Enable with cd wrapper mode (recommended)
nvm auto-use enable --cd
# Reload your profile
. $PROFILE
The auto-use setup will automatically detect that you're on Unix and configure the correct paths (using forward slashes instead of backslashes).
Adding to PowerShell Profile:
To make nvm available in every PowerShell session, add the following to your PowerShell profile ($PROFILE):
# Set up Universal NVM for PowerShell on macOS/Linux
$Env:NVM_HOME = "$HOME/.unvm"
$Env:PATH = "$Env:NVM_HOME/bin:$Env:PATH"
function nvm {
& "$Env:NVM_HOME/bin/nvm.ps1" @args
}
To find your profile location: $PROFILE (typically ~/.config/powershell/Microsoft.PowerShell_profile.ps1 on Unix)
To create it if it doesn't exist:
New-Item -Path $PROFILE -ItemType File -Force
Uninstalling Universal NVM
To completely remove Universal NVM from your system.
On Unix (macOS/Linux):
Using cURL:
curl -o- https://raw.githubusercontent.com/jchip/universal-nvm/main/bin/universal-nvm-uninstall.sh | bash
or wget:
wget -qO- https://raw.githubusercontent.com/jchip/universal-nvm/main/bin/universal-nvm-uninstall.sh | bash
The uninstall script will:
- Remove NVM configuration blocks from shell profiles (
.bashrc, .bash_profile, .zshrc, .zshenv)
- Remove the macOS LaunchAgent (
~/Library/LaunchAgents/com.universal-nvm.plist)
- Remove the Linux environment configuration (
~/.config/environment.d/10-universal-nvm.conf)
- Delete the NVM installation directory (default:
~/.unvm) and all installed Node.js versions
After running the uninstall script, close and reopen your terminal windows, and log out and log back in to clear environment variables.
On Windows (PowerShell):
cd $Env:USERPROFILE;
Invoke-WebRequest https://raw.githubusercontent.com/jchip/universal-nvm/main/bin/universal-nvm-uninstall.ps1 -OutFile universal-nvm-uninstall.ps1;
.\universal-nvm-uninstall.ps1;
del universal-nvm-uninstall.ps1
The uninstall script will:
- Remove
NVM_HOME and NVM_LINK from registry environment variables
- Remove NVM paths from your user PATH in the registry
- Delete the NVM installation directory (default:
%USERPROFILE%\.unvm) and all installed Node.js versions
After running the uninstall script, close and reopen your PowerShell windows, and log out and log back in to clear environment variables.
Usage
Usage: nvm <command> [options]
Commands:
nvm install <version> install the given version of Node.js
nvm uninstall <version> uninstall the given version of Node.js
nvm use <version> use the given version of Node.js in current shell
nvm auto-use [action] automatically use version from .nvmrc, .node-version,
or package.json
nvm auto-use enable [--cd] - enable automatic switching on cd
--cd: use cd wrapper mode (more efficient, only triggers on cd command)
nvm auto-use disable - disable automatic switching
nvm stop undo effects of nvm in current shell
[aliases: unuse]
nvm link <version> permanently link the version of Node.js as default
nvm unlink permanently unlink the default version
nvm ls list all the installed Node.js versions
nvm ls-remote list remote versions available for install
nvm cleanup remove stale local caches
nvm postinstall [version]
Invoke custom post install script for the given version
nvm init-env
(windows) Generate cmd file to initialize env for nvm
nvm undo-env (windows) Generate cmd file to undo env for nvm
Options:
--proxy, -p Set network proxy URL [string]
--verifyssl, --ssl, --no-ssl Turn on/off verify SSL certificate
[boolean] [default: true]
--corepack, --no-corepack Enable corepack after installation
[boolean]
--latest Match latest version to uninstall
--version, -V, -v Show version number
--help, -?, -h Show help. Add a command to show its help
[string]
Error: No command given
envs:
NVM_PROXY - set proxy URL
HTTP_PROXY - fallback proxy for HTTP requests
HTTPS_PROXY - fallback proxy for HTTPS requests
NVM_VERIFY_SSL - (true/false) turn on/off SSL certificate verification (default: true)
NVM_COREPACK_ENABLED - (true/false) enable corepack on install (default: false)
Proxy priority: -p flag > NVM_PROXY > HTTPS_PROXY > HTTP_PROXY
Examples:
nvm install lts
nvm install latest
nvm install 20 --corepack
nvm use 20
nvm uninstall 22.3
doc: https://www.npmjs.com/package/universal-nvm
Auto-Use: Automatic Version Switching
Universal NVM can automatically switch Node.js versions when you change directories. When enabled, it will check for .nvmrc, .node-version, or package.json files and automatically switch to the specified version.
Quick Start:
nvm auto-use enable
nvm auto-use enable --cd
nvm auto-use disable
nvm auto-use
Two modes available:
Auto-use offers two different modes for triggering version switches:
Which mode to choose:
nvm auto-use enable
nvm auto-use enable --cd
Note for Zsh users: Zsh always uses the optimal chpwd_functions mechanism (triggers only on actual directory change), so the --cd flag has no effect. Zsh users automatically get the best of both worlds!
What nvm auto-use enable does:
- Bash/Zsh: Adds auto-use setup to
~/.bashrc, ~/.bash_profile, or ~/.zshrc
- PowerShell: Adds auto-use setup to your PowerShell profile (
$PROFILE)
- Automatically detects your shell and modifies the correct profile file
After enabling, restart your terminal or source your profile:
source ~/.bashrc
source ~/.bash_profile
source ~/.zshrc
. $PROFILE
How it works:
- When you change directories, auto-use checks for version files (
.nvmrc, .node-version, or package.json)
- If found and a different version is needed, it switches and shows:
Using node v20.10.0 (auto-use from .nvmrc)
- If the version is already active, it does nothing (fast and silent!)
- If the version isn't installed, it shows an error once per shell session:
Version 16.0.0 from .nvmrc not installed
- The error is only shown once - subsequent
cd commands won't repeat the same error
- This helps you know which version to install without spamming your terminal
- If no version file is found, it does nothing (no error messages)
Manual vs Automatic invocation:
- Automatic (via
cd/prompt hooks): Uses --silent flag to suppress "no version file found" errors
- Manual (typing
nvm auto-use): Shows all messages including "no version file found" errors
When auto-use is triggered automatically by changing directories, you'll see:
- ✓ Version switch messages (always shown)
- ✓ "Version not installed" errors (shown once per shell session)
- ✗ "No version file found" errors (suppressed)
Version Files (.nvmrc, .node-version, and package.json)
When you run nvm use or nvm auto-use without specifying a version, Universal NVM will automatically look for a version specification in the current directory.
Supported sources (in priority order):
.nvmrc - nvm-specific version file (checked first)
.node-version - Universal Node.js version file (checked if .nvmrc not found)
package.json → engines.node - Fallback to package.json engines field (checked if no version files exist)
Usage:
echo "20.10.0" > .nvmrc
echo "20.10.0" > .node-version
cat > package.json << EOF
{
"name": "my-project",
"engines": {
"node": ">=18.0.0"
}
}
EOF
nvm use
File format:
.nvmrc and .node-version files should contain a plain text version number on a single line:
20.10.0
Or with the v prefix:
v20.10.0
Semver ranges:
All version sources support semantic versioning (semver) ranges. Universal NVM will automatically select the highest installed version that satisfies the requirement.
In .nvmrc or .node-version:
>=18.0.0
^20.0.0
20
In package.json engines.node:
The engines.node field supports the same semver syntax:
{
"engines": {
"node": ">=18.0.0"
}
}
{
"engines": {
"node": "^20.0.0"
}
}
{
"engines": {
"node": ">=18.0.0 <21.0.0"
}
}
If no installed version matches a semver range, you'll see a helpful error message suggesting which version to install.
Priority when multiple sources exist:
If multiple version sources exist in the same directory, Universal NVM will prefer them in this order:
$ cat .nvmrc
18.20.0
$ cat .node-version
20.10.0
$ cat package.json
{
"engines": { "node": ">=16.0.0" }
}
$ nvm use
Benefits of each approach:
.nvmrc - Best for teams using traditional nvm:
- Standard for nvm users
- Supports both exact versions and semver ranges
- Most familiar to developers using nvm
.node-version - Best for cross-tool compatibility:
- Universal standard for Node.js version specification
- Supports both exact versions and semver ranges
- Makes your project more portable
package.json engines.node - Best for existing projects:
- Already part of Node.js ecosystem
- Supports semver ranges for flexibility
- Single source of truth (no separate version file needed)
- Automatically used as fallback if no .nvmrc or .node-version exists
Environments
These env flags can be set:
NVM_PROXY | string | An URL to a network proxy (highest priority) |
https_proxy | string | An URL to a network proxy for HTTPS (lowercase, npm convention) |
HTTPS_PROXY | string | An URL to a network proxy for HTTPS (uppercase) |
http_proxy | string | An URL to a network proxy for HTTP (lowercase, npm convention) |
HTTP_PROXY | string | An URL to a network proxy for HTTP (uppercase) |
NVM_VERIFY_SSL | true/false | Controls SSL certificate verification (default: true) |
NVM_COREPACK_ENABLED | true/false | Enable corepack after installation (default: false) |
Proxy Priority:
- Command-line
-p flag (highest priority)
NVM_PROXY (overrides all protocol-specific proxies)
- Protocol-specific proxy (matches URL being fetched):
- For HTTPS URLs:
https_proxy → HTTPS_PROXY → http_proxy → HTTP_PROXY
- For HTTP URLs:
http_proxy → HTTP_PROXY
Following npm convention, lowercase environment variables are checked first, then uppercase.
SSL Certificate Verification (NVM_VERIFY_SSL)
By default, Universal NVM verifies SSL/TLS certificates when downloading Node.js from distribution servers. This ensures you're downloading from a trusted source.
When to disable SSL verification:
You may need to set NVM_VERIFY_SSL=false in these scenarios:
- Corporate proxies with SSL inspection - Your company's network intercepts HTTPS connections with self-signed certificates
- Internal mirrors - You're using an internal Node.js mirror with self-signed certificates
- Development environments - Testing with local servers using self-signed certificates
How to use:
export NVM_VERIFY_SSL=false
nvm install lts
$Env:NVM_VERIFY_SSL = "false"
nvm install lts
nvm install lts --no-ssl
Security Warning: Disabling SSL verification makes you vulnerable to man-in-the-middle attacks. Only disable it when you trust your network and understand the risks. Re-enable verification after completing your task:
export NVM_VERIFY_SSL=true
$Env:NVM_VERIFY_SSL = "true"
Corepack Support (NVM_COREPACK_ENABLED)
Corepack is a built-in Node.js feature (available since v16.9.0) that manages package managers like Yarn and pnpm. It allows you to use the exact package manager version specified in your project's package.json without manually installing them.
When to enable corepack:
- Using Yarn or pnpm - Your project uses Yarn or pnpm instead of npm
- Version consistency - You want to ensure everyone on your team uses the same package manager version
- Modern projects - You're working with projects that specify
packageManager in package.json
How to use:
export NVM_COREPACK_ENABLED=true
nvm install lts
$Env:NVM_COREPACK_ENABLED = "true"
nvm install lts
nvm install 20 --corepack
nvm install 18 --no-corepack
What corepack does:
After installing Node.js, Universal NVM will automatically run corepack enable, which:
- Makes
yarn and pnpm commands available
- Respects the
packageManager field in your package.json
- Automatically uses the correct package manager version for your project
Example package.json with packageManager:
{
"name": "my-project",
"packageManager": "pnpm@9.1.0",
"dependencies": {
"express": "^4.18.0"
}
}
With corepack enabled, running pnpm install will automatically use pnpm version 9.1.0, even if you don't have it installed globally.
Note: If corepack fails to enable (e.g., on Node.js versions before v16.9.0), Universal NVM will show a warning but will not fail the installation. You can manually enable it later with:
corepack enable
Priority: --corepack flag > NVM_COREPACK_ENABLED env var > default (false)
nvx - Execute with local node_modules
The nvx command allows you to run commands from your local node_modules/.bin directory without needing to specify the full path. It only runs locally installed packages, making it fast and predictable for running project-specific tools.
Basic Usage
nvx eslint src/
nvx prettier --write .
nvx jest --watch
Show Help
nvx --help
nvx -h
Installing to PATH (macOS/Linux only)
On macOS and Linux, you can optionally add the Universal NVM bin directory to your system PATH to make nvm commands available in GUI applications (like VS Code).
Install to User PATH (recommended)
This adds Universal NVM to your user's PATH. Works with GUI applications and doesn't require sudo:
macOS:
nvx --install-to-user
Linux:
nvx --install-to-user
Install to System PATH (all users)
This adds Universal NVM to the system-wide PATH for all users. Requires sudo:
macOS:
sudo nvx --install-to-system
Linux:
sudo nvx --install-to-system
Note for Windows users: On Windows, the installation script automatically adds both %NVM_HOME%\bin and %NVM_LINK% to your user PATH in the Windows registry. This makes Universal NVM, node, and npm immediately available to all applications (terminal, GUI apps like VS Code, etc.) without needing to run any additional commands. The nvx --install-to-user and nvx --install-to-system commands are therefore not needed on Windows.
How it Works
The nvx --install-to-user command uses platform-specific mechanisms to make Universal NVM available to GUI applications:
macOS:
Creates a LaunchAgent at ~/Library/LaunchAgents/com.universal-nvm.plist that runs at login to set environment variables for the user session. This makes Universal NVM available to:
- All GUI applications (VS Code, editors, etc.)
- Terminal windows
- Background processes
The LaunchAgent adds both paths to your environment:
~/.unvm/bin - nvm commands (nvm, nvx)
~/.unvm/nodejs/bin - Node.js executables (node, npm) - only available after running nvm link <version>
Linux:
Creates a systemd user environment file at ~/.config/environment.d/10-universal-nvm.conf. This file is read by systemd-based desktop environments at login and makes Universal NVM available to:
- All GUI applications launched from the desktop
- Applications started by systemd user services
- Any process in your user session
The environment file adds both paths:
~/.unvm/bin - nvm commands (nvm, nvx)
~/.unvm/nodejs/bin - Node.js executables (node, npm) - only available after running nvm link <version>
Important: The ~/.unvm/nodejs/bin directory is a symlink created by nvm link <version> that points to the default Node.js version. You must run nvm link to set up a default Node.js version before GUI applications can access node and npm. The install script does this automatically.
Note: On Linux systems not using systemd, this feature may not work. In that case, you can manually add the paths to your ~/.profile or consult your distribution's documentation for setting user environment variables.
Contributing and Release
Development
- Clone the repository
- Install fyn globally:
npm install -g fyn
- Install dependencies:
fyn install
- Make your changes
- Run tests:
fyn run test
- Run tests in watch mode:
fyn run test:watch
- Run tests with coverage:
fyn run test:coverage
- Test your changes on the target platform(s)
Testing:
This project uses Vitest for testing. The test suite includes:
- Unit tests for proxy configuration and priority logic
- Integration tests with a custom test proxy server
- Tests for malformed requests and error handling
- Real-world tests with nodejs.org URLs
Release Process
This project uses xrun for versioning and releasing. Do not use npm version or npm publish directly.
-
Update CHANGELOG.md - Add a new entry at the top with the version and date:
## X.Y.Z MMM DD, YYYY
- feat: description of new feature
- fix: description of bug fix
-
Bump version - Choose the appropriate version bump:
xrun version --patch
xrun version --minor
xrun version --major
-
Release - Publish to npm:
xrun release
License
MIT