| name | chezmoi-sync |
| description | Sync changes made to live dotfiles back into the chezmoi source repo. Use when the user has edited a file in their home directory (or other chezmoi target) and wants the chezmoi source (plain files, `.tmpl` templates, or included partials under `.chezmoitemplates/`) updated so `chezmoi diff` is clean again. Triggers on: "sync to chezmoi", "pull changes into chezmoi", "update the template to match", "make chezmoi diff empty".
|
| compatibility | Requires `chezmoi` on PATH. Must be run with the user's chezmoi source directory accessible (typically ~/.local/share/chezmoi). |
chezmoi-sync
Reverse-apply edits from the destination (live home dir) back into the chezmoi
source repo. The goal: after this skill runs, chezmoi diff for the target
file(s) reports nothing.
Inputs
- Filename (optional): a target path like
~/.finicky.js or ~/.config/fish/config.fish.
- If provided, only that file is synced.
- If not provided, list all differing files and ask the user which to sync.
Workflow
1. Discover differences
- If the user gave a filename, skip to step 2 with just that path.
- Otherwise run
chezmoi diff with no arguments and parse which target files
have differences. Each diff block starts with an underlined header that is
the target-relative path (for example .finicky.js or
.config/fish/config.fish).
- Present the list of differing files to the user and ask which ones to sync.
Do not assume "all" - wait for an explicit choice.
2. For each file the user selected
- Run
chezmoi source-path <target> to find the source file in the repo.
- Run
chezmoi diff <target> to inspect exact differences.
- Compare the live file with the rendered target:
- Live content:
cat <target> (or read directly)
- Rendered target content:
chezmoi cat <target>
- Decide where the change actually belongs (see "Templates and partials" below).
- Edit the appropriate source file(s).
- Re-run
chezmoi diff <target>. If it still shows differences, iterate until
it is clean.
3. Report
Summarize which source files were touched for each synced target, and confirm
chezmoi diff is clean for every file that was synced.
Do NOT commit changes. The user reviews and commits themselves.
Templates and partials
The source for a target may be:
- Plain file (e.g.
dot_gitignore): just mirror the edit.
- Template file with
.tmpl suffix: contains Go text/template syntax with
expressions like {{ if .personal }}...{{ end }} or partial includes like
{{ template "finicky/common" }}. Do NOT blindly overwrite - preserve
template expressions and only change the static parts that changed in the
live file.
- Partial under
.chezmoitemplates/<name>: when a .tmpl does
{{ template "finicky/linear" }}, the real content lives in
home/.chezmoitemplates/finicky/linear. Find it by grepping, or by looking
at the .tmpl includes and matching template names to filenames under
.chezmoitemplates/.
How to locate the right file when templates are involved
- Run
chezmoi source-path <target> - that gives the top-level source file.
- Read it. If it is short and only does
{{ template "x" . }} includes,
the real edits go into the partial(s) under .chezmoitemplates/x.
- Match content: read each candidate partial and find the lines that
correspond to the diff hunks. Edit the partial that contains those lines.
- If a diff hunk spans content generated by template logic (e.g. the line
only exists when
.personal is true), make sure the edit is inside the
matching {{ if ... }} block so other hosts are not affected.
Guarding against breaking other hosts
Before editing, consider whether the change is host-specific or universal:
- Hardcoded paths that differ per machine (Firefox profile dirs, usernames on
non-
del-boy hosts, per-host package lists) probably belong inside a
{{ if eq .chezmoi.hostname "..." }} guard, a per_host entry in
packages.yaml, or a runtime-dispatch function inside the file itself
(as done in ~/.finicky.js with FIREFOX_PROFILES_BY_HOST).
- Universal tweaks (new alias, fixed typo, reordered block) just go into the
shared source.
If the edit looks host-specific, ask the user how they want it scoped:
guard with a template conditional, add a per-host data entry, or keep it
universal.
Useful commands
chezmoi diff
chezmoi diff <target>
chezmoi source-path <target>
chezmoi cat <target>
chezmoi data
chezmoi execute-template < file
Safety rules
- Never run
chezmoi apply. That pushes source state onto the live file and
would clobber the user's work before it is saved.
- Never commit or push. Only edit source files.
- Do not add new
{{ onepasswordRead "op://..." }} calls without a
{{ if .secure_env }} guard - they fail on machines without 1Password.
- If a live file contains secrets (tokens, keys) that are not already in the
source, stop and ask the user how to handle them. Do not paste secrets into
the repo.
- Respect existing project conventions (see the repo's
AGENTS.md if present).
Example session
User: "Sync ~/.finicky.js back into chezmoi."
chezmoi diff ~/.finicky.js - shows a block of new code and two changed args lines.
chezmoi source-path ~/.finicky.js -> home/dot_finicky.js.tmpl.
- Read
dot_finicky.js.tmpl - it only includes partials. The diffed content
matches home/.chezmoitemplates/finicky/linear.
- Edit that partial: add the new helper, swap hardcoded paths for the helper call.
chezmoi diff ~/.finicky.js - clean.
- Report: "Updated
home/.chezmoitemplates/finicky/linear. Diff is empty."