# nvm-desktop: a Tauri GUI and nvmd CLI for switching Node.js versions

> nvm-desktop pairs a desktop app with the nvmd command line tool to install, switch and pin Node.js versions on macOS, Windows and Linux. The CLI is the part that survives contact with real projects, and the per-project binding is the feature worth checking before you migrate.

**1111mp/nvm-desktop** — Node Version Manager Desktop - A desktop application to manage multiple active node.js versions.

- Repository: https://github.com/1111mp/nvm-desktop
- Website: https://github.com/1111mp/nvm-desktop
- Stars: 1,400 · Forks: 74
- Language: TypeScript
- License: MIT
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/1111mp-nvm-desktop

## The problem nvm-desktop targets, and the audience it assumes

Node.js version management on a single machine is a solved problem with an awkward interface. The command line managers assume you live in a terminal. The Windows-specific tooling assumes you live on Windows. nvm-desktop takes the position that the same person wants both a window to browse available releases in and a shell command to switch versions without leaving the project directory.

The README lists the intended outcomes directly: install and uninstall Node.js versions quickly, switch the global version with one command or click, pin versions per project, keep environments isolated across versions, and choose GUI or CLI based on workflow. That last point is the design thesis. The GUI is for discovery and visual management; the CLI, invoked as nvmd, is for automation, scripts and terminal-first work. Both front ends sit on the same data directory, so a version installed by clicking appears in nvmd ls.

The audience is therefore a developer on macOS, Windows or Linux who already understands what a global Node version is, and who has felt the friction of a repository that needs an older runtime than the one installed system-wide. It is not aimed at CI containers, where a base image or a setup action is the cheaper answer, and it is not aimed at teams that want Node versions declared in a committed file and resolved automatically by other tooling.

## How the shims, versions directory and projects.json fit together

The architecture is a Tauri application: a Rust backend in src-tauri with a React and TypeScript front end in src, built with Vite. The package.json scripts confirm the split, with dev mapped to tauri dev and ui:dev mapped to vite for front-end-only work. The updater plugin is present as a dependency, which is how the app checks for new releases.

The runtime model is the part that matters. nvm-desktop stores everything under ~/.nvmd on macOS and Linux, and %HOMEPATH%\.nvmd on Windows. Inside that directory the README names five entries: bin/ holding shims for node, npm, npx, nvmd and corepack; versions/ holding the installed Node.js runtimes; a default file recording the global default version; projects.json holding per-project version bindings; and setting.json holding app settings such as mirror and language.

The shims in bin/ are what make switching work without restarting a shell. When you install a version, its runtime lands in its own directory under versions/, and the shim resolves which one to execute. A global switch rewrites the default file. A project binding writes an entry into projects.json, and the shim checks the current directory against those bindings before falling back to the global default. That is why nvmd use 18.20.4 --project followed by node -v reports the older version inside that directory only.

One consequence of this layout is worth stating plainly: isolation is the default. The README's FAQ says global npm packages are not shared between Node.js versions, and offers npm config set prefix "/path/to/shared-global" as the escape hatch. That is a real behavioural difference from managers that keep a single global prefix, and it changes how much disk the tool consumes once you have several runtimes installed.

## Installing nvm-desktop and running a first project binding

The README does not give a package-manager command. It points at GitHub Releases, so the install path is downloading a build for your platform from the releases page and running it. After that, the README asks you to confirm the toolchain is on your PATH by checking three versions in a terminal.

```bash
nvmd -V
node -v
npm -v
```

If any of those fail, the shims in ~/.nvmd/bin are not being picked up by your shell, and nothing else will work until they are. This is the first thing to verify, before installing a runtime.

With the CLI reachable, install a specific Node.js release. The README's example uses 20.18.0.

```bash
nvmd install 20.18.0
nvmd ls
```

The install downloads the runtime into ~/.nvmd/versions, and nvmd ls should list it alongside anything already present. Then make it the global default.

```bash
nvmd use 20.18.0
node -v
```

The node -v output should report v20.18.0. The switch is what the default file records, so a new shell in any directory resolves to that version.

For a repository that needs an older runtime, run the project-scoped form from the project root. The README's example pins 18.20.4.

```bash
nvmd use 18.20.4 --project
node -v
```

Inside that directory node -v should now report the pinned version, and the entry is written to projects.json. Two more commands round out the surface: nvmd current reports the active version, nvmd which node and nvmd which npm print executable paths, and nvmd uninstall 16.20.2 removes a runtime. The README's recommended workflow is exactly this sequence: open the project root, pin a version, confirm with node -v, then install dependencies.

## Where the isolation model costs you, and when to pick something else

The default isolation is the trade-off at the centre of this tool. Every installed runtime keeps its own global package tree, so a CLI you installed globally under one version is not there under another. That is correct behaviour if you are chasing a dependency-resolution bug that only appears on one runtime, and it is pure overhead if your workflow assumes a stable set of global tools across every version you keep around. The README acknowledges the gap and points at npm config set prefix, but that setting is global to your npm configuration, not scoped to nvm-desktop, so applying it changes behaviour for every Node.js version on the machine.

Disk usage follows from the same design. Each version under ~/.nvmd/versions is a full runtime, and there is no documented pruning or garbage-collection command beyond nvmd uninstall for versions you name explicitly. The README does not describe what happens to a projects.json entry when the version it references is uninstalled, and it does not document rollback if a switch leaves a shell in an unexpected state.

A second limitation is the install channel. Because the README directs users to GitHub Releases rather than a package manager, updates arrive through the app's updater plugin or by downloading a new build. If your environment requires software to come from a system package repository, this project does not fit that policy, and no amount of GUI convenience changes it.

Finally, the tool is per-machine and per-user. Nothing in the README describes a committed file that declares a project's Node version for other people or for CI. The binding lives in projects.json under your home directory, so a teammate cloning the same repository gets no version guarantee from it.

## How nvm-desktop differs from the command-line managers you already know

The obvious comparison is with the original nvm shell script and with nvm-windows. Both are terminal-only, and both are installed through their own mechanisms rather than a desktop installer. nvm-desktop's difference is not the version list, which is the same set of Node.js releases; it is that a GUI and a CLI read and write one shared state directory, and that per-project bindings are a first-class operation rather than something you assemble from a shell hook.

A second comparison is with version managers that read a committed file, such as the .node-version file that this repository itself carries at its root. That approach makes the version a property of the repository, visible in code review and reproducible on a fresh clone. nvm-desktop makes it a property of your machine. If your priority is that every contributor and every CI job resolves the same runtime without a manual step, the committed-file approach is the better fit and nvm-desktop is the wrong tool. If your priority is a visual inventory of what is installed and a quick switch while you work, the trade-off runs the other way.

The GUI also covers ground the CLI does not expose in the README: browsing available versions before installing, and settings for mirror and language. The mirror setting matters if you are downloading runtimes from a region where the default source is slow, and it is not something the CLI examples in the README show you how to change.

## Maintenance, licence and what upgrading involves

The repository is not archived, and the last push was on 2026-08-28. Releases are tagged with a version number and a display name, with v4.4.0 published on 2026-07-28, v4.3.3 on 2026-06-13 and v4.3.2 on 2026-04-10. The cadence is regular enough that a user should expect to update the application rather than install it once and forget it.

Upgrade cost is low for the CLI surface. The command set documented in the README is small and stable in shape: install, ls, use, current, uninstall, which, plus the --project flag. The risk sits in the data directory rather than the commands. Because versions/, projects.json and setting.json live under your home directory, an upgrade that changes the format of projects.json is a migration you cannot opt out of, and the README does not document a rollback path or a backup step before upgrading. Copying ~/.nvmd before a major version bump is cheap insurance that the documentation does not mention.

Building from source is a separate matter. The README lists Rust, Node.js and pnpm as prerequisites, with pnpm check, pnpm install and pnpm dev to run it, and pnpm build to produce artifacts under ./src-tauri/target/release/bundle. That is a Tauri toolchain, so anyone building rather than downloading is committing to keeping Rust and the platform's webview dependencies current.

The licence is MIT, which permits commercial and private use and modification, and requires the licence text and copyright notice to be preserved in distributions. That is a permissive arrangement, but it is not legal advice, and anyone redistributing a modified build should read the LICENSE file in the repository rather than this summary.

## Conclusion

Adopt nvm-desktop if you want a graphical way to browse and install Node.js builds and a CLI that can pin a version to a project root with nvmd use <version> --project. Do not adopt it if you need a package-manager install path or you rely on shared global npm packages across versions, since the README states environments are isolated by default. Verify first that nvmd -V, node -v and npm -v resolve after installation, then confirm that ~/.nvmd contains versions/, projects.json and setting.json before you bind any repository to a version.

## FAQ

### What is nvm-desktop in PC terms?

It is a cross-platform Node.js version manager that ships as a desktop application called nvm-desktop plus a command line tool called nvmd. It installs Node.js runtimes, switches the global version, and binds a version to an individual project.

### Is there an nvm-desktop for Windows?

Yes. The README states the tool supports macOS, Windows and Linux, and on Windows it stores its data under %HOMEPATH%\.nvmd rather than the home directory path used on macOS and Linux.

### How do I install nvm-desktop on Ubuntu or Windows 10?

The README does not give a package-manager command for either platform. It directs you to download a build from GitHub Releases, then confirm nvmd -V, node -v and npm -v all resolve in a terminal before installing any Node.js version.

### Are global npm packages shared between Node.js versions in nvm-desktop?

By default no, because the README says environments are isolated. To share them you set a common prefix with npm config set prefix "/path/to/shared-global".

### Should I use the nvm-desktop GUI or the nvmd CLI?

The README recommends the GUI for discovery and visual management, and the CLI for automation, scripts and terminal-first work. Both operate on the same data directory, so a version installed in the window shows up in nvmd ls.

### Where does nvm-desktop keep its files?

On macOS and Linux under ~/.nvmd, and on Windows under %HOMEPATH%\.nvmd. That directory holds bin/ shims, versions/ runtimes, the default global version, projects.json bindings and setting.json app settings.

## Sources

- [Official documentation](https://github.com/1111mp/nvm-desktop)
- [Official README](https://github.com/1111mp/nvm-desktop#readme)
- [Project repository](https://github.com/1111mp/nvm-desktop)
- [Release notes](https://github.com/1111mp/nvm-desktop/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/1111mp-nvm-desktop
