Templates¶
Delimiter Layers¶
This repository uses custom chezmoi delimiters ([{ }]) so that just's {{ }} passes through untouched. See
Conventions for the rules.
Two-Phase Example¶
chezmoi:template:left-delimiter=[{ right-delimiter=}]
# Chezmoi injects this at apply time
chezmoi_src := "[{ .chezmoi.sourceDir }]"
# Just evaluates this at runtime
some-recipe:
@echo "Source: {{ chezmoi_src }}"
Three-Layer Escaping (Chezmoi → Just → Docker)¶
When Docker/Go format strings appear inside just recipes, there are three {{ }} consumers:
| Layer | Delimiters | When | Example |
|---|---|---|---|
| Chezmoi | [{ }] |
chezmoi apply |
[{ .isMacos }] |
| Just | {{ }} |
recipe execution | {{ name }}, {{ invdir }} |
| Docker/Go | {{ }} |
command runtime | {{.ID}}, {{.LogPath}} |
Just interprets {{ }} first, so Docker format strings need escaping — double the opening braces: {{{{.ID}} →
{{.ID}}. The closing }} does not need doubling.
# Source (.tmpl) # Rendered just file # Shell output
docker ps --format '{{{{.ID}}' # → '{{.ID}}' # → container ID
docker inspect --format '{{{{.State}}}' # → '{{.State}}' # → map[...]
Shared Template Data¶
Reusable values are defined in .chezmoidata/data.yaml and accessible in all templates via dot notation:
# .chezmoidata/data.yaml
status:
ok: "\u001b[32mOK:\u001b[0m"
fail: "\u001b[31mFAIL:\u001b[0m"
success: "\u001b[32mSUCCESS:\u001b[0m"
warning: "\u001b[33mWarning:\u001b[0m"
Usage in templates:
This keeps colour codes DRY and consistent across all scripts.
Conditional Patterns¶
Use these patterns to handle platform differences:
# Skip on Bluefin (tool provided by system)
[{- if not .isBluefin }]
brew "starship"
[{- end }]
# Guard for Linux (e.g., font cache)
[{- if .isLinux }]
fc-cache -f
[{- end }]
# OS-specific logic
[{- if .isMacos }]
# macOS only
[{- else if .isLinux }]
# Linux only
[{- end }]
Because .isMacos, .isLinux, etc. are custom data flags (not built-in chezmoi values), they can be overridden via
chezmoi execute-template --override-data — this is how the full-render test generates all platform variants from a
single machine.
Externally-Modified Files (Modify Templates)¶
Some config files are shared between chezmoi and external tools that rewrite them at runtime. For example,
~/.docker/config.json is managed by chezmoi (to set currentContext and cliPluginsExtraDirs) but Docker also
rewrites it — reordering JSON keys and stripping trailing newlines. A standard chezmoi template treats the rendered
output as the complete desired state, so any external rewrite causes a perpetual diff.
The Problem¶
| Approach | Outcome |
|---|---|
Standard template (config.json.tmpl) |
Perpetual diff — Docker reformats the file after every apply |
create_ prefix |
One-shot — chezmoi never updates the file once it exists |
run_onchange_ script |
Imperative, needs jq, invisible to chezmoi diff |
The Solution: modify_ with deepEqual Guard¶
A modify template
receives the existing file contents via .chezmoi.stdin, merges in the desired keys, and uses deepEqual to decide
whether to rewrite:
{{- /* chezmoi:modify-template */ -}}
{{- $config := dict -}}
{{- if ne .chezmoi.stdin "" -}}
{{- $config = fromJson .chezmoi.stdin -}}
{{- end -}}
{{- $desired := deepCopy $config -}}
{{- $desired = set $desired "currentContext" "colima" -}}
{{- $desired = set $desired "cliPluginsExtraDirs" (list (joinPath (lookPath "brew" | dir | dir) "lib/docker/cli-plugins")) -}}
{{- if deepEqual $config $desired -}}
{{- .chezmoi.stdin -}}
{{- else -}}
{{- toPrettyJson "\t" $desired }}
{{ end -}}
How it works:
- Keys already correct:
deepEqualreturns true → stdin is passed through verbatim (preserving the external tool's formatting). Chezmoi sees zero diff. - Keys missing or wrong:
deepEqualreturns false → file is rewritten withtoPrettyJson. Subsequent runs will then pass through verbatim. - File doesn't exist (fresh machine): stdin is empty → template creates the file from scratch.
- External tool adds new keys: Those keys flow into both
$configand$desiredviadeepCopy, so they are preserved.
When to Use¶
Use a modify template when:
- Chezmoi needs to ensure specific keys in a file that external tools also modify
- The external tool reformats the file (key reordering, whitespace changes)
- You want
chezmoi diffandchezmoi statusvisibility into the file's state
Do not use modify templates for files that chezmoi fully owns — a standard template is simpler and sufficient.