macOS on Steroids
The ultimate macOS setup guide for developers who want peak productivity.
This is my almanac for setting up a new macOS machine to my workflows.
Setting up with a coding agent? Run the sections top to bottom. The Brewfile is safe to re-run, and the steps that need a password, a license, or a click in System Settings say so.
Initial System Setup
Step 1: Basic macOS Configuration
Before installing any applications, let's configure macOS for optimal productivity:
1Enable tap to click:
System Settings → Trackpad → Point & Click → Tap to click2Speed up key repeat rate:
defaults write -g InitialKeyRepeat -int 15defaults write -g KeyRepeat -int 23Show hidden files in Finder:
defaults write com.apple.finder AppleShowAllFiles YESkillall Finder4Disable press-and-hold for accented characters:
defaults write -g ApplePressAndHoldEnabled -bool false5Show path bar in Finder:
defaults write com.apple.finder ShowPathbar -bool true6Show status bar with available space in Finder:
defaults write com.apple.finder ShowStatusBar -bool true7Enable Quit option for Finder:
defaults write com.apple.Finder QuitMenuItem 1killall FinderWhat this does: The path bar shows your current folder location at the bottom of Finder windows, while the status bar displays available disk space and item counts. Enabling the Quit menu item allows you to fully quit Finder (useful when Pumba's Panel is your primary file browser)!
8Dock: right edge, small, instant auto-hide, a Quick Note hot corner (bottom-right), and nothing in it but Zen, not even recent apps. The Hyper keys below launch everything else, so the Dock barely needs to exist:
# Position, size, auto-hide defaults write com.apple.dock orientation -string right defaults write com.apple.dock tilesize -int 32 defaults write com.apple.dock autohide -bool true defaults write com.apple.dock autohide-delay -float 0 defaults write com.apple.dock autohide-time-modifier -float 0.4 # No "suggested and recent apps" section defaults write com.apple.dock show-recents -bool false # Bottom-right hot corner → Quick Note defaults write com.apple.dock wvous-br-corner -int 14 defaults write com.apple.dock wvous-br-modifier -int 0 # Dock contents: wipe Apple's defaults, pin only Zen # (run this part after the Brewfile below has installed dockutil and Zen) dockutil --remove all --no-restart dockutil --add /Applications/Zen.app --no-restart killall Dock
9Turn off macOS's built-in window tiling so it doesn't fight Rectangle:
defaults write com.apple.WindowManager EnableTilingByEdgeDrag -bool false defaults write com.apple.WindowManager EnableTopTilingByEdgeDrag -bool false defaults write com.apple.WindowManager EnableTilingOptionAccelerator -bool false defaults write com.apple.WindowManager EnableTiledWindowMargins -bool false
10Dark mode and natural scrolling off (log out to apply). Menu bar icon spacing is left to Bartender, which resets the spacing keys anyway:
defaults write -g AppleInterfaceStyle -string Dark defaults write -g com.apple.swipescrolldirection -bool false
11Free up system shortcuts: Raycast takes ⌘Space, CleanShot takes ⌘⇧3/4/5, and ⌃Space, ⌃←/⌃→ and ⌃1 stop switching input sources and Spaces. Put Raycast on ⌘Space and start it first, so you're never left without a launcher:
defaults write com.raycast.macos raycastGlobalHotkey -string "Command-49" # 49 = Space open -a Raycast
Then take the shortcuts away from macOS:
# id:char,keycode,modifiers. Screenshots 28-31 + 184, input source 60-61,
# Spotlight 64-65, move a Space left/right 79 + 81, Desktop 1 118
for s in 28:51,20,1179648 29:51,20,1441792 30:52,21,1179648 31:52,21,1441792 \
184:53,23,1179648 60:32,49,262144 61:32,49,786432 64:32,49,1048576 \
65:32,49,1572864 79:65535,123,8650752 81:65535,124,8650752 118:65535,18,262144; do
id=${s%%:*}; IFS=, read -r a b c <<< "${s#*:}"
defaults write com.apple.symbolichotkeys AppleSymbolicHotKeys -dict-add "$id" \
"<dict><key>enabled</key><false/><key>value</key><dict><key>parameters</key><array><integer>$a</integer><integer>$b</integer><integer>$c</integer></array><key>type</key><string>standard</string></dict></dict>"
done
/System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -uThen, in CleanShot's settings, set ⌘⇧3 / ⌘⇧4 / ⌘⇧5 as its fullscreen, area, and all-in-one shortcuts
12App preferences. Quit each app first, or it writes its old settings back on exit. Rectangle keeps only almost-maximize on ⌃⌥↩ plus the half-screen defaults, Trimmy trims on its own with its hotkeys off, and CleanShot saves to Downloads:
R=com.knollsoft.Rectangle
defaults write $R alternateDefaultShortcuts -bool true
defaults write $R allowAnyShortcut -bool true
defaults write $R hideMenubarIcon -bool true
defaults write $R launchOnLogin -bool true
defaults write $R almostMaximize -dict keyCode -int 36 modifierFlags -int 786432
for a in topHalf bottomHalf topLeft topRight bottomLeft bottomRight center \
firstThird centerThird lastThird firstTwoThirds centerTwoThirds lastTwoThirds \
maximize maximizeHeight larger smaller restore; do
defaults write $R $a -dict
done
T=com.steipete.trimmy
defaults write $T generalAggressiveness -string high
defaults write $T terminalAggressiveness -string high
defaults write $T KeyboardShortcuts_trimClipboard -bool false
defaults write $T KeyboardShortcuts_pasteOriginal -bool false
defaults write pl.maketheweb.cleanshotx exportPath -string "$HOME/Downloads"13Keep the screen on. The display and the Mac never sleep on idle (closing the lid still sleeps it), and there's no screen saver:
sudo pmset -a displaysleep 0 sleep 0 defaults -currentHost write com.apple.screensaver idleTime -int 0
14No widgets. A new Mac puts Calendar, Weather, and Photos widgets on the desktop; hide the widget layer (log out to apply), and stop Photos from opening whenever an iPhone is plugged in:
# System Settings → Desktop & Dock → Show Widgets: off (desktop and Stage Manager) defaults write com.apple.WindowManager StandardHideWidgets -int 1 defaults write com.apple.WindowManager StageManagerHideWidgets -int 1 # Don't open Photos when an iPhone or camera is connected defaults -currentHost write com.apple.ImageCapture disableHotPlug -bool YES
15Remove the stock apps I don't use. Only the App Store bundles can go: GarageBand, iMovie, Keynote, Numbers, and Pages, about 8.5 GB with GarageBand's sound library (skip the Logic folder if you use Logic Pro). They go to the Trash, so this is undoable:
for app in GarageBand iMovie Keynote Numbers Pages \
"Keynote Creator Studio" "Numbers Creator Studio" "Pages Creator Studio"; do
[ -d "/Applications/$app.app" ] && sudo mv "/Applications/$app.app" ~/.Trash/
done
sudo mv "/Library/Application Support/GarageBand" "/Library/Application Support/Logic" \
"/Library/Audio/Apple Loops" ~/.Trash/Safari and everything in /System/Applications (Mail, Music, TV, Maps, News…) live on the sealed system volume and can't be deleted without turning off SIP, which isn't worth it. They stay out of the way anyway: the Dock holds only Zen, and the defaults further down send every file type to my own apps.
Wallpapers & Visual Setup
Desktop Wallpapers
My collection of desktop wallpapers:




Twitter Banners
For your Twitter account banners and social media:





Profile Pictures
For consistency across all your accounts:





Installing Homebrew & Core Applications
Step 1: Install Homebrew
Homebrew is the essential package manager for macOS. It simplifies installing and managing applications.
Run this command in Terminal:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"After installation, add Homebrew to your PATH:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofileeval "$(/opt/homebrew/bin/brew shellenv)"Step 2: Install Essential Applications
Now let's install all the applications you'll need. I've organized them by category with detailed explanations:
One-Command Installation
Install everything at once with a Brewfile. brew bundle installs each entry on its own, so one renamed or broken cask doesn't sink the rest, and re-running it only installs what's missing:
Priority: Little Snitch goes in first. It needs admin rights, and you approve its system extension and network filter in System Settings → Privacy & Security, so it's watching before the rest of the install starts phoning home.
brew bundle --file=- <<'EOF'
# Priority: the outbound firewall goes in first
cask "little-snitch"
# Third-party taps (Homebrew only loads taps you trust)
tap "steipete/tap"
# CLI tools
brew "node@24", link: true
brew "fnm"
brew "python"
brew "git"
brew "git-lfs"
brew "gh"
brew "uv"
brew "bun"
brew "zoxide"
brew "atuin"
brew "fzf"
brew "yt-dlp"
brew "gallery-dl"
brew "ffmpeg"
brew "exiftool"
brew "pandoc"
brew "poppler"
brew "ghostscript"
brew "watch"
brew "duti"
brew "dockutil"
brew "mas"
brew "rclone"
brew "apify-cli"
cask "gcloud-cli"
# Browsers
cask "zen"
cask "arc"
cask "google-chrome"
# AI and dev tools
cask "claude"
cask "chatgpt"
cask "claude-code@latest"
cask "codex"
cask "ghostty"
cask "zed"
cask "orbstack"
cask "ngrok"
cask "steipete/tap/codexbar", trusted: true
# Productivity and system
cask "obsidian"
cask "raycast"
cask "bettertouchtool"
cask "rectangle"
cask "bartender" # Bartender 7 = macOS 27 only; on macOS 26 install Bartender 6 (see below)
cask "flux-app"
cask "steipete/tap/trimmy", trusted: true
cask "cotypist"
cask "alcove"
cask "iloader"
cask "mole-app"
# Office and reading (mail, calendar, dictation and files live in Pumba)
cask "libreoffice"
cask "calibre"
# Communication
cask "discord"
cask "slack"
cask "telegram"
cask "zoom"
# Creative and media
cask "cleanshot"
cask "pixelsnap"
cask "screen-studio"
cask "figma"
cask "iina"
# Audio, privacy, fonts
cask "finetune"
cask "soundsource"
cask "protonvpn"
cask "font-jetbrains-mono-nerd-font"
EOFThen the few things Homebrew can't install:
# Mac App Store: sign in to the App Store app first (mas needs sudo)
sudo mas install 937984704 6446206067 6469021132 310633997 # Amphetamine, Klack, PDFgear, WhatsApp
# pnpm through corepack (respects each repo's packageManager pin)
npm install -g corepack && corepack enable pnpm
# Grok CLI
curl -fsSL https://x.ai/cli/install.sh | bashNot in the Brewfile on purpose: DaVinci Resolve (no cask), Pear Desktop (pinned version), and Pumba (built from source), all below.
Core Command Line Tools
brew install node@24 && brew link --force node@24Node.js - JavaScript runtime, pinned to the 24 LTS line. node@24 is keg-only, so link it to put node/npm on your PATH. apify-cli pulls in the latest node as a dependency, and its npm files block the link; brew link --overwrite --force node@24 fixes it (apify-cli keeps its own Node)
brew install fnm && fnm default systemfnm - Per-project Node versions: cd into a repo and fnm switches to the version in its .nvmrc (installing one is fnm install <version>). fnm default system keeps Homebrew's node@24 everywhere else. Shell hook in the .zshrc additions below
brew install pythonPython - Essential programming language for scripting and development
brew install git git-lfs && git lfs installGit - Version control system (brew version is more up-to-date than macOS default), plus Git LFS for repos with large binary files
brew install uvuv - Extremely fast Python package and project manager, written in Rust
brew install zoxidezoxide - Smarter cd command that remembers your most used directories
brew install atuinAtuin - Magical shell history with sync across machines
brew install yt-dlpyt-dlp - Download videos/images from YouTube and 1000+ other sites
brew install gallery-dlgallery-dl - Download image galleries and collections from Instagram, Twitter/X, Reddit, Pinterest, and hundreds of other sites
brew install fzffzf - Command-line fuzzy finder for files, history, and processes
brew install ghGitHub CLI - PRs, issues, releases, and auth from the terminal. Coding agents lean on it heavily
brew install ffmpeg exiftool pandoc poppler ghostscriptMedia & document toolbelt:
- ffmpeg - convert, trim, and transcode any audio/video
- exiftool - read, write, and strip photo/video metadata
- pandoc - convert between Markdown, DOCX, HTML, PDF, and friends
- poppler / ghostscript - PDF text extraction, rendering, and compression
brew install --cask gcloud-cli && brew install rcloneCloud CLIs: Google Cloud (gcloud, bq) and rclone, which syncs files to and from any cloud storage
brew install watchwatch - rerun a command every N seconds
brew install apify-cliApify CLI - Run and deploy Apify scrapers (Actors) from the terminal
curl -fsSL https://x.ai/cli/install.sh | bashGrok CLI - xAI's terminal coding agent. Installs to ~/.grok/bin and adds itself to your PATH
npm install -g corepack && corepack enable pnpmpnpm through corepack, so each repo gets the pnpm version its packageManager field pins
Browsers
brew install --cask zenZen Browser - Privacy-focused browser with excellent customization. My default browser
brew install --cask arcArc - Chromium browser with spaces and a vertical sidebar. My second browser, on Hyper + Q
brew install --cask google-chromeChrome - Primary browser with excellent DevTools
Development Tools
brew install --cask claudeClaude - Anthropic's desktop app: chat, plus a Code tab that runs Claude Code sessions with a GUI. My main agent surface (Hyper + E)
brew install --cask claude-code@latestClaude Code - Anthropic's terminal coding agent. The @latest cask tracks the fast release channel; plain claude-code is the stable channel. Skills, plugins, and config are covered further down
brew install --cask codexCodex CLI - OpenAI's terminal coding agent. The desktop Codex experience lives inside the ChatGPT app (below)
brew install --cask zedZed - Free, open-source editor written in Rust, and my default app for every text and code file (setup below). It opens fast, the gutter marks lines changed against git, Project Diff shows every uncommitted change, and the Git Panel stages hunks and commits, so it doubles as my git client. zed . opens a folder
brew install --cask orbstackOrbStack - Drop-in Docker Desktop replacement plus lightweight Linux VMs. Faster, lighter on battery, and the docker CLI just works
brew install --cask ngrokngrok - Expose a localhost port on a public URL for webhooks and demos
brew install --cask ghosttyGhostty - Fast, feature-rich terminal emulator, and my default terminal (setup below)
brew install --cask steipete/tap/codexbarCodexBar - Free, open-source menu bar app that keeps every AI coding usage window, credit balance, and reset timer in view across 40+ providers (Codex, Claude Code, Cursor, and more). No login required
Productivity & System Tools
gh repo clone wimpywarlord/pumba ~/Documents/pumbaPumba - My own app (Hyper + A): a fully local meeting notetaker. It lives in the menu bar, notices when a meeting starts, records your mic and only the meeting app's audio, and writes notes where every point links back to the moment it was said. Transcription and summaries run on the Mac. It also took over from four apps I used to install: Mail (Gmail) replaces Meru, Calendar replaces Notion Calendar, Dictation replaces VoiceInk, and Panel, a keyboard-first file browser, replaces ForkLift. Build and install it with scripts/install.sh; the README lists what that needs (Xcode 26.6 with the Metal Toolchain, a local signing identity, and the model download)
brew install --cask obsidianObsidian - Local-first Markdown knowledge base. Plain files on disk, so agents can read and write my notes too (Hyper + D)
brew install --cask raycastRaycast - Launcher with clipboard history, snippets, window commands, and extensions. On ⌘Space (Step 11 takes that shortcut away from Spotlight)
brew install --cask bettertouchtoolBetterTouchTool - Customize trackpad gestures, keyboard shortcuts, and Touch Bar
brew install --cask flux-appf.lux - Adjust screen color temperature based on time of day
brew install --cask rectangleRectangle - Window management made simple with keyboard shortcuts (my trimmed-down config is in Step 12)
brew install --cask bartenderBartender - My go-to menu bar manager. Hide, reorder, and reveal menu bar items, with triggers, hotkeys, and per-item show/hide rules. Paid, the most polished option. Heads-up: the cask now installs Bartender 7, which only runs on macOS 27 (on macOS 26 it quits with "macOS 26 compatibility isn't ready yet"). On macOS 26, install the last Bartender 6 instead, checked against the hash Homebrew recorded for it:
curl -fsSL -o /tmp/Bartender6.zip "https://downloads.macbartender.com/B2/updates/6-6-2/Bartender%206.zip" echo "e178616bc09956e39f0ab0ff9112b8fe89f744b406f8e417fb7b2aaf3524e064 /tmp/Bartender6.zip" | shasum -a 256 -c ditto -x -k /tmp/Bartender6.zip /Applications/
sudo mas install 937984704Amphetamine - Keep your Mac awake. Free from the Mac App Store with advanced triggers and session control
sudo mas install 6446206067Klack - Satisfying mechanical keyboard sounds for every keystroke. Available on the Mac App Store
brew install --cask steipete/tap/trimmyTrimmy - Watches your clipboard and folds multi-line shell snippets (pipes, redirects, line continuations) into a single pasteable line. I run it on auto-trim with its hotkeys off (Step 12). No dock icon, no network, no daemon
brew install --cask cotypistCotypist - On-device AI that predicts your next words in every Mac app. Press Tab to accept. Open source — make your own version
brew install --cask alcoveAlcove - Turns the notch into a Dynamic Island — music controls, notifications, and widgets in the dead space. Lightweight, one-time purchase
brew install --cask iloaderiloader - iOS sideloading companion for getting apps onto your iPhone from the Mac
Office & Documents
brew install --cask libreofficeLibreOffice - Free and powerful office suite
sudo mas install 6469021132PDF Gear - Excellent free PDF editor with annotation tools, from the Mac App Store. My default PDF app
brew install --cask calibrecalibre - Ebook library manager and converter. How books get onto my Kobo
Communication
brew install --cask discordDiscord - Community and team communication
sudo mas install 310633997WhatsApp - Popular messaging platform. I use the Mac App Store build (Hyper + R)
brew install --cask slackSlack - Work and team communication
brew install --cask telegramTelegram - Fast messaging with a native macOS client
brew install --cask zoomZoom - Video calls
Creative & Media Tools
brew install --cask cleanshotCleanShot X - Advanced screenshot and screen recording tool
brew install --cask pixelsnapPixelSnap 2 - Pixel-perfect on-screen measurement tool with edge detection. Measure distances, sizes, and grab colors anywhere on screen. Integrates with CleanShot for design and dev work (Hyper + P)
brew install --cask screen-studioScreen Studio - Professional screen recording with beautiful animations
DaVinci Resolve - Professional video editing and color grading. The Homebrew cask is gone, so download the installer from Blackmagic directly
brew install --cask figmaFigma - Collaborative design tool for UI/UX
Media Players
brew install --cask iinaIINA - Modern media player designed specifically for macOS. My default for all audio and video (setup below)
brew install --cask pear-devs/pear/pear-desktopPear Desktop - Unofficial YouTube Music desktop app (formerly th-ch/youtube-music) with ad-block, plugins, and a proper native window. Installs as YouTube Music.app
I'm pinned to 3.11.0. 3.12.0 was a regression for my setup, so the brew cask (which tracks latest) is not the way to restore it. Pull the exact DMG from GitHub releases instead:
cd ~/Downloads curl -LO https://github.com/pear-devs/pear-desktop/releases/download/v3.11.0/YouTube-Music-3.11.0-arm64.dmg MOUNT=$(hdiutil attach -nobrowse YouTube-Music-3.11.0-arm64.dmg | grep -o '/Volumes/.*') rm -rf "/Applications/YouTube Music.app" cp -R "$MOUNT/YouTube Music.app" /Applications/ hdiutil detach "$MOUNT" defaults read "/Applications/YouTube Music.app/Contents/Info.plist" CFBundleShortVersionString # → 3.11.0
Settings and plugins live in ~/Library/Application Support/YouTube Music and survive a swap of the .app. Back that folder up if you care about your config.
Keeping it pinned: plain brew upgrade skips this cask (auto_updates), so the daily routine is safe. Never run brew upgrade --greedy or brew reinstall --cask pear-desktop — both drag in latest. Inside the app, keep auto-update off (Options menu, or set "autoUpdates": false under options in config.json) and decline the update prompt if it ever shows.
Audio Utilities
brew install --cask finetuneFineTune - My pick. Free, open-source per-app volume control and audio routing in the menu bar
brew install --cask soundsourceSoundSource - My backup, since I own a license. Advanced per-app volume control, audio routing, and system-wide EQ
Security & Privacy
brew install --cask little-snitchLittle Snitch - Outbound firewall. See and block every connection every app tries to make. Priority install: it's first in the Brewfile, and it needs admin rights plus a manual approval of its system extension. The Network Monitor window is only the traffic viewer: quit it (⌘Q) to keep it out of the Dock and ⌘Tab, and the firewall keeps running
brew install --cask protonvpnProtonVPN - Secure VPN service with strong privacy focus
brew install --cask chatgptChatGPT - Official OpenAI desktop app. As of July 2026, the standalone Codex app has merged into ChatGPT: one app with Chat, Work, and Codex modes. No separate Codex desktop install — update ChatGPT (or your old Codex app) and switch to the Codex view for repos, diffs, PRs, and agent coding. You can set Codex as the default view / app icon if you live in the coding agent
Terminal Setup with Oh My Zsh
Step 1: Install Oh My Zsh
Oh My Zsh is a framework for managing your Zsh configuration with tons of helpful features.
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"The installer replaces ~/.zshrc (the old one is saved as ~/.zshrc.pre-oh-my-zsh), so run it before anything else appends to that file, or re-run the Grok installer afterwards
Step 2: Install Powerlevel10k Theme
The most powerful and customizable Zsh theme:
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10kThen edit your ~/.zshrc:
nano ~/.zshrcChange the theme line to:
ZSH_THEME="powerlevel10k/powerlevel10k"Powerlevel10k's icons need a Nerd Font:
brew install --cask font-jetbrains-mono-nerd-fontThen pick JetBrainsMono Nerd Font as the terminal font.
Step 3: Install Essential Zsh Plugins
zsh-autosuggestions
Suggests commands as you type based on your history:
git clone https://github.com/zsh-users/zsh-autosuggestions.git $ZSH_CUSTOM/plugins/zsh-autosuggestionszsh-syntax-highlighting
Provides syntax highlighting for your shell commands:
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM/plugins/zsh-syntax-highlightingzsh-fast-syntax-highlighting
Faster and more feature-rich syntax highlighting:
git clone https://github.com/zdharma-continuum/fast-syntax-highlighting.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/fast-syntax-highlightingzsh-autocomplete
Real-time auto-completion as you type:
git clone --depth 1 -- https://github.com/marlonrichert/zsh-autocomplete.git $ZSH_CUSTOM/plugins/zsh-autocompleteEnabling the Plugins
Edit your ~/.zshrc file and update the plugins line:
nano ~/.zshrcFind the line that says plugins=(git) and replace it with:
plugins=(git zsh-autosuggestions zsh-syntax-highlighting fast-syntax-highlighting zsh-autocomplete)Apply the changes:
source ~/.zshrcConfiguration Wizard: After restarting your terminal, Powerlevel10k will run a configuration wizard. Choose options that match your aesthetic preferences! Run it in Ghostty, which has the Nerd Font icons built in; elsewhere it falls back to a plain ASCII prompt. Moving from another Mac? Copy the old ~/.p10k.zsh over instead and skip the wizard.
Step 4: Advanced Terminal Tools Setup
Initialize Shell History with Atuin
Set up magical shell history sync:
echo 'eval "$(atuin init zsh)"' >> ~/.zshrcatuin import autoThe init line is what actually binds Ctrl+R and the up arrow to Atuin; without it Atuin is installed but does nothing. fzf (below) also claims Ctrl+R, and whichever loads last in ~/.zshrc wins, so keep this line after the fzf one. The import pulls in your existing shell history (on a fresh Mac there's none yet, so it errors harmlessly)
Moving from another Mac? Copy ~/.local/share/atuin/history.db and ~/.config/atuin/config.toml across, but on the old Mac flush the write-ahead log first, or the copy comes out malformed:
sqlite3 ~/.local/share/atuin/history.db 'pragma wal_checkpoint(TRUNCATE)'Configure Zoxide for Smart Navigation
Initialize zoxide in your shell:
echo 'eval "$(zoxide init zsh)"' >> ~/.zshrcNow use z instead of cd - it remembers your most used directories
Setup FZF Integration
Add fuzzy finding to your shell:
$(brew --prefix)/opt/fzf/installEnables Ctrl+R for history search and Ctrl+T for file search
Step 5: Handy ~/.zshrc Additions
Auto-Activate Python Virtual Environments
Activates the nearest .venv whenever you cd into a project, puts pnpm on the PATH, and lets fnm switch Node per project:
# Auto-activate Python virtual environment if .venv exists (no auto-deactivate)
function auto_activate_env() {
local dir=$PWD
while [ "$dir" != "/" ]; do
if [ -d "$dir/.venv" ]; then
source "$dir/.venv/bin/activate"
echo "✅ Activated virtual environment ($dir/.venv)"
return
fi
dir=$(dirname "$dir")
done
}
autoload -U add-zsh-hook
add-zsh-hook chpwd auto_activate_env
# Also activate immediately on shell startup
auto_activate_env
# pnpm
export PNPM_HOME="$HOME/Library/pnpm"
case ":$PATH:" in
*":$PNPM_HOME:"*) ;;
*) export PATH="$PNPM_HOME:$PATH" ;;
esac
# pnpm end
# fnm: per-project Node versions from .nvmrc (Homebrew's node@24 stays the default)
eval "$(fnm env --use-on-cd --version-file-strategy=recursive --corepack-enabled --log-level=error --shell zsh)"
# zsh caches command paths; re-hash after fnm switches Node on cd
_fnm_rehash() { rehash }
add-zsh-hook chpwd _fnm_rehashGhostty Terminal Configuration
Essential Ghostty Settings
My full Ghostty config, in ~/.config/ghostty/config:
# Restore windows, tabs, and splits on relaunch
window-save-state = always
# ~75 MB of scrollback per terminal (the value is in bytes; agent logs get long)
scrollback-limit = 75000000
cursor-style = bar
cursor-style-blink = true
background-opacity = 0.95
background-blur-radius = 20What this does: Ghostty remembers your window positions, sizes, open tabs, and split configurations across sessions, and keeps enough scrollback that long agent runs never fall off the top. Config reference
Make Ghostty the Default Terminal
Ghostty is my default terminal. Point executables and .command / .tool scripts at it so a double-click opens Ghostty instead of Terminal (needs duti from the Brewfile):
GHOSTTY=com.mitchellh.ghostty
duti -s "$GHOSTTY" public.unix-executable all
duti -s "$GHOSTTY" com.apple.terminal.shell-script all
duti -s "$GHOSTTY" command all
duti -s "$GHOSTTY" tool all
# Verify: both should print Ghostty
duti -x command
duti -x tool.sh and .zsh files stay with Zed for editing (see the Zed defaults below).
Hyper Key Setup & Macros
Ultimate Productivity Shortcuts
Using BetterTouchTool's Hyper Key (⌘⌥⌃⇧). Never use your eyes for navigation (vision search is slow), use your muscle memory:
Configure these shortcuts in BetterTouchTool:
- Caps Lock → Act as Hyper Key (⌘⌥⌃⇧)
- Hyper + Q → Launch Arc
- Hyper + W → Launch Zen Browser
- Hyper + E → Launch Claude
- Hyper + R → Launch WhatsApp
- Hyper + A → Pumba on Notes / to-dos (BetterTouchTool "Open URL" with
pumba://notes, which also launches it) - Hyper + S → Launch ChatGPT (includes Codex)
- Hyper + D → Launch Obsidian
- Hyper + F → Launch Discord
- Hyper + G → Launch YouTube Music
- Hyper + N → Launch Figma
- Hyper + P → PixelSnap (set this one in PixelSnap's own settings, not BetterTouchTool)
- Hyper + 1 / 2 → Switch to Desktop 1 / 2. Two desktops max: add the second one in Mission Control
- Pumba's own (set in Pumba's settings, not BetterTouchTool, or BetterTouchTool swallows them): Hyper + T dictation, Y paste last dictation, C calendar, X mail, Z Panel, M recording, V Splinter
Tip: The Hyper Key eliminates conflicts with existing shortcuts while giving you instant access to any app. It's the most efficient way to navigate your Mac! On a new machine, export your BetterTouchTool preset and import it instead of rebuilding these by hand.
Development Environment Setup
Bun - Fast JavaScript Runtime
Install Bun, a fast all-in-one JavaScript runtime and toolkit:
brew install bunBun is in homebrew-core now, so brew upgrade keeps it current. The old curl -fsSL https://bun.sh/install | bash installer still works if you prefer ~/.bun
What is Bun? Bun is a modern JavaScript runtime that's significantly faster than Node.js. It includes a bundler, test runner, and package manager all in one. Perfect for modern web development!
Python Environment with uv
We already installed uv via Homebrew earlier. Now let's use it to manage Python versions:
uv python install 3.12Homebrew already brings a current Python 3.13/3.14 for scripts; uv manages the per-project versions. Run uv python pin 3.12 inside a project to write its .python-version
Why uv? uv is an extremely fast Python package and project manager written in Rust. It's 10-100x faster than pip and handles both package management and Python version management in one tool!
Git Configuration
Set up your Git identity and preferences:
git config --global user.name "Your Name"git config --global user.email "your.email@example.com"git config --global init.defaultBranch maingit config --global pull.rebase trueSSH Keys for GitHub
Generate and add SSH keys for secure GitHub access:
ssh-keygen -t ed25519 -C "your.email@example.com"eval "$(ssh-agent -s)"ssh-add ~/.ssh/id_ed25519pbcopy < ~/.ssh/id_ed25519.pubNow go to GitHub → Settings → SSH Keys and paste
Or let the GitHub CLI do the key upload and auth in one go:
gh auth loginPick GitHub.com → SSH → your id_ed25519.pub. This also gives coding agents a working gh for PRs and issues
My Global CLAUDE.md & AGENTS.md
Every coding agent I run inherits the same thinking style. I keep this prompt in my global ~/.claude/CLAUDE.md and a matching ~/.codex/AGENTS.md so Claude Code and Codex both reason the way I do by default. The block at the bottom routes work to the skills below, and the BuilderIO installer writes it for you:
Be organized, accurate, thorough, and detailed without unnecessary verbosity.
Treat me as an expert. Do not dumb things down.
Optimize for truth and correctness over approval, conformity, politeness, or harmony. If I'm wrong, say so directly.
Value good arguments over authorities or sources. Consider serious contrarian arguments alongside consensus expert views.
When useful, present the strongest counterargument to any position I appear to hold.
Do not capitulate when I push back unless I provide new evidence or a better argument.
Do not anchor on numbers, estimates, or assumptions I provide; generate your own independently.
Be skeptical by default. Look for hidden assumptions, failure modes, and ways to improve the answer, product, argument, or system.
My epistemology is the same as David Deutsch or Karl Popper. Naval Ravikant has serious resonance with my thinking loops.
Be surprisingly resourceful. Suggest non-obvious solutions. Be proactive and anticipate my needs. Assume I am high-agency and can make practically anything happen.
Cite sources. Use examples liberally.
Open-minded and impossible to offend. Be provocative, argumentative, and pointed when useful.
When copy editing, always mark changes inline.
About me: Kshitij (tjay) Dhyani (@type_tjay on X)
Founding engineer at an a16z-backed startup. Previously co-founded Ghostfeed (exited). Entrepreneur, technical, range of knowledge/experience.
<!-- BEGIN @agent-native/skills -->
When operating as Claude Fable, use the /efficient-fable skill always.
When using a high-cost frontier model for codebase-heavy work, use the /efficient-frontier skill always.
When writing final response status indicators, use the /quick-recap skill always.
When long-running or parallel work needs usage-limit checks, use the /stay-within-limits skill always.
<!-- END @agent-native/skills -->Claude Code & Codex Skills
Skills are reusable instruction packs that live in ~/.claude/skills/ and load on demand. These are the ones I keep installed:
npx skills add jakubkrehel/skills --skill '*' -g -a claude-code -a codex -yThe skills CLI installs a skill repo once into ~/.agents/skills/ (which Codex reads natively), symlinks it into Claude Code, and tracks sources in ~/.agents/.skill-lock.json. -g installs for your user instead of the current project, -a picks the agents (leave it out and you get a skills folder for every agent the CLI knows), --skill picks skills from a repo, and -y skips the prompts. Every install below follows this pattern
Code Quality
- thermo-nuclear-code-quality-review - Brutally strict maintainability review. Blocks files past 1,000 lines, rejects ad-hoc spaghetti conditionals, questions thin abstractions and magical behavior, and enforces architectural boundaries. From Cursor's team kit
npx skills add https://github.com/cursor/plugins/tree/main/cursor-team-kit/skills/thermo-nuclear-code-quality-review -g -a claude-code -a codex -yAgent Orchestration & Usage
From BuilderIO/skills, which ships its own installer. --update-instructions also writes the routing block at the bottom of the CLAUDE.md above. Install all four in one run: each run rewrites that block with only its own skills, so a loop of single installs leaves just the last one:
npx @agent-native/skills@latest add \
--skill efficient-fable --skill efficient-frontier --skill stay-within-limits --skill quick-recap \
--client claude-code --client codex --scope user --update-instructions --no-connectefficient-fable- Run Claude Fable as the orchestrator while cheaper subagents do token-heavy research, coding, and testingefficient-frontier- Same orchestration pattern for any high-cost frontier model: delegate heavy lifting, keep planning and final review on the expensive modelstay-within-limits- Respects 5-hour and weekly usage limits — pauses near the cap and resumes when the window clearsquick-recap- Red/yellow/green status block convention for final agent responses
Frontend & Design
npx skills add jakubkrehel/skills --skill '*' -g -a claude-code -a codex -y
npx skills add jakubkrehel/make-interfaces-feel-better -g -a claude-code -a codex -y
npx skills add anthropics/skills --skill frontend-design -g -a claude-code -a codex -y
npx skills add vercel-labs/agent-skills --skill vercel-react-best-practices --skill web-design-guidelines -g -a claude-code -a codex -y
npx skills add ibelick/ui-skills --skill '*' -g -a claude-code -a codex -y- jakubkrehel/skills - The set I use most after the BuilderIO four. better-interface runs one review across better-accessibility, better-colors, better-layout, better-typography, better-writing, and better-ui (concentric border radius, optical alignment, surface depth, hit areas). Also break, explain-interface, interface-review, and variant
frontend-design- Distinctive, production-grade frontend interfaces that avoid generic AI aesthetics (anthropics/skills)- ibelick/ui-skills - Opinionated constraints for building interfaces. ui-skills-root routes to the smallest useful set: baseline-ui, improve-ui, fixing-accessibility, fixing-metadata, fixing-motion-performance, and create-design-md
web-design-guidelines- Reviews UI code for Web Interface Guidelines compliance — accessibility, UX, and design audits (vercel-labs/agent-skills)vercel-react-best-practices- React and Next.js performance optimization guidelines from Vercel Engineering (vercel-labs/agent-skills)- make-interfaces-feel-better - Design-engineering details that make interfaces feel polished: micro-interactions, enter/exit animations, shadows, typography, tabular numbers
Writing & Content
npx skills add blader/humanizer -g -a claude-code -a codex -y- humanizer - Strips signs of AI-generated writing, based on Wikipedia's "Signs of AI writing" guide
tiktok-hooks- Generates Gen-Z / college-apps TikTok hooks for the first 1-3 seconds of a video
No public source for tiktok-hooks and create-plan (a concise read-only planner): copy their folders from the previous Mac's ~/.claude/skills.
Claude Code Plugins
From the official claude-plugins-official marketplace. A fresh install only knows the built-in directory, so add the marketplace first, then install each one:
claude plugin marketplace add anthropics/claude-plugins-official
for p in commit-commands code-simplifier context7 playwright github figma vercel frontend-design swift-lsp; do
claude plugin install "$p@claude-plugins-official"
donecommit-commands- /commit and /commit-push-pr in one stepcode-simplifier- Agent that simplifies recently changed code without changing behaviorcontext7- Pulls current library docs instead of relying on stale training dataplaywright- Browser automation for testing and clicking through flowsgithub,figma,vercel- First-party integrations for repos, design files, and deploysfrontend-design,swift-lsp- Design guidance and Swift language server support
The github plugin's MCP server needs a GITHUB_PERSONAL_ACCESS_TOKEN in your environment, and figma and vercel sign in through /mcp inside Claude Code. Rather than minting a separate token, I hand it the gh login from the Keychain, in ~/.zshrc:
export GITHUB_PERSONAL_ACCESS_TOKEN="$(/opt/homebrew/bin/gh auth token 2>/dev/null)"MCP Servers
claude mcp add --scope user --transport http linear https://mcp.linear.app/mcpLinear issues and projects from inside any Claude Code session
claude mcp add --scope user --transport http supabase "https://mcp.supabase.com/mcp?features=docs%2Caccount%2Cdatabase%2Cdebugging%2Cdevelopment%2Cfunctions%2Cbranching"Supabase docs, databases, logs, edge functions, and branches. Signs in through /mcp on first use
claude mcp add --scope user davinci-resolve -- "/Applications/DaVinci Resolve/DaVinci Resolve.app/Contents/Applications/ResolveMCP"The MCP server built into DaVinci Resolve 21 (names can't contain spaces, hence davinci-resolve): scripting, LUTs, and DCTLs from inside Claude Code. Install Resolve first
System Maintenance
Regular Updates
Keep your system and applications up to date:
# Update Homebrew and all packagesbrew update && brew upgrade# Update Oh My Zshomz update# Update npm packages globallynpm update -gCloud Backup: Additionally, use iCloud to sync your important folders.
Mole - Deep Clean Your Mac
Mole deep cleans and optimizes your Mac — find large files, clear caches, and reclaim disk space with a clean, fast UI.
brew install --cask mole-appMole - Multi-language Mac cleaner and optimizer. Mole now lives in Homebrew proper: the mole-app cask is the desktop app, and brew install mole gets the CLI. I keep it menu bar only, out of the Dock and ⌘Tab (quit Mole first):
defaults write com.tw93.MoleApp hideDockIcon -bool trueFinal Tips & Tricks
Touch ID for sudo
Enable Touch ID for sudo commands:
sed "s/^#auth/auth/" /etc/pam.d/sudo_local.template | sudo tee /etc/pam.d/sudo_localDon't edit /etc/pam.d/sudo directly: macOS updates overwrite it and silently turn Touch ID back off. sudo_local is included by it and survives updates
Paste Without Formatting
Set up ⌘⇧V for paste without formatting in every app:
System Settings → Keyboard → Keyboard Shortcuts → App ShortcutsAdd shortcut for "Paste and Match Style" with ⌘⇧V

Reference: Reddit guide on paste without formatting
CleanShot X Auto Copy Setup
Enable auto copy to clipboard in CleanShot X for seamless screenshot workflow:
CleanShot X → Preferences → General → Auto copy to clipboardPosition the setting on the right side for easy access
Make CleanShot X the Default Image Viewer
macOS keeps reverting image defaults back to Preview because the "Open With → Change All" Finder dialog only binds a single UTI at a time and silently breaks when LaunchServices gets out of sync. Fix it permanently by setting every image UTI via duti:
brew install dutiA CLI for binding default apps by UTI — what the macOS GUI should have been
# CleanShot X's bundle ID is pl.maketheweb.cleanshotx
duti -s pl.maketheweb.cleanshotx public.jpeg all
duti -s pl.maketheweb.cleanshotx public.png all
duti -s pl.maketheweb.cleanshotx public.tiff all
duti -s pl.maketheweb.cleanshotx public.heic all
duti -s pl.maketheweb.cleanshotx public.heif all
duti -s pl.maketheweb.cleanshotx public.webp all
duti -s pl.maketheweb.cleanshotx com.compuserve.gif all
duti -s pl.maketheweb.cleanshotx public.image all
# Verify it stuck
duti -x jpg
duti -x pngIf it still reverts, your LaunchServices database is corrupt — rebuild it and re-run the binds:
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user
killall FinderWhy this works: Finder's "Change All" writes to a per-extension preference that other apps (and macOS updates) can stomp on. duti writes directly to the LaunchServices preferences plist using the canonical UTI, which is the same mechanism macOS itself uses internally — so the binding survives reboots, app updates, and OS upgrades.
Make IINA the Default Audio & Video Player
Same playbook as CleanShot above, but for IINA — the only macOS video player worth running. Bind every common audio/video UTI to com.colliderli.iina so QuickTime and Music stop hijacking your double-clicks:
IINA=com.colliderli.iina
# --- Video UTIs ---
for uti in \
public.movie public.video public.audiovisual-content \
public.mpeg-4 public.mpeg public.mpeg-2-video \
public.avi public.3gpp public.3gpp2 \
com.apple.quicktime-movie com.apple.m4v-video \
com.microsoft.windows-media-wmv com.microsoft.advanced-systems-format \
org.webmproject.webm public.flc-animation; do
duti -s "$IINA" "$uti" all
done
# --- Audio UTIs ---
for uti in \
public.audio public.mp3 public.mpeg-4-audio public.aac-audio \
public.aifc-audio public.aiff-audio \
com.apple.m4a-audio com.apple.coreaudio-format \
com.microsoft.waveform-audio \
org.xiph.flac org.xiph.ogg-audio com.real.realaudio; do
duti -s "$IINA" "$uti" all
done
# --- Extension fallbacks for formats with non-canonical UTIs ---
# (.ts is deliberately left out: it's TypeScript far more often than MPEG-TS video)
for ext in mkv opus webm flac ogg m2ts mts mxf wv ape \
rm rmvb ra asf vob flv f4v divx dv mp2 m3u m3u8; do
duti -s "$IINA" "$ext" all
done
# Force-register IINA so LaunchServices knows its claims
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "/Applications/IINA.app"
killall FinderVerify with duti -x mp4, duti -x mkv, duti -x mp3 — all three should print IINA.
Gotchas: A few obscure formats (tak, amv, xvid) have no registered UTI on macOS and will fail silently — ignore them. .pls playlists are aggressively claimed by Apple Music and IINA doesn't even declare them; not worth fighting since you'll likely never see one. Everything that matters (mp4 / mov / mkv / webm / mp3 / m4a / flac / opus / wav) sticks permanently.
Same trick for PDFs, pointing them at PDF Gear:
duti -s com.pdfeditor.pdfeditormac com.adobe.pdf allAnd Zen for web links (macOS asks you to confirm the browser change):
duti -s app.zen-browser.zen http
duti -s app.zen-browser.zen httpsMake Zed the Default for Text & Code
Out of the box, macOS scatters text files everywhere: Markdown into whatever ebook app claimed it, JSON into the browser, CSV into ChatGPT, .ts into a video player. I want all of it in Zed: it opens fast, and its gutter shows what changed against git. One script fixes it, and routes Word docs to LibreOffice while it's at it:
ZED=dev.zed.Zed
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "/Applications/Zed.app"
# --- Text, code, config, and data types, including ones other apps grab ---
for uti in public.plain-text public.source-code public.script public.shell-script \
public.json public.xml public.yaml public.comma-separated-values-text \
net.daringfireball.markdown com.apple.property-list com.apple.log \
com.microsoft.typescript public.toml com.microsoft.ini org.iso.sql; do
duti -s "$ZED" "$uti" all
done
# --- Extensions: bind each through duti, and collect the ones it can't ---
NOTYPE=()
for ext in md markdown mdx txt log json jsonc yaml yml toml xml plist csv tsv \
ini cfg conf env lock js mjs cjs ts tsx jsx py sh zsh bash swift \
c h cpp hpp java rb php go rs kt lua css scss sass less sql graphql \
vue svelte astro svg; do
duti -s "$ZED" "$ext" all 2>/dev/null
duti -x "$ext" 2>/dev/null | head -1 | grep -qx "Zed" || NOTYPE+=("$ext")
done
# --- No registered type: write those as extension handlers, the way Finder's
# "Change All" does, then restart LaunchServices so it reloads them ---
D=com.apple.LaunchServices/com.apple.launchservices.secure
defaults export $D /tmp/ls.plist
python3 - "${NOTYPE[@]}" <<'EOF'
import plistlib, sys
p, exts = "/tmp/ls.plist", sys.argv[1:]
d = plistlib.load(open(p, "rb"))
hs = [h for h in d.get("LSHandlers", []) if h.get("LSHandlerContentTag") not in exts]
hs += [{"LSHandlerContentTag": e,
"LSHandlerContentTagClass": "public.filename-extension",
"LSHandlerRoleAll": "dev.zed.zed",
"LSHandlerPreferredVersions": {"LSHandlerRoleAll": "-"}} for e in exts]
d["LSHandlers"] = hs
plistlib.dump(d, open(p, "wb"))
EOF
defaults import $D /tmp/ls.plist && killall lsd
# --- Word-processor docs -> LibreOffice (sheets and slides already go there) ---
for ext in docx doc rtf odt; do
duti -s org.libreoffice.script "$ext" all
doneGotchas: Run it as one script, after the IINA block above. Some extensions have a registered type (.tsx is com.microsoft.typescript, .toml and .cfg are public.toml), and macOS ignores an extension handler for those, which is why the first loop binds them by type. The rest make duti fail with error -50 and go through the plist. Editing the plist without the killall lsd doesn't stick: LaunchServices keeps its own copy in memory and writes it back over your change. macOS may pop a confirmation for a type another app already owns (.ts vs IINA); pick Zed. Verify with duti -x tsx. Installing Xcode later can hand .tsx to IINA again; fix it with duti -s dev.zed.Zed com.microsoft.typescript all.