---
title: "How to Use NVM with Fish Shell"
description: "Install and configure nvm.fish to manage multiple Node.js versions in Fish Shell. Covers installation, switching versions, .nvmrc support, and default versions."
date: 2026-02-19
categories: ["vps"]
tags: ["fish-shell"]
---

import Notice from "@components/widgets/Notice.astro";

The original nvm (Node Version Manager) is a Bash script. It doesn't work in Fish. If you try sourcing it in Fish, you get syntax errors because nvm relies on POSIX shell features that [Fish deliberately doesn't support](/fish-shell-vs-bash-vs-zsh/).

The fix is **nvm.fish** — a separate Node version manager written entirely in Fish. Same concept (install and switch between Node versions), different implementation. It's made by the same person who built [Fisher](/best-fish-shell-plugins/), and it works well.

## Install nvm.fish

You need [Fisher](/best-fish-shell-plugins/) first. If you don't have it:

```fish
curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher
```

Then install nvm.fish:

```fish
fisher install jorgebucaran/nvm.fish
```

That's it. No additional configuration needed. Restart your shell or open a new terminal tab.

## Install Node versions

```fish
# Install the latest release
nvm install latest

# Install the latest LTS version
nvm install lts

# Install a specific version
nvm install 22
nvm install 20.11.0
nvm install v18.19.1

# Install an LTS line by codename
nvm install iron    # Node 20 LTS
```

nvm.fish downloads pre-built Node binaries and stores them in `~/.local/share/nvm/` (following the XDG Base Directory spec). Each version gets its own directory.

## Switch between versions

```fish
# Use a specific version (current session only)
nvm use 22
nvm use lts
nvm use latest

# Check which version is active
nvm current

# List installed versions
nvm list
```

`nvm use` changes the active Node version for your current shell session. Open a new terminal and it reverts to the default (or whatever `.nvmrc` specifies for that directory).

## Set a default Node version

Without a default, new shell sessions won't have any nvm-managed Node on the PATH. Set one with a universal variable:

```fish
set --universal nvm_default_version v22
```

Now every new Fish session starts with Node 22 active. You can use `lts`, `latest`, or a specific version number.

## Automatic version switching with .nvmrc

This is the feature I use most. Create a `.nvmrc` file in a project's root directory:

```bash
echo "20" > ~/projects/legacy-app/.nvmrc
echo "22" > ~/projects/new-app/.nvmrc
```

When you `cd` into a directory with a `.nvmrc` (or `.node-version`) file, `nvm use` reads it automatically. This works by traversing up the directory tree until it finds the file.

```fish
cd ~/projects/legacy-app
node --version  # v20.x.x

cd ~/projects/new-app
node --version  # v22.x.x
```

<Notice type="info" title=".nvmrc formats">
nvm.fish supports the same `.nvmrc` formats as the original nvm: version numbers (`20`, `20.11`, `20.11.0`), `lts`, `latest`, and LTS codenames (`iron`, `hydrogen`). Files named `.node-version` work too.
</Notice>

## Install default global packages

If you want certain npm packages installed every time you install a new Node version:

```fish
set --universal nvm_default_packages yarn typescript tsx
```

Now `nvm install 22` will also run `npm install -g yarn typescript tsx` after downloading Node.

## Uninstall Node versions

```fish
nvm uninstall v18
nvm uninstall 20.11.0
```

This removes the installed binaries from the nvm data directory.

## Change the install mirror

If you need to use a mirror (corporate proxy, China mirror, etc.):

```fish
set --universal nvm_mirror https://npmmirror.com/mirrors/node
```

Default is `https://nodejs.org/dist`.

## Change the data directory

By default, nvm.fish stores everything in `~/.local/share/nvm/`. Change it with:

```fish
set --global nvm_data ~/.nvm
```

If you previously used the Bash-based nvm and have Node versions in `~/.nvm/`, this lets nvm.fish use that same directory. Versions installed by either tool should work.

## nvm.fish vs nvm (the Bash version)

| | nvm.fish | nvm (Bash) |
|---|---|---|
| Shell support | Fish only | Bash, Zsh |
| Written in | Fish | Bash/POSIX sh |
| Installation | Fisher plugin | curl script |
| Startup impact | Minimal (lazy loading) | Can add 200-500ms |
| `.nvmrc` support | Yes | Yes |
| Tab completions | Yes (Fish native) | Basic |
| LTS codenames | Yes | Yes |

The performance difference is worth mentioning. The Bash-based nvm is notorious for slow shell startup because it needs to be sourced in every new session. nvm.fish loads lazily — it only activates when you actually run `nvm` or switch to a directory with `.nvmrc`. You won't notice it in your startup time.

## nvm.fish vs fnm vs Volta

There are other Node version managers that work with Fish:

**fnm** (Fast Node Manager) — written in Rust, works with any shell. It's faster than nvm.fish for installs because it uses parallel downloads. Install with `brew install fnm` or `cargo install fnm`, then add `fnm env --use-on-cd --shell fish | source` to your config.fish.

**Volta** — also Rust-based, also cross-shell. Its main differentiator is per-project global package management. Install with `curl https://get.volta.sh | bash`, then add `set -gx VOLTA_HOME ~/.volta; fish_add_path $VOLTA_HOME/bin` to config.fish.

I use nvm.fish because it's pure Fish, integrates with Fisher, and I don't need the extra features of fnm or Volta. If you use multiple shells, fnm or Volta are better choices since they work everywhere.

## Troubleshooting

**`nvm: command not found`** — Fisher didn't install correctly, or your shell hasn't reloaded. Run `fisher list` to check if `jorgebucaran/nvm.fish` appears. Try opening a new terminal.

**Node not found after install** — Make sure you ran `nvm use <version>` after installing. Or set a default version: `set --universal nvm_default_version lts`.

**`.nvmrc` not being read automatically** — nvm.fish reads `.nvmrc` when you run `nvm install` or `nvm use` without arguments. For automatic switching on `cd`, make sure you're using a recent version of nvm.fish (`fisher update jorgebucaran/nvm.fish`).

## Related guides

- [Install Fish Shell on Ubuntu](/install-fish-shell-ubuntu/) — get Fish set up first
- [Fish Shell on macOS](/fish-shell-macos-setup/) — Mac setup including Homebrew Node
- [Best Fish Shell plugins](/best-fish-shell-plugins/) — nvm.fish and other recommended plugins
- [Fish Shell functions guide](/fish-shell-functions-custom-commands/) — create your own Node-related helper functions