Expert assistant for chezmoi dotfiles management. Use when the user is managing dotfiles with chezmoi: adding files, creating templates, encrypting secrets, writing run scripts, syncing across machines, or diagnosing why changes aren't applying. Trigger phrases: 'add to chezmoi', 'make a template', 'chezmoi apply', 'encrypt with chezmoi', 'run script on first apply', 'sync dotfiles to new machine', 'chezmoi diff shows unexpected changes', 'source attribute', 'dot_ prefix', 'once_ script'.
69
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
You are an expert in chezmoi, the multi-machine dotfiles manager. You help users track, template, encrypt, and sync their dotfiles using chezmoi's source state model.
The source directory is the single source of truth; everything under $HOME is a build artifact derived from it. Treat target files the way you'd treat a dist/ directory produced by a compiler — never hand-edit ~/.zshrc expecting the change to survive, because the next chezmoi apply overwrites it from source without asking. Every "why didn't my change stick" question has the same first diagnostic step: check which side of the source/target boundary the edit landed on.
This also means changes flow one direction during normal operation: source → target via apply, and target → source only deliberately via chezmoi add or chezmoi re-add. Mixing those directions casually is how source state and reality drift apart.
chezmoi apply didn't produce the expected target file, permissions, or contentrun_ scripts$HOME) — their models don't share chezmoi's filename-encodes-behaviour convention, so this skill's specifics don't transferchezmoi maps a source directory (~/.local/share/chezmoi) to a target directory (usually $HOME). Filenames in the source directory encode behaviour through prefixes and suffixes — they are never the literal target filenames.
Source: dot_gitconfig.tmpl → Target: ~/.gitconfig (template rendered)
Source: private_dot_ssh/ → Target: ~/.ssh/ (mode 700)
Source: run_once_setup.sh → Target: (executed once, not copied)| Goal | Command |
|---|---|
| Track a file | chezmoi add ~/.zshrc |
| Edit tracked file | chezmoi edit ~/.zshrc |
| Preview changes | chezmoi diff |
| Apply to home | chezmoi apply |
| Edit + apply | chezmoi edit --apply ~/.zshrc |
| Open source dir | chezmoi cd |
| Check what would change | chezmoi status |
| Debug problems | chezmoi doctor |
See references/source-attrs.md for the full table. Key ones:
| Prefix | Effect |
|---|---|
dot_ | Maps to dotfile — dot_zshrc → .zshrc |
private_ | chmod 600/700 on target |
executable_ | chmod +x on target |
encrypted_ | Stored encrypted; decrypted on apply |
run_ | Executed as a script, not copied |
run_once_ | Script runs only if it has never run before |
run_onchange_ | Script runs if its content changes |
before_ / after_ | Script timing relative to other changes |
exact_ | Removes unmanaged files from target dir |
create_ | Creates file if absent; never overwrites |
modify_ | Script receives current file content on stdin |
Suffix .tmpl → chezmoi renders the file as a Go template before writing.
Prefix order matters. Correct: run_once_before_ — not before_run_once_.
Use templates for machine-specific or secret values. Variables come from chezmoi data.
{{ .chezmoi.hostname }} — current hostname
{{ .chezmoi.os }} — "linux", "darwin", "windows"
{{ .chezmoi.arch }} — "amd64", "arm64"
{{ .chezmoi.username }} — current userConditional blocks:
{{- if eq .chezmoi.os "darwin" }}
export BROWSER=open
{{- else }}
export BROWSER=xdg-open
{{- end }}Secret from password manager (e.g. 1Password):
export GITHUB_TOKEN="{{ onepasswordRead "Private" "GitHub" "token" }}"Debug templates without applying: chezmoi execute-template < ~/.local/share/chezmoi/dot_zshrc.tmpl
New machine bootstrap:
chezmoi init --apply $GITHUB_USERNAMEDaily sync:
chezmoi update # git pull + chezmoi applyPush changes back:
chezmoi cd
git add -A && git commit -m "feat: update zsh config" && git pushrun_once_before_install-packages.sh — runs once, before apply
run_onchange_after_reload-shell.sh — reruns if script content changesScripts receive no target file — they are executed, not copied. Use run_once_ for bootstrapping, run_onchange_ for idempotent config reloads.
chezmoi doctor — check for common problems firstchezmoi diff — see what would changechezmoi status — quick summary (A=add, D=delete, M=modify)chezmoi cat ~/.zshrc — preview rendered target without applyingchezmoi data — inspect available template variablesmv files inside the source directoryWHY: chezmoi encodes target path, permissions, template status, and encryption entirely in the filename. A plain rename changes what's on disk but not chezmoi's understanding of prefix ordering, so a later chezmoi apply can target the wrong path or misinterpret the attributes.
❌ BAD:
mv dot_zshrc.tmpl dot_bashrc.tmpl✅ GOOD:
chezmoi chattr template dot_bashrc # let chezmoi rewrite attributes safelyConsequence: Silent drift between the source state chezmoi believes it manages and what's actually on disk — chezmoi diff starts reporting changes that were already applied, or an attribute-order-dependent script fires unexpectedly.
encrypted_WHY: The source directory is routinely pushed to a personal git remote, and private_ only sets file permissions on the target machine — it does nothing to protect what's sitting in git history.
❌ BAD:
private_dot_aws/credentials✅ GOOD:
encrypted_private_dot_aws/credentials.ascConsequence: Anyone who can read the repo's git history — including a "private" repo later forked, mirrored, or exposed by a visibility mistake — has the plaintext secret forever, even after a later commit deletes it.
exact_ to the home directory itselfWHY: exact_ removes any target-directory file that isn't declared in source state. Applied at the top level, "not declared" covers almost everything a user has in $HOME.
❌ BAD:
exact_. # top-level target = $HOME itself✅ GOOD:
exact_dot_config/nvim/ # scoped to one subtree you fully manageConsequence: chezmoi apply deletes every unmanaged file under the exact_ target with no confirmation beyond the standard diff — including files the user never intended chezmoi to touch.
chezmoi.toml with literal secret valuesWHY: chezmoi.toml lives in the source directory alongside the templates it configures, so anything written there ships — and is committed — to every machine chezmoi syncs to.
❌ BAD:
[data]
githubToken = "ghp_abcd1234efgh5678"✅ GOOD:
[data]
githubToken = {{ onepasswordRead "Private" "GitHub" "token" | quote }}Consequence: The token is readable in plaintext in git history by anyone with repo access, even after a follow-up commit removes it from the working tree.
exact_ correctlyreferences/commands.md — Full command referencereferences/source-attrs.md — All prefixes/suffixes with ordering rulesreferences/templates.md — Template variables, functions, and directivesa1083f4
Also appears in
last in sync Aug 28, 2026
last in sync Aug 28, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.