MCPInstall

chezmoi

Manage dotfiles with chezmoi — the source-state dotfile manager that uses filename attributes (dot, private, encrypted, runonce), Go templates, and password-manager integration to keep one set of dotfiles working across many machines. Use when the user says "set up dotfiles", "manage my dotfiles", "bootstrap a new machine", "chezmoi", "encrypt my SSH key in dotfiles", "template dotfiles per OS", "add secrets to dotfiles", "what should be in my .chezmoi.toml.tmpl", or asks how to share configs across macOS / Linux / servers. Also trigger when the user is staring at a fresh machine and wants the one-liner that gets them home, or when they're about to commit something sensitive into a dotfiles repo. Do NOT use for stow / yadm / rcm or other dotfile managers, generic git repo setup, or password-manager setup unrelated to dotfiles.

Installs
58
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/paulnsorensen/skillz-that-grillz --skill chezmoi
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads chezmoi automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

chezmoi

Wrap chezmoi — manage dotfiles across machines using source-state semantics, Go templates, and at-rest encryption.

When to use

  • Bootstrapping dotfiles on a new machine
  • Adding a new file to existing chezmoi-managed dotfiles
  • Templating a dotfile per-OS, per-host, or per-role (work vs. personal)
  • Adding secrets via 1Password / Bitwarden / age / gpg
  • Writing a run_once_ install script
  • Diagnosing "chezmoi apply changed something I didn't expect"
  • Designing the .chezmoi.toml.tmpl config template for a fleet of machines

Mental model

chezmoi maps a source directory (~/.local/share/chezmoi, a git repo) to a target directory (the user's home). Source filenames carry attribute prefixes that determine target name and behavior. Source files with a .tmpl suffix are rendered as Go text/template and written to their target paths. Files under .chezmoitemplates/ are reusable template fragments included by other templates — they do not produce target files on their own. A config file at ~/.config/chezmoi/chezmoi.toml (typically generated from .chezmoi.toml.tmpl on first init) holds per-machine variables.

The two reasons people get into trouble:

  1. They edit files directly under ~/.local/share/chezmoi/ instead of using chezmoi edit $TARGET. This breaks templates and decrypt round-trips.
  2. They commit secrets in plaintext "because the repo is private". Repos leak, forks leak, history is forever. Use a secret backend.

Where the config file lives

Two files, easy to confuse. Both can be in toml, yaml, json, or jsonc (auto-detected by extension; two formats present at once is an error, not "first one wins"):

FilePathWho writes it
chezmoi.<fmt> (the config)$XDG_CONFIG_HOME/chezmoi/chezmoi.<fmt>, default ~/.config/chezmoi/chezmoi.<fmt> (.toml most common). NOT in the source repo.Generated by chezmoi init (or apply --init) from the template below. Per-machine. Holds secrets, API tokens, machine-specific settings — never commit.
.chezmoi.<fmt>.tmpl (the config template)Source-state root: ~/.local/share/chezmoi/.chezmoi.<fmt>.tmpl (.toml most common). Committed to the dotfiles repo.You write it. Uses promptBoolOnce / promptChoiceOnce / promptStringOnce so a fresh machine generates the right config on first init.

Override locations with --config <path> (use --config-format <fmt> if the extension is unusual). Look up effective values with chezmoi cat-config and chezmoi dump-config.

Protocol

1. Detect what the user wants

User saysGo to
"set up chezmoi from scratch" / "new machine"§2 Bootstrap
"add this file to my dotfiles"§3 Add a file
"make this dotfile depend on OS / host"references/templating.md
"encrypt this" / "store this token"references/secrets.md
"run a script on first apply"references/scripts.md
"chezmoi did something weird"references/pitfalls.md
"design my full setup"references/bootstrap.md

2. Bootstrap (new machine)

The full one-liner that clones, renders templates, and applies in one shot:

sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply $GITHUB_USERNAME

For a fully fleshed .chezmoi.toml.tmpl recipe with promptBoolOnce for work-vs-personal-vs-headless, see references/bootstrap.md.

3. Add a file

chezmoi add ~/.zshrc                  # plain copy
chezmoi add --template ~/.gitconfig   # add as a template (.tmpl suffix added)
chezmoi add --encrypt ~/.ssh/config   # encrypted at rest
chezmoi chattr +template ~/.zshrc     # turn an existing managed file into a template
chezmoi edit ~/.zshrc                 # edit the SOURCE — handles decrypt + .tmpl correctly

Then the safe-apply ritual (§5).

4. File-naming reference

The table users get wrong most often. Prefixes must appear in a specific order, and the allowed prefix set depends on the target type — /reference/source-state-attributes/ is the canonical source.

PrefixEffect on target
dot_Add leading . (dot_zshrc → ~/.zshrc)
private_Strip group + world permissions (mode 0600 / 0700)
readonly_Strip all write permission bits
executable_Add executable bit
empty_Allow empty file (default would remove it)
encrypted_Decrypt source via age/gpg before writing target
symlink_Create a symlink instead of a regular file (file form, target is symlink target)
exact_ (dirs)Delete anything in target dir not present in source
create_Create target only if missing — never overwrite
modify_Treat source as a script (or template, see below) that produces target contents
run_Treat source as a script to execute (not a target file)
before_ / after_Order scripts relative to applying files
once_ (scripts)Run only when contents have not been run successfully before
onchange_ (scripts)Run only when contents change for THIS filename
remove_Remove the target if it exists
external_ (dirs)Mark a directory as an external — pairs with .chezmoiexternal.<fmt> / .chezmoiexternals/; chezmoi ignores attributes on child entries
literal_ (anywhere)Stop parsing further attributes from this point

Allowed prefix order per target type (the order is rigid; rearranging is a parse error):

Target typeAllowed prefixes (in order)Optional suffix
Directoryremove_, external_, exact_, private_, readonly_, dot_—
Regular fileencrypted_, private_, readonly_, empty_, executable_, dot_.tmpl
Create filecreate_, encrypted_, private_, readonly_, empty_, executable_, dot_.tmpl
Modify filemodify_, encrypted_, private_, readonly_, executable_, dot_.tmpl
Remove fileremove_, dot_—
Scriptrun_, once_ or onchange_, before_ or after_.tmpl
Symlinksymlink_, dot_.tmpl

Suffix .tmpl makes the file a template. .age / .asc are stripped automatically when the corresponding encryption is configured.

Modify file detail. A modify_ source is a script by default — it reads the current target on stdin and writes the new target to stdout. If the file contains the string chezmoi:modify-template, lines containing that marker are stripped and the rest is interpreted as a template; the existing target is exposed in .chezmoi.stdin. Use the template form when you want to surgically edit a structured file (JSON, TOML, YAML); use the script form when you need a real interpreter (jq, awk, sed).

5. Safe-apply ritual

Before any apply that touches important files, run the inspection trio:

chezmoi status              # one line per changed file
chezmoi diff                # unified diff of pending changes
chezmoi apply --dry-run -v  # full plan, including scripts that would run
chezmoi apply               # only after the above looks right

For routine pulls on a machine you trust:

chezmoi update                                          # = git pull --autostash --rebase + apply
chezmoi git pull -- --autostash --rebase && chezmoi diff # preview only — no apply

6. Edit safely

chezmoi edit ~/.zshrc       # opens source in $EDITOR, handles .tmpl + encryption
chezmoi cd                  # subshell in the source directory (for git operations)
chezmoi re-add              # refresh source from current target after editing target
chezmoi merge ~/.zshrc      # 3-way merge target ↔ source ↔ destination
chezmoi merge-all           # 3-way merge every file whose actual ≠ target (add --init to re-render config first)

Editor resolution: edit.command → $VISUAL → $EDITOR → vi (or notepad.exe on Windows). chezmoi prints a warning if the editor returns in < edit.minDuration (default 1s) — that catches the "I opened the file but didn't actually edit it" case. Set to 0 to silence.

Never open ~/.local/share/chezmoi/encrypted_dot_ssh/... or *.tmpl files directly in your editor — the file you see isn't the file chezmoi sees.

7. Application order (mental model)

chezmoi apply is deterministic. Each run does:

  1. Read source state, read destination state, compute target state.
  2. Run run_before_ scripts in ASCII order of target name.
  3. Update entries in ASCII order of target name. Directories (including directories materialized by externals) are written before the files they contain. Externals are fetched/expanded during this phase.
  4. Run run_after_ scripts in ASCII order.

Implications:

  • A run_before_ script must not read a file that an external will provide — externals are applied in phase 3, not before.
  • Target names are compared with all attribute prefixes stripped. Given create_alpha and modify_dot_beta, .beta is updated before alpha because .beta < alpha in ASCII.
  • chezmoi assumes source and destination don't change during a run. A run_before_ script that writes into either violates that assumption — behavior is undefined.

8. Partial-file management

When chezmoi shouldn't own the whole file, pick a pattern based on who the file belongs to:

modify_ — user owns the file, chezmoi stamps a block. The source reads the existing target on stdin and writes the new target on stdout.

Script form, modify_dot_zshrc:

#!/usr/bin/env bash
set -euo pipefail
# Strip any prior chezmoi block from the existing file …
awk '/# chezmoi:begin/{s=1;next} /# chezmoi:end/{s=0;next} !s'
# … then append the current managed block.
cat <<'EOF'

# chezmoi:begin
export EDITOR=nvim
alias g=git
# chezmoi:end
EOF

Template form (for structured files), modify_dot_config_private_app.yaml.tmpl:

{{- /* chezmoi:modify-template */ -}}
{{- $cfg := dict -}}
{{- if .chezmoi.stdin -}}{{- $cfg = .chezmoi.stdin | fromYaml -}}{{- end -}}
{{- $_ := set $cfg "telemetry" false -}}
{{- $_ := set $cfg "user" (dict "email" .email) -}}
{{ toYaml $cfg }}

The if .chezmoi.stdin guard handles the initial-apply case where the target doesn't exist yet. Use fromJsonc / fromToml / fromYaml + toPrettyJson / toToml / toYaml for the round-trip.

.chezmoitemplates/ — chezmoi owns the file, fragments are shared. Reusable blocks live under .chezmoitemplates/, pulled into regular templates with {{ template "name" . }} (or includeTemplate "name" . when you need to pipe the result through a function):

.chezmoitemplates/zsh-prompt          # one file
dot_zshrc.tmpl                        # {{ template "zsh-prompt" . }}
dot_config/fish/config.fish.tmpl      # {{ template "zsh-prompt" . }} too

Choose the pattern by ownership. modify_ when the user can freely edit the file outside the managed block. .chezmoitemplates/ when chezmoi renders the whole file but you want to DRY shared sections. Mixing both in one target is usually a smell.

Hard rules

These are non-negotiable. Each one corresponds to a real foot-gun:

  1. Never commit plaintext secrets, even to a private repo. Repos leak, get forked, get logged, get backed up. Pick a backend from references/secrets.md.
  2. Never edit encrypted or templated source files directly. Use chezmoi edit $TARGET so the decrypt and template round-trips happen.
  3. Always inspect before applying on shared/important files — chezmoi diff or chezmoi apply --dry-run -v. exact_ on a directory deletes unmanaged entries; you want to see that coming.
  4. prompt* template functions belong only in the config-file template (.chezmoi.toml.tmpl). Using them in regular dotfile templates causes a prompt on every apply / diff / status, which defeats automation.

Secrets decision tree (summary)

Full details in references/secrets.md. Pick exactly one per repo.

  • Public repo + cloud password manager → 1Password CLI / Bitwarden template functions. Secrets fetched at apply time, never on disk.
  • Private repo + offline-friendly → age (encrypted_ prefix). Identity at ~/.config/chezmoi/key.txt, lives outside the repo.
  • Sharing across a team → SOPS-encrypted .chezmoidata/secrets.yaml.
  • Air-gapped / first-bootstrap → gitignored plaintext .chezmoidata/local.yaml (transitional, not a long-term answer).

Mixing backends multiplies moving parts without making anything more secure.

Templating quick reference

Full details in references/templating.md.

{{- if eq .chezmoi.os "darwin" }}
export HOMEBREW_PREFIX="/opt/homebrew"
{{- else if eq .chezmoi.os "linux" }}
export PATH="/usr/local/bin:$PATH"
{{- end }}

{{- if and (eq .chezmoi.os "darwin") (lookPath "brew") }}
# brew is installed
{{- end }}

email = {{ .email | quote }}

Built-in template variables include .chezmoi.os, .chezmoi.arch, .chezmoi.hostname, .chezmoi.username, .chezmoi.homeDir, .chezmoi.sourceDir. User-defined data lives under [data] in chezmoi.toml, or any .chezmoidata/*.{toml,yaml,json} file.

chezmoi runs templates with Go's missingkey=error option, so a typo like {{ .gitub.user }} fails the apply instead of rendering empty. Override via [template] options = ["missingkey=zero"] only if you have a concrete reason — losing the typo guard is rarely worth it.

For symlink targets, leading/trailing whitespace in the rendered result is stripped, and an empty result removes the symlink. For file targets, an empty render removes the file (use the empty_ prefix to keep it).

Special files and directories

All entries in the source dir beginning with . are ignored except the specials below. They are evaluated in this order on every operation: .chezmoiroot → .chezmoi.<fmt>.tmpl → data files → .chezmoitemplates/ → .chezmoiignore → .chezmoiremove → externals → .chezmoiversion.

PathRole
.chezmoirootSingle-line file pointing at a sub-directory as the source root
.chezmoi.<fmt>.tmplConfig-file template used on first chezmoi init (and on --init)
.chezmoidata.<fmt> / .chezmoidata/Data merged into the template . namespace before any template renders
.chezmoitemplates/Reusable template fragments ({{ template "name" . }}) — no target files
.chezmoiscripts/Scripts not bound to a target file; honor run_before_ / run_after_
.chezmoiignorePer-target ignore list — source-relative, templatable
.chezmoiremoveTargets to remove on apply — templatable
.chezmoiexternal.<fmt> / .chezmoiexternals/Pull files/archives from URLs at apply time
.chezmoiversionMin chezmoi version required by this source repo

.chezmoiignore matches source-relative paths (e.g. dot_zshrc), not target paths. People get this wrong constantly.

<fmt> means toml, yaml, json, or jsonc. The directory forms (.chezmoidata/, .chezmoiexternals/) merge their contents in lexical order with any same-prefix file forms — useful for splitting big config across files or composing externals per role.

What you don't do

  • Write a competing dotfile manager or shim around chezmoi apply
  • Edit files under ~/.local/share/chezmoi/ directly when they are templates or encrypted
  • Commit a .env / secrets.yaml to a "private" repo
  • Suggest chezmoi apply without first running chezmoi diff on a shared machine
  • Use prompt* template functions outside of .chezmoi.toml.tmpl
  • Mix multiple secret backends (age + 1Password + SOPS) in the same repo without a clear, written reason

Gotchas

  • fork/exec ...: exec format error running a templated script means a newline before #!. Add - inside the closing }} on the first template line to suppress it.
  • fork/exec ...: permission denied for scripts means $TMPDIR is mounted noexec. Set scriptTempDir in chezmoi.toml.
  • Windows line endings (CRLF) in templates produce broken shell scripts on Linux/macOS. Add * text eol=lf to a .gitattributes in the dotfiles repo, or set core.autocrlf = input.
  • chezmoi init on a new machine before .chezmoi.toml.tmpl exists silently skips per-machine prompts. Land that template before adding host-specific files.
  • chezmoi doctor is the first command to run when something is off — it reports missing dependencies (op, age, etc.), broken paths, and shell integration issues in one pass.
  • Context7 may be unavailable. The chezmoi CLI is self-documenting via chezmoi help and chezmoi help <command>; fall back to that.
  • Two config files (e.g. both chezmoi.toml and chezmoi.yaml) in ~/.config/chezmoi/ is an error, not "first one wins". When migrating formats, delete the old file in the same commit.
  • Config format is detected by extension. Force it with --config-format if you pipe a config from an unusual path.
  • chezmoi <unknown> looks for chezmoi-<unknown> on $PATH (git-style plugin convention) before failing. Useful for adding repo-local helpers; surprising when a typo silently runs an unrelated binary.

Reference URL index

The chezmoi docs evolve fast — new template functions, new config keys, new prefixes every few releases. When a question goes deeper than this skill, fetch the live page rather than guessing from training data. Prefer mcp__tavily__tavily_extract (single URL, extract_depth: "advanced", format: "markdown") — it returns the canonical /reference/* content directly. Use Context7 only as a fallback. Do not tavily_map or crawl — the URLs below are stable; pick the exact one.

Example call shape:

mcp__tavily__tavily_extract(
  urls: ["https://www.chezmoi.io/reference/templates/functions/jq/"],
  extract_depth: "advanced",
  format: "markdown",
)

Map of what lives where:

TopicURL
Concepts (source / target / destination / working tree)/reference/concepts/
Source-state attribute order per target type/reference/source-state-attributes/
Target types (file / dir / symlink / script / modify / create / remove)/reference/target-types/
Application order on chezmoi apply/reference/application-order/
All command-line flags (global / common / developer)/reference/command-line-flags/
Per-command reference (chezmoi <name>)/reference/commands/<name>/
Configuration file structure/reference/configuration-file/
Hooks (read-source-state / apply / etc.)/reference/configuration-file/hooks/
Interpreters for scripts by extension/reference/configuration-file/interpreters/
Special files (.chezmoiignore etc.)/reference/special-files/<name>/
Special directories (.chezmoidata/ etc.)/reference/special-directories/<name>/
Template variables (.chezmoi.os etc.)/reference/templates/variables/
Template directives (chezmoi:template:, etc.)/reference/templates/directives/
Built-in template functions/reference/templates/functions/<name>/
init template functions (promptBoolOnce etc.)/reference/templates/init-functions/<name>/
Password-manager template functions/reference/templates/<vendor>-functions/<name>/ (1password, bitwarden, dashlane, doppler, ejson, gopass, keepassxc, keeper, keyring, lastpass, pass, passhole, protonpass, vault, aws-secrets-manager, azure-key-vault, secret)
GitHub template functions/reference/templates/github-functions/<name>/
Plugins/reference/plugins/

Heuristic: when the user asks "what does prefix X do" → source-state- attributes; "what does chezmoi <cmd> do" → commands/<cmd>; "what template var holds Y" → templates/variables; "how do I read a secret from Z" → templates/<vendor>-functions. Fetch only the page you need with mcp__tavily__tavily_extract — single URL, advanced depth — so the answer is always grounded in the canonical docs as of today, not what this skill happened to know when it was last edited.

FAQ

What does the chezmoi skill do?

Manage dotfiles with chezmoi — the source-state dotfile manager that uses filename attributes (dot, private, encrypted, runonce), Go templates, and password-manager integration to keep one set of dotfiles working across many machines. Use when the user says "set up dotfiles", "manage my dotfiles", "bootstrap a new machine", "chezmoi", "encrypt my SSH key in dotfiles", "template dotfiles per OS", "add secrets to dotfiles", "what should be in my .chezmoi.toml.tmpl", or asks how to share configs across macOS / Linux / servers. Also trigger when the user is staring at a fresh machine and wants the one-liner that gets them home, or when they're about to commit something sensitive into a dotfiles repo. Do NOT use for stow / yadm / rcm or other dotfile managers, generic git repo setup, or password-manager setup unrelated to dotfiles.

How do I install chezmoi?

Run npx skills add https://github.com/paulnsorensen/skillz-that-grillz --skill chezmoi in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/chezmoi/ (personal) or .claude/skills/chezmoi/ (project).

Which AI agents can use chezmoi?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is chezmoi safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains chezmoi?

It is published by paulnsorensen in paulnsorensen/skillz-that-grillz. It has 58 recorded installs.

More from paulnsorensen/skillz-that-grillz

View all →

skillz

paulnsorensen/skillz-that-grillz

Add, improve, audit, wedge, or autoimprove a skill. Improve and audit also accept a sub-agent definition. The result runs predictably on Claude Code, Codex, OMP, and other Agent Skills hosts. Use for /skillz , "improve this skill", "autoimprove this skill", "optimize this skill", "tighten this skill", "audit this agent", "new skill for X", "skill not triggering", "fix trigger rate", "wedge this", "turn this repeated work into a CLI", or "what in this skill should be a CLI". Do NOT use for CLAUDE.md or system-prompt edits, or for code changes that a cheese pipeline skill owns.

Security96 installs

gh

paulnsorensen/skillz-that-grillz

Complete GitHub tasks using the gh CLI — pull request inspection, review, and merge, issues, CI checks, releases, workflow runs, code search, repo and label management. Use when the user says "merge PR", "check CI", "list issues", "review PR", "PR status", "close issue", "trigger workflow", "view release", "search repos", or invokes /gh. Use git (log, diff, status) for read-only local context only. Do NOT use for committing, staging, pushing, or PR creation — use /plate for those. Do NOT use for code-quality review — use a dedicated review skill.

release

paulnsorensen/skillz-that-grillz

Open the skill to read its SKILL.md instructions.

59 installs

prek

paulnsorensen/skillz-that-grillz

Onboard prek (Rust-powered pre-commit) into any project and suggest hooks tailored to the language/framework. Use when the user says "add prek", "set up pre-commit hooks", "configure prek", "what hooks should I use", or when you notice a project without a prek.toml that would benefit from pre-commit checks. Also trigger when the user wants to add new hooks to an existing prek.toml, audit their hook config, or migrate from pre-commit to prek. Covers Rust, Python, TypeScript/JavaScript, Go, Ruby, and Shell projects. Do NOT use for husky, lint-staged, or CI pipeline hook configuration — this skill is specifically for prek.

serena-config

paulnsorensen/skillz-that-grillz

Open the skill to read its SKILL.md instructions.

57 installs

safe-settings

paulnsorensen/skillz-that-grillz

Set up GitHub's safe-settings (a Probot-based GitHub App from the github org) for declarative, org-wide repository policy as code. Use when the user says "settings as code", "safe-settings", "manage repos declaratively", "centralize repo settings", "org-level branch protection", "scaffold an admin repo", "github settings app", or invokes /safe-settings on an org that wants to manage repo settings, branch protection, rulesets, labels, teams, environments, and collaborators from one admin repo. Scaffolds the admin-repo layout (settings.yml + suborgs/ + repos/), the GitHub App installation steps, and a scheduled full-sync GitHub Actions workflow. Distinct from /gh (per-task ops) and /gh-bootstrap (one-shot gh api config of a single repo) — this skill is for org-scale settings as code that reconciles continuously.

Popular code quality & workflow skills

View category →

grill-me

mattpocock/skills

A relentless interview to sharpen a plan or design.

Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.

handoff

mattpocock/skills

Compact the current conversation into a handoff document for another agent to pick up.

domain-modeling

mattpocock/skills

Build and sharpen a project's domain model. Use when discussing codebase terminology, writing or editing a GLOSSARY.md, or recording or editing an ADR.

codebase-design

mattpocock/skills

Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.

diagnosing-bugs

mattpocock/skills

Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.