Skip to content

macOS setup

A setup guide for programmers, etc., on macOS.

Initial setup

First, upgrade macOS by running

softwareupdate --install --all --agree-to-license

Enable FileVault.

Danger

Remember to save your encryption key!

Homebrew

Install Homebrew and update it with brew update && brew upgrade. macOS ships with severely outdated versions of ZSH and especially Bash. Use Brew to install both shells, along with the GNU core utils:

brew install bash zsh coreutils

Configure your shell

Follow: Shell setup .

brew-refill alias

Prerequisites

This uses commonrc-config.sh functions, which ~/.commonrc should source. commonrc::add_line <line> simply adds <line> in ~/.commonrc if it doesn’t exist.

Add a brew-refill command:

commonrc::add_line \
  'alias brew-refill="brew update && brew upgrade && brew cleanup printf '\n\n\n\n\n' && brew doctor"'

From that, you can run brew-refill to update Brew and its packages, and to fix problems.

Although Homebrew only recommends running brew doctor if there’s a problem, chances are you’ll eventually need to run it, so it’s not a bad idea to deal with those issues immediately rather than to accumulate a daunting stack of issues to fix simultaneously later. Note that doctor does nothing on its own: You need to follow the instructions it outputs.

Xcode

You will probably need Xcode to build some software package. Install it through the App Store.

Replace or supplement macOS utilities

First, declare this gnu_brew function for GNU packages that Brew does not automatically add to PATH. This function makes the GNU tool the default. It runs brew install pkg, uses brew --prefix pkg to get a path like /opt/homebrew/opt/pkg, and adds the subdirectory libexec/gnubin/ or bin/ to the PATH in ~/commonrc.

gnu_brew() {
  local p
  brew install "$1" || return $?
  bash -c 'which $1 | grep homebrew' && return $?
  p=$(brew --prefix $1 || exit $?)
  commonrc::prepend_to_path "$p"/libexec/gnubin "$p"/bin || return $?
}

GNU diffutils

The diff from macOS is outdated, so install GNU diffutils via Brew. The package provides GNU diff (2-way), diff3 (3-way), sdiff (merge), and cmp (binary). To override the default diff, you may need to adjust your PATH as shown.

gnu_brew diffutils

Curl

macOS’s Curl is outdated, so replace it using Brew.

brew install curl
_curl=$(brew --prefix curl)
commonrc::prepend_to_path "$_curl/bin"
commonrc::add_line "export LDFLAGS=\"-L$_curl/lib\""
commonrc::add_line "export CPPFLAGS=\"-I$_curl/include\""
commonrc::add_line "export PKG_CONFIG_PATH=\"$_curl/lib/pkgconfig\""

OpenSSH

Note: How Heartbleed barely affect macOS

macOS mostly uses its own SSL/TLS implementation but continued to ship with OpenSSL. When Heartbleed was discovered in 2014, macOS was shipping with OpenSSL so ancient that it was rendered immune. That was luck, not good security policy.

macOS ships with a strange custom SSH server and an outdated copy of LibreSSL. (They recently switched from OpenSSL to LibreSSL, which is good.) Install OpenSSH and ssh-copy-id, and add ssh-copy-id your PATH:

gnu_brew openssl
gnu_brew ssh-copy-id

Bug: Brew OpenSSH and LibreSSL

The OpenSSH from Brew comes with OpenSSL, not LibreSSL. That’s unfortunate but not really a problem. You can install LibreSSL with brew install libressl. But, to get OpenSSH to use it, you’ll need to find an alternate package or build from source.

GPG and the GitHub CLI

Install GnuPG and the GitHub CLI:

brew install gnupg gh

vim

Get an improved copy of vi improved from Brew. Run these commands, checking the output from which vim:

brew install vim && bash -c 'which vim'

grep, find, sed, and awk

To install these and add them to your PATH, run

