Post

Install npm Globals on macOS without sudo

Fix NVM permissions, reset npm prefix, and install global packages on macOS without sudo.

Install npm Globals on macOS without sudo

Global npm installs fail on macOS when NVM directories retain root ownership or npm falls back to /usr/local. Follow this playbook to repair permissions, purge broken installs, and keep NVM-managed globals working without sudo.

Verify your environment

Confirm NVM controls your Node.js toolchain before touching permissions. Capture versions and confirm the shell you configure.

1
2
3
nvm --version
node --version
echo $SHELL

0.39.7 v23.7.0 /bin/zsh

Back up ~/.npmrc and ~/.nvm so you can revert if an experiment breaks.

Repair ownership inside ~/.nvm

Reassign ownership of the entire NVM tree to eliminate rename-denied errors. Run this once per machine after any sudo-based install.

1
2
sudo chown -R "$(whoami)" ~/.nvm
ls -la ~/.nvm/versions/node/v23.7.0/lib/node_modules

drwxr-xr-x 12 localuser staff 384 Oct 10 10:22 .

The -R flag rewrites ownership recursively so every versioned Node folder inherits your user account.

Clear broken global packages

Remove partial global installs that block npm’s reify step. Replace the package name if a different module failed.

1
2
npm list -g --depth=0
rm -rf ~/.nvm/versions/node/v23.7.0/lib/node_modules/@openai

$HOME/.nvm/versions/node/v23.7.0/lib +– npm@10.9.0 `– @openai/codex@0.0.1

Swap @openai with the module that misbehaved: rm -rf ~/.nvm/versions/node/$(node -v)/lib/node_modules/<package>.

The --depth=0 flag limits the listing to top-level globals so you can spot stale packages fast. The rm -rf combination removes the leftover directory; -r recurses through nested files and -f skips prompts.

Align npm prefix with NVM

Delete any custom prefix so npm respects NVM-managed directories. Then reapply the active node version without legacy overrides.

1
2
3
npm config delete prefix
npm config get prefix
nvm use --delete-prefix v23.7.0 --silent

$HOME/.nvm/versions/node/v23.7.0

The --delete-prefix option tells NVM to purge old npm prefix metadata before switching versions.

Remove lingering prefix or globalconfig lines from ~/.npmrc if the warning returns.

Reload the active Node version and PATH

Reactivate the target Node.js release and guarantee its bin directory lives at the front of PATH.

1
2
3
4
nvm use v23.7.0
echo 'export PATH="$HOME/.nvm/versions/node/$(node -v)/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
which node

Now using node v23.7.0 (npm v10.9.0) $HOME/.nvm/versions/node/v23.7.0/bin/node

Appending the PATH export to ~/.zshrc keeps the NVM bin ahead of system paths in future shells.

Verify the shell config references the NVM bootstrap: grep -n "nvm.sh" ~/.zshrc.

Install the global package

With ownership and prefix aligned, reinstall the package without sudo and verify both the library path and the CLI.

1
2
3
npm install -g @openai/codex
npm list -g --depth=0
which codex
  • @openai/codex@0.0.1 $HOME/.nvm/versions/node/v23.7.0/lib $HOME/.nvm/versions/node/v23.7.0/bin/codex

Troubleshooting

  • EACCES rename during install — Rerun the ownership fix, delete the half-written module, and retry the install.
  • npm warns about prefix — Remove every prefix= or globalconfig= line from ~/.npmrc, then repeat the prefix alignment step.
  • CLI not on PATH — Reload the shell or run source ~/.zshrc, and confirm the node bin directory appears when you print the PATH.
  • npm config get prefix returns /usr/local — Reactivate Node with nvm use v23.7.0, delete the prefix again, and remove any Homebrew Node that shadows NVM.

☕ Support My Work

If you found this post helpful and want to support more content like this, you can buy me a coffee!

Your support helps me continue creating useful articles and tips for fellow developers. Thank you! 🙏

This post is licensed under CC BY 4.0 by the author.