Summary
Installing nvm on an Apple Silicon Mac is usually not hard, but the confusing part starts after the install: nvm: command not found, VS Code using a different Node version, Homebrew’s Node taking priority, or an old project requiring Node 14 on an arm64 machine.
The practical approach is simple. Install nvm with the official script, load it from the right zsh profile, install the Node.js LTS version you need, and commit a .nvmrc file per project. If something looks wrong, check the shell, the CPU architecture, and the actual Node path before reinstalling everything.
In this article
- Why Node version management matters on Mac
- Install nvm and set up Node.js
- Best practices for projects and teams
- Common mistakes
- Failure cases and fixes
- Conclusion
- References
Why Node version management matters on Mac
Node.js version problems appear more often than they should. One project may still run on Node 18, while a new project expects Node 22 or 24. If you rely on one system-wide Node installation, npm install may succeed but the build can fail, or the build may pass while a package behaves differently at runtime.
nvm, short for Node Version Manager, lets you switch Node.js versions per project:
# Project A
nvm use 18
# Project B
nvm use 24
For Apple Silicon Macs, the main points are zsh configuration, arm64 support, and old Node versions that may still require Rosetta or an x86_64 environment.
Sources checked for this guide
The Korean source article was revised against official and version-specific sources. The same facts are preserved here.
| Source | What was checked |
|---|---|
| nvm official README | Install script, zsh loading code, .nvmrc, LTS commands, Homebrew notice |
| nvm GitHub Releases | Latest nvm release used in this article: v0.40.5 |
| Node.js downloads and release pages | LTS, Current, Maintenance LTS, and EOL concepts |
| Apple Support | zsh as the default shell since macOS Catalina |
| Homebrew documentation | Apple Silicon Homebrew path: /opt/homebrew |
| Volta and fnm docs | Alternative Node version managers |
Install nvm and set up Node.js
Step 1. Check your shell and CPU architecture
On modern macOS, the default shell is usually zsh. Check it first:
echo $SHELL
A typical result is:
/bin/zsh
Then check the CPU architecture:
uname -m
On Apple Silicon, this usually returns:
arm64
If you see zsh and arm64, most of the setup below should be read as a ~/.zshrc-based setup.
Step 2. Install nvm with the official script
Use the official nvm install script. At the time checked for the Korean source, the current nvm release is v0.40.5.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash
If your environment uses wget, this form is also available:
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash
The installer usually creates ~/.nvm and adds nvm loading lines to a shell profile.
Step 3. Reload zsh or reopen the terminal
If nvm does not work immediately after installation, do not reinstall first. In many cases, the shell profile has simply not been reloaded yet.
source ~/.zshrc
Or close the terminal completely and open it again. Then verify nvm like this:
command -v nvm
This is normal:
nvm
Step 4. Check the zsh loading lines
Your ~/.zshrc should contain the nvm loading code. A common setup is:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
The nvm README also documents an $XDG_CONFIG_HOME-aware variant:
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
For a personal Mac development machine, the first version is often enough. If your company manages shared dotfiles or shell profiles, check the second style as well.
Step 5. Install Node.js LTS
For a new project, starting with the LTS line is usually the safest default:
nvm install --lts
Check the installed versions:
node -v
npm -v
To make the currently selected latest Node the default:
nvm alias default node
To pin a specific major version as the default:
nvm alias default 24
Step 6. Add a project-specific .nvmrc
For real projects, this is the most useful part. Put a .nvmrc file at the project root so every developer can use the same Node version.
For a Node 24 project, the file can simply contain:
24
To follow the latest LTS line, you can use:
lts/*
Then run this in the project directory:
nvm install
nvm use
A README can keep the onboarding sequence short and clear:
nvm install
nvm use
npm install
A committed .nvmrc prevents many “works on my machine” build problems caused by mismatched Node versions.
Step 7. Optional: automatically run nvm use when changing directories
If you do not want to type nvm use manually, you can add a zsh hook:
autoload -U add-zsh-hook
load-nvmrc() {
local node_version="$(nvm version)"
local nvmrc_path="$(nvm_find_nvmrc)"
if [ -n "$nvmrc_path" ]; then
local nvmrc_node_version="$(nvm version "$(cat "$nvmrc_path")")"
if [ "$nvmrc_node_version" = "N/A" ]; then
nvm install
elif [ "$nvmrc_node_version" != "$node_version" ]; then
nvm use
fi
elif [ "$node_version" != "$(nvm version default)" ]; then
nvm use default
fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc
This is optional. Some developers dislike the extra output or startup delay, so it is better as a personal preference than a forced team rule.
When Rosetta matters on Apple Silicon
If you use a current Node.js LTS release, Rosetta is usually not the first thing to worry about. According to the nvm documentation, Node.js provides Apple Silicon arm64 Darwin binaries starting with Node.js v16.0.0.
| Node.js version | Meaning on Apple Silicon |
|---|---|
| Node.js 16 and newer | arm64 Darwin binaries are available |
| Node.js 14.17 and newer | Experimental arm64 support is mentioned for source builds |
| Older Node.js 14 and below | Rosetta 2 or an x86_64 environment may be required |
Check the Node runtime architecture:
node -p "process.arch"
On an arm64 Node runtime, this prints:
arm64
Should you install nvm with Homebrew?
For nvm specifically, the safer answer is no. The nvm README states that Homebrew installation is not supported. If you run into nvm issues, the official project usually points you back to the official install-script method.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash
Homebrew is convenient for many development tools. For nvm, following the official install path avoids one common source of confusion.
nvm vs Volta vs fnm
nvm is not the only Node version manager. If you are choosing a team standard from scratch, Volta and fnm are worth comparing.
| Tool | Characteristics | Good fit |
|---|---|---|
| nvm | Widely used shell-based Node version manager | When existing docs and .nvmrc compatibility matter |
| Volta | Strong at pinning Node, npm, yarn, and pnpm tool versions | When a team wants stricter JavaScript tooling consistency |
| fnm | Rust-based, fast, and supports .nvmrc |
When you want nvm-like behavior with faster startup |
For a personal development setup, nvm is still a reasonable starting point. For a team, the tool matters less than documenting the Node version in README and matching CI with local development.
Best practices for projects and teams
Commit .nvmrc
A .nvmrc file is small but valuable. Front-end and Node backend projects often fail because one developer is on a different Node major version.
24
Place it at the project root and commit it to Git.
Document the first-run commands
Make the first run obvious in README:
nvm install
nvm use
npm install
npm run dev
This removes guesswork during onboarding.
Match CI and local Node versions
If local development uses Node 24 but CI uses Node 20, results may differ. Match GitHub Actions, Jenkins, or other CI settings with the version in .nvmrc.
Leave a reason for old Node versions
If a project must stay on Node 14 or 16, write down why. A note about package compatibility or production constraints is much more useful than “we have always used it this way.”
Common mistakes
Using which nvm as the main check
nvm is loaded as a shell function, not a normal standalone executable. Prefer:
command -v nvm
Putting the loading code in the wrong profile file
The installer may choose one of ~/.bashrc, ~/.bash_profile, ~/.zshrc, or ~/.profile. On a zsh-based Mac, check ~/.zshrc first.
grep NVM_DIR ~/.zshrc
Mixing Homebrew Node and nvm Node without noticing
If Node was previously installed with brew install node, your PATH may still pick up the Homebrew binary.
which node
node -v
When nvm is active, the path usually contains .nvm:
/Users/your-name/.nvm/versions/node/v24.x.x/bin/node
Creating .nvmrc but never running nvm use
A .nvmrc file is a version marker. It does not automatically switch Node unless you add an auto-switch hook.
nvm use
Assuming VS Code and Terminal load the same shell profile
VS Code’s integrated terminal can use a different default profile. Compare the output in VS Code and in the normal Terminal app:
echo $SHELL
command -v nvm
node -v
Failure cases and fixes
Case 1. nvm: command not found after installation
This is the classic failure. It is often not a failed install; the shell profile has not been loaded.
source ~/.zshrc
command -v nvm
If nothing is printed, check the loading lines:
grep NVM_DIR ~/.zshrc
If they are missing, add:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
Then reload:
source ~/.zshrc
Case 2. nvm works in Terminal but not in VS Code
Check these commands inside VS Code first:
echo $SHELL
command -v nvm
node -v
Run the same commands in the normal Terminal app and compare. If they differ, use VS Code’s Terminal: Select Default Profile and confirm that zsh is used and ~/.zshrc is loaded.
Case 3. Homebrew Node is used instead of nvm Node
Do not look only at node -v. Check the actual binary path:
which node
node -v
npm -v
A nvm-managed Node normally looks like:
/Users/your-name/.nvm/versions/node/v24.x.x/bin/node
On Apple Silicon, a Homebrew Node often appears under:
/opt/homebrew/bin/node
If you plan to use nvm for per-project versions, run:
nvm use
which node
You do not always have to remove Homebrew Node, but you should know which Node your shell is actually running.
Case 4. .nvmrc exists but Node does not switch automatically
This is expected. .nvmrc records the project’s intended Node version. It does not switch by itself.
nvm install
nvm use
If you want automatic switching, add the zsh hook shown above. For teams, it is usually better to document the commands than to require everyone to use the same hook.
Case 5. Old Node installation fails on Apple Silicon
Current LTS versions usually work well on arm64. The problem is old Node versions. nvm documents arm64 Darwin binaries from Node.js v16.0.0, while older Node versions may need Rosetta or an x86_64 environment.
uname -m
node -p "process.arch"
If possible, upgrade the project to a supported LTS line. If an old version is truly required, write the reason in README so the next developer does not rediscover the same limitation.
Conclusion
nvm on Apple Silicon is mostly a shell and path problem, not a complicated Node problem. Install nvm through the official script, confirm zsh loads it, and verify the actual Node path with which node.
For personal projects, nvm is enough to start. For team projects, commit .nvmrc, document nvm install and nvm use, and keep CI on the same Node version. That small setup prevents many avoidable install and build errors.
References
- nvm GitHub README
- nvm latest release
- Node.js Downloads
- Node.js Releases
- Apple Support: Use zsh as the default shell on your Mac
- Homebrew Official Site
- Volta Official Site
- fnm GitHub README
Read the original Korean post.
Please show some love to Korean, too.