macOS setup for software development
I’ve been using Linux as my daily-driver OS for professional software development since 2019.
In 2021 I had a short, company-mandated stint with macOS, and it went badly enough that I swore I’d never touch it
again.
Looking back, most of it was self-inflicted: I tried to force my Linux workflow and keyboard shortcuts into macOS,
used an external keyboard whose layout was not Mac-compatible and then made it worse by remapping keys like Cmd and
Ctrl in an attempt to bring some familiarity back. I also really, really missed a tiling window manager.
Unsurprisingly the whole thing didn’t work and I switched back to Linux as soon as I could.
By the beginning of 2025, a few things had changed:
- I stopped caring about using a tiling window manager. My setup made context-switching too easy: one shortcut to change workspaces and suddenly I’m “taking a quick look” on slack whenever something gets hard or boring.
- The performance difference between my laptop and the Macbooks was very noticeable: running a linter on my company’s main monorepo was taking 2-3x more time than on my colleagues’ Macbooks.
- I missed the ecosystem: my AirPods never quite worked on Linux (to be fair, I didn’t fight it much), some apps like Slack or Spotify were clearly second class on Linux
- LLMs were clearly an industry changing technology and apps like ChatGPT or Claude did not exist on Linux. Although in retrospect these apps weren’t that important I really didn’t want to miss out on the bleeding edge of the industry and Linux was clearly not being treated as a first class target of app developers.
So I switched to a MacBook Pro M4. And, annoyingly for my past self, it’s been great: everything is fast, the screen is so good that I ditched my external monitor, and the keyboard + trackpad combo is excellent.
The biggest difference this time is that I didn’t try to “fix” macOS into Linux. No key remaps, no forcing it. I just learned the shortcuts and everything clicked right away.
As the saying goes: never say never.
Setup
- Install Ghostty terminal emulator.
- Install Xcode Command Line Tools with
xcode-select --install - Install Homebrew
- Disable Spotlight hotkey. Install Raycast.
- Install ohmyzsh to manage zsh (default macOS shell)
- Install zsh-peco-history to improve shell history search using
Ctrl+R[1] - Install mise to manage different versions of tooling (node, python, ruby, etc)
- Install Jetbrain’s toolbox app to manage all IDE’s I use
- Install claude code.
- Setup zsh aliases [2]
- Setup ssh for Github and create a GPG signing key
- Setup macOS keyboard with the help of https://mac-key-repeat.zaymon.dev/
defaults write -g InitialKeyRepeat -int 12defaults write -g KeyRepeat -int 1
- Change Finder settings
chflags nohidden ~/Libraryto show Library folderdefaults write com.apple.finder AppleShowAllFiles -boolean trueto show hidden filesdefaults write com.apple.finder ShowPathbar -bool trueto show path bar
Footnotes
1. zsh-peco-history config ↩︎
# .zshrc
HISTSIZE=10000000
SAVEHIST=10000000
setopt EXTENDED_HISTORY # Write the history file in the ":start:elapsed;command" format.
setopt INC_APPEND_HISTORY # Write to the history file immediately, not when the shell exits.
setopt SHARE_HISTORY # Share history between all sessions.
setopt HIST_EXPIRE_DUPS_FIRST # Expire duplicate entries first when trimming history.
setopt HIST_IGNORE_DUPS # Don't record an entry that was just recorded again.
setopt HIST_IGNORE_ALL_DUPS # Delete old recorded entry if new entry is a duplicate.
setopt HIST_FIND_NO_DUPS # Do not display a line previously found.
setopt HIST_IGNORE_SPACE # Don't record an entry starting with a space.
setopt HIST_SAVE_NO_DUPS # Don't write duplicate entries in the history file.
setopt HIST_REDUCE_BLANKS # Remove superfluous blanks before recording entry.
2. Aliases ↩︎
I make heavy use of aliases on my ~/.zshrc file to help me navigate to common directories or open projects on the
appropriate IDE. Some examples:
export EDITOR='vim'
# .zshrc
alias ezshrc="$EDITOR $HOME/.zshrc"
alias szshrc="source $HOME/.zshrc"
# projects
export PROJECTS_HOME="$HOME/projects"
export AOC="$PROJECTS_HOME/aoc-2022"
alias aoc="cd $AOC"
alias iaoc="launch_rubymine $AOC"
# functions
launch_rubymine() {
nohup $HOME/bin/rubymine $1 > /dev/null 2>&1 &
}
I can type ezshrc from anywhere in my terminal to edit my zsh config file and then szshrc to source it.