nvm 0.40.7: The Per-Shell Node Version Manager That Still Runs on Plain POSIX Sh
nvm installs and switches between Node.js versions from a POSIX shell, with per-project version files and aliases.
At a glance
- What is it?
- nvm is a per-user, per-shell Node.js version manager for POSIX shells. It installs multiple Node versions, switches via aliases or .nvmrc files, and works in bash, zsh, fish, and even dash. The trade-off is a shell-function design that demands careful PATH management and a sourcing step in every new shell.
- Who is it for?
- Adopt nvm if you work in a POSIX shell (bash, zsh, fish) and need per-project Node versions with minimal setup. Avoid it if you are on native Windows (use nvm-windows or fnm instead) or if you need a single static binary with no shell function overhead.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What nvm Solves and Who It Is For
nvm solves a specific problem: developers who must run different Node.js versions for different projects, or who need to test against multiple releases without reinstalling. The README shows a direct workflow: `nvm install 24` then `nvm use 22` and the active `node` command changes. That is the entire promise. It is for anyone who lives in a POSIX shell: bash, zsh, fish, dash, ksh, or sh. It is also for macOS users and for Windows users running WSL. It is not for native Windows without a compatibility layer, and the README's compatibility section hints at that. The tool is designed to be installed per-user, not system-wide, and it is invoked per-shell. That means each new terminal window must source nvm again unless you set a default. It is a simple model, but it has consequences.
How nvm Works: Shell Functions, Not Binaries
nvm is not a compiled binary. It is a shell script that defines a function, also named `nvm`. When you run `nvm use 22`, the function modifies the current shell's environment, specifically the `PATH` variable, to point to the directory containing Node 22's binaries. That is why it must be sourced, not executed. The install script clones the repository to `~/.nvm` and adds two lines to your profile file: one that sets `NVM_DIR` and one that sources `nvm.sh`. The sourcing is what loads the function into your current shell. The README's example output shows `Now using node v22.22.1` after `nvm use 22`, which is the function changing `PATH` and then reporting the new version. This design means nvm can work in any POSIX shell because it only uses standard shell constructs. But it also means that if you run `nvm` from a script without sourcing it first, you get a command not found error. That is a core constraint.
Getting It Running: Install, Source, and Verify
The README gives a one-liner for installation: `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash`. The same command works with `wget` if you prefer. The script clones the repo and attempts to edit your profile file. If it picks the wrong profile, you can set `PROFILE` to the correct path and rerun. You can also prevent it from editing any profile by setting `PROFILE=/dev/null`. After installation, you must either open a new shell or source the profile manually. To verify, the README suggests running `command -v nvm` to confirm the function is loaded. For a fresh shell, the profile snippet sets `NVM_DIR` to `$HOME/.nvm` or `$XDG_CONFIG_HOME/nvm` if that variable is set. You can add `--no-use` to the source line to avoid auto-selecting a default version. The installer supports customizing `NVM_SOURCE`, `NVM_DIR`, and `NODE_VERSION` as environment variables. These are real commands and variables you can use.
Per-Project Versions with .nvmrc and Aliases
The README includes a section on `.nvmrc` files, which let you pin a Node version per project. You create a file containing a version number, and then `nvm use` reads it. The README also describes aliases, which are named shortcuts for specific versions. For example, you can set an alias like `nvm alias default 20` to make that the fallback when no `.nvmrc` is present. The deeper shell integration section shows how to automatically call `nvm use` when you enter a directory containing a `.nvmrc`. The README provides snippets for bash, zsh, and fish. For bash, it suggests adding a function to your `cd` hook that checks for a `.nvmrc` and runs `nvm use`. This is a manual setup step; nvm does not do it automatically. That is a limitation: you have to write your own shell hook. The README gives the code, but it is not built-in.
Real Limitations: PATH Pollution and Non-Interactive Shells
One genuine limitation is that nvm modifies `PATH` in a way that can be hard to reason about. Each `nvm use` prepends a new Node directory, and if you switch versions frequently, your `PATH` can accumulate entries. The README includes a section on restoring `PATH`, which suggests that this is a known problem. Another limitation is non-interactive shells. In a Docker container, the README notes that regular profile files are not sourced, so nvm does not load automatically. You have to manually source `nvm.sh` in your Dockerfile or entrypoint. This makes nvm awkward for CI jobs unless you explicitly handle it. The README has a dedicated subsection for Docker for CICD jobs, which indicates the maintainers know this is a friction point. If you need a version manager that works in a plain `sh` script without sourcing, nvm is the wrong tool.
Alternatives: nvm-windows and fnm
The most direct alternative is nvm-windows, which is a separate project for native Windows. It uses a symlink approach rather than shell functions, so it works in cmd or PowerShell without sourcing. The difference is fundamental: nvm-windows does not need a profile snippet because it is a real executable. Another alternative is fnm, a Node version manager written in Rust. fnm is a compiled binary that does not require shell functions for basic use, though it still needs a shell integration for automatic version switching. The key difference is that fnm is faster because it is precompiled, and it does not require a shell function to be loaded into every shell session. If you are on Linux or macOS and want a single binary with no profile edits, fnm is a reasonable choice. nvm's advantage is that it is pure shell, so it works in any POSIX shell including dash and ksh, which fnm may not support as cleanly.
Maintenance, Upgrade, and License
nvm is actively maintained, with recent releases in 2026 (v0.40.7, v0.40.6, v0.40.5). Upgrading is done by rerunning the install script, which the README states will update the existing installation. The repository is not archived, and the default branch is master. The license is MIT, which permits commercial use, modification, and distribution with attribution. There is no separate contributor license agreement mentioned. The maintenance cost is low for users: you only need to rerun the install script to get updates. However, the shell-function design means that any shell profile changes you made for nvm must be preserved across upgrades. The README does not mention a migration path for custom aliases or settings, so you should back up your `.nvmrc` files and any shell hooks you added. The project has a maintainers section and a project support section, but no explicit funding model is described in the README.
Editorial conclusion
Adopt nvm if you work in a POSIX shell (bash, zsh, fish) and need per-project Node versions with minimal setup. Avoid it if you are on native Windows (use nvm-windows or fnm instead) or if you need a single static binary with no shell function overhead. Before adopting, verify that your shell profile is correctly edited by the installer, test that `nvm use` works in a fresh shell, and decide whether the per-shell sourcing model fits your CI images. nvm is a mature, MIT-licensed tool, but its core value depends on you accepting the shell-function approach.
Community notes