Dotfiles + brew bundle for setting up a fresh macOS machine.
# 1. Install Homebrew if not already installed
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 2. Clone this repo
git clone https://github.com/sgup/new-mac-setup.git ~/.dotfiles
cd ~/.dotfiles
# 3. Sign into the Mac App Store via the GUI (`open -a "App Store"`).
# Required for the `mas` entries in the Brewfile β Apple no longer
# supports `mas signin` from the CLI.
# 4. Install everything from the Brewfile (formulae + casks + MAS apps)
brew bundle install
# 5. Symlink the dotfiles into $HOME (and Ghostty config into its app dir)
./install.sh
# 6. Apply macOS preference tweaks
./macos/defaults.shAfter that, open a fresh terminal β the new shell config + theme + tools light up immediately.
enabledPlugins in settings.json is inert on its own β Claude Code does not
install from it, so a machine can look correctly configured and have no plugins at
all. claude/sync-plugins.sh closes that gap: it merges the tracked fragment,
registers the marketplaces, and installs everything marked enabled. install.sh
runs it, so superpowers and friends arrive on a fresh machine without manual steps.
Skills are a separate mechanism from plugins. The ~/.claude/skills/* entries
are symlinks into ~/.agents/skills/, installed by an external skill manager that
pins each one in claude/skill-lock.json. That manifest is tracked for provenance,
but the ~8 MB of third-party skill content is not β copy ~/.agents/ across when
setting up a new machine, or reinstall from the lock with the manager that wrote it.
For an always-on Ubuntu box (a VPS you drive over SSH/mosh from the Mac), one command installs the same shell β p10k, atuin, zoxide, fzf, eza, mise, the aliases and functions:
curl -fsSL https://raw.githubusercontent.com/sgup/new-mac-setup/main/linux/provision.sh | bashIt installs the portable half of the Brewfile via apt, clones this repo to ~/.dotfiles,
and hands off to ./install.sh, which links linux/.zshrc instead of .zshrc when it
detects Linux.
The two shell configs are kept as separate files rather than one file full of OS guards.
Every place they diverge is marked LINUX in linux/.zshrc β editor (nvim, no Zed),
zsh plugin paths (/usr/share, not $(brew --prefix)/share), PNPM_HOME, and the fzf
keybinding location. Skipped entirely: Ghostty (the terminal lives on the client),
JAVA_HOME/ANDROID_HOME, and the mobile toolchain β anything needing Xcode can do
nothing on Linux.
| File | Purpose |
|---|---|
Brewfile |
All formulae + casks installed via brew install. Restored with brew bundle install. |
.zshrc |
Zsh config: history, plugins, mise, atuin, fzf, eza aliases, helper functions. |
.p10k.zsh |
Powerlevel10k theme settings (generated by p10k configure). |
.gitconfig |
Git aliases, user info, delta as the diff pager. |
ghostty/config |
Ghostty terminal: font, theme, blur, keybindings, quick terminal, command-finish notifications. |
macos/defaults.sh |
macOS system preferences (defaults write). |
AGENTS.md |
Shared context for every coding agent (branch discipline, secrets). Symlinked to ~/.codex/AGENTS.md; Claude imports it via @~/.dotfiles/AGENTS.md. |
CLAUDE.md |
Claude Code global instructions (imports AGENTS.md). Symlinked to ~/.claude/CLAUDE.md. |
claude/rules/ |
Claude Code rule files β model routing, Context7 doc lookups. Each is symlinked into ~/.claude/rules/. |
claude/settings.plugins.json |
Marketplaces, enabled plugins, skill overrides. Merged into ~/.claude/settings.json so machine-specific keys survive. |
claude/sync-plugins.sh |
Applies that fragment and installs the enabled plugins. Run by install.sh. |
claude/marketplaces.json |
Every plugin marketplace, source only. settings.json records only hand-added ones, so this is the complete list. |
claude/skill-lock.json |
Manifest of the ~/.agents/skills set (source repo + pinned hash per skill). Reference only β not consumed by install.sh. |
install.sh |
Symlinks every dotfile from this repo into the right home location. |
Shell
- Powerlevel10k prompt with instant prompt enabled.
- mise for managing Node/Python (replaces nvm + pyenv).
- atuin for SQLite-backed shell history with fuzzy
Ctrl+R. - zoxide as
cd(frecency-ranked). - fzf with
batpreviews onCtrl+T,eza --treeonAlt+C. - zsh-history-substring-search β type a prefix, hit β/β to walk matching history.
Terminal
- Ghostty with JetBrains Mono Nerd Font.
- Quick terminal bound to
Cmd+Shift+.(slide-down, system-wide). notify-on-command-finishbounces the dock when a >30s command finishes in an unfocused tab.- Linear-corrected alpha blending + thickened fonts for crisp text on retina.
Git
- delta as the pager β side-by-side diffs with syntax highlighting.
merge.conflictstyle = zdiff3for clearer conflict markers.
Development tools
bat(highlightedcat),eza(modernls),fd(modernfind),ripgrep(fast grep).ghfor GitHub workflows.httpie,jq,glow,tlrc(tldr).
Mobile / backend
cocoapods,ruby@3.3,watchman,xcodegenfor React Native + iOS builds.flyctlfor Fly.io deploys,libpqforpsql/pg_dump,zulu@17JDK for Android.
Apps (Mac App Store + casks)
- Security β 1Password.
- Productivity β Things (todo), Bear (notes), DaisyDisk (disk usage), Wipr (Safari content blocker), Dark Reader for Safari.
- Apple suite β Keynote, Numbers, Pages, iMovie, GarageBand, Final Cut Pro, Xcode.
- Communication β Signal, WhatsApp, Discord, Zoom, Mimestream (native Gmail client).
- Browsers β Helium (primary, Chromium privacy-focused), Google Chrome (backup, web dev).
- Editor + terminal β Zed (
EDITOR/VISUAL), Ghostty (terminal β config in this repo). - Dev β Docker, Figma, TablePlus (Postgres GUI).
- AI β ChatGPT, Claude desktop, Perplexity, Ollama (local LLMs).
- Media β Spotify, IINA (video player).
- Utilities β AppCleaner, Caffeine, Mac Mouse Fix, MonitorControl.
- Backup β Backblaze (sign in with your account to activate the subscription).
- Network / dev β Tailscale (mesh VPN), ngrok (local tunnel).
Manual installs (no Homebrew package)
- Linear β issue tracker. Download the macOS app from the website.
- Astro β App Store Optimization (ASO) tool. Download from the website.
Mobile / AI tooling (installed by install.sh, not Homebrew)
- Claude Code β Anthropic's native installer
(
~/.local/bin/claude). Sign in on first launch withclaude. - pnpm β standalone installer at
$HOME/Library/pnpm(matchesPNPM_HOMEin.zshrc). - EAS CLI β installed via
npm i -ginto mise's active node (soeas build/submit/updateworks in any fresh shell). - Run
npx expo-doctorinside any Expo app to check SDK/dependency drift.
Android setup (post-install)
After brew bundle install brings in Android Studio, open it once and let it
download the SDK + a system image, then verify in .zshrc that ANDROID_HOME
points at ~/Library/Android/sdk (it does by default). JAVA_HOME for the JDK
is also pre-wired in .zshrc to the Zulu 17 cask install.
The Brewfile is curated, not auto-dumped. It captures the dev tools and apps needed for a productive day-one setup β not every CLI ever experimented with.
If you brew install something new and decide it earns a permanent spot, add it
to the Brewfile by hand. Don't run brew bundle dump --force on this repo β it
will re-add every transient tool currently installed and undo the curation.
To check what's installed locally but missing from the Brewfile:
brew bundle check --verbose # list anything missing
brew leaves | sort > /tmp/installed.txt # explicitly-installed formulae
grep -oE '^brew "[^"]+"' Brewfile | sort > /tmp/in-brewfile.txt
diff /tmp/installed.txt /tmp/in-brewfile.txt # what's driftedFor dotfile edits, the symlinks created by install.sh mean changes to
~/.zshrc, ~/.gitconfig, ~/.p10k.zsh, and the Ghostty config already
propagate to this repo automatically β just git add and commit.
If you didn't symlink, copy them in manually:
cd ~/.dotfiles
cp ~/.zshrc .zshrc
cp ~/.p10k.zsh .p10k.zsh
cp ~/.gitconfig .gitconfig
cp "$HOME/Library/Application Support/com.mitchellh.ghostty/config" ghostty/config
git add -A && git commit -m "Sync from $(hostname)" && git push