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

Danger

Remember to save your encryption key securely!

Enable FileVault.

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

First, navigate to Settings… ➤ Privacy & Security ➤ Full Disk Access. Add Terminal to the list of apps that can access all files.

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 strongly 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)
  • yq (same as jq but for YAML)
  • btop (top/htop replacement)
  • p7zip (7zip)

To install them all, run

brew install eza ydiff bat ripgrep fd fzw jq yq p7zip
Suggested packages

These packages may be useful:

Security and connections

Disable quarantining downloads

FYI

To remove the attribute from a single file, use xattr -d com.apple.quarantine <path>.

Some applications on macOS choose to mark all downloaded files with the extended file attribute (xattr) com.apple.quarantine. That includes mainstream browsers.

defaults write com.apple.LaunchServices LSQuarantine -bool NO

Optionally, disable Gatekeeper

Run this to enable the option to disable Gatekeeper:

sudo spctl --master-disable

Warning

Gatekeeper also does useful things like code signing. Only disable it if it’s still getting in the way after disabling the auto-quarantine.

Then, if needed, you can disable Gatekeeper altogether by navigating to System Settings ➤ Privacy & Security ➤ Security ➤ Allow applications from and choosing the newly appearing option Anywhere.

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

Rust

For Rust, just install the Rust toolchain.

Java

For Java, download the latest JDK from Temurin.

To understand why you should use Temurin, see whichjdk.com. In particular, do not use Java 8, java.com, jdk.java.net, a pre-installed JDK, or the openjdk apt package.

Pro-tip – macOS

Temurin releases are available on Homebrew, so just run

brew install --cask temurin

Make sure it’s on your $PATH by checking the version via java --version and javac --version. Example:

❯ openjdk 24.0.1 2025-04-15
OpenJDK Runtime Environment Temurin-24.0.1+9 (build 24.0.1+9)
OpenJDK 64-Bit Server VM Temurin-24.0.1+9 (build 24.0.1+9, mixed mode, sharing)

Python

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 ➤ Use as Defaults.

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.

Make the Dock show/hide instantly.

You can have the Dock auto-hide but pop up instantly by running

defaults write com.apple.dock autohide-delay -float 0
defaults write com.apple.dock autohide-time-modifier -int 0
killall Dock

Set shortcuts and Hot Corners.

Under System Settings ➤ Desktop & Dock, see (at the very bottom) Shortcuts… and Hot Corners…. I use this:

  • top right: Launchpad
  • bottom right: Mission Control
  • bottom left: Application Windows

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 mostly useless 🌐︎ key.

Caution: This has the unfortunate downside of disabling the F1 … F12 keys. 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.

Aliases to find things

I keep forgetting where macOS puts certain files, so I use aliases to find them:

# List my notes in the Stickies app.
alias ls-stickies='eza -l -s created $HOME/Library/Containers/com.apple.Stickies/Data/Library/Stickies/*.rtfd/TXT.rtf'

# List screenshots I just took.
alias ls-screenshots='eza -l -s created $HOME/Desktop/Screenshot *.png'

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