gnu_brew grep
gnu_brew findutils
gnu_brew gnu-sed
gnu_brew gawk

Additional utilities

These are useful utilities that macOS doesn’t provide, optional but recommended.

  • eza (ls replacement)
  • ydiff (diff replacement)
  • bat (cat replacement)
  • delta (diff replacement)
  • ripgrep (rg) (grep replacement)
  • fd (find replacement)
  • fzw (fuzzy finder)
  • jq (like sed/awk but for JSON)
  • btop (top/htop replacement)

To install them all, run

brew install eza ydiff bat ripgrep fd fzw jq

Security and connections

Configure Git, SSH, and GPG

Follow: Shell setup .

Generate a certificate

If you need a certificate, set a static IP address and generate a certificate with certbot. Choose “None of the above” for Software. Then follow the instructions exactly, including the “Automating renewal” section. This may not work through some company and university firewalls.

Programming languages and frameworks

C/C++

Prerequisites

gnu_brew is defined in a section above.

gnu_brew make
brew install autoconf cmake

Java, Rust, and Python

For Rust, just install the Rust toolchain.

For Java, download JDK 21 LTS from Temurin (or a newer non-LTS version if preferred). Do not use Java 8, java.com, or OpenJDK. Make sure it’s on your $PATH by checking the version via java --version in a new shell.

For Python, install and use uv. You don’t need anything else – and you really shouldn’t use anything else. Make your life easier: (1) Leave your system Python alone, (2) don’t install Python via a package manager, and (3) install and use Conda/Mamba only if necessary.

_[LTS]: Long-Term Support _[JDK]: Java Development Kit

Tweaks

Finder

Make a few adjustments to Finder settings.

  • Show hidden files by running
defaults write com.apple.Finder AppleShowAllFiles true \
  && killall Finder
  • Show filename extensions: Do this in Finder ➤ Settings… ➤ Advanced.
  • Add your home folder to the SideBar: File ➤ Add to sidebar.
  • Show full filenames: Check Finder ➤ Settings… ➤ Advanced ➤ Show all filename extensions.
  • (Optional) Show folders on top: Check Finder ➤ Settings… ➤ Advanced ➤ Keep folders on top.
  • Show directory size: Check View ➤ Show View Options ➤ Show item info, then click Use as Defaults. (Optional: Set Sort By to Name.)

Other UI tweaks

  • Use 24-hour time and yyyy-mm-dd: Under System Settings ➤ General ➤ Date & Time, enable 24-hour time and Show 24-hour time on Lock Screen. Under System Settings ➤ General ➤ Language & Region, change Date Format. You can also change Number Format to the IEEE-, NIST-, and JCGM- recommended 1 234 567.89.
  • Review Shortcuts and Hot Corners: Under System Settings ➤ Desktop & Dock, see (at the very bottom) Shortcuts… and Hot Corners…. (I have hot corners for Launchpad in the top right and Mission Control on the bottom right.)
  • Stop macOS from adding . after two spaces: Annoyingly, this happens even when typing code in an IDE. Under System Settings ➤ Keyboard ➤ Text Input ➤ Input Sources ➤ Edit…, uncheck Add period with double-space.
  • Repurpose the useless 🌐︎ key: You can do this under System Settings ➤ Keyboard ➤ Keyboard Shortcuts… ➤ Modifier Keys ➤ Globe (🌐︎) key. (I mapped it to ⌘ (retaining ⌘) to make it easier to switch to/from Windows, where CTRL is in the same position.)

Cleanup

  1. Remove GarageBand files under System Settings ➤ General ➤ Storage ➤ Music Creation.
  2. Disable unwanted startup apps under System Settings ➤ General ➤ Login Items.

Optional apps

  • Terminal: For the much-loved iTerm2, run brew install --cask iterm2.
  • Text editor: For Sublime, run brew install --cask sublime-text.

Credits: Cole Helsell drafted the original version of this guide with me.