How to use npm global without sudo on OSX

When running npm and node, you may find yourself getting permission errors that ultimately lead you to using `sudo` in your commands. While this helps get around the issue in the short-term, it also places stricter permissions on those installs and it becomes a slippery slope where soon you may need sudo for more than you bargained for. Also, do you really want to be using `sudo` to install npm packages?

I went down this path and some experienced Mac developers helped me see why I needed to relieve myself of `sudo` for npm. Since then I've read several great posts with directions on how to do this including Dan Herbert's fixing npm for Homebrew users and Sindre Sorhus's No Sudo instructions. Each of these has something to offer, of which I combined into a single set of steps in this post. Also, special thanks to Brian Noyes, Ward Bell, Jesse Warden, Mike Callaghan, and Sam Artioli for their help.

Some people already have node and npm packages. So there is some cleanup to do first. Others have fresh machines, so it's a bit easier. While these steps are not the only way to go, they have been repeatable on a few machines for me. So why create a new set of instructions? For one, I can add some additional comments of what is going on to try to explain what's really happening. Also, I was able to take some of the steps and make them all run from terminal, so you can literally copy and paste some of them (see where this is recommended below).

Disclaimer: I offer no warranty nor guarantee of the success of these steps. These are simply what works in my experience. Follow these steps with a cautious eye as you would any steps you find on the internet.

I also encourage you to refer to either of the posts I mention above as they are both excellent and have also worked for me.

What Are We Really Doing?

Good question! When node installs it puts npm packages in a specific folder, usually `/usr/local/lib/node_modules`. This location is what we are moving in these steps. Why? Because that location requires root permissions and thus the use of sudo proliferates needlessly. So these steps are all about moving the location of where the npm packages will live, and then pointing OSX and node to the new location via paths. Think of it as moving to a newer neighborhood :)

Homebrew

I assume you have Homebrew. If not, go get it. It's awesome for OSX. You can install tons of great stuff quickly and efficiently with it. Instructions are at the link or for your convenience, run this:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"  

Already Have Node ?

If you have Node installed already via brew, remove it and npm first. Run step 1 by itself and be careful, we are running as sudo and we are removing files forcefully.

This removes, forcefully, everything in the old npm folders.

sudo rm -rf /usr/local/lib/node_modules  
sudo rm -rf ~/.npm  

This removes node and puts it back without npm

brew uninstall node  

Install Node and NPM

  1. This adds node, sans npm
    brew install node --without-npm

  2. Create a directory for your global packages. I prefer to name my folder .npm-packages, you can choose what you want as long as you replace it throughout these steps. The ${HOME} is a variable that translates to ~/ or /Users/john/ for me.
    mkdir "${HOME}/.npm-packages"

  3. Reference this directory for future usage in your .bashrc file. The echo command helps write the statement. The >> tells it where to write it which is followed by the file to write it to.
    echo NPM_PACKAGES="${HOME}/.npm-packages" >> ${HOME}/.bashrc

  4. Indicate to npm where to store your globally installed package, in your ~/.npmrc file.
    echo prefix=${HOME}/.npm-packages >> ${HOME}/.npmrc

  5. This gets and installs the latest npm, which is 2.1.16 at the time of this writing.
    curl -L https://www.npmjs.org/install.sh | sh

  6. Ensure node will find the packages by adding the path to your .bashrc. Notice the escape characters before special characters.
    echo NODE_PATH=\"\$NPM_PACKAGES/lib/node_modules\:\$NODE_PATH\" >> ${HOME}/.bashrc

  7. Ensure you'll find installed binaries by adding the following to your .bashrc.
    echo PATH=\"\$NPM_PACKAGES/bin\:\$PATH\" >> ${HOME}/.bashrc

  8. Ensure that you source your .bashrc file by adding the following to your .bash_profile.
    echo source "~/.bashrc" >> ${HOME}/.bash_profile

  9. Source your .bashrc file once. Previous step did this for the future, but this does it right away.
    source ~/.bashrc

These echo commands will create the file if it is not already there. But if the file is there, it will simply append these commands to the end of the file. If you already had these it will add a duplicate, which you then should remove. See the section below for details.

Checking Your Files

When you are done, you should have a files that looks something like the following:

~/.npmrc

prefix=/Users/john/.npm-packages

~/.bashrc

NPM_PACKAGES=/Users/john/.npm-packages  
NODE_PATH="$NPM_PACKAGES/lib/node_modules:$NODE_PATH"  
PATH="$NPM_PACKAGES/bin:$PATH"  

~/.bash_profile

Make sure you have the source ~/.bashrc in your ~/.bash_profile

To see the files beginning with . such as .bashrc and .npmrc you need to show hidden files for OSX. In terminal run the following command: defaults write com.apple.finder AppleShowAllFiles YES

Verification

Run these commands to test if you were successful:

  • Run node -v to see the version of node
  • Run npm -v to see the version of npm
  • Run npm list -g --depth=0 to see the global npm packages you have installed (should just be npm right now)

Advanced Users

For advanced users, the rest of these can be run via copy and paste into terminal.

brew install node --without-npm  
mkdir "${HOME}/.npm-packages"  
echo NPM_PACKAGES="${HOME}/.npm-packages" >> ${HOME}/.bashrc  
echo prefix=${HOME}/.npm-packages >> ${HOME}/.npmrc  
curl -L https://www.npmjs.org/install.sh | sh  
echo NODE_PATH=\"\$NPM_PACKAGES/lib/node_modules:\$NODE_PATH\" >> ${HOME}/.bashrc  
echo PATH=\"\$NPM_PACKAGES/bin:\$PATH\" >> ${HOME}/.bashrc  
echo source "~/.bashrc" >> ${HOME}/.bash_profile  
source ~/.bashrc  

Handling Multiple Node Versions

What happens when a new version of node is released? What if you need version 0.10.36 for one app and 4.4.2 for another? Did you know version 6 is out now too? Yikes! it would be great if we could manage multiple versions of node on the same computer.

Check out this post for more on how to tackle multiple versions of node.

Tweet Post Share Update RSS

Hi, I'm John Papa. I author this blog, create courses for Pluralsight and am a Google Developer Expert and Microsoft Regional Director. I travel speaking at events and train technology thought leaders

Tags:
node npm osx sudo