Node.js and Bun versions, with a sandbox around every install
Install and switch runtimes, and nvx follows the version each project pins when you enter its folder. Installs from npm, yarn, pnpm and bun, and tools started with npx or bunx, run inside an OS sandbox. It limits where they can write and blocks hosts you did not allow.
irm https://nvx.run/install.ps1 | iexWhat nvx does
It switches runtimes per project, checks what you are about to install, and contains the install while it runs. A policy file in the repo governs the checks and the sandbox. Full docs →
Versions, per project
Install and pin Node.js or Bun, and switch on cd from a .nvmrc, .node-version or package.json. Session-scoped, so a new terminal is unaffected until it reads the same pin.
Checked before it runs
Before anything runs, nvx checks each package for known advisories, lookalike names and a very recent publish date. For an npm install the advisory and age checks cover every package npm resolves, dependencies included. A version published in the last 24 hours waits for your approval, because that is when a compromised release is usually caught.
Installs, contained
You type the same command. nvx runs it inside the platform sandbox (AppContainer, Landlock or Seatbelt) with a throwaway HOME and a scrubbed environment. It can write to the project and that home. Outbound connections reach only the hosts the allowlist names or you approve.
Governed by a file in your repo
The rules live in .nvx-policy.json, next to the code they cover, reviewed in a pull request and enforced on the machine. -y, --agent-mode and NVX_YES cannot widen the sandbox. An org baseline, set with "enforced": true in the global policy, is one a project may tighten and not loosen. nvx policy check gives CI a distinct exit code per failure, and nvx audit export hands the record of every block to a compliance pipeline.
How nvx compares
| Feature | nvx | nvm | fnm | volta | asdf | mise |
|---|---|---|---|---|---|---|
| Windows, macOS, Linux | ✓ | macOS, Linux | ✓ | ✓ | macOS, Linux | ✓ |
| Runtimes | Node.js, Bun | Node.js | Node.js | Node.js | many, via plugins | many, via backends |
| Auto-switch per project | ✓ | shell hook | ✓ | on invocation | on invocation | ✓ |
| Verified downloads | ✓ | ✓ | Not offered | Not offered | varies by plugin | ✓ |
| Supply-chain checks | ✓ | Not offered | Not offered | Not offered | Not offered | Not offered |
| Sandboxed installs | ✓* | Not offered | Not offered | Not offered | Not offered | opt-in, not Windows |
| Network allowlist | ✓ | Not offered | Not offered | Not offered | Not offered | opt-in, not Windows |
| Secrets hidden | ✓* | Not offered | Not offered | Not offered | Not offered | opt-in, not Windows |
| Policy file in repo | ✓ | Not offered | Not offered | Not offered | Not offered | opt-in, not Windows |
* With platform exceptions. On Windows, bun installs contained only on the drive Windows is installed on. On macOS, a contained install can read files outside the project, though not credential files such as ~/.ssh. Known limitations has the rest.
Out-of-the-box defaults, checked against each project on 18 September 2026. volta's maintainers announced in November 2025 that it is unmaintained.
Install
One command installs nvx on Windows, macOS or Linux. It is also on npm as @fstubner/nvx.
Command line
Try it
Questions
Common questions about nvx. What it does not cover is listed in full in Known limitations.
Basics
What is nvx?
nvx installs, switches and pins Node.js and Bun versions on Windows, macOS and Linux, and runs package installs inside an OS sandbox. It is one static binary with no dependencies.
What does it need to run?
Windows on x64, macOS on Apple silicon or Intel, or Linux on x86_64 or arm64. nvx is one static binary and needs nothing installed alongside it.
On Linux the sandbox needs kernel 5.13 or later with Landlock enabled and unprivileged user namespaces. The network allowlist also needs the ip command from iproute2. When one is missing, contained commands refuse to run, so nothing runs uncontained. nvx doctor checks whether a contained process can start. On macOS the sandbox uses sandbox-exec, which ships with macOS.
Does it replace nvm, fnm or volta?
Yes. nvx installs, switches, pins and auto-switches on cd just as they do. On Windows, that includes NVM for Windows, a separate project despite the name. What nvx adds beyond any of them is containment. Installs run inside an OS sandbox with a scrubbed environment and an egress allowlist, on Windows, macOS and Linux.
The platforms differ in the details. macOS contains reads of credential stores only, and on Windows bun installs contained only on the drive Windows is installed on. Known limitations lists the rest.
Do I have to change how I run npm?
No. nvx puts shims on PATH, so npm install is still npm install. It is contained when it runs code you did not write, and nothing else about your workflow changes.
Can one project use both Node.js and Bun?
Yes. nvx use node@20 and nvx use bun@1.2 activate independently in the same shell, and neither takes the other off PATH. Toolchains installed outside nvx stay visible and run alongside them, uncontained unless they run through nvx.
The Docker provider picks its image from the active runtime, node:<version> or oven/bun:<version>. It has no setting for another image, so a stack that needs both in one container needs your own Dockerfile or docker-compose setup.
Containment
What can a contained install actually reach?
Your project directory, including its lockfile and node_modules, and a throwaway home directory of its own. Environment variables are scrubbed. It can write to the project and that home. It can read the project's .git and cannot write it. Outbound connections are limited to an allowlist that by default names the npm registry and the OSV vulnerability API, and GitHub's download hosts for Bun.
Is macOS protected the same way as Windows and Linux?
No. On Windows and Linux a contained install cannot read your home directory. On macOS the Seatbelt profile allows filesystem reads and denies the known credential stores by path. SSH keys, cloud credentials and your npm token are out of reach on all three. On macOS other files in your home, other projects included, can still be read by absolute path. Writes and outbound connections are contained on macOS too.
npm 12 blocks install scripts by default. Is this still needed?
It closes the biggest hole, and nvx is about what is left.
Packages that genuinely need a build step get approved, and that approval is permanent, so a later compromise of an approved package inherits it. Your bundler, test runner and dev server evaluate package code, which no script setting touches. A git dependency can override the git binary through .npmrc and run despite --ignore-scripts. Older npm and yarn classic have no per-package mechanism at all.
Containment is also a different thing from detection. The packages in the August 2026 ChainDrop compromise carried valid GitHub Actions provenance.
Is my own code sandboxed too?
Not by default. Containment covers installs and updates, such as npm install and npm update, and ad-hoc tool runners such as npx and bunx. npm run build, npm test and node run uncontained at the standard isolation level. Set isolation.level to strict to extend containment to your own code.
What happens when an install tries to reach a host I have not allowed?
At an interactive terminal nvx asks whether to allow that host, and a yes lasts for that run only. With nobody to answer, it refuses the connection and names the host.
To allow a host for good, add it to isolation.network.allow_hosts in a policy file. nvx will not honour a project file that widens the allowlist until you have approved that file. Passing -y or --agent-mode, or setting NVX_YES, approves neither the host nor the file, because an agent will answer yes to anything.
Can I run a dev server, or reach a local service, from the sandbox?
Yes. On Windows a server started in the sandbox reports itself listening, but Windows refuses connections into it from outside, so publish the port with --expose. nvx --expose 5173:8080 npx vite makes port 5173 inside reachable at 8080, and the two numbers must differ. Linux and macOS need no flag.
For a service already running on your machine, use --connect for one run or allow_hosts in a policy. Containment has the details.
Does it work with AI coding agents?
Yes, with no configuration. An agent runs the same npm install and npx commands you would, and the nvx shims on PATH check and contain them the same way.
That reduces the risk from typosquats, known-vulnerable versions and install scripts, and is no guarantee against a determined or novel attacker. SECURITY.md has the threat model and its limits.
Using it
What does the sandbox cost in speed?
On Windows a contained command costs a few hundred milliseconds to about a second, because nvx prepares an isolated home and checks permissions first. A project's first contained run takes a few seconds. Measured on Windows 11, a project's first contained run took about 2.4 s and each one after took about 390 ms. A second Windows 11 machine, measured on 2026-08-29, gave 2.9 s first and 785 ms steady, the median of 8 runs. The first run after nvx stages a new runtime copies the whole distribution and has been measured at 45 s to 3 minutes.
A command that is not contained pays only the shim's dispatch, about 75 ms on Windows. Three runs on one machine gave medians of 73.8, 74.2 and 77.1 ms. No figure has been established on Linux or macOS. The enforcement matrix has the measurements.
Does switching versions affect my other terminals?
No. nvx use and the switch on cd set PATH and NPM_CONFIG_PREFIX in the shell they run in, and change no system-wide path or link. A build running in another terminal is unaffected. Commands has the details.
Does nvx handle TypeScript and bundler commands?
Yes. Global and project-local tools such as tsc, ts-node, vite and webpack run on the selected Node.js version. Project-local tools are contained only at the strict isolation level, like your own code. Containment has the details.
Can I install it from winget, Homebrew, Scoop or npm?
npm, yes. npm install -g @fstubner/nvx installs the binary for your platform and runs no install script. winget, Homebrew and Scoop not yet. The install script and the prebuilt release binaries work on all three platforms.
Can I use it in CI?
Yes. Once nvx install has added the project's version, the shims run it with no shell setup. A CI step only needs ~/.nvx/bin on PATH. With no terminal attached every prompt is refused, so a check that would ask fails the step instead of waiting.
NVX_YES=true approves the install-time checks, and each approval is printed and recorded. It does not approve a new egress host or a project policy that widens the sandbox. nvx policy check gives CI a distinct exit code for each kind of failure.
How do I uninstall it?
Take back what nvx granted, then delete it. On Windows, if you ever ran nvx setup, run nvx setup --undo from an Administrator terminal. Run nvx grants reset --all. Then delete ~/.nvx, remove the nvx lines from your shell profile, and take ~/.nvx/bin off your PATH. Installation has the steps in order.