Personal dotfiles managed with chezmoi. One command to bootstrap a fresh macOS or Linux machine with shell, terminal, editor, and developer tooling.
Required
-
Xcode Command Line Tools (for
git, needed by chezmoi)xcode-select --install
Optional — only if you want secrets resolved from 1Password:
- Install 1Password from https://1password.com/downloads/
- Sign in with your account
- Enable Settings → Developer → Integrate with 1Password CLI
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply <github-username>Replace <github-username> with the GitHub user that owns this repo.
The installer will:
- Download the chezmoi binary
- Clone this repo to
~/.local/share/chezmoi - Prompt for a few questions (git identity, which optional features to install)
- Install Homebrew + the packages selected by your feature flags
- Apply config files (
~/.zshrc,~/.gitconfig,~/.tmux.conf, etc.) - Run one-time scripts (TPM, fonts, SSH keygen if enabled)
- Optionally clone and apply a private overlay repo (see below)
- Homebrew
- zsh + Antidote plugin manager + custom prompt
- Core CLI:
eza,zoxide,fzf,bat,wget,gh,jq,git-delta - 1Password CLI (
op) — used by the optional private overlay for secret resolution
| Feature flag | Installs |
|---|---|
ssh |
Generates an ed25519 SSH key |
tmux |
tmux + TPM + Catppuccin theme |
neovim |
Neovim + LazyVim config |
ghostty |
Ghostty terminal + Berkeley Mono fonts (macOS) |
finicky |
Finicky browser router (macOS) |
macos_apps |
iTerm2, Rectangle (macOS) |
sublime_text |
Sublime Text user preferences |
php |
PHP + Composer + Laravel Valet |
mise |
mise + Node LTS |
bun |
Bun runtime |
gcloud |
Google Cloud SDK (macOS cask) |
aws |
AWS CLI |
claude_code |
~/.claude/CLAUDE.md + settings.json |
Re-run with different selections any time:
chezmoi init --apply <github-username>Or edit ~/.config/chezmoi/chezmoi.toml and run chezmoi apply.
For machine-specific or work-related config that shouldn't live in this public
repo, you can opt into a private overlay during chezmoi init. When enabled:
- After SSH is set up, the installer clones a second repo (default name:
dotfiles-private) under your GitHub user. - That repo is applied on top of this one, overriding files of the same destination path.
- Typical contents: a workplace-specific
~/.claude/CLAUDE.md,~/.claude/asdev.local.mdwith real account IDs, and a~/.zshrc.workthat resolves secrets from 1Password viaop read.
The overlay is opt-in. If you say no at init, this repo works standalone.
The overlay clones via SSH, so it requires an SSH key registered on GitHub.
On a brand-new machine the first apply runs roughly:
- Install Homebrew + packages → succeeds
- Apply config files → succeeds
- Generate SSH key → succeeds, prints public key
- Try to clone private overlay → stops with a helpful message because GitHub doesn't know your new key yet
After step 4, paste the public key at https://github.com/settings/keys, then
re-run chezmoi apply. The second pass picks up where the first left off.
.chezmoi.toml.tmpl # init prompts (git identity, features)
.chezmoiignore.tmpl # OS/feature gating
.chezmoidata/defaults.toml # versions and other static data
.chezmoiscripts/ # one-shot install scripts
run_onchange_before_00-homebrew.sh.tmpl
run_onchange_before_10-brew-bundle.sh.tmpl
run_once_after_05-fonts.sh.tmpl
run_once_after_15-ssh-keygen.sh.tmpl
run_once_after_20-tmux-plugins.sh.tmpl
run_once_after_30-php-valet.sh.tmpl
run_once_after_31-mise-node.sh.tmpl
run_once_after_32-bun.sh.tmpl
run_onchange_after_90-private-overlay.sh.tmpl
assets/ # binary assets (fonts, Rectangle config)
dot_zshrc, dot_zsh_plugins.txt # → ~/.zshrc, ~/.zsh_plugins.txt
dot_zshrc.local.tmpl # → ~/.zshrc.local (tool init blocks)
dot_tmux.conf, dot_finicky.js # → ~/.tmux.conf, ~/.finicky.js
dot_gitconfig.tmpl # → ~/.gitconfig (templated)
dot_hushlogin # → ~/.hushlogin
private_dot_claude/ # → ~/.claude/ (chmod 700)
private_dot_config/nvim/ # → ~/.config/nvim
private_dot_config/ghostty/ # → ~/.config/ghostty
Library/Application Support/.../ # → ~/Library/Application Support/...
-
Pick where it lives:
- Static config file → drop it at the right path with
dot_/private_dot_prefixes - Brew/cask package → add to the rendered Brewfile in
.chezmoiscripts/run_onchange_before_10-brew-bundle.sh.tmpl - Shell init line → add a guarded block to
dot_zshrc.local.tmpl - One-time install (curl, clone, etc.) → new
.chezmoiscripts/run_once_after_<N>-<name>.sh.tmpl
- Static config file → drop it at the right path with
-
If the tool is optional, add a feature flag:
- Prompt in
.chezmoi.toml.tmpl - Conditional gate in
.chezmoiignore.tmpl(for files) or at the top of the script (for run_once) - Conditional block in the Brewfile renderer
- Prompt in
-
Verify with:
chezmoi diff chezmoi apply --dry-run --verbose
chezmoi: warning: config file template has changed
Run chezmoi init (without --apply) to regenerate the local config from
the new template, then chezmoi apply to apply changes.
Private overlay won't clone
Make sure your SSH key is on GitHub and ssh -T git@github.com reports
"successfully authenticated". Re-run chezmoi apply.
A tool you don't want is being installed
Edit ~/.config/chezmoi/chezmoi.toml and flip the feature flag to false,
then chezmoi apply.
To stop chezmoi from managing files:
chezmoi forget <target>To unset a feature flag, edit ~/.config/chezmoi/chezmoi.toml. Note that
chezmoi removes its tracking but does not delete already-installed brew
packages or files written by run_once scripts — clean those up manually.