Init & Add

Lesson 1 · chezmoi · ~10 minutes

By the end of this lesson, you'll have chezmoi installed, initialized from your existing dotfiles repo, and your first file under management. This is the foundation everything else builds on.

The Mental Model

Chezmoi keeps two separate copies of your dotfiles:

How chezmoi manages your files
GitHub Repo
Your dotfiles on GitHub
Source State
~/.local/share/chezmoi/
Target State
Your actual ~ files

The source state is a local git repo that chezmoi owns. It stores your files with special naming conventions (like dot_gitconfig for .gitconfig). The target state is your actual home directory — the real files your tools use.

You edit the source state. When you run chezmoi apply, it pushes those changes to the target. This separation is what makes templates, conditionals, and multi-machine configs possible — the source can contain logic that renders differently on each machine.

Key insight

Your existing dotfiles repo becomes the remote for chezmoi's source state. You're not replacing your repo — you're giving it a smarter local manager.

Exercise: Get chezmoi running

Step 1: Install

brew install chezmoi

Verify it works:

chezmoi --version

Step 2: Initialize from your repo

Point chezmoi at your existing dotfiles GitHub repo:

chezmoi init https://github.com/YOUR_USERNAME/YOUR_DOTFILES_REPO.git

This clones your repo into ~/.local/share/chezmoi/. Your existing files are now the source state — but chezmoi isn't managing any target files yet.

If your repo has raw dotfiles at the root

If your repo contains files like .gitconfig directly (not using chezmoi naming), that's fine. Chezmoi will treat it as an empty source state. You'll add files explicitly in the next step, which converts them to chezmoi's naming convention.

Step 3: Add your first file

Pick a dotfile that's identical across all three machines — something with no machine-specific content. Good candidates: .vimrc, .tmux.conf, or .editorconfig. Avoid files that differ per machine (like .gitconfig if you use different emails) — those will become templates in Lesson 2.

chezmoi add ~/.editorconfig

This copies the file into the source state with chezmoi's naming convention (e.g., dot_editorconfig). Now chezmoi is managing it.

Step 4: See what's managed

chezmoi managed

You should see your file listed. This command shows everything chezmoi is currently tracking.

Step 5: Verify the round-trip

chezmoi diff

This should show nothing — the source and target are in sync because you just added the file from the target. If you see output, it means there's a discrepancy (which shouldn't happen on first add).

Initialized from an existing repo?

If your dotfiles repo already had files in it before you ran chezmoi init, you'll see diff output for all those pre-existing files — not just the one you added. This is normal. Chezmoi sees the gap between your source state and your home directory. Don't run chezmoi apply yet — you'll sort this out as you bring files under management one by one.

Step 6: Commit and push

The source state is a git repo. Commit your newly-managed file:

chezmoi cd
git add .
git commit -m "chore: add first file to chezmoi management"
git push
exit

chezmoi cd drops you into the source directory. After committing, exit returns you to your previous shell.

Shortcut

You can also use chezmoi git -- add . and chezmoi git -- commit -m "message" to run git commands without cd-ing into the source directory.

What just happened

CommandWhat it did
chezmoi init <repo>Cloned your repo as the source state
chezmoi add <file>Copied a target file into the source state
chezmoi managedListed all files chezmoi is tracking
chezmoi diffShowed differences between source and target
chezmoi cdOpened a shell in the source directory

Knowledge check

Where does chezmoi store its source state on macOS?
Correct. The source state lives at ~/.local/share/chezmoi/ following the XDG Base Directory spec. This entire directory is a git repo.
Not quite. Chezmoi follows the XDG Base Directory spec — the source state lives at ~/.local/share/chezmoi/.
What does chezmoi add ~/.zshrc do?
Right. add copies the file into the source state with chezmoi's naming convention. The original stays in place — chezmoi never symlinks or moves your actual files.
Chezmoi never symlinks or moves files. add copies the target file into the source state, renaming it with chezmoi conventions (e.g., dot_zshrc). The original stays untouched.
If chezmoi diff shows no output after adding a file, what does that mean?
Exactly. No output from diff means the source state and target state match perfectly. This is expected right after an add since the source was just copied from the target.
No output means everything is in sync. Since you just copied the target into the source with add, they should be identical. Diff only shows output when there's a discrepancy.

Next up

You now have chezmoi managing one file identically across machines. But the real power comes when configs differ between machines. In Lesson 2: Templates & Machine Detection, you'll learn to use .chezmoi.hostname and custom data to render machine-specific configs from a single source file.

Recommended Reading

chezmoi Quick Start — The official walkthrough. Covers everything in this lesson plus the multi-machine setup you'll do next. ~5 minute read.

Questions? Ask me anything that's unclear. I'm your teacher — I can explain the source/target model differently, troubleshoot init issues, or help you decide which files to add first.
Next →