Chezmoi Script Lifecycle¶
Execution Phases¶
During chezmoi apply, scripts run in three phases:
beforescripts execute- Managed files are applied
afterscripts execute
Scripts without an explicit before_ or after_ in the name run interleaved with managed files in alphabetical
order by target name. Always use explicit before_ or after_ prefixes to avoid ambiguity.
Chezmoi naming
A source file is what lives in this repo. Chezmoi derives a target name by stripping special prefixes and suffixes
from the source filename. For managed files, the target is the real destination in $HOME (e.g., dot_zshrc.tmpl →
~/.zshrc). For scripts, the target name is only used for sort ordering — no file is created (e.g.,
run_once_before_00-install-brew.sh.tmpl → 00-install-brew.sh).
Source Attributes¶
| Source attribute | Effect |
|---|---|
dot_ |
Replaced with . |
run_ |
Marks file as a script |
once_, onchange_ |
Script execution condition |
before_, after_ |
Script execution phase |
executable_ |
Sets execute permission |
private_ |
Removes group/world permissions |
exact_ |
Removes unmanaged files in target directory |
create_ |
Only writes if target doesn't exist |
modify_ |
Runs as a modify template (receives existing content via stdin) |
.tmpl suffix |
Processes file as a template |
See chezmoi source state attributes for the full reference.
Execution Conditions¶
| Prefix | Behaviour |
|---|---|
run_ |
Runs on every chezmoi apply |
run_once_ |
Runs once (tracked by content hash) |
run_onchange_ |
Runs when the rendered script content changes |
Combined Prefixes¶
Timing and condition combine as:
| Prefix | When | How often |
|---|---|---|
run_once_before_ |
Before files | Once |
run_once_after_ |
After files | Once |
run_onchange_before_ |
Before files | On content change |
run_onchange_after_ |
After files | On content change |
run_before_ |
Before files | Every apply |
run_after_ |
After files | Every apply |
Ordering¶
Within each phase, scripts run in alphabetical order by filename. Use numeric prefixes to control this:
run_once_before_00-install-brew.sh ← runs first (before phase)
run_once_before_01-setup-zshrc.sh ← runs second (before phase)
← managed files applied →
run_once_after_10-brew-bundle.sh ← runs first (after phase)
run_after_20-setup-dotfiles-repo.sh ← runs second (after phase)
run_onchange_after_30-update-fonts.sh ← runs third (after phase)
run_once_after_99-reminders.sh ← runs last (after phase)
The once/onchange/always distinction does not affect sort order — all scripts within a phase are sorted together.
Conventions¶
See Code Style for scripting rules (idempotency, error handling, platform checks). Use custom template delimiters per the guidelines.