Part of getting my 2015 MacBook back into shape for development in 2026 was reinstalling the work environment from scratch, including Node.js and Claude Code. The first obstacle was a classic that anyone who has installed global npm packages on macOS knows: the EACCES error.
The classic error
npm install -g some-package
npm ERR! code EACCES
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied
This error appears because, by default, npm tries to install global packages in a system folder (usually /usr/local/lib/node_modules) owned by root, not by the current user. Any attempt to write there without elevated permissions fails.
Why the fix is NOT sudo
The most common reaction is to put sudo in front of the command: sudo npm install -g some-package. It works, but it creates a future problem: it mixes files installed as root with files installed as a normal user inside the same Node folder. The next time you try to update a package without sudo it may fail again on permissions — or worse, create hard-to-trace inconsistencies between package versions installed with and without administrator privileges.
The right fix: change npm's prefix
Instead of forcing administrator permissions on a system folder, the recommended practice is to tell npm to install global packages in a folder inside the user's home, where elevated permissions are never needed:
mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
These four lines create a dedicated folder for global packages, tell npm to use it as the prefix, and add its binaries folder to the shell's PATH so globally installed commands (like claude) are recognized from any folder.
Installing Claude Code
With the prefix configured, installing Claude Code is clean, with no sudo needed:
npm install -g @anthropic-ai/claude-code
claude --version
And to set the default model for the plan you use:
claude config set --global model sonnet
Good practices on limited hardware
Once the environment is installed, a few habits make a difference on a Mac with limited RAM or CPU:
- Launch
claudefrom the specific project folder, not from your home folder — it reduces the context the tool needs to scan - Avoid running Docker and Claude Code at the same time during heavy builds — both compete hard for CPU and memory
- Close unnecessary browser tabs while working with intensive terminal tools — as covered in Chrome vs Safari on an old Mac, every Chrome tab is one more process competing for the same resources
None of these practices is exclusive to old hardware — they're good habits on any machine. But on a 2015 Mac with limited resources, following them or not is the difference between a smooth development environment and a frustrating one.
Frequently asked questions
Why does npm install -g throw the EACCES error?
The "EACCES: permission denied" error appears because, by default, npm tries to install global packages in a system folder that requires administrator permissions. The fix isn't sudo; it's changing npm's global install folder to one inside the user's home.
Why isn't sudo npm install -g recommended?
Using sudo solves the immediate error but mixes administrator permissions into the installation of Node packages, which can later cause permission conflicts that are hard to debug, especially when updating Node or npm. The recommended practice is that npm never needs sudo to install global packages.
How do I install Claude Code on macOS?
With Node.js installed and npm's prefix configured correctly (no sudo needed), the command is 'npm install -g @anthropic-ai/claude-code'. Check it with 'claude --version' and start it with the 'claude' command from your project folder.
Which Claude model should I use by default on limited hardware?
The command 'claude config set --global model sonnet' sets the default model. On limited hardware, avoiding heavy builds or Docker containers while Claude Code runs helps keep the system responsive, since they compete for CPU and memory.