Core concepts
Destination directory
Destination directory
The directory that chezmoi manages, usually your home directory (
~).Target
Target
A file, directory, or symlink in the destination directory that chezmoi manages.
Destination state
Destination state
The current state of all the targets in the destination directory.
Source state
Source state
Declares the desired state of your home directory, including templates that use machine-specific data. It contains only regular files and directories.
Source directory
Source directory
Where chezmoi stores the source state. By default it is
~/.local/share/chezmoi.Config file
Config file
Contains machine-specific data. By default it is
~/.config/chezmoi/chezmoi.toml.Target state
Target state
The desired state of the destination directory. It is computed from the source state, the config file, and the destination state. The target state includes regular files and directories, and may also include symbolic links, scripts to be run, and targets to be removed.
Working tree
Working tree
The git working tree. Normally it is the same as the source directory, but can be a parent of the source directory.
State flow diagram
Here’s how chezmoi transforms your source state into your destination state:Understanding entries
chezmoi uses the generic term entry to describe something that it manages. Entries can be:- Files
- Directories
- Symlinks
- Scripts
- Remove operations
Entry types in source state
SourceStateFile
Regular files in the source directory. Include attributes parsed from the file name (like
dot_, executable_, encrypted_).SourceStateDir
Directories in the source directory. Include attributes parsed from the directory name (like
exact_, private_).Entry types in target state
TargetStateFile
A file with contents and permissions in the destination.
TargetStateDir
A directory in the destination.
TargetStateSymlink
A symbolic link in the destination.
TargetStateScript
A script that should be executed.
TargetStateRemove
An entry that should be removed from the destination.
Actual state entries
The actual state represents what currently exists in your destination directory.
ActualStateAbsent: Entry does not existActualStateDir: Entry is a directoryActualStateFile: Entry is a fileActualStateSymlink: Entry is a symlink
Source state attributes
chezmoi encodes metadata about files using special prefixes and suffixes in filenames. This is how a regular file becomes a dotfile, executable, or template.Common prefixes
| Prefix | Effect | Example |
|---|---|---|
dot_ | Rename to use a leading dot | dot_bashrc → .bashrc |
executable_ | Add executable permissions | executable_script.sh → executable file |
private_ | Remove all group and world permissions | private_key → mode 600 |
readonly_ | Remove all write permissions | readonly_config → read-only file |
encrypted_ | File is encrypted in source state | encrypted_secrets.txt.age |
empty_ | Ensure file exists even if empty | empty_file |
create_ | Create if doesn’t exist, don’t modify if it does | create_config.json |
modify_ | Run as script to modify existing file | modify_settings.sh |
remove_ | Remove the entry if it exists | remove_oldfile |
run_ | Execute as a script | run_setup.sh |
symlink_ | Create a symbolic link | symlink_config |
exact_ | Remove anything not managed by chezmoi | exact_directory/ |
Script-specific prefixes
run_once_
Only run if contents haven’t been run successfully before.
run_onchange_
Run whenever the script contents change.
before_
Execute before updating files.
after_
Execute after all files are updated.
Common suffixes
| Suffix | Effect |
|---|---|
.tmpl | Treat file contents as a Go template |
.literal | Stop parsing suffix attributes |
Prefix order matters
- Regular file
- Create file
- Script
- Directory
encrypted_ → private_ → readonly_ → empty_ → executable_ → dot_The apply workflow
When you runchezmoi apply, here’s what happens:
Read source state
chezmoi reads all files and directories from the source directory (
~/.local/share/chezmoi).Parse attributes
For each entry, chezmoi parses the filename to extract attributes (prefixes and suffixes).
Execute templates
Files with
.tmpl suffix are executed as Go templates using data from the config file and built-in variables.Compute target state
Each source state entry computes its corresponding target state entry (what it should be in your home directory).
Compare states
chezmoi compares the target state with the actual state to determine what changes are needed.
Apply changes
chezmoi applies the minimal set of changes to make the actual state match the target state:
- Create missing files/directories
- Update modified files
- Remove extra files (in
exact_directories) - Execute scripts
- Update permissions
System abstraction
chezmoi abstracts all operating system interactions through aSystem interface. This enables powerful features:
System implementations
RealSystem
RealSystem
The actual underlying system that performs real file operations.
DryRunSystem
DryRunSystem
Wraps RealSystem for
--dry-run mode. Allows reads to pass through but silently discards all writes.DebugSystem
DebugSystem
Wraps RealSystem for
--debug mode. Logs all calls to the underlying system.This layered architecture is what makes features like
--dry-run and --debug possible without modifying the core logic.Persistent state
chezmoi maintains a persistent state to track what it has managed. This is stored as a two-level key-value store:Why persistent state?
Change detection
Detect if a third party has modified a file since chezmoi last wrote it.
Script execution
Track which
run_once_ and run_onchange_ scripts have been executed.EntryState storage
chezmoi stores the SHA256 hash of each entry’s contents in persistent state, rather than the full contents, to avoid storing secrets.
Path handling
chezmoi uses type-safe path handling to prevent errors:AbsPath: Absolute pathsRelPath: Relative pathsSourceRelPath: Relative path within the source directory with attribute handlingExtPath: External paths from user input (may include~for home directory)
Execution order
chezmoi performs actions in a deterministic order:Encryption support
Encryption tools are abstracted through anEncryption interface:
AGE encryption
Modern, simple file encryption with
age.GPG encryption
Traditional encryption with GnuPG.
.age or .asc) automatically stripped when determining the target name.
Interactive workflow diagram
Key takeaways
Declarative: You specify what you want, chezmoi figures out how to get there.
Idempotent: Running
chezmoi apply multiple times produces the same result.Safe: Dry-run mode, atomic operations, and persistent state tracking prevent accidents.
Flexible: Templates, attributes, and scripts provide powerful customization.