Skip to main content

Why nvm Is Written as a Shell Script

There is a circular problem at the heart of the Node version manager. You install nvm so you can switch between multiple versions of Node, but if nvm itself depended on Node to run, you would need a working Node installation before you could install Node. That makes no sense for a bootstrap tool. The practical answer the community settled on is to write nvm as a plain POSIX shell script that has no dependency on Node at all. It only needs a shell, and on a Unix system you already have one.

This is not an accident or a style preference. It is a hard requirement baked into how the tool works. nvm is installed by sourcing a single install script with your shell: you run a curl or wget command, pipe it to sh, and the function is added to your shell. From that moment nvm manages Node installations per user inside a directory like the home folder, and it switches between versions by changing a symlink. None of that touches Node itself, which keeps the tool usable even when no Node version is present yet.

There is a second, subtler reason the shell script approach is the right call, and it is worth appreciating on a fresh machine. The shell is the one piece of software guaranteed to exist in any environment where you would want Node in the first place. If you chose a compiled binary or a Node-based installer, you would inherit the very chicken and egg problem the tool exists to solve. A shell script sidesteps the dependency spiral entirely and works across sh, dash, ksh, zsh, and bash.

For a senior developer, this design is a small lesson in bootstrap tooling. When you build a tool whose job is to manage a runtime, you should not build it on that same runtime. You want the smallest, most universal thing available as your foundation. The script has to be careful about quoting and POSIX compatibility because it runs in many shells, which adds real maintenance burden, but that burden is the price of the guarantee it provides.

The shell script design also changes how people use it in practice. Because nvm is a shell function rather than a child process, it can affect your current shell's environment, which is exactly what you want when you switch a version and need your new session to pick it up. A Node program spawned as a subprocess could not mutate your parent shell's PATH the way the script does. The whole workflow depends on this integration.

So the next time you run nvm use and wonder why the tool is a wall of shell code instead of a tidy compiled binary, the answer is deliberate. It is written as a shell script because you cannot use Node to install Node, and because the meta-programming job of changing your interactive environment belongs in the shell. It is a case where the oldest, least glamorous technology in the stack turns out to be the exact right tool for the job.

We use cookies for ads and analytics.