This repo documents the actual current setup of my Mac — apps, tools, and settings. It's meant to reflect reality, not a wishlist, so I can rebuild this machine (or set up a new one) accurately.
- Profiles: Home vs Work
- What Mac do I have?
- OS Settings
- Quick Launching & Window Management
- Homebrew
- Menu Bar Utilities
- Web Browser
- Other Apps I Use Daily
- Terminal
- Node.js
- VS Code
- Custom Scripts
- Local Backup (not on GitHub)
This one repo covers both my Home and Work Macs. Most of it is shared; where the two machines differ (installed apps, VS Code extensions), the lists are split:
*-common.txt— installed on both machines*-home.txt— Home-only*-work.txt— Work-only
install.sh takes the profile as an argument and installs common + profile-specific:
./install.sh home # or: ./install.sh workRight now the Work profile files are empty placeholders. Here's how to pull in the Work Mac's real setup:
-
Clone the repo there (or
git pullif it's already cloned):git clone https://github.com/christwellman/mac-setup.git cd mac-setup -
Run the diagnostics to capture what's actually installed/configured:
./diagnostics/collect.sh > diagnostics/report.txt ./scripts/backup-local.sh # optional — also gives you a manual-apps.txt for that machine
Both outputs are gitignored, so they stay on the Work Mac unless you move them somewhere yourself (paste the contents to Claude in a session with access to this repo, copy the file over some other way, etc.).
-
Fill in the Work files using that report as the source of truth:
brew-formulae-work.txt,brew-casks-work.txt,vscode-extensions-work.txt,zshrc-work.zsh. Anything that matches what's already in the equivalent*-home.txt/zshrc-common.zshshould move into the*-common.txtfile /zshrc-common.zshinstead of being duplicated in-work. -
Wire it up on the Work Mac:
./install.sh work
-
Commit and push from whichever machine has the changes — it's the same repo either way.
If you'd rather have Claude do the reconciliation (same as we did for Home), just get diagnostics/report.txt from the Work Mac into a session that has access to this repo and ask it to fill in the Work profile — steps 3–4 are exactly what it'll do.
Home profile. Mac mini (M4, base chip), Model Identifier Mac16,10.
- Apple M4, 10-core CPU (4 performance + 6 efficiency)
- 24GB RAM
These are my preferred settings for Desktop, Finder and the Dock.
I don't like the Desktop, Stage Manager or Widget features, so I disable them.
- System Settings
- Desktop & Dock
- Stage Manager -> off (confirmed via
defaults read com.apple.WindowManager GloballyEnabled= 0)
- Stage Manager -> off (confirmed via
- Desktop & Dock
Note: the exact state of the individual "show widgets" / "show desktop items" checkboxes wasn't independently reverified against
defaults— the underlying keys are ambiguous across macOS versions. Check by eye in System Settings if it matters.
Current actual settings (verified via defaults read):
- Show Path Bar -> on
- Show Status Bar -> on
- Show all filename extensions -> on
- New Finder windows show -> All My Files (not Home Folder — this drifted from an earlier preference; change it in Finder -> Settings -> General if you'd rather have Home Folder)
- Desktop icons: external hard drives and removable media currently show on the desktop; internal hard drives and mounted servers do not
- Size -> ~47pt (small-ish, not minimum)
- Position -> bottom (default — an earlier preference called for the left side; change in System Settings -> Desktop & Dock if you want that back)
- Automatically hide and show the Dock -> on
- Animate opening applications -> off
- Show suggested and recent apps in the Dock -> off
Not currently using a dedicated launcher or window manager app (no RayCast, Alfred, Rectangle, or AltTab installed) — relying on macOS defaults (Spotlight, Mission Control, standard Cmd+Tab). Revisit this section if that changes.
Homebrew installs tools and apps from the command line. To install it:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Formulae and casks actually in use are tracked per-profile (see Profiles: Home vs Work above): brew-formulae-common.txt / brew-formulae-home.txt / brew-formulae-work.txt, and the equivalent brew-casks-*.txt files.
./install.sh home # or work — installs common + profile-specific formulae, casks, and VS Code extensionsCustom taps in use on this machine: sapireli/airprint_bridge (for the AirPrint bridge formula used by ~/bin/airprint_bridge_launcher.sh) and steipete/tap.
scripts/brew-update.sh does the Homebrew/cask/MAS side of this in one go — updates formulae, upgrades outdated casks, prompts for Mac App Store updates, cleans up old versions, runs brew doctor, and logs everything to ~/Logs/:
./scripts/brew-update.sh # run it
./scripts/brew-update.sh --dry-run # see what it would do firstFor macOS itself (not covered by the script):
softwareupdate --list
sudo softwareupdate --install [name listed]Hidden Bar
Hidden Bar hides menu bar icons after a timeout when a lot of background apps are running.
brew install --cask hiddenbarItsycal puts a calendar in the menu bar.
brew install --cask itsycalCurrent menu bar clock settings: date display appears to be set to "Never" (ShowDate = 2); "Show Day of Week" currently reads as on, which doesn't match an earlier preference for it to be off — check System Settings -> Control Center -> Clock if that matters to you.
Currently running standard Firefox (not Developer Edition, despite what an earlier version of this doc said):
brew install --cask firefoxExtension preferences (not independently re-verified against the actual browser profile, carried over from earlier notes):
- Tabliss - simple new tab page
- OneTab - consolidate open tabs
- Dark Reader - dark mode everywhere
- uBlock Origin - adblocker
- Privacy Badger - tracker blocker
- Decentraleyes - local CDN caching to reduce cross-site tracking
This list is the Home profile (brew-casks-home.txt); see Profiles for how Work differs.
- 1Password CLI (
1password-cli) - command-line access to 1Password vaults - aText (
atext) - text expansion / snippets - Beekeeper Studio (
beekeeper-studio) - SQL database GUI client - Calibre (
calibre) - ebook management/conversion - Claude Code (
claude-code) - Anthropic's CLI coding agent - Inkscape (
inkscape) - vector graphics editor - Keyboard Maestro (
keyboard-maestro) - macros / automation - LM Studio (
lm-studio) - run local LLMs - Querious (
querious) - MySQL/MariaDB GUI client - qView (
qview) - lightweight image viewer - Slack (
slack) - team chat - Sublime Text (
sublime-text) - text editor - Synology Assistant (
synologyassistant) - manage the Synology NAS - Syntax Highlight (
syntax-highlight) - Quick Look syntax highlighting for code files - VS Code (
visual-studio-code) - code editor - WakaTime (
wakatime) - coding time tracking - WordService (
wordservice) - system-wide text services
Install them all at once (combined with whichever profile you're on):
./install.sh home # or workI use iTerm2.
brew install --cask iterm2Current actual profile settings (Default profile):
- Font -> Monaco 12
- Working Directory -> fixed to home directory (an earlier preference had this set to "reuse previous session's directory" — change under Profiles -> Default -> General if you want that back)
- Foreground color -> a light gray (not the lime green documented previously)
zsh (the macOS default) with Oh My Zsh, theme robbyrussell.
~/.zshrc is tracked in this repo, split the same way as everything else:
zshrc-common.zsh— shared: oh-my-zsh bootstrap,nvm, iTerm2 shell integration, general aliases, and theytmd/xtmd/ytdlfunctions from Custom Scriptszshrc-home.zsh/zshrc-work.zsh— profile-specific: Go (GOROOT/GOPATH), a pinned Python 3.11 as defaultpython/python3, the Google Cloud SDK,hugo— currently all filed under Home, move to common if Work needs them too~/.zshrc.local— not tracked, machine-only secrets/aliases (e.g. the local SSH target alias that used to live in plain.zshrc)
install.sh <profile> wires this all up: it symlinks ~/.zshrc to this repo's zshrc dispatcher (backing up whatever was there first, as ~/.zshrc.backup.<timestamp>), symlinks the right profile pieces into ~/.zshrc.d/, and creates an empty ~/.zshrc.local if one doesn't exist yet.
There's also an old, stale dotfiles/setup snapshot in iCloud Drive (~/Library/Mobile Documents/com~apple~CloudDocs/dotfiles) from a previous job — it's not synced with or representative of this repo; ignore it.
- Follow this guide to set up an SSH key for GitHub
- Follow this guide to add it to your GitHub account
nvm manages Node versions.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bashnvm install 22
nvm use 22
node --versionCurrently installed globally (via npm list -g):
lighthouse- run Lighthouse audits from the CLIuipro-cli- internal/personal CLI toolcorepackandnpmship bundled with Node itself, not separately installed
npm install -g lighthouse uipro-cliVS Code is my editor. Extensions are tracked per-profile, same pattern as Homebrew: vscode-extensions-common.txt, vscode-extensions-home.txt (current Home list, from code --list-extensions), vscode-extensions-work.txt (TODO).
Install them all (combined with whichever profile you're on):
./install.sh home # or workSmall personal CLI scripts live in bin/ and are symlinked into ~/bin so they're on $PATH. They're written as PEP 723 single-file scripts run via uv run, so uv handles their dependencies automatically — no venv setup needed.
brew install uvgit clone https://github.com/christwellman/mac-setup.git
cd mac-setup
./install.sh home # or workinstall.sh symlinks everything in bin/ into ~/bin, and — when given a profile — also installs that profile's Homebrew formulae/casks and VS Code extensions (see Profiles: Home vs Work). Re-run it any time after git pull to pick up new/updated scripts or package lists.
ytmd.py— YouTube Transcript Downloader. Fetches a video's transcript and saves it as markdown to~/downloads/transcripts.xtmd.py— X/Twitter Thread Downloader. Saves a thread as markdown to~/downloads/threads.ytdl.py— YouTube video downloader. Saves video + metadata to~/downloads/videos.
ytmd, xtmd, and ytdl are defined in zshrc-common.zsh and available automatically once ~/.zshrc is symlinked via install.sh <profile> (see Dotfiles) — no manual copy-paste needed.
scripts/backup-local.sh captures two things into a backup/ folder that's gitignored — it never leaves this machine:
- App inventory (
backup/apps-inventory.txt,backup/manual-apps.txt) — everything in/Applications, cross-referenced against Homebrew casks and Mac App Store apps, plus a best-effort list of what's left over (installed some other way — direct download, DMG, etc., the wayAmphetamineandSophos Homeused to show up in the old setup docs). - App preferences (
backup/preferences/) — every~/Library/Preferences/*.plist, plus known~/Library/Application Support/folders for apps that store real config there (VS Code, Sublime Text, Keyboard Maestro, aText, iTerm2, Beekeeper Studio).
./scripts/backup-local.shThis intentionally does not get committed — preference files can carry API keys, license data, or auth tokens (WakaTime's config is a real example). Treat backup/ as a local safety net, not something to publish. Re-run it whenever you want a fresh snapshot; it overwrites in place.