n
A dependency-free Bash CLI for interactively installing and switching Node.js versions.
Repository Health
Technical Analysis
n is a command-line tool for managing multiple Node.js versions on macOS, Linux, and other Unix-like systems. Unlike version managers that rely on shell functions, sourced scripts, and per-shell subshells, n is a single Bash script that downloads a prebuilt Node.js release and installs it directly into a configurable prefix (/usr/local by default), overwriting the active version in place.
Run n on its own to get an interactive menu of already-downloaded versions, or n <version> to install a specific release by number, codename (lts, argon, boron), or an auto mode that reads .nvmrc, .node-version, or a project’s package.json engines field. Cached downloads make repeat installs and switches fast, and companion commands (n which, n run, n exec, n rm, n prune) let you inspect, execute against, or clean up cached versions without touching the active install.
Created and maintained by TJ Holowaychuk, with active stewardship from the community since, n has been a fixture of Node.js tooling since 2011 and remains one of the most widely used version switchers precisely because it avoids the shell-integration complexity that tools like nvm require.
What You Get
- An interactive terminal menu (
n) that lists cached Node.js versions and lets you select, install, or delete one with arrow keys or vim-style j/k navigation - Direct version installs via
n <version>supporting exact versions, partial versions (n 18), LTS codenames (argon,boron,carbon), and thelts/latest/currentaliases - An
autoversion-resolution mode that reads.n-node-version,.node-version,.nvmrc, or a project’spackage.jsonengines field to pick the right version for the current directory - Companion commands
n which,n run, andn execfor inspecting or executing against a cached Node.js version without changing the active install - Cache management commands (
n rm,n prune,n ls,n ls-remote) for removing stale cached versions or listing what’s installed and available remotely - Configurable install location and cache location via
N_PREFIXandN_CACHE_PREFIX, plus mirror and architecture overrides for restricted networks or unusual platforms
Common Use Cases
- Local Node.js version switching - a developer moving between projects pinned to different Node.js versions runs
n autoin each project directory to pick up the version specified in.nvmrcorpackage.json - One-shot CI/container installs - a Dockerfile pipes the
nscript directly from GitHub and runsn install --cleanup ltsto install Node.js and immediately discard the cache, keeping the image small - Preserving a newer npm across installs - a developer who has manually upgraded npm sets
N_PRESERVE_NPM=1so that switching Node.js versions withndoesn’t downgrade npm to the version bundled with the target Node.js release - Working behind a corporate proxy or in a restricted region - a user sets
N_NODE_MIRRORto an internal or regional mirror (e.g. an npmmirror.com endpoint) so Node.js downloads succeed without direct access to nodejs.org
Under The Hood
Architecture
n is implemented as a single Bash script (bin/n, roughly 1,700 lines) with no external runtime dependencies beyond standard Unix tools (curl/wget, tar) and an optional jq or node for resolving complex engines ranges. Execution begins with argument parsing that maps subcommands (install, run, exec, which, rm, prune, ls, ls-remote) and flags to a set of top-level Bash functions, followed by dispatch into version-resolution helpers (get_auto_version, get_nvmrc_version, get_engine_version) and installation routines (install, activate, clean_copy_folder) that download a tarball, verify it, and copy its contents into the configured prefix. State is deliberately minimal: the cache directory on disk is the only persistent store, and there is no daemon, shell hook, or sourced profile function — every invocation is a fresh, self-contained script execution.
Tech Stack
The project has no application-level dependencies; it is pure Bash targeting macOS, Linux, and WSL, using curl or wget for downloads and tar (with optional xz support) for extraction. Development tooling is limited to Bats (Bash Automated Testing System) with the bats-assert and bats-support helper libraries for the test suite, plus a Makefile for local test invocation and Dockerfiles under test/dockerfiles for testing across multiple base images.
Code Quality
The repository has an extensive Bats test suite covering install behavior, version resolution (auto, engine, nvmrc), listing, offline mode, and uninstall paths, run against several Docker base images to validate cross-distribution behavior. The script consistently uses readonly for constants, structured log/verbose_log/abort helpers for consistent output, and comments documenting each function’s synopsis, though as a Bash codebase it has no static type system — correctness relies on the test suite and shellcheck-style discipline (visible in inline shellcheck disable comments) rather than compiler guarantees.
What Makes It Unique n’s defining design choice is refusing shell integration: it does not modify shell profiles, define shell functions, or require sourcing — every other Node.js version manager in wide use relies on some form of shell hook to change the active version. By simply overwriting a single prefix directory, n trades multi-version-per-shell flexibility for simplicity and predictability, which explains its enduring popularity in Docker images and CI pipelines where shell integration is friction rather than a feature.