M
MeshWorld.
Node.js Developer Tools How-To Linux macOS 6 min read

How to Install and Use nvm (Node Version Manager)

Jena
By Jena

The system-installed Node.js is almost never the version you want. Different projects need different versions, and apt install nodejs gives you whatever is in the distro’s package repository — often years behind. nvm solves this: install it once, then switch Node versions per project or per shell.

:::note[TL;DR]

  • Install: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
  • Install Node: nvm install --lts or nvm install 22
  • Switch version: nvm use 22
  • Pin project version: create .nvmrc with 22 in your project root
  • Auto-switch on cd: add the shell hook to your .zshrc/.bashrc :::

Prerequisites

  • macOS, Linux, or WSL2 (Windows Subsystem for Linux)
  • curl installed (curl --version to check)
  • bash or zsh shell
  • No system Node.js conflicts — nvm works alongside them, but it’s cleaner to uninstall the system Node first if you have one

How do you install nvm?

Run the install script. This downloads nvm and adds the initialization lines to your shell config:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash

After the script runs, reload your shell config:

# If you use bash
source ~/.bashrc

# If you use zsh
source ~/.zshrc

The installer adds these lines to your shell config automatically. If nvm is not found after sourcing, check that they’re present:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

Verify the installation:

nvm --version
# 0.40.1

How do you install Node.js with nvm?

Install the latest LTS (Long Term Support) version — this is the right choice for most projects:

nvm install --lts

Or install a specific version:

nvm install 22        # Install Node 22 (latest patch automatically)
nvm install 20.11.0   # Install exact version
nvm install 18        # Install latest Node 18 patch

List what you have installed:

nvm ls

Install the latest available version of Node:

nvm install node      # "node" is an alias for the latest version

After installing, verify:

node --version
npm --version

How do you switch between Node versions?

# Switch to a version you already have installed
nvm use 22
nvm use 20
nvm use --lts

# Check which version is currently active
nvm current
# v22.x.x

# Use the system Node.js (if you had one before nvm)
nvm use system

nvm use only changes the version for the current shell session. Open a new terminal and you’re back to the default.


How do you set a default version?

# Use Node 22 by default in every new shell
nvm alias default 22

# Or point default at the LTS alias
nvm alias default lts/*

After setting a default, every new terminal starts with that version. Check with nvm alias to see all defined aliases.


How do you pin a Node version per project?

Create a .nvmrc file in your project root:

# In your project directory
echo "22" > .nvmrc
# or a specific version
echo "20.11.0" > .nvmrc

Now anyone who runs nvm use in that directory gets the right version:

cd my-project
nvm use
# Found '/home/user/my-project/.nvmrc' with version <22>
# Now using node v22.x.x (npm vx.x.x)

To auto-switch when you cd into a directory, add a shell function to your config.

For zsh — add to ~/.zshrc:

autoload -U add-zsh-hook

load-nvmrc() {
  local nvmrc_path
  nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version
    nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$(nvm version)" ]; then
      nvm use
    fi
  elif [ -n "$(PWD=$OLDPWD nvm_find_nvmrc)" ] && [ "$(nvm version)" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}

add-zsh-hook chpwd load-nvmrc
load-nvmrc

For bash — add to ~/.bashrc:

cdnvm() {
    command cd "$@" || return $?
    nvm_path="$(nvm_find_nvmrc)"
    if [ -n "$nvm_path" ]; then
        nvm use
    fi
}
alias cd='cdnvm'

What are the other useful nvm commands?

# List all installed versions
nvm ls

# List all available versions to install
nvm ls-remote

# List LTS versions only
nvm ls-remote --lts

# Reinstall global npm packages from a previous version
nvm install 22 --reinstall-packages-from=20

# Uninstall a version
nvm uninstall 18

# Run a script with a specific version without switching
nvm exec 18 node script.js

# Run the nvm-managed Node in a one-off command
nvm run 20 --version

# Where is nvm installed?
echo $NVM_DIR

How do you uninstall nvm?

# Remove the nvm directory
rm -rf "$HOME/.nvm"

Then remove the nvm lines from ~/.bashrc, ~/.zshrc, and ~/.profile.


Summary

  • nvm installs via a curl script and adds init lines to your shell config
  • nvm install --lts for the current LTS, or nvm install 22 for a specific major version
  • nvm use 22 switches the current session; nvm alias default 22 sets the persistent default
  • .nvmrc pins a version per project; the auto-switch hook makes nvm use run automatically on cd

FAQ

nvm is slow to start my shell. How do I fix it?

The nvm init script adds ~100ms to every shell startup. If that bothers you, add this lazy-loading snippet to your .zshrc or .bashrc instead of the standard init lines:

nvm() {
  unset -f nvm
  export NVM_DIR="$HOME/.nvm"
  [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
  nvm "$@"
}
node() {
  unset -f node
  export NVM_DIR="$HOME/.nvm"
  [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
  node "$@"
}

nvm only loads when you first run nvm or node, not on every shell open.

Should I use nvm or fnm?

fnm (Fast Node Manager) is a newer alternative written in Rust — startup time is under 1ms versus ~50-100ms for nvm. If shell startup speed matters or you’re on Windows, fnm is worth considering. If you’re on Linux/macOS and don’t have dozens of projects requiring different Node versions, nvm is fine and has broader documentation.

npm says “permission denied” when installing global packages. What’s wrong?

This usually means npm is trying to write to a system directory. With nvm, global packages should install into ~/.nvm/versions/node/vX.X.X/lib/node_modules/ without needing sudo. Check npm config get prefix — if it shows /usr or /usr/local, your npm is pointing to the system install, not the nvm-managed one. Run nvm use first to activate the nvm Node.