Chezmoi for Distro-Hoppers
A practical, start-to-finish guide to keeping your personal Linux setup reproducible.
If you enjoy trying Linux distributions, reinstalling a system, or maintaining more than one machine, you eventually meet the same chore: rebuilding the small choices that make a computer feel like yours. Shell settings, terminal profiles, launcher preferences, text-expansion snippets, and application configuration all live in scattered files—usually “dotfiles”—inside your home directory.
chezmoi is a tool for recording the configuration you deliberately want to keep, storing it in a Git repository, and applying it back to a new machine. It does not back up an entire home directory or install every application for you. It is a focused, reviewable way to restore your configuration.
Start small. A good first repository might contain
.bashrc, a terminal profile, and a few application settings. Add more only after you understand what each file contains.
The mental model
chezmoi keeps a source state: the version of your configuration that you want machines to have. By default, that source directory is:
~/.local/share/chezmoi
Its files are named safely for Git. For example, the live file ~/.bashrc becomes ~/.local/share/chezmoi/dot_bashrc. Directories such as ~/.config/albert become directories under the source state as well.
Think of the workflow as a one-way pipeline that you control:
live configuration in ~/ → chezmoi source state → Git history → private GitHub repo
↓
chezmoi apply on another machine
chezmoi addcopies an existing live file into the source state.chezmoi editchanges the source state—the future desired version.chezmoi diffpreviews the difference between the source state’s desired result and the live file.chezmoi applymakes the live file match the desired result.- Git records and synchronizes the source state; chezmoi does the configuration deployment.
This separation is the reason it works so well for distro hopping: a reinstall can erase the live files, while the Git repository retains the desired configuration.
Before you begin
Decide what belongs in the repository
Good candidates are human-maintained settings and portable snippets:
- shell, Git, editor, window-manager, and terminal settings;
- launcher configuration (for example, Albert);
- text-expansion configuration (for example, Espanso);
- terminal profiles (for example, Terminator or Tilda);
- application preferences that do not contain secrets or machine-specific caches.
Usually avoid caches, logs, databases, browser profiles, large generated data, tokens, private keys, and anything whose purpose you cannot explain. A private repository reduces accidental exposure, but it is not encryption and it does not make secrets safe to commit.
Read a file before tracking it. Git history is durable: deleting a committed secret from the latest version does not necessarily remove it from earlier commits. Use a password manager or chezmoi’s encryption features for secrets, and rotate any secret committed by mistake.
Install ChezMoi and Git on Linux Mint
Mint is Ubuntu-based. The distribution packages are convenient, though their version can lag. Either of the following approaches is reasonable:
# Mint/Ubuntu packages
sudo apt update
sudo apt install chezmoi git
Or use the installation method recommended by the official ChezMoi install page, then verify:
chezmoi --version
git --version
Install and authenticate GitHub CLI (optional but recommended)
You only need GitHub CLI (gh) if you want to create and manage GitHub repositories from the terminal. Follow GitHub CLI’s Linux installation instructions for the current supported repository setup, then authenticate:
gh auth login
gh auth status
Choose GitHub.com, the preferred protocol (SSH is convenient for private repos), and complete the browser/device login flow. If you use SSH, verify it separately:
ssh -T git@github.com
First-time setup on an existing machine
Initialize ChezMoi once:
chezmoi init
chezmoi source-path
The second command should print a path like ~/.local/share/chezmoi. To work inside that directory in a subshell:
chezmoi cd
pwd
chezmoi cd is especially useful before Git commands; exit returns to the previous directory.
Add your first file
chezmoi add ~/.bashrc
chezmoi managed
managed lists paths managed by ChezMoi. The add operation copies the current file into the source state; it does not remove the live file.
From here forward, prefer editing the source state:
chezmoi edit ~/.bashrc
chezmoi diff ~/.bashrc
chezmoi apply -v ~/.bashrc
The -v flag reports what ChezMoi changes. -n -v is an excellent safe preview: it shows the planned action without changing files.
Adding application configurations
Application config usually lives under ~/.config. These are illustrative examples; inspect each directory before adding it:
chezmoi add ~/.config/albert
chezmoi add ~/.config/copyq
chezmoi add ~/.config/espanso
chezmoi add ~/.config/terminator
chezmoi add ~/.config/tilda
Adding a directory recursively captures its current contents. That is fast, but it can also capture runtime data you do not want. Review immediately:
chezmoi managed
chezmoi status
chezmoi diff ~/.config/espanso
Track only the Espanso files you actually want
Suppose you added all of Espanso and then decide its cache, logs, or generated files should stay local. First remove its source-state copy while leaving the live files alone:
chezmoi forget ~/.config/espanso
Then add only the portable files or folders you choose. Common examples might be the user configuration and match definitions (confirm the paths on your installation):
chezmoi add ~/.config/espanso/config
chezmoi add ~/.config/espanso/match
forget means “stop managing this path”; it does not delete the target in ~/.config. Confirm the new scope with:
chezmoi managed | rg 'espanso'
Inspecting changes safely
chezmoi status: what the two columns mean
chezmoi status compares three states: (1) what ChezMoi last wrote, (2) what currently exists on disk, and (3) the desired state generated from the source directory.
chezmoi status
The first status character shows the difference from last-written → actual. The second shows the difference from actual → desired, which is what chezmoi apply would do.
| Output | Meaning |
|---|---|
M path |
The live file matches the last write, but the desired source version differs; apply would modify it. |
M path |
The live file changed since ChezMoi last wrote it, but it already matches the desired source version. |
MM path |
The live file changed since ChezMoi last wrote it and it still differs from desired state; inspect before applying. |
A / D |
An entry was or will be added/deleted, depending on the column. |
An empty status is normally good: no managed entry needs attention. The precise letters are documented in the official status reference.
chezmoi diff: see content, not just a letter
# All managed differences
chezmoi diff
# One application or one file
chezmoi diff ~/.config/albert
chezmoi diff ~/.config/espanso
chezmoi diff ~/.bashrc
Read a diff before applying when a program has modified its own config, or before committing a newly added directory. diff does not change anything.
chezmoi re-add: adopt intentional live edits
If you edited a managed file directly in ~/ and want that live version to become the new desired source state:
chezmoi re-add ~/.bashrc
chezmoi re-add ~/.config/terminator
This copies the target back into the source state. Follow it with chezmoi diff and Git review. Do not use it blindly: it can adopt accidental application changes.
CopyQ .dat files: a deliberate-data example
CopyQ may store settings and history in database-like .dat files under ~/.config/copyq. You may also encounter filenames that look Base64-encoded, such as a string ending in =. Base64 is an encoding that lets arbitrary bytes be represented with filename-safe text; it is not encryption and does not by itself reveal whether a file is safe to publish.
Discover candidate files without modifying them:
find ~/.config/copyq -type f -name '*.dat' -print
file ~/.config/copyq/* 2>/dev/null
Then make a conscious policy choice:
- track a small preferences database only if it restores useful settings and contains no sensitive clipboard history;
- do not track clipboard-history databases by default—clipboard contents can include passwords, private messages, API keys, and copied documents;
- if a file is binary, expect Git diffs to be unhelpful and repository history to grow as it changes.
If you decide a specific .dat file is appropriate, add that file, not the entire directory:
chezmoi add ~/.config/copyq/NAME.dat
Treat clipboard data as sensitive by default. A private GitHub repository is still shared with anyone granted access, is retained in backups and Git history, and can be exposed by account compromise.
Git, explained in plain language
Git is the change history for the ChezMoi source directory, not the tool that applies dotfiles.
| Git concept | In this workflow |
|---|---|
| Working tree | The files currently in ~/.local/share/chezmoi. |
Stage (git add) |
The exact source-state changes selected for the next snapshot. |
| Commit | A named, local snapshot of staged changes. |
| Remote | Another copy of the repository, such as GitHub’s origin. |
| Push | Upload local commits to the remote. |
| Pull | Download and integrate remote commits into the local source directory. |
A clean Git status means the source directory has no uncommitted changes; it says nothing by itself about whether the live dotfiles match source. Use both tools:
chezmoi status # source state versus live home directory
chezmoi cd
git status # source-state files versus Git history
exit
Create a new private GitHub repository from the terminal
This avoids the “two local clones” confusion: the ChezMoi source directory becomes the Git working tree you push. Do this after reviewing the files you plan to publish.
chezmoi cd
git status
git add .
git commit -m "Initial chezmoi configuration"
gh repo create dotfiles \
--private \
--source=. \
--remote=origin \
--push
git remote -v
exit
gh repo create with --source=. creates a GitHub repository from the existing local repository; --remote=origin names the remote; --push pushes the current branch. These options are described in the official GitHub CLI manual.
If you created an empty repository on GitHub first instead, you do not need to recreate it. Attach it to the source directory:
chezmoi cd
git remote add origin git@github.com:$GITHUB_USERNAME/dotfiles.git
git branch -M main
git push -u origin main
exit
If that GitHub repository already contains a README commit, do not force-push over it. Pull and reconcile histories first, or create the remote using gh repo create from the local repository as above.
Normal day-to-day SOP
When you intentionally change a configuration
# Prefer source-first edits
chezmoi edit ~/.config/espanso/match/base.yml
chezmoi diff ~/.config/espanso
chezmoi apply -v ~/.config/espanso
# Save the source-state change in Git and sync it
chezmoi cd
git status
git add .
git commit -m "Update Espanso matches"
git push
exit
When an application changed a managed file
chezmoi status
chezmoi diff ~/.config/terminator
# Only if you want the live version to become canonical
chezmoi re-add ~/.config/terminator
chezmoi cd
git diff
git add .
git commit -m "Update Terminator preferences"
git push
exit
When receiving changes on another existing machine
chezmoi update -v
update pulls the source repository and applies the result. For a cautious preview, inspect Git and ChezMoi separately first:
chezmoi cd
git pull --ff-only
exit
chezmoi diff
chezmoi apply -v
Restore after a fresh install or distro hop
Install ChezMoi and Git first, then clone and apply your repository. For a private repo over SSH:
chezmoi init --apply git@github.com:$GITHUB_USERNAME/dotfiles.git
Or initialize, preview, then apply—a gentler first restore:
chezmoi init git@github.com:$GITHUB_USERNAME/dotfiles.git
chezmoi diff
chezmoi apply -v
Afterward, install the applications whose configs you manage (Albert, CopyQ, Espanso, Terminator, Tilda, and so on). ChezMoi restores files; an absent application will not suddenly exist because its configuration was restored.
Fresh machines have their own hardware, desktop environment, and package versions. Keep configs portable where possible; use ChezMoi templates later for genuine per-machine differences rather than copying one machine’s paths everywhere.
Verification and troubleshooting
# Where is ChezMoi’s source state?
chezmoi source-path
# Open a shell there and inspect Git
chezmoi cd
git status
git remote -v
exit
# What does ChezMoi manage?
chezmoi managed
# Is the live home directory aligned with desired state?
chezmoi status
chezmoi diff
# Preview every pending filesystem action, without applying it
chezmoi -n -v apply
# Diagnose common installation/configuration issues
chezmoi doctor
If a restored configuration does not take effect, check that the application is installed, that it reads the path you restored, and that it has been restarted. If chezmoi diff shows an unexpected overwrite, stop and inspect the source and live file before apply.
Cheat sheet
# Setup
chezmoi init
chezmoi add ~/PATH/TO/FILE_OR_DIRECTORY
# See and apply desired changes
chezmoi status
chezmoi diff [~/PATH]
chezmoi -n -v apply # safe preview
chezmoi apply -v [~/PATH]
# Manage scope and adopt live changes
chezmoi managed
chezmoi forget ~/PATH # stop managing; keeps the live path
chezmoi re-add ~/PATH # copy intentional live edits into source
chezmoi edit ~/PATH # edit the source-state version
# Git source state
chezmoi source-path
chezmoi cd
git status
git add . && git commit -m "Describe the change" && git push
exit
# Restore / synchronize
chezmoi init --apply git@github.com:$GITHUB_USERNAME/dotfiles.git
chezmoi update -v