NVM lets you install and switch between multiple Node.js versions on the same machine — essential for working on projects that require different Node versions. This reference covers every command you need, from first install to CI setup.
Quick reference
The 25 operations that cover 90% of everyday NVM use.
| Command | What it does |
|---|---|
nvm install node |
Install the latest Node.js |
nvm install 20 |
Install Node.js 20 (latest patch) |
nvm install 20.15.1 |
Install a specific version |
nvm use 20 |
Switch to Node 20 in current shell |
nvm use --lts |
Switch to the latest LTS version |
nvm current |
Show the active Node.js version |
nvm ls |
List all installed versions |
nvm ls-remote |
List all available versions |
nvm ls-remote --lts |
List available LTS versions |
nvm alias default 20 |
Set default version for new shells |
nvm alias default node |
Set latest as default |
nvm uninstall 18 |
Remove a Node.js version |
nvm run 18 app.js |
Run a file with a specific version |
nvm exec 18 npm test |
Run a command with a specific version |
nvm which 20 |
Show path to Node.js binary |
nvm install --reinstall-packages-from=18 |
Install version + migrate global packages |
nvm use |
Auto-detect version from .nvmrc |
nvm install |
Install version from .nvmrc |
nvm alias lts/* 20 |
Create a named alias |
nvm unalias myalias |
Remove a named alias |
nvm cache clear |
Clear the NVM download cache |
nvm deactivate |
Reset PATH to system Node |
nvm version-remote 18 |
Show latest patch for Node 18 |
nvm use system |
Switch to system-installed Node |
node -v && npm -v |
Verify active Node and npm version |
Installation
Linux and macOS
Install via the official install script:
# Install latest version of NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Or with wget
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
The script appends this to your shell config (~/.bashrc, ~/.zshrc, or ~/.profile):
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
Reload your shell:
source ~/.bashrc # or ~/.zshrc
nvm --version # verify: 0.39.7
Windows
On Windows, use nvm-windows (a separate project):
- Download the installer from github.com/coreybutler/nvm-windows/releases
- Run
nvm-setup.exe - Open a new terminal (as Administrator for first use)
nvm version # verify installation
nvm install 20 # install Node 20
nvm use 20 # activate it
node -v # v20.x.x
Note: nvm-windows has slightly different syntax. This cheat sheet covers POSIX nvm; nvm-windows commands are mostly the same but check its README for differences.
Installing Node.js versions
# Install latest stable release
nvm install node
# Install latest LTS (Long Term Support) — recommended for production
nvm install --lts
# Install a specific major version (latest patch for that major)
nvm install 20
nvm install 18
nvm install 22
# Install an exact version
nvm install 20.15.1
# List all remote versions for a major
nvm ls-remote 20
# Install, and migrate global packages from another version
nvm install 20 --reinstall-packages-from=18
LTS vs Current:
| Release | Description | When to use |
|---|---|---|
| LTS (Even numbers: 18, 20, 22…) | Long-term support, 30 months of patches | Production apps, team projects |
| Current (Odd numbers: 19, 21…) | Latest features, shorter support window | Trying new Node.js features |
| Latest | Bleeding edge | Personal experimentation only |
Switching versions
# Switch to a specific version in the current shell
nvm use 20
nvm use 18.20.4
# Switch to the latest LTS
nvm use --lts
# Switch to the latest installed
nvm use node
# Switch to the system Node.js (outside NVM)
nvm use system
# Check the active version
nvm current # e.g. v20.15.1
node -v # same output
npm -v # bundled npm version
nvm useonly affects the current terminal session. New terminals use the default.
Setting the default version
# Set default for all new shells
nvm alias default 20
nvm alias default 18.20.4
nvm alias default node # always use latest installed
nvm alias default --lts # always use latest LTS
# Create a named alias
nvm alias production 20.15.1
nvm use production
# List all aliases
nvm alias
# Remove an alias
nvm unalias production
Listing versions
# List installed versions
nvm ls
# Example output:
# v18.20.4
# -> v20.15.1 (current)
# v22.5.0
# default -> 20 (-> v20.15.1)
# lts/* -> lts/iron (-> v20.15.1)
# List all available remote versions
nvm ls-remote
# List available LTS versions only
nvm ls-remote --lts
# List available LTS versions for Node 20
nvm ls-remote 20 --lts
# Find the latest remote version for a major
nvm version-remote 20 # v20.15.1
The .nvmrc file
.nvmrc is a file at the root of your project specifying the required Node.js version. It makes version switching automatic:
# Create .nvmrc
echo "20" > .nvmrc
# or exact version
echo "20.15.1" > .nvmrc
# or LTS name
echo "lts/iron" > .nvmrc
# In the project directory — install and use the version from .nvmrc
nvm install # installs if not present
nvm use # switches to it
Automatically switch on cd (bash):
Add to ~/.bashrc:
cdnvm() {
command cd "$@" || return $?
nvm_path="$(nvm_find_up .nvmrc | tr -d '\n')"
if [[ ! $nvm_path = *[^[:space:]]* ]]; then
declare default_version
default_version="$(nvm version default)"
if [[ $default_version == "N/A" ]]; then
nvm use default
elif [[ $(nvm current) != "$default_version" ]]; then
nvm use default
fi
elif [[ -s "$nvm_path/.nvmrc" && -r "$nvm_path/.nvmrc" ]]; then
declare nvm_version
nvm_version=$(<"$nvm_path/.nvmrc")
declare locally_resolved_nvm_version
locally_resolved_nvm_version="$(nvm ls --no-colors "$nvm_version" | tail -1 | tr -d '\->*' | tr -d '[:space:]')"
if [[ "$locally_resolved_nvm_version" == "N/A" ]]; then
nvm install "$nvm_version"
elif [[ $(nvm current) != "$locally_resolved_nvm_version" ]]; then
nvm use "$nvm_version"
fi
fi
}
alias cd='cdnvm'
cdnvm "$PWD"
Automatically switch on cd (zsh with zsh-nvm plugin):
# In ~/.zshrc
export NVM_AUTO_USE=true
Or use avn for automatic version switching across all shells.
Running commands with a specific version
Without switching the active version:
# Run a file with Node 18
nvm run 18 server.js
nvm run 18 -- --inspect server.js # pass Node flags
# Run any command with Node 18
nvm exec 18 npm install
nvm exec 18 npx prettier --write .
# Check which binary would be used
nvm which 18 # /home/user/.nvm/versions/node/v18.20.4/bin/node
Global packages and version migration
Global packages (npm install -g) are per Node.js version. When you switch versions, previously installed globals are not available.
# Install global packages on the new version, migrating from old
nvm install 20 --reinstall-packages-from=18
# Manually reinstall globals on current version
nvm reinstall-packages 18
# List global packages for current version
npm list -g --depth=0
# Check globals for a specific version
nvm exec 18 npm list -g --depth=0
Best practice: Keep global installs minimal. Use npx for one-off tools, and devDependencies for project tools.
NVM in CI/CD
# GitHub Actions
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc" # reads .nvmrc
cache: "npm"
- run: npm ci
- run: npm test
In CI, prefer
actions/setup-nodeover installing NVM — it's faster and already available. Thenode-version-file: ".nvmrc"option makes it use the same version as local development.
# If you must use NVM in a shell script
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install # reads .nvmrc
nvm use
npm ci
npm test
Uninstalling versions and NVM itself
# Uninstall a specific Node.js version
nvm uninstall 18
nvm uninstall 18.20.4
# Deactivate NVM in the current shell (reset PATH)
nvm deactivate
# Uninstall NVM entirely
rm -rf "$NVM_DIR"
# Then remove the lines NVM added to ~/.bashrc / ~/.zshrc
Performance: speed up NVM shell startup
NVM can slow down shell startup because it sources a shell script on every new terminal. Options:
Option 1: Lazy loading (bash/zsh)
Replace the NVM init lines in your .bashrc/.zshrc with:
# Lazy load NVM — only runs when you first call nvm/node/npm
nvm() {
unset -f nvm node npm npx
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm "$@"
}
node() {
unset -f nvm node npm npx
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
node "$@"
}
npm() { node; npm "$@"; }
npx() { node; npx "$@"; }
Option 2: Switch to fnm (Fast Node Manager)
fnm is NVM-compatible (reads .nvmrc) and written in Rust — 40× faster startup:
# Install fnm
curl -fsSL https://fnm.vercel.app/install | bash
# Same commands as NVM
fnm install 20
fnm use 20
fnm default 20
fnm ls
Common NVM workflows
Starting a new Node.js project:
# Create project directory
mkdir my-project && cd my-project
# Install and pin a Node.js version
nvm install 20
nvm use 20
echo "20" > .nvmrc # pin for the team
# Initialize project
npm init -y
git init
echo "node_modules/" >> .gitignore
Troubleshooting a version-specific bug:
# Test with multiple versions without changing default
nvm exec 18 npm test
nvm exec 20 npm test
nvm exec 22 npm test
Upgrading Node.js version on a project:
# Install new version
nvm install 22
# Install project dependencies
nvm exec 22 npm install
# Run tests
nvm exec 22 npm test
# If tests pass, update .nvmrc and set as default
echo "22" > .nvmrc
nvm alias default 22
nvm use 22
# Update package.json engines field
# "engines": { "node": ">=22.0.0" }
NVM vs alternatives
| Tool | Language | Speed | .nvmrc support |
Windows | Notes |
|---|---|---|---|---|---|
| nvm | Shell | Slow startup | Yes | No (nvm-windows is separate) | Most widely used |
| fnm | Rust | Fast | Yes | Yes | Drop-in NVM replacement |
| volta | Rust | Fast | Per-project package.json |
Yes | Manages npm/yarn too |
| asdf | Shell | Medium | .tool-versions |
Limited | Manages many languages |
| n | Shell | Fast | .node-version |
No | Simpler, no shell patching |
| nvm-windows | Go | Medium | Yes | Yes | Windows-only, different codebase |
7 common mistakes
1. Forgetting that nvm use is session-scoped
# BAD — only affects THIS terminal
nvm use 20
# New terminal still uses default version
# GOOD — set the default
nvm alias default 20
2. Installing global packages then switching versions
# BAD — global package lost after switching
nvm use 18
npm install -g typescript
nvm use 20
tsc --version # command not found!
# GOOD — reinstall globals or use npx
nvm install 20 --reinstall-packages-from=18
# or use npx for one-offs:
npx tsc --version
3. Not committing .nvmrc
# BAD — teammates use different Node.js versions
# (no .nvmrc in repo)
# GOOD — commit .nvmrc so everyone uses the same version
echo "20" > .nvmrc
git add .nvmrc
git commit -m "chore: pin Node.js version to 20"
4. Using nvm install node instead of a specific version
# RISKY — "node" changes over time
nvm install node
# BETTER — pin a major version
nvm install 20 # always gets latest 20.x.x
nvm install 20.15.1 # exact pin
5. Slow shell startup (not lazy-loading)
# BAD — sources NVM on every shell start (50-500ms delay)
# (default install)
# GOOD — lazy load or switch to fnm
# See "Performance" section above
6. Running NVM in non-interactive scripts without sourcing
#!/bin/bash
# BAD — nvm not available in non-interactive shells
nvm use 20 # nvm: command not found
# GOOD — source nvm first
#!/bin/bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm use 20
7. Not updating NVM itself
# NVM is updated separately from Node.js
# To update NVM, re-run the install script — it upgrades in-place
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Check current NVM version
nvm --version
6 FAQ
Q: What is the difference between NVM and Node.js?
Node.js is the JavaScript runtime. NVM is a tool to install and manage multiple Node.js versions. You install NVM once, then use it to install different versions of Node.js. Think of NVM as a package manager for Node.js itself.
Q: Should I use LTS or Current?
Use LTS for anything that needs to run reliably — production servers, team projects, CI/CD. LTS versions receive security and bug fixes for 30 months. Use Current only to try out new Node.js features in personal projects.
Q: Why does nvm use not persist across terminal sessions?
nvm use only modifies the PATH in the current shell process. When you open a new terminal, it inherits the default. Use nvm alias default <version> to permanently set what new terminals get.
Q: Can I use NVM and Volta together?
Yes, but they can conflict if both modify PATH in your shell config. Pick one version manager and use it consistently. Volta is particularly good for projects where you want to lock both Node.js and npm/yarn versions without shell magic.
Q: How do I use NVM in a Docker container?
For Docker, skip NVM. Instead, use the official Node.js image:
FROM node:20-alpine
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .
CMD ["node", "server.js"]
If you truly need NVM inside Docker (e.g., testing across versions), install it in the Dockerfile:
FROM ubuntu:22.04
ENV NVM_DIR /root/.nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash \
&& . "$NVM_DIR/nvm.sh" \
&& nvm install 20 \
&& nvm alias default 20
ENV PATH $NVM_DIR/versions/node/v20.15.1/bin:$PATH
Q: What is .node-version vs .nvmrc?
.nvmrc is the NVM standard; .node-version is used by tools like n and volta. NVM reads .nvmrc by default. Many tools (fnm, asdf, volta, GitHub Actions setup-node) support both formats. Use .nvmrc for broadest compatibility.