Setup a New Mac

Here is a list of my favorite things to do to properly setup macOS for scientific work. I periodically update it; feel free to leave a comment if something breaks. This should work on macOS 11 on Intel; see my post on Apple Silicon to track progress on a similar setup.

Basic setup

First things first, to install pretty much anything you need Xcode. Go grab it from the Mac AppStore. You’ll need the “command-line tools” as well, but that will be installed automatically by the next step. If you want to do it manually, type this in a terminal:

xcode-select --install
sudo xcodebuild -license

This includes all the useful open-source tools Unix developers expect, like git, clang, and more. You’ll have to agree to the license.

If this ever breaks (click to expand)

The following lines will fix problems if this breaks:

xcode-select --reset
sudo xcodebuild -license

Next, install HomeBrew, this is the my favorite package manager for Macs.

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Brew installs

I am providing a brew bundle file here. It can be installed by running brew bundle. See the docs here. Or see a nice blog post here for a quick introduction to bundles.

tap "homebrew/bundle"       # First line of a bundle
tap "homebrew/cask"         # Not needed on command line
tap "homebrew/cask-fonts"   # Just needed for font casks below
tap "homebrew/core"         # Not needed on command line

# Building tools
brew "boost"        # C++ library
brew "ccache"       # Faster builds by caching
brew "cmake"        # Build software projects
brew "ninja"        # Replacement for make
brew "doxygen"      # Doxygen generates C++ documentation
brew "pre-commit"   # Allows pre-commit hooks to be installed and managed
brew "tbb"          # Threaded building blocks from Intel
brew "swig"         # Software wrapper interface generator
brew "qt"           # The Qt Toolkit

# General utilities
brew "colordiff"    # More colorful diffs outside of git
brew "coreutils"    # Basic stuff with a g prefix
brew "gnu-sed"      # Adds the gsed command, more powerful than BSD sed
brew "gnu-time"     # Nicer timing
brew "openssl"      # Security stuff
brew "git"          # The latest version of git instead of Apple's older one
brew "git-gui"      # A quicker way to apply partial changes
brew "htop"         # htop is better than top for checking processes
brew "tree"         # tree is nice for looking at directories
brew "wget"         # Mac's have curl by default, but not wget
brew "bash"         # Bash 5 instead of 3, in case you need it
brew "rename"       # Rename files utility
brew "clang-format" # Format C++ files
brew "tmux"         # Split windows and saving terminal sessions (screen replacement)
brew "gh"           # GitHub's command line interface, from gh's tap
brew "bat"          # Nicely colorized replacement for cat

# Personal customization options
brew "fish"         # My favorite shell. Might move to zsh when macOS does, though
brew "lmod"         # See my posts on lmod
brew "macvim"       # VI for macOS, with mvim graphical interface too
brew "interactive-rebase-tool" # Run git config --global sequence.editor interactive-rebase-tool
brew "bash-completion" # Nicer completion for bash if you use it

# Programming languages
brew "python"       # Python 3.8
brew "numpy"        # Now is Python3 only (numpy@1.16 is for python@2)
brew "go"           # Used by hugo, can be useful to have
brew "node"         # Javascript (for gitbooks, etc)
brew "yarn"         # Package manager for node.js
brew "ruby"         # Just to be extra sure the system Ruby never gets modified
brew "rbenv"        # Use this for Ruby (pyenv also exists)
brew "rust"         # Was trying out mdbook
brew "lua"          # Lightweight language like Python
brew "java"         # Meh. What can I say?

# Python programs
brew "pipx"         # Better way to add PyPI applications
brew "pipenv"       # All-in-one environment tool
brew "nox"          # Tool for standard development environments
brew "tox"          # Old tool for standard development environments
brew "poetry"       # Nice all-in-one packaging tool
brew "jupyterlab"   # Programming environment
brew "black"        # Python formatting
brew "mypy"         # Python type checking
brew "cookiecutter" # Quickly start new projects

# Packages
brew "hugo"         # Fast website generator
brew "pandoc"       # Convert between document formats
brew "pdftk-java"   # PDF Tool Kit (Java port)
brew "qt"           # The #1 graphics library for C++ and Python
brew "root"         # High Energy Physics toolkit

brew "libsodium"    # Have no idea why I needed this


# Fonts
cask "font-hack-nerd-font"
cask "font-sauce-code-pro-nerd-font"

# Core
cask "iterm2"       # A great terminal
cask "mactex"       # LaTeX. Huge.
cask "miniconda"    # Nice way to get a system Conda install
cask "java"         # The programming language vm

# Programs
cask "google-chrome"# Since once and a while a site doesn't work with Safari
cask "gimp"         # Photo editor
cask "blender"      # The 3D application
cask "inkscape"     # 2D vector drawings

# Editors
cask "macdown"      # Nice Markdown
cask "texstudio"    # Nice IDE for LaTeX
cask "meld"         # Compare files graphically.
cask "tikzit"       # Fast drawings
cask "visual-studio-code"

# Daemons
cask "docker"       # Allows running and building docker images
cask "dropbox"      # The cloud
cask "synergy"      # Share a mouse and keyboard between computers. Free option is okay.
cask "amethyst"     # Simulate a non-overlapping window manager with keyboard shortcuts
cask "xquartz"      # Legacy Linux apps may need this

# Chat
cask "mattermost"
cask "skype"
cask "slack"
cask "element"

If you want to install these by hand, just change brew "xxx" to brew install xxx on the command line, and cask "xxx" to brew install cask xxx. You shouldn’t need to “tap” the casks, though if you want the fonts I’m using, you will want to either tap it or run .

Anything else that is not open-source, or is hard to build, is still installable by homebrew as a cask. Plus, you can upgrade casks, so this is slightly better than installing the package by hand. (Casks are homebrew formula that just wrap an existing installer).

GH tool

You’ll want to setup the gh tool with:

gh config set git_protocol ssh

Other

ITerm2

You should open up ITerm2 (installed above) and make it the default shell and install the terminal utilities (both in the main menu). Pin to dock. Set SauceCodePro Nerd Font as the main font (you can/should do this in the normal terminal, too).

SSH Key

If you want to download the brew bundle (or anything, really) from GitHub, it’s a good idea to setup an SSH Key. In short:

ssh-keygen
# enter a passphrase
pbcopy < ~/.ssh/id_rsa.pub
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa

And add the following to .ssh/config:

Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_rsa

While you are at it, feel free to set git config --global user.name and git config --global user.email.

Fish

If you want to use fish, add /usr/local/bin/fish to /etc/shells and then run:

chsh -s /usr/local/bin/fish

Install fisher:

curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish

This works best when you use the extended fonts in your terminal (Select SauceCodePro Nerd Font), and then run:

set -g theme_nerd_fonts yes
fisher install oh-my-fish/theme-bobthefish

Note:

Now that zsh comes default, there is less of a need to switch. You may prefer Oh MyZsh instead. Use sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" to install.

Here are a few useful environment variables to set. I don’t like getting too far from the default, but these are pretty useful. These persist across logins:

set -Ux CMAKE_GENERATOR Ninja
set -Ux VIRTUAL_ENV_DISABLE_PROMPT 1
set -Ux CTEST_OUTPUT_ON_FAILURE 1

Use set -UxL to list.

Jupyterlab and key Python utilities

Since you can run kernels from Conda in any JupyterLab install, I like to install it directly into the Homebrew Python 3 instance - but this is now handled through a brew formula for jupyterlab. So far, I still sometimes install the following utilities. You probably should not do this, and just allow homebrew to manage your Python instance, using virtual environment for everything else. But if you do, then run this:

python3 -m pip install pyforest plumbum

Now, make sure you install nb_conda_kernels into your conda environments, and you’ll be able to see them without activating the environments!

Quality of life

I like to change capslock into escape, which is in keyboard settings, and must be done per-keyboard.

VIM

It is important to have installed macvim from brew directly, and not the cask, or otherwise the vi command will not be changed to the new vim. Here is my vimrc, which includes directions. I used to use the ultimate VIM package, but this is much more flexible; still adjusting to fill in gaps. Things will break if you use the system vim; you should at least run:

git config --global core.editor $(which vim)

to make sure you do not open the old vim instead when committing with git. Remove the $ if you took my suggestion and are using fish.

" On startup, Vim Plug: https://github.com/junegunn/vim-plug will be
" installed. Also, all initial plugs will also be installed.
" After changing the Plugs or adding this fill run :PlugInstall
" Use git config --global core.editor $(which vim) to ensure you do
" not run system VIM!
"
" Based on searches from https://vimawesome.com

" Automatic install if not yet installed
if empty(glob('~/.vim/autoload/plug.vim'))
  silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
    \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
endif

" Vim-Plug
call plug#begin('~/.vim/plugged')

" Nicer defaults
Plug 'tpope/vim-sensible'

" Nicer searching
Plug 'haya14busa/is.vim'

" Nicer status bar
Plug 'vim-airline/vim-airline'

" Code completer for VIM
" Requires brew install vim or macvim
Plug 'valloric/youcompleteme', {'do':'./install.py --clangd-completer --ts-completer'}

" Github marks in the gutter
Plug 'airblade/vim-gitgutter'

" Pretty for HTML + Jinga2
Plug 'Glench/Vim-Jinja2-Syntax'

" File browser
Plug 'scrooloose/nerdtree'
Plug 'Xuyuanp/nerdtree-git-plugin'

" Support EditorConfig
Plug 'editorconfig/editorconfig-vim'

" Remember position when entering a file
Plug 'farmergreg/vim-lastplace'

" Git support in vim
Plug 'tpope/vim-fugitive'

" TOML support for vim
Plug 'cespare/vim-toml'

" Linter/fixer support (LSP)
Plug 'dense-analysis/ale'

call plug#end()

" Nicer powerline
let g:airline_powerline_fonts = 1
let g:airline#extensions#ale#enabled = 1

" Ale should use virtualenv by default
let g:ale_python_auto_virtualenv = 1

let g:ale_linters = {
\   'python': ['ruff'],
\}
let g:ale_fixers = {
\   'python': ['ruff', 'black'],
\}

" Nerdtree customize
map <C-n> :NERDTreeToggle<CR>

" Extra customization
set mouse=a
set spell

" Needed to use is.vim
:set hlsearch

" MacVim needs a nicer font too
set guifont=SauceCodePro\ Nerd\ Font

" Reasonable indentations
set expandtab tabstop=4 shiftwidth=4 softtabstop=4

" Putting should not copy too by default in visual mode
vnoremap p "_dP

autocmd Filetype python setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4
autocmd Filetype ruby setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2
autocmd Filetype html setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2
autocmd Filetype markdown setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2
autocmd Filetype css setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2
autocmd Filetype scss setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2
autocmd Filetype cmake setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2

command Date execute "normal a<C-R>=strftime('%FT%T%z')<CR><ESC>"
macos