A modern developer tooling stack for macOS, deployed in one command. Every tool is chosen for speed, ergonomics, and native macOS integration; no legacy defaults, no bloat.
The stack: Fish replaces Zsh (faster startup, better defaults). Starship replaces Oh My Zsh themes (cross-shell, instant). Ghostty replaces iTerm2 (GPU-rendered, native). delta replaces diff (syntax-highlighted). eza, bat, fd, ripgrep, zoxide, fzf replace ls, cat, find, grep, cd, Ctrl+R. 1Password handles secrets via op:// templates; nothing is ever stored in git. All managed by chezmoi with a gum-powered setup wizard.
Requirements: macOS 12+, Apple Silicon (Intel works too). First run takes ~30 minutes (Homebrew downloads).
git clone https://github.com/dwarvesf/dotfiles ~/dotfiles
cd ~/dotfiles && ./install.shA styled setup wizard (gum) will prompt for your name, email, editor, headless mode, and whether you use 1Password. Everything adapts accordingly. On a headless/server machine, GUI apps, dev toolchains, and casks are skipped automatically.
Flags:
./install.sh --check-- dry-run, validates without applying./install.sh --force-- teardown and reinit from scratch./install.sh --config-only-- deploy config files only, skip brew/mas/defaults
Adopt on an existing Mac
Already have brew, fish, and your tools installed? Use --config-only to deploy just the config files without re-running brew bundle, mas installs, or macOS defaults:
git clone https://github.com/dwarvesf/dotfiles ~/dotfiles
cd ~/dotfiles && ./install.sh --config-onlyThis will:
- Link chezmoi source to
~/dotfiles/home - Prompt for your name, email, editor, headless mode, 1Password
- Deploy all config files to
$HOME - Skip brew bundle, Mac App Store apps, macOS defaults, toolchain installs
Then switch your shell and reload:
# Set fish as default (if not already)
grep -q /opt/homebrew/bin/fish /etc/shells || echo /opt/homebrew/bin/fish | sudo tee -a /etc/shells
chsh -s /opt/homebrew/bin/fish
# Open a new terminal to pick up the configsAlternative: bootstrap without git
On a truly fresh Mac, git requires Xcode CLT (10+ minutes to install). These methods skip that:
Via chezmoi directly (no git, no Homebrew):
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply dwarvesfVia Homebrew + chezmoi (no git):
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(/opt/homebrew/bin/brew shellenv)"
brew install chezmoi
chezmoi init --apply dwarvesfNote: These methods clone into
~/.local/share/chezmoi/(chezmoi's default) instead of~/dotfiles. The git clone method is better for active development since you control the repo location.
Fork and customize
# 1. Fork this repo on GitHub
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/dotfiles ~/dotfiles
cd ~/dotfiles
# 3. Edit what you want (see "Customization" below)
# 4. Run
./install.sh- Installs Homebrew (if missing)
- Installs chezmoi
- Runs setup wizard (styled prompts for name, email, editor, headless mode, 1Password)
- Deploys all config files to
$HOME - Runs automation scripts:
brew bundle-- installs ~80 packages + casks- Mac App Store apps via
mas - macOS defaults (Dock, Finder, keyboard, trackpad, screenshots)
- Sets Fish as default shell
- Installs Foundry (cast), Rust, npm/uv tools
- VS Code extensions
- Verifies key files were deployed
| Layer | Tools |
|---|---|
| Shell | Fish + Starship prompt + plugins (autopair, done, sponge, async-prompt) |
| Terminal | Ghostty (catppuccin-mocha, JetBrains Mono) |
| Multiplexer | tmux (C-a prefix, vim nav, fzf session picker, project launcher) |
| Editors | VS Code + Zed (settings, extensions, MCP servers) |
| Git | .gitconfig (delta diffs, aliases) + .gitignore + commit template |
| SSH | 1Password SSH Agent (optional), modular config.d/ |
| Secrets | 1Password (op://) + macOS Keychain -- never in git |
| Packages | Layered Brewfile (base/dev/apps) + Mac App Store (mas) |
| Languages | mise (Node, Python, Go, Ruby) via .tool-versions |
| Containers | OrbStack / Docker config |
| macOS | 30+ defaults write (Dock left, fast key repeat, Finder, screenshots) |
| Web3/DeFi | Foundry (cast), fish aliases + helper functions |
- Layered Brewfile -- base tools always install; dev toolchains and GUI apps are conditional. Set
headless=truefor servers. - Zero plaintext secrets -- 1Password
op://references in templates, macOS Keychain for the rest. The rendered secrets only exist on your machine, never in git. - 13-command CLI --
dotfiles sync,dotfiles doctor,dotfiles bench,dotfiles backup... no need to remember raw chezmoi commands. - CI-tested weekly -- shellcheck + chezmoi dry-run on macOS. Catches regressions before your next fresh install.
- Graceful degradation -- works with or without 1Password. Skip web3, skip Mac App Store, pick your editor. Everything is opt-in.
The dotfiles wrapper provides ergonomic commands:
dotfiles edit ~/.config/fish/config.fish # edit a config
dotfiles diff # preview changes
dotfiles sync # apply everything
dotfiles update # pull latest + apply
dotfiles status # managed file count + pending diffs
dotfiles doctor # health check (tools, config, drift)
dotfiles bench # benchmark shell startup time
dotfiles backup # back up config + age key to 1Password
dotfiles encrypt-setup # guided age encryption setupAdding a Homebrew package:
dotfiles edit ~/.Brewfile # add the line
dotfiles sync # auto-runs brew bundleRaw chezmoi commands
chezmoi edit ~/.config/fish/config.fish
chezmoi diff
chezmoi apply
chezmoi apply --refresh-externals| File | What to change |
|---|---|
home/dot_Brewfile.tmpl |
Add/remove Homebrew packages and casks (layered: base/dev/apps) |
home/dot_config/fish/config.fish.tmpl |
Shell aliases, paths, tool integrations |
home/dot_config/ghostty/config |
Terminal theme, font, keybindings |
home/dot_config/tmux/tmux.conf |
tmux prefix, keybindings, status bar |
home/dot_config/code/settings.json |
VS Code theme, font, settings |
home/dot_config/code/extensions.txt |
VS Code extensions (one per line) |
home/dot_config/zed/settings.json.tmpl |
Zed theme, MCP servers |
home/dot_tool-versions |
Global language versions |
home/.chezmoiscripts/run_once_after_mas-apps.sh.tmpl |
Mac App Store apps |
home/.chezmoiscripts/run_once_after_macos-defaults.sh.tmpl |
macOS system preferences |
home/.chezmoiexternal.toml |
Fish plugins to auto-download |
Secrets are injected at chezmoi apply time and never stored in git.
With 1Password (recommended):
# Store the secret
op item create --vault=Developer --category=api_credential --title="OpenAI" password="sk-..."
# Reference it in a template (e.g., secrets.fish.tmpl)
set -gx OPENAI_API_KEY "{{ onepasswordRead "op://Developer/OpenAI/password" }}"With macOS Keychain:
keychain-set MY_TOKEN "secret-value" # store
keychain-env MY_TOKEN # load into current shellOn-demand loading (no apply needed):
op-env GITHUB_TOKEN "op://Vault/GitHub Token/password" # 1Password
keychain-env MY_TOKEN # Keychain
web3-env # ETH_RPC_URL + EtherscanEncrypted files (age)
For files too complex for template injection (kubeconfig, VPN configs, certificates):
# Guided setup (generates key, prints next steps)
dotfiles encrypt-setup
# Then add encrypted files
chezmoi add --encrypt ~/.kube/config
# Creates home/encrypted_dot_kube/config.age in the repoManual setup if you prefer:
brew install age
age-keygen -o ~/.config/chezmoi/key.txt
# Copy the public key (age1...) from output
chezmoi edit-config # uncomment age section, paste public key
# Backup key.txt to 1Password as a Secure NoteRemoving what you don't need
- No web3? Delete web3 aliases from
config.fish.tmpl, removecast_*functions, remove Foundry from install script - No 1Password? Answer "no" during
chezmoi init-- all 1Password sections are skipped - No Mac App Store? Delete
run_once_after_mas-apps.sh.tmpl - Different editor?
chezmoi initprompts for your choice (VS Code, Zed, Neovim, Vim)
Run dotfiles doctor to diagnose issues:
$ dotfiles doctor
Dotfiles health check
=====================
[ok] chezmoi installed
[ok] chezmoi source linked
[ok] fish is default shell
[ok] homebrew installed
[ok] 1Password CLI: signed in
[ok] 1Password SSH agent: socket exists
[ok] ~/.gitconfig exists
[ok] ~/.config/fish/config.fish exists
[ok] ~/.ssh/config exists
[ok] git identity: Your Name <you@email.com>
[ok] fzf
[ok] bat
...
[ok] no drift detected
All checks passed.
Built with chezmoi. Inspired by halostatue/dotfiles and narze/dotfiles.
MIT