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
-
zsh-peco-historyconfig:
↩# .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. -
I make heavy use of aliases on my
~/.zshrcfile 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
ezshrcfrom anywhere in my terminal to edit my zsh config file and thenszshrcto source it. ↩