git:20260422.a9374aa to git:20260923.7852cb4

84 added, 7 removed. Audit A to A.

---
name: chezmoi-assistant
description: "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'."
---
# Chezmoi Assistant
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.
+ ## Mindset
+
+ 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.
+
+ ## When to Use
+
+ - The user is adding, templating, encrypting, or syncing dotfiles specifically through chezmoi (not editing shell/editor config in the abstract)
+ - Diagnosing why `chezmoi apply` didn't produce the expected target file, permissions, or content
+ - Bootstrapping chezmoi on a new machine, or writing `run_` scripts
+
+ ## When NOT to Use
+
+ - General shell, editor, or tool configuration questions with no chezmoi involvement — answer those directly rather than routing through chezmoi mechanics
+ - Other dotfile managers (GNU Stow, yadm, a bare git repo in `$HOME`) — their models don't share chezmoi's filename-encodes-behaviour convention, so this skill's specifics don't transfer
+
## Mental Model
chezmoi 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)
```
## Daily Workflow
| 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` |
## Source State Attributes
See [`references/source-attrs.md`](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_`.
## Templates
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 user
```
Conditional 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`
## Multi-Machine Setup
New machine bootstrap:
```bash
chezmoi init --apply $GITHUB_USERNAME
```
Daily sync:
```bash
chezmoi update # git pull + chezmoi apply
```
Push changes back:
```bash
chezmoi cd
git add -A && git commit -m "feat: update zsh config" && git push
```
## Run Scripts
```
run_once_before_install-packages.sh — runs once, before apply
run_onchange_after_reload-shell.sh — reruns if script content changes
```
Scripts receive no target file — they are executed, not copied. Use `run_once_` for bootstrapping, `run_onchange_` for idempotent config reloads.
## Troubleshooting Workflow
1. `chezmoi doctor` — check for common problems first
2. `chezmoi diff` — see what would change
3. `chezmoi status` — quick summary (A=add, D=delete, M=modify)
4. `chezmoi cat ~/.zshrc` — preview rendered target without applying
5. `chezmoi data` — inspect available template variables
## Anti-Patterns
- NEVER manually rename files in the source dir. WHY: Attributes must follow strict ordering rules; use `chezmoi chattr` instead.
+ ### NEVER manually rename or `mv` files inside the source directory
- NEVER store plaintext secrets in source state without `encrypted_`. WHY: The source directory is typically a public git repo.
+ **WHY:** 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.
- NEVER use `exact_` on home directory itself. WHY: It will delete every unmanaged file in `$HOME`.
+ ❌ BAD:
+ ```bash
+ mv dot_zshrc.tmpl dot_bashrc.tmpl
+ ```
- NEVER commit `chezmoi.toml` with actual secrets. WHY: Config values should use template functions to pull from the keychain/password manager at apply time.
+ ✅ GOOD:
+ ```bash
+ chezmoi chattr template dot_bashrc # let chezmoi rewrite attributes safely
+ ```
+ **Consequence:** 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.
+
+ ### NEVER store plaintext secrets in source state without `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.asc
+ ```
+
+ **Consequence:** 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.
+
+ ### NEVER apply `exact_` to the home directory itself
+
+ **WHY:** `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 manage
+ ```
+
+ **Consequence:** `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.
+
+ ### NEVER commit `chezmoi.toml` with literal secret values
+
+ **WHY:** `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:
+ ```toml
+ [data]
+ githubToken = "ghp_abcd1234efgh5678"
+ ```
+
+ ✅ GOOD:
+ ```toml
+ [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.
+
## Eval Scenarios
- - [Scenario 01: Track and template a config file](evals/scenario-01.md)
- - [Scenario 02: Bootstrap a new machine](evals/scenario-02.md)
- - [Scenario 03: Write a run-once setup script](evals/scenario-03.md)
+ - [Scenario 1: Track and template a config file](evals/scenario-1/task.md)
+ - [Scenario 2: Bootstrap a new machine](evals/scenario-2/task.md)
+ - [Scenario 3: Write a run-once setup script](evals/scenario-3/task.md)
+ - [Scenario 4: Add secrets to chezmoi safely](evals/scenario-4/task.md)
+ - [Scenario 5: Rename a tracked file and scope `exact_` correctly](evals/scenario-5/task.md)
## References
- [`references/commands.md`](references/commands.md) — Full command reference
- [`references/source-attrs.md`](references/source-attrs.md) — All prefixes/suffixes with ordering rules
- [`references/templates.md`](references/templates.md) — Template variables, functions, and directives