How nvm Handles Apple Silicon (arm64) Architecture Detection and Installation
nvm detects Apple Silicon by mapping uname -m output (aarch64 or armv8l) to arm64, then forces x64 binaries via Rosetta 2 for Node versions below 16.0.0 while using native arm64 builds for Node 16 and later.
The nvm-sh/nvm repository provides a POSIX-compliant shell script for managing multiple Node.js versions. Understanding how nvm handles Apple Silicon arm64 architecture detection ensures you install the correct binary for your M1, M2, or M3 Mac without compatibility issues.
How nvm Detects macOS and Apple Silicon Architecture
nvm determines your system architecture through two core functions defined in nvm.sh: nvm_get_os and nvm_get_arch.
OS Detection via nvm_get_os
Located around lines 2100–2114 in nvm.sh, the nvm_get_os function reads uname -a to classify the operating system. On macOS, this returns darwin, which nvm uses to determine that it should look for macOS-compatible Node binaries.
Architecture Mapping in nvm_get_arch
The nvm_get_arch function (lines 2116–2145 in nvm.sh) handles arm64 architecture detection by executing uname -m (or platform-specific fallbacks) to obtain the hardware identifier.
On Apple Silicon Macs, uname -m returns aarch64 or armv8l. The function contains a case statement that maps these values to the internal string arm64:
# Simplified excerpt from nvm.sh nvm_get_arch
case "${HOST_ARCH}" in
aarch64 | armv8l)
HOST_ARCH="arm64"
;;
esac
This normalization ensures that nvm consistently refers to Apple Silicon as arm64 throughout the installation process.
Binary Selection Logic for Apple Silicon Macs
Once nvm detects darwin as the OS and arm64 as the architecture, it applies version-specific rules to determine whether to download a native arm64 binary or fall back to an x64 binary running under Rosetta 2.
Version-Based Architecture Fallback
The critical logic resides around lines 2400–2418 in nvm.sh. When you request a Node version, nvm checks if the version predates native Apple Silicon support:
NVM_OS="$(nvm_get_os)"
NVM_ARCH="$(nvm_get_arch)"
…
# Apple Silicon special case for older Node versions
if \
nvm_version_greater '14.17.0' "${VERSION}" \
|| (nvm_version_greater_than_or_equal_to "${VERSION}" '15.0.0' && nvm_version_greater '16.0.0' "${VERSION}") \
; then
if [ "_${NVM_OS}" = '_darwin' ] && [ "${NVM_ARCH}" = 'arm64' ]; then
NVM_ARCH=x64
fi
fi
Why the switch to x64?
- Node v14.17.0 introduced experimental Apple Silicon support, but official arm64 binaries were not shipped until Node v16.0.0.
- For versions between 14.17.0 and 15.x, nvm forces
NVM_ARCH=x64on macOS arm64 machines, causing it to download the x64 binary that macOS runs under Rosetta 2. - For versions ≥ 16.0.0, the architecture remains
arm64, and nvm fetches the native arm64 tarball for optimal performance.
Practical Examples: Installing Node on M1/M2 Macs
Here is how nvm Apple Silicon arm64 architecture detection behaves in practice:
# On an M1 Mac (darwin + arm64)
$ nvm install 14 # < 14.17.0 → nvm falls back to x64 binary via Rosetta
Downloading and installing node v14.21.3...
$ nvm install 16 # native arm64 binary is available
Downloading and installing node v16.20.2 (arm64)...
# Verify the architecture of the installed node
$ nvm use 16
Now using node v16.20.2 (arm64)
$ node -p "process.arch"
arm64
Summary
- nvm detects Apple Silicon by running
uname -min thenvm_get_archfunction (lines 2116–2145 ofnvm.sh), mappingaarch64andarmv8lto the internalarm64identifier. - For Node versions below 16.0.0, nvm forces
x64architecture on macOS arm64 machines (lines 2400–2418), causing Rosetta 2 to run the Intel binary. - For Node 16 and later, nvm preserves the
arm64architecture and downloads native Apple Silicon binaries for optimal performance. - The
nvm_get_osfunction classifies macOS asdarwinto trigger these Apple-specific code paths.
Frequently Asked Questions
Does nvm automatically use Rosetta 2 on Apple Silicon?
Yes, but only for Node versions that lack native arm64 support. According to the source code in nvm.sh, nvm automatically switches the architecture from arm64 to x64 when installing Node versions between 14.17.0 and 15.x, or versions below 14.17.0. This forces the download of Intel x64 binaries, which macOS runs under Rosetta 2 translation.
Which Node versions have native arm64 support for macOS?
Native Apple Silicon support was introduced experimentally in Node v14.17.0, but official arm64 binaries for macOS were not consistently available until Node v16.0.0. As implemented in nvm.sh, versions 16 and later retain the arm64 architecture identifier and download native binaries, while earlier versions fall back to x64.
How can I verify which architecture my Node binary uses?
After installing a Node version with nvm, run node -p "process.arch" in your terminal. If the output is arm64, you are running a native Apple Silicon binary. If the output is x64 (on an M1/M2/M3 Mac), the binary is running under Rosetta 2 translation. You can also check the installation output from nvm, which prints the architecture in parentheses, such as Downloading and installing node v16.20.2 (arm64).
What happens if I try to install Node 13 on an M1 Mac?
If you attempt to install Node 13 (or any version below 14.17.0) on an Apple Silicon Mac using nvm, the tool will detect your system as darwin with arm64 architecture. However, because these versions predate any Apple Silicon support, nvm will force the architecture to x64 and download the Intel macOS binary. Your system will then execute this x64 binary using Rosetta 2, allowing the outdated Node version to run despite the architecture mismatch.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →