Personal macOS setup. One command on a fresh Mac brings the whole environment up: Homebrew, modern CLI stack, terminal, shell, and dotfiles.
Managed with chezmoi (declarative, no symlinks).
Packages managed with Homebrew via a Brewfile.
git clone https://github.com/<you>/dotfiles.git ~/Documents/dotfiles
cd ~/Documents/dotfiles
./bootstrap.shbootstrap.sh is idempotent — re-run it anytime to sync new packages or dotfiles.
It will:
- Install Xcode Command Line Tools (if missing)
- Install Homebrew (if missing)
- Install every package in
Brewfile(CLI tools + GUI apps) - Run
chezmoi init --apply, prompting once for your name + git email - Render templates and write dotfiles to
$HOME - Run
mise installto install language runtimes declared inhome/dot_config/mise/config.toml
.
├── README.md
├── bootstrap.sh # entry point — fresh-Mac installer
├── Brewfile # everything brew installs
├── .chezmoiroot # tells chezmoi the source root is `home/`
└── home/ # chezmoi source — everything here ends up in $HOME
├── .chezmoi.toml.tmpl # prompts on init (name, email)
├── .chezmoiignore # patterns to skip when applying
├── dot_zshrc # → ~/.zshrc
├── dot_zprofile # → ~/.zprofile
├── dot_gitconfig.tmpl # → ~/.gitconfig (templated)
└── dot_config/ # → ~/.config/
├── starship.toml
├── ghostty/config
├── mise/config.toml # languages managed by mise
└── git/ignore # global gitignore
| Source name | Becomes | Why |
|---|---|---|
dot_zshrc |
~/.zshrc |
dot_ prefix → leading . |
dot_gitconfig.tmpl |
~/.gitconfig |
.tmpl → Go template |
dot_config/starship.toml |
~/.config/starship.toml |
nested directories work as-is |
Full reference: https://www.chezmoi.io/reference/source-state-attributes/
chezmoi, starship, eza, bat, fd, ripgrep, fzf, zoxide, atuin, jq, gh, lazygit, neovim, tmux, mise.
- Terminal & editors: Ghostty, Zed, DataGrip
- Browsers: Google Chrome
- Communication: Discord
- Productivity: Raycast, AltTab, Shottr, Linear, Spotify
- Dev infra: OrbStack, Leapp, Cloudflare WARP
- AI: Claude desktop, Codex desktop, Wispr Flow, VibeProxy
node @ latest · python @ latest · go @ latest · rust @ latest · java 17 + 11
The version latest resolves to whatever is current when mise install runs.
Re-pin or add tools by editing home/dot_config/mise/config.toml.
- Append a line to
Brewfile(brew "tool-name"orcask "app-name"). - Run
brew bundle --file=./Brewfile.
- Edit
home/dot_config/mise/config.toml. chezmoi apply(or re-run./bootstrap.sh).mise install.
cd my-project
mise use java@11 # writes a local mise.toml in this projectbrew update && brew upgrade && brew bundle --file=./Brewfile
mise upgrade
chezmoi applychezmoi edit ~/.zshrc— opens the source file in$EDITOR.chezmoi diff— preview what would change.chezmoi apply— write the change to$HOME.
chezmoi add ~/.somefile # imports into the source dir
# then commit the new file in this repo~/.zshrc.local— sourced fromdot_zshrcif it exists. Drop machine-specific exports, aliases, or work secrets there. Never committed.
chezmoi init --source ~/Documents/dotfiles- One installer (
bootstrap.sh) — five steps, plain bash, < 60 lines. - One package list (
Brewfile) — add a line, runbrew bundle. - One dotfile manager (
chezmoi) — files inhome/are the source of truth. - No magic — every file is plain text, every alias is explicit, every tool
integration is guarded by
command -vso missing tools never break the shell.
Want to add a new tool category (e.g. macOS defaults, VS Code settings, ssh
config)? Create the file in home/ using the chezmoi naming convention and
commit it. No code changes needed elsewhere.
Want machine variants (work vs personal)? Add fields to
home/.chezmoi.toml.tmpl (e.g. promptStringOnce . "profile" "work or personal")
and gate templates with {{ if eq .profile "work" }}…{{ end }}.