OpenPLUTO

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

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:

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

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:

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

Further reading