My Mac setup
For a while my feeds were full of Omarchy. It's DHH's opinionated take on Arch Linux: Hyprland tiling windows, everything driven from the keyboard, terminal tools everywhere and a consistent theme across the lot. The hype was hard to ignore, so I installed it and played with it.
I liked a lot of it. But the more I used it, the clearer it became that the things I liked were ideas, not Linux features:
- Windows that tile themselves, with gaps, borders and numbered workspaces.
- Keyboard first, with a launcher for everything.
- Minimal chrome: no dock, no clutter, a terminal that looks good.
- Good command-line tools, set up properly from the start.
All of that can be rebuilt on macOS, on hardware I think is much nicer and that I already own. This note is that setup: the apps, what they do, how I use them and the commands to install the lot.
The setup lives in a repo
Everything is in one git repo. The README is a numbered guide I can run top to bottom on a fresh Apple Silicon Mac: install Homebrew, install the apps, configure macOS, then link the config files. Each tool's config lives in a config/ folder and is symlinked into the place the tool expects, so editing the repo changes the live setup.
# Run from the root of the repo
ln -sfn "$PWD/config/zsh/.zshrc" "$HOME/.zshrc"
ln -sfn "$PWD/config/starship.toml" "$HOME/.config/starship.toml"
ln -sfn "$PWD/config/ghostty/config" "$HOME/.config/ghostty/config"
ln -sfn "$PWD/config/zed/settings.json" "$HOME/.config/zed/settings.json"
ln -sfn "$PWD/config/aerospace/aerospace.toml" "$HOME/.aerospace.toml"
ln -sfn "$PWD/config/borders/bordersrc" "$HOME/.config/borders/bordersrc"Anything secret, like tokens, API keys and cluster credentials, stays out of the repo. The shared .zshrc sources a local file if it exists:
[[ -r "$HOME/.zshrc.local" ]] && source "$HOME/.zshrc.local"macOS itself
Before anything else, I strip macOS back.
- Dock: small, hidden automatically and empty, with indicators and suggested apps turned off. With a launcher and tiling, there's nothing left to click it for.
- Menu bar: hidden automatically too.
- Appearance: Auto, so it follows light and dark through the day.
- Keyboard: key repeat set to fast and the repeat delay to short. This matters a lot once you move around with keys.
- Trackpad: "swipe between full-screen applications" turned off, so macOS Spaces don't fight AeroSpace's workspaces.
The rest is done from the terminal: Apple's developer tools, Rosetta, hidden files in Finder and no Dock animations.
# Apple's command-line tools and Rosetta
xcode-select --install
softwareupdate --install-rosetta --agree-to-license
# No "Last login" message in new terminals
touch "$HOME/.hushlogin"
# Show hidden files in Finder
defaults write com.apple.finder AppleShowAllFiles -bool true
killall Finder
# Make the Dock appear instantly
defaults write com.apple.dock launchanim -bool false
defaults write com.apple.dock autohide-time-modifier -float 0
defaults write com.apple.dock autohide-delay -float 0
killall DockTiling windows with AeroSpace
AeroSpace is the heart of it. It's an i3-style tiling window manager for macOS: new windows split the screen between them instead of piling up, and everything is on the keyboard. It's the closest thing to Hyprland I've found on a Mac.
- Five workspaces that always exist, on Alt+1 to 5. Alt+Shift+a number sends the current window there.
- Vim-style movement: Alt+H J K L moves focus, and adding Shift moves the window itself.
- Alt+Tab flips between the current and last workspace.
- A service mode on Alt+Shift+; for rarer jobs: reset the layout, float a window, or close everything except the current one.
- 16 pixel gaps between windows and around the screen edge.
- Starts at login, so the layout is there from the first window.
start-at-login = true
persistent-workspaces = ["1", "2", "3", "4", "5"]
gaps.inner.horizontal = 16
gaps.inner.vertical = 16
gaps.outer.left = 16
gaps.outer.right = 16
gaps.outer.top = 16
gaps.outer.bottom = 16
[mode.main.binding]
alt-h = 'focus left'
alt-shift-h = 'move left'
alt-1 = 'workspace 1'
alt-shift-1 = 'move-node-to-workspace 1'
alt-tab = 'workspace-back-and-forth'One extra setting makes it feel finished: AeroSpace can show the workspaces in the macOS menu bar, like a Linux status bar.
defaults write bobko.aerospace displayStyle -string i3OrderedBorders
JankyBorders draws a rounded border around every window: light grey on the focused window, dark grey on the rest. With tiling, it's the quickest way to see where the keyboard is pointing.
options=(
style=round
width=6.0
active_color=0xffe2e2e3
inactive_color=0xff414550
)
borders "${options[@]}"The terminal
Ghostty
Ghostty is my terminal. It's fast, native and configured with a plain text file. Mine has no title bar, slight transparency with a heavy blur, the One Dark theme and the Meslo Nerd Font, installed with Homebrew, so prompt icons render.
The best feature is the quick terminal. Command+Shift+Space drops a terminal down over whatever I'm doing, from any app, and the same keys put it away.
theme = Atom One Dark
background-opacity = 0.9
background-blur = 80
macos-titlebar-style = hidden
window-padding-x = 8
window-padding-y = 8
font-family = MesloLGS Nerd Font Mono
font-size = 15
keybind = cmd+shift+space=toggle_quick_terminalThe shell
Zsh with Oh My Zsh for its git plugin, then the same tools Omarchy ships:
- Starship for the prompt, using a Catppuccin powerline theme. It shows the folder, git branch and status, the language version for the current project, the time and how long the last command took. Each machine gets its own symbol at the start of the prompt, so I always know which one I'm on.
- zoxide replaces
cd. It learns which folders I visit, socd blogjumps straight to the right one from anywhere. - fzf for fuzzy search through files and shell history, wired into the shell's key bindings.
- zsh-syntax-highlighting colours commands as I type, so typos show up before I hit enter.
- fnm manages Node versions and switches automatically when I
cdinto a project that pins one.
eval "$(fnm env --use-on-cd --shell zsh)"
eval "$(starship init zsh)"
eval "$(zoxide init --cmd cd zsh)"
source <(fzf --zsh)Yazi
Yazi is a fast terminal file manager. I've set it to open text and code files in Zed, so I can browse a project in the terminal and jump straight into an editor.
Every app I install
Everyday
- Vorssaint: a free, open-source menu bar toolkit that replaces a handful of apps. Its command bar sits on Command+Space, and it also gives me clipboard history, a quick launcher, keep-awake, system monitors, a volume mixer, screenshots and screen recording, and extras in the notch like a calendar, timers and downloads. Its settings are exported to the repo, so a new Mac gets the same setup with one import.
- Ghostty: the terminal, set as the default.
- Zed: my editor. It's fast, has AI built in, and its settings are symlinked from the repo too.
- FluidVoice: offline voice-to-text with AI clean-up, so I can talk instead of type.
- Superhuman: email, driven from the keyboard.
- Blip: sends files of any size between devices.
- Lightcraft: a photo library manager and raw developer.
- Klack: mechanical keyboard sounds for a laptop keyboard, from the Mac App Store. It isn't necessary, but it's fun.
- Slack, WhatsApp and Spotify, plus Google Drive for files and NordVPN for a VPN.
- Dashlane: passwords, with its Safari extension.
- ani-cli: anime from the terminal. It's not productive, but it's very Linux.
AI tools
- Claude and ChatGPT: the desktop chat apps.
- Codex: OpenAI's coding agent in the terminal.
- T3 Code: a minimal app for running coding agents. I run the nightly build.
- Grok Bot: AI teammates that work across other apps and tools.
Development
- OrbStack: runs Docker containers and Linux machines. It's a lighter, faster replacement for Docker Desktop, and
orbctl startbrings it up from the terminal. - GitHub CLI (
gh) and GitHub Desktop: pull requests, issues and repos from the terminal, plus a desktop client for the same.gh auth loginalso creates and uploads an SSH key, which saves a whole setup step. - Postman: for poking at APIs.
- ngrok: tunnels to localhost, for testing webhooks or showing someone a local build.
- Cyberduck: browses servers and cloud storage buckets.
- Biome: formatting and linting for JavaScript and TypeScript in one fast tool.
- fnm for Node, plus EAS CLI for building Expo apps. Expo itself runs per project through
npx expo. - multi-git-status: scans a folder of repos and lists the uncommitted, untracked and unpushed changes in each.
- Mole: deep-cleans caches and leftovers to win back disk space.
- jira-cli: Jira tickets from the terminal.
Kubernetes and infrastructure
- kubectl (aliased to
k), Helm and Argo CD's CLI for deploying. - k9s: a terminal UI for browsing and managing clusters.
- kubeseal: encrypts secrets so they can be committed to git safely.
- doctl and docker-machine for the cloud side. Cluster credentials are merged into the local kube config, never committed.
Installing everything
On a fresh Mac, it's Homebrew first, then two commands for almost everything:
# Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
# Desktop apps and the terminal font
brew install --cask aerospace ngrok nordvpn orbstack postman codex chatgpt \
claude cyberduck zed slack fluidvoice blip spotify t3-code@nightly ghostty \
google-drive grok-bot lightcraft vorssaint github superhuman whatsapp \
font-meslo-lg-nerd-font
# Command-line tools
brew install ankitpokhrel/jira-cli/jira-cli argocd biome derailed/k9s/k9s \
docker-machine doctl felixkratz/formulae/borders fnm fzf gh helm \
kubernetes-cli kubeseal mole multi-git-status pystardust/ani-cli/ani-cli \
starship zoxide zsh-syntax-highlighting yaziThen the shell, Node and the accounts:
# Oh My Zsh
git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$HOME/.oh-my-zsh"
# The latest Node.js as the default, plus EAS for Expo builds
fnm install --latest --use
fnm default "$(fnm current)"
npm install --global eas-cli
# GitHub over SSH
gh auth login --hostname github.com --git-protocol ssh --web
# Containers
orbctl startAfter that: link the config files, start the borders service with brew services start borders, import the Vorssaint settings, sign in to the apps and it's done.
The short version
- Steal the ideas, not the operating system. Tiling, a launcher and good terminal tools made Omarchy feel great, and none of them need Linux.
- Put your setup in git. A README you can run top to bottom, plus symlinked config files, turns setting up a new Mac into copying commands, and every tweak is saved.
- Keep secrets out of it. One local file that isn't in the repo means the whole setup can be shared without leaking anything.
- Stay portable. Most of these tools also run on Linux, so if I ever do switch, most of the setup comes with me.