Working from $HOME

Sometimes there’s a tool I need, but I’d rather not install it globally. What follows here is a quick reference for installing to my home directory from various sources.

This PATH setting covers everything below:

PATH=~/bin:~/.local/bin:$PATH

Regarding ~/bin versus ~/.local/bin, the latter is where I install third-party software, and the former is my personal scripts and wrappers.

Node with npm

Install node with dnf install node (Fedora) or brew install node (macOS).

npm has two installation modes: local and global. Local mode installs in node_modules under the current working directory, especially for projects with dependencies managed by package.json. Global mode normally installs to /usr or /usr/local which requires sudo, but you can configure it to install to your home directory instead:

✸ npm config set prefix '${HOME}/.local'

Installing prettier, the opinionated code formatter:

✸ npm install -g prettier

This installs the package in ~/.local/lib/node_modules/prettier and creates a symlink at ~/.local/bin/prettier for running it:

✸ which prettier
~/.local/bin/prettier

✸ prettier --version
1.19.1

Upgrade with npm update -g prettier, and uninstall with npm uninstall -g prettier

Node with yarn

I’m not sure there’s a good reason to use yarn for global installs instead of npm, but for reference…

After preparing npm above, install yarn with npm i -g yarn

yarn has the same local/global modes as npm, and similarly, you can override the global installation dir:

✸ yarn config set prefix '${HOME}/.local'

Installing cssunminifier:

✸ yarn global add cssunminifier

This installs the package in ~/.config/yarn/global/node_modules/cssunminifier but it creates a symlink in ~/.local/bin according to the configured prefix, so the end result is largely the same as npm:

✸ which cssunminifier
~/.local/bin/cssunminifier

✸ cssunminifier --version
cssunminifier 0.0.1 (CSS Unminifier) [JavaScript]

Upgrade is yarn global upgrade cssunminifier, and uninstall is yarn global remove cssunminifier

Python with pip

pip accepts --user to install to your home directory. Note that if you have pip3 available, you probably want to use that instead, but some packages are still only available for Python 2. You can mix and match because they install to versioned directories:

✸ python2 -c 'import site; print(site.USER_SITE)'
/home/aron/.local/lib/python2.7/site-packages

✸ python3 -c 'import site; print site.USER_SITE'
/home/aron/.local/lib/python3.7/site-packages

On my Linux system, pip3 install --user makes executables available at ~/.local/bin but on Mac the executables land in a versioned directory: ~/Library/Python/3.7/bin. For now, I’m working around this by setting up a symlink in advance:

✸ mkdir -p ~/.local/bin
✸ mv ~/Library/Python/3.7/bin/* ~/.local/bin/
✸ rmdir ~/Library/Python/3.7/bin
✸ ln -sv ~/.local/bin ~/Library/Python/3.7/bin
/Users/aron/Library/Python/3.7/bin -> /Users/aron/.local/bin

Installing black, the uncompromising code formatter:

✸ pip3 install --user black

✸ which black
~/.local/bin/black

✸ black --version
black, version 19.10b0

Upgrade is pip3 install --user --upgrade and uninstall is pip3 uninstall (without --user)

Ruby with gem

gem accepts --user-install to install to your home directory. Unfortunately on Fedora the executable lands in ~/bin which is my personal scripts area—I’d rather install packages to ~/.local/bin. On Mac the executable lands in ~/.gem/ruby/2.6.0/bin which isn’t on my PATH.

The easy fix is the following line in ~/.gemrc:

gem: --user-install --bindir ~/.local/bin

Installing rubocop, the Ruby linter:

✸ gem install rubocop

✸ which rubocop
~/.local/bin/rubocop

✸ rubocop --version
0.80.0

Upgrade is gem update rubocop and uninstall is gem uninstall rubocop

Rust with cargo

Install rust to your home directory with rustup. You can also use dnf or brew, but rustup provides a more recent compiler, even nightly if you want it.

Regardless how Rust is installed, cargo installs to ~/.cargo by default, with executables in ~/.cargo/bin. This isn’t a versioned directory, but I really prefer to use ~/.local/bin, so I make the symlink:

✸ mkdir -p ~/.local/bin
✸ mv ~/.cargo/bin/* ~/.local/bin
✸ rmdir ~/.cargo/bin
✸ ln -sv ~/.local/bin ~/.cargo/bin
/home/aron/.cargo/bin -> /home/aron/.local/bin

Installing ripgrep, the really fast recursive grep:

✸ cargo install ripgrep
Installed package `ripgrep v11.0.2` (executable `rg`)

✸ which rg
~/.local/bin/rg

✸ rg --version
ripgrep 11.0.2

Go with go get

Go installs in ~/go by default, but you can keep it out of your visible home directory by directing it to a different location, with binaries in the converged bin-dir for convenience:

✸ go env -w GOPATH=$HOME/.go
✸ go env -w GOBIN=$HOME/.local/bin

That writes to ~/.config/go/env which the go command reads. Alternatively you can set these in your shell profile—it’s up to you.

Installing elvish, the friendly interactive shell:

✸ go get -u github.com/elves/elvish

✸ which elvish
~/.local/bin/elvish

✸ elvish
~> █