This document provides guidance for AI coding agents when working with the Node Version Manager (nvm) codebase.
nvm is a version manager for Node.js, implemented as a POSIX-compliant function that works across multiple shells (sh, dash, bash, ksh, zsh). The codebase is primarily written in shell script and emphasizes portability and compatibility.
- Main script:
nvm.sh- Contains all core functionality and the mainnvm()function - Installation script:
install.sh- Handles downloading and installing nvm itself - Execution wrapper:
nvm-exec- Allows running commands with specific Node.js versions - Bash completion:
bash_completion- Provides tab completion for bash users - Tests: Comprehensive test suite in
test/directory using the urchin test framework
The core functionality file containing:
- Main
nvm()function (starts around line 3000) - All internal helper functions (prefixed with
nvm_) - Command implementations for install, use, ls, etc.
- Shell compatibility logic
- POSIX compliance utilities
Handles nvm installation via curl/wget/git:
- Downloads nvm from GitHub
- Sets up directory structure
- Configures shell integration
- Supports both git clone and script download methods
Simple wrapper script that:
- Sources nvm.sh with
--no-useflag - Switches to specified Node version via
NODE_VERSIONenv var or.nvmrc - Executes the provided command with that Node version
- Internal functions:
nvm_install_binary(),nvm_install_source(),nvm_download_artifact() - Downloads and installs specified Node.js version
- Automatically
nvm uses that version after installation - Supports LTS versions, version ranges, and built-in aliases (like
node,stable) and user-defined aliases - Can install from binary or compile from source
- When compiling from source, accepts additional arguments that are passed to the compilation task
- Internal functions:
nvm_resolve_alias(),nvm_version_path(),nvm_change_path() - Switches current shell to use specified Node.js version
- Updates PATH environment variable
- Supports
.nvmrcfile integration
- Internal functions:
nvm_ls(),nvm_tree_contains_path() - Lists installed Node.js versions
- Supports pattern matching and filtering
- Shows current version and aliases
- Internal functions:
nvm_ls_remote(),nvm_download(),nvm_ls_remote_index_tab() - Lists available Node.js versions from nodejs.org and iojs.org, or the env-var-configured mirrors
- Supports LTS filtering and pattern matching
- Downloads version index on-demand
- Internal functions:
nvm_alias(),nvm_alias_path() - Creates text files containing the mapped version, named as the alias name
- Special aliases:
default,node,iojs,stable,unstable(note:stableandunstableare deprecated, from node's pre-v1 release plan) - Stored in
$NVM_DIR/alias/directory
- Internal functions:
nvm_ls_current() - Shows currently active Node.js version
- Returns "system" if using system Node.js
- Internal functions:
nvm_version_path(),nvm_resolve_alias() - Shows path to specified Node.js version
- Resolves aliases and version strings
- Cache management for downloaded binaries and source code
- Clears or shows cache directory path
- Diagnostic information for troubleshooting
- Shows environment, tool versions, and paths
- Removes nvm modifications from current shell
- Restores original PATH
- Completely removes nvm from shell environment
- Unsets all nvm functions and variables
nvm_resolve_alias()- Resolves aliases to version numbersnvm_version()- Finds best matching local versionnvm_remote_version()- Finds best matching remote versionnvm_normalize_version()- Standardizes version stringsnvm_version_greater()- Compares version numbersnvm_version_greater_than_or_equal_to()- Version comparison with equalitynvm_get_latest()- Gets latest version from a list
nvm_install_binary()- Downloads and installs precompiled binariesnvm_install_source()- Compiles Node.js from sourcenvm_download_artifact()- Downloads tarballs or binariesnvm_compute_checksum()- Verifies download integritynvm_checksum()- Checksum verification wrappernvm_get_mirror()- Gets appropriate download mirrornvm_get_arch()- Determines system architecture
nvm_change_path()- Updates PATH for version switchingnvm_strip_path()- Removes nvm paths from PATHnvm_version_path()- Gets installation path for versionnvm_version_dir()- Gets version directory namenvm_prepend_path()- Safely prepends to PATH
nvm_is_zsh()- Shell detection for zshnvm_is_iojs_version()- Checks if version is io.jsnvm_get_os()- Operating system detectionnvm_supports_source_options()- Checks if shell supports source options
nvm_download()- Generic download functionnvm_ls_remote()- Lists remote versionsnvm_ls_remote_iojs()- Lists remote io.js versionsnvm_ls_remote_index_tab()- Parses remote version index
nvm_echo(),nvm_err()- Output functionsnvm_has()- Checks if command existsnvm_sanitize_path()- Cleans sensitive data from pathsnvm_die_on_prefix()- Validates npm prefix settingsnvm_ensure_default_set()- Ensures default alias is setnvm_auto()- Automatic version switching from .nvmrc
nvm_alias()- Creates or lists aliasesnvm_alias_path()- Gets path to alias filenvm_unalias()- Removes aliasesnvm_resolve_local_alias()- Resolves local aliases
nvm_ls()- Lists local versionsnvm_ls_current()- Shows current versionnvm_tree_contains_path()- Checks if path is in nvm treenvm_format_version()- Formats version display
nvm uses the urchin test framework for shell script testing.
test/
├── fast/ # Quick unit tests
├── slow/ # Integration tests
├── sourcing/ # Shell sourcing tests
├── install_script/ # Installation script tests
├── installation_node/ # Node installation tests
├── installation_iojs/ # io.js installation tests
└── common.sh # Shared test utilities
npm install # Installs urchin, semver, and replace toolsnpm test # Runs tests in current shell (sh, bash, dash, zsh, ksh)
make test # Runs tests in all supported shells (sh, bash, dash, zsh, ksh)
make test-sh # Runs tests only in sh
make test-bash # Runs tests only in bash
make test-dash # Runs tests only in dash
make test-zsh # Runs tests only in zsh
make test-ksh # Runs tests only in kshmake TEST_SUITE=fast test # Only fast tests
make TEST_SUITE=slow test # Only slow tests
make SHELLS=bash test # Only bash shell./test/fast/Unit\ tests/nvm_get_arch # Run single test (WARNING: This will exit/terminate your current shell session)
./node_modules/.bin/urchin test/fast/ # Run fast test suite
./node_modules/.bin/urchin 'test/fast/Unit tests/nvm_get_arch' # Run single test safely without shell termination
./node_modules/.bin/urchin test/slow/ # Run slow test suite
./node_modules/.bin/urchin test/sourcing/ # Run sourcing test suite- Tests should work across all supported shells (sh, bash, dash, zsh, ksh)
- Define and use a
die()function for test failures - Clean up after tests in cleanup functions
- Mock external dependencies when needed
- Place mocks in
test/mocks/directory - Mock files should only be updated by the existing
update_test_mocks.shscript, and any new mocks must be added to this script
- bash - Full feature support
- zsh - Full feature support
- dash - Basic POSIX support
- sh - Basic POSIX support
- ksh - Limited support (experimental)
sudo apt-get update
sudo apt-get install bash zsh dash ksh
# sh is typically provided by dash or bash and is available by default# bash and zsh are available by default, bash is not the default shell for new user accounts
# Install other shells via Homebrew
brew install dash ksh
# For actual POSIX sh (not bash), install mksh which provides a true POSIX sh
brew install mksh# Test in specific shell
bash -c "source nvm.sh && nvm --version"
zsh -c "source nvm.sh && nvm --version"
dash -c ". nvm.sh && nvm --version"
sh -c ". nvm.sh && nvm --version" # On macOS: mksh -c ". nvm.sh && nvm --version"
ksh -c ". nvm.sh && nvm --version"- zsh: Requires basically any non-default zsh option to be temporarily unset to restore POSIX compliance
- dash: Limited feature set, avoid bash-specific syntax
- ksh: Some features may not work, primarily for compatibility testing
- Runs test suite across multiple shells and test suites
- Uses
scriptcommand for proper TTY simulation - Matrix strategy covers shell × test suite combinations
- Excludes install_script tests from non-bash shells
- Lints all shell scripts using shellcheck
- Tests against multiple shell targets (bash, sh, dash, ksh)
- Note: zsh is not included due to shellcheck limitations
- Uses Homebrew to install latest shellcheck version
- Runs additional linting and formatting checks
- Validates documentation and code style
- Configured in
.travis.yml - Tests on multiple Ubuntu versions
- Installs shell environments via apt packages
# Simulate CI environment locally
unset TRAVIS_BUILD_DIR # Disable Travis-specific logic
unset GITHUB_ACTIONS # Disable GitHub Actions logic
make testbrew install shellchecksudo apt-get install shellcheck# Download from https://github.com/koalaman/shellcheck/releases
wget https://github.com/koalaman/shellcheck/releases/download/latest/shellcheck-latest.linux.x86_64.tar.xz
tar -xf shellcheck-latest.linux.x86_64.tar.xz
sudo cp shellcheck-latest/shellcheck /usr/local/bin/shellcheck -s bash nvm.sh
shellcheck -s bash install.sh
shellcheck -s bash nvm-exec
shellcheck -s bash bash_completionshellcheck -s sh nvm.sh # POSIX sh
shellcheck -s bash nvm.sh # Bash extensions
shellcheck -s dash nvm.sh # Dash compatibility
shellcheck -s ksh nvm.sh # Ksh compatibility# shellcheck disable=SC2039- Allow bash extensions in POSIX mode# shellcheck disable=SC2016- Allow literal$in single quotes# shellcheck disable=SC2001- Allow sed usage instead of parameter expansion# shellcheck disable=SC3043- Allowlocalkeyword (bash extension)
- Quoting: Always quote variables:
"${VAR}"instead of$VAR - POSIX compliance: Avoid bash-specific features in portable sections
- Array usage: Use
set --for positional parameters instead of arrays, which are not supported in POSIX - Local variables: Declared with
local FOOand then initialized on the next line (the latter is for ksh support)
- Use 2-space indentation
- Follow POSIX shell guidelines for portability
- Prefix internal functions with
nvm_ - Use
nvm_echoinstead ofechofor output - Use
nvm_errfor error messages
- Test changes across all supported shells
- Avoid bash-specific features in core functionality
- Use
nvm_is_zshto check when zsh-specific behavior is needed - Mock external dependencies in tests
- Cache expensive operations (like remote version lists)
- Use local variables to avoid scope pollution
- Minimize subprocess calls where possible
- Implement lazy loading for optional features
- Use
nvm debugcommand for environment information - Enable verbose output with
set -xduring development - Test with
NVM_DEBUG=1environment variable - Check
$NVM_DIR/.cachefor cached data issues
- PATH modification: nvm modifies PATH extensively; be careful with restoration
- Shell sourcing: nvm must be sourced, not executed as a script
- Version resolution: Aliases, partial versions, and special keywords interact complexly
- Platform differences: Handle differences between Linux, macOS, and other Unix systems
- Network dependencies: Many operations require internet access for version lists
- Concurrent access: Multiple shells can conflict when installing versions simultaneously
nvm works on Windows via several compatibility layers:
- Full nvm functionality available
- Important: Ensure you're using WSL2, not WSL1 - see Microsoft's WSL2 installation guide for up-to-date instructions
- Install Ubuntu or other Linux distribution from Microsoft Store
- Follow Linux installation instructions within WSL2
- POSIX-compatible environment for Windows
- Download Cygwin from cygwin.com and run the installer
- During installation, include these packages: bash, curl, git, tar, and wget
- May require additional PATH configuration
- Comes with Git for Windows
- Limited functionality compared to full Linux environment
- Some features may not work due to path translation issues, including:
- Binary extraction paths may be incorrectly translated
- Symlink creation may fail
- Some shell-specific features may behave differently
- File permissions handling differs from Unix systems
- Install WSL2 using the official Microsoft guide: https://docs.microsoft.com/en-us/windows/wsl/install
- Install Ubuntu or preferred Linux distribution from Microsoft Store
- Follow standard Linux installation within WSL2
- Install Git for Windows (includes Git Bash) from https://git-scm.com/download/win
- Open Git Bash terminal
- Run nvm installation script
- Download and install Cygwin from https://www.cygwin.com/install.html
- Include bash, curl, git, tar, and wget packages during installation
- Run nvm installation in Cygwin terminal
This guide should help AI coding agents understand the nvm codebase structure, testing procedures, and development environment setup requirements.