My 2026 MacBook Air Developer Setup: Clean, Lean, and Reproducible
March 2, 2026 · 12 min read
- MacOS
- Developer Setup
- Tooling
- Productivity
- Performance
I spent two days rebuilding my M2 MacBook Air after hitting the memory ceiling with app clutter. The strategy was ruthless: factory reset, then install only what I actually use. This guide documents the process and the setup I landed on.
The Problem
Over 18 months, my MacBook accumulated:
- Multiple browser profiles with hundreds of tabs
- Docker images I'd forgotten about
- Orphaned Python virtual environments
- Xcode command-line tools that I never fully cleaned
- System caches for apps I no longer use
Result: 17 GB of swap on an M2 with 16 GB RAM. Mail would stall, Xcode/AndroidStudio builds would timeout, and simple context switches felt sluggish.
The realization: I didn't need a bigger Mac. I needed discipline.
Goals for the New Setup
- Memory discipline: Know exactly what's running and why.
- Small toolset: One shell, one terminal, one primary editor, intentional browser roles.
- Reproducible: New Mac in minutes via Brewfile + config files.
- Fast: Minimal startup overhead, no heavy frameworks or automation overhead.
1. Factory Reset (Erase All Content and Settings)
This was the hardest part for me psychologically, but the cleanest path.
Before I went ahead with the reset, I did the following:
- Backup critical projects: Git push everything to GitHub, mostly some projects I started but lazy enough to not even create first commit.
- Export configs: Create a
backup_configs.zipcontaining:
Reset steps:
- Go to System Settings → General → Transfer or Reset → Erase All Content and Settings.
- Enter Apple ID password to sign out of iCloud.
- Confirm the erase (takes ~10 minutes).
- On reboot, select Set up as new (no Migration Assistant).
Result:
- ~198 GB free (on a 256 GB drive).
- 0 bytes swap on first boot.
- It feels noticeably snappier immediately.
Reference: PCMag's factory reset guide
2. Base macOS Settings
I skipped the exotic tweaks and just enabled what helps:
- Displays → Built-in Display:
- Privacy & Security:
- Apple Intelligence (beta): Skip for now (reduces background processing).
- App-level zoom instead of changing resolution:
3. Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add to PATH (Apple Silicon)
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
brew --versionVerify it works:
brew list4. Brewfile: Package Everything
Create Brewfile in the home directory or repo root. This is the entire dev environment in one file:
# Brewfile
# Core tools
brew "git"
brew "wget"
brew "curl"
brew "gh" # GitHub CLI for faster repo cloning + PRs
brew "uv" # fast Python package & project manager (replaces pip/pipenv)
brew "atuin" # better history for terminal
brew "rclone" # because it's convinient management for remote drives
# Browsers
cask "google-chrome" # job applications, work portals
cask "firefox" # email, calendar, personal accounts
cask "brave-browser" # distraction-free reading, ad blocking
# Terminal & Editors
cask "ghostty" # primary terminal (minimal, fast)
cask "zed" # primary editor (Rust-based, lightning fast)
cask "visual-studio-code" # backup for extensions ecosystem
cask "sublime-text" # optional lightweight edits
# Knowledge & notes
cask "obsidian" # knowledge base
# Fonts (required for terminal)
cask "font-fira-code"
cask "font-fira-code-nerd-font"
# Utilities
cask "jiggler" # stop screen from sleeping
cask "vlc" # media playback
# cask "rectangle" # comment out for now; add later if you miss it
cask "obsidian"
cask "slack"
cask "raycast"
cask "skim"
# cask "basictex"
cask "mactex" # tex file compatibility
cask "zoom"
cask "proton-pass"
#cask "brave-browser"
cask "temurin" # jdk dependency
cask "chromedriver" # automation testing
cask "intellij-idea-ce"
cask "eclipse-java"Install everything at once:
cd ~
brew bundleNote: This will also check if any outdated brew packages are present within the system
following is taken from google search results:
brew outdated – Lists all installed formulae and casks that have newer versions available.
Use brew outdated --formula to list only command-line tools (formulae).
Use brew outdated --cask to list only GUI applications (casks).
Use brew outdated --greedy to include casks marked as "auto-updateable" or with version :latest.On a new Mac, this brings you from zero to a full dev environment in ~20 minutes.
Why this specific list?
- No Docker Desktop: Use OrbStack later if containers are needed (lighter).
- No VS Code by default: Zed is my primary editor now; Code is for its extensions and my familarity over the years.
- No Slack/Discord/WhatsApp: These are bandwidth hogs. Browser versions only. (This is what helped me significantly)
- No Xcode: Install command-line tools only when needed:
xcode-select --install. - Sublime: This is a no-brainer for me, I cannot thank the developer of this IDE enough. Its almost the only IDE I feel most comfortable with even after using I don't know how many :P
And how can I forget Sublime config. Here we go, my standard config:
{
"save_on_focus_lost": true,
"show_definitions": true,
"preview_on_click": false,
"goto_anything_exclude_gitignore": true,
"ui_scale": 1.2,
"rulers": [80, 120],
"highlight_modified_tabs": true,
"show_encoding": true,
"show_line_endings": true,
"scroll_speed": 2.0,
"hot_exit": true,
"font_face": "FiraCode Nerd Font",
"font_size": 13,
"line_padding_top": 2,
"line_padding_bottom": 2,
"font_options": ["liga"],
"highlight_line": true,
"caret_style": "phase",
"wide_caret": true,
"overlay_scroll_bars": "enabled",
"show_tab_close_buttons": false,
"scroll_past_end": true,
"word_wrap": true,
"draw_white_space": "selection",
"trim_trailing_white_space_on_save": true,
"ensure_newline_at_eof_on_save": true,
"tab_size": 4,
"translate_tabs_to_spaces": true,
"detect_indentation": true,
"index_files": true,
"index_exclude_patterns":
[
"node_modules/*",
"dist/*",
"build/*"
],
"theme": "Default Dark.sublime-theme",
"folder_exclude_patterns":
[
".svn",
".hg",
"CVS",
".Trash",
".Trash-*",
"node_modules",
"dist",
"build",
".cache",
"__pycache__"
],
"binary_file_patterns":
[
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
"*.zip",
"*.tar.gz",
"*.min.js"
],
"ignored_packages":
[
"Vintage",
],
"color_scheme": "Packages/Material Theme/schemes/Material-Theme-Palenight.tmTheme",
}5. Shell Setup: Fast and Minimal
I deliberately skip heavy frameworks (no oh-my-zsh, no Starship) to keep startup under 100ms.
Edit ~/.zshrc:
# ============== PATH ==============
export PATH="$HOME/.local/bin:$PATH"
# Homebrew (fallback)
if [ -x /opt/homebrew/bin/brew ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
# ============== HISTORY ==============
HISTSIZE=10000
SAVEHIST=10000
HISTFILE=~/.zsh_history
setopt SHARE_HISTORY # share history across all open terminals
setopt HIST_IGNORE_DUPS # ignore duplicate commands in history
# ============== ALIASES ==============
alias ll='ls -lah'
alias la='ls -A'
alias gs='git status'
alias gl='git log --oneline --graph --decorate'
alias gp='git push'
alias gc='git commit -m'
# ============== EDITOR ==============
export GIT_EDITOR="zed" # use Zed for git commitsReload:
source ~/.zshrcShell startup time check:
time zsh -i -c exitShould be <100ms. If it's higher, something is slow. (Hint: oh-my-zsh plugins and heavy functions cause this.)
6. Ghostty Configuration
Ghostty is fast, GPU-accelerated, and has sane defaults. I only customize fonts and padding.
Create ~/.config/ghostty/config:
# Font and appearance
theme = GitHub Dark Default
font-family = "FiraCode Nerd Font"
font-size = 16
font-thicken = true
font-thicken-strength=1
adjust-cell-height=1
window-padding-x = 10
window-padding-y = 10
copy-on-select = true
confirm-close-surface = true
clipboard-paste-protection = false
background-opacity = 0.85
background-blur=16
background=#000000
macos-titlebar-style = hiddenGotcha: After editing the config, fully quit and relaunch Ghostty (not just close the window). Cmd+Q then reopen.
If the theme or font doesn't exist, Ghostty silently falls back to defaults. Verify:
# Check if the font is installed
fc-list | grep -i "FiraCode"Reference: Ghostty docs | Minimal config guide
7. Project Organization and Git Workflow
Keep projects under one directory:
mkdir -p ~/Developer
cd ~/DeveloperClone repos via GitHub CLI (faster than git clone for authenticated users):
gh auth login # once per machine
gh repo clone <user>/<repo>Monitor uncommitted work
Create a helper script ~/check_repos.sh:
#!/bin/bash
echo "Scanning for dirty git repos..."
find ~/Developer -name ".git" -type d 2>/dev/null | while read gitdir; do
repo="${gitdir%/.git}"
status=$(git -C "$repo" status --porcelain 2>/dev/null)
unpushed=$(git -C "$repo" log --branches --not --remotes --oneline 2>/dev/null)
if [[ -n "$status" || -n "$unpushed" ]]; then
echo "⚠️ $repo"
[[ -n "$status" ]] && echo " Uncommitted changes"
[[ -n "$unpushed" ]] && echo " Unpushed commits"
fi
done
echo "Done."Make it executable:
chmod +x ~/check_repos.sh
./check_repos.shRun this before bed or before major system changes to catch uncommitted work.
8. Browser Discipline: Explicit Roles
One browser eating 8 GB of RAM because I had 300 tabs is a design failure, not a hardware failure.
Define explicit roles:
Rules:
- Only open the browser I need for the task.
- Close tabs regularly (max ~20 per window).
- Use browser profiles to separate contexts.
This simple discipline prevents the "just one more tab" spiral.
9. Memory and Disk Hygiene
The setup is minimal, but discipline matters:
Monthly:
# Clean up old Homebrew cache
brew cleanup
# Check for large files
du -sh ~/Library/Caches/*Weekly:
# Run the repo checker
~/check_repos.shRestart cadence:
- Restart every 1–2 days to clear any memory leaks or swap buildup.
- Monitor with Activity Monitor: Window → Memory.
Clear Quick Look cache (optional):
If PDF previews or image thumbnails are eating disk space:
qlmanage -r cacheThis clears the Quick Look thumbnail cache. First previews after will rebuild; that's normal.
10. Restore Personal Files (After Everything Else)
Once the system is stable, restore personal data:
unzip ~/Personal.zip -d ~/Personal_restore
# Review and move files to appropriate locations11. Optional: LaTeX (if needed)
If I have to write reasearch documentation or produce PDFs with formulas:
# Add to Brewfile
cask "mactex"
# Or to Homebrew formula list
brew install --cask mactex-no-gui # CLI tools only, ~2 GB smaller
# Add to ~/.zshrc
export PATH="/Library/TeX/texbin:$PATH"12. Future Additions (Only When Needed)
I have kept these in my back pocket:
- Containers: Replace Docker Desktop with OrbStack (lighter, faster).
- AI tools: Move from temporary credits to browser-based AI (Claude, Perplexity) or editor plugins.
- Advanced terminal: tmux, custom keybindings—only if you find a genuine need.
Repository Structure
Store the setup in a GitHub repo (mac-dev-setup-2026):
mac-dev-setup-2026/
├── Brewfile
├── zshrc (copy of ~/.zshrc)
├── ghostty-config (copy of ~/.config/ghostty/config)
├── check_repos.sh
└── README.mdOn a new Mac:
git clone https://github.com/<your-username>/mac-dev-setup-2026.git
cd mac-dev-setup-2026
brew bundle
cp zshrc ~/.zshrc
mkdir -p ~/.config/ghostty && cp ghostty-config ~/.config/ghostty/configDone in 15 minutes.
Key Takeaway
The machine already had the power for the workloads I needed but The environment needed more intention.
By saying no to accumulated clutter and yes only to deliberate tools, I went from a sluggish 16 GB MacBook to one that feels lightweight and predictable. The factory reset hurt for an hour but the discipline pays dividends every day.
Have you done a full reset before? What's the longest you've gone without restarting your dev machine? Feel free to reach out with questions or your own setup hacks.