Skip to main content
Questions about why chezmoi works the way it does, and the reasoning behind key design decisions.
No, you don’t have to! chezmoi edit is a convenience command with useful features, but there are multiple ways to edit your dotfiles.Option 1: Use chezmoi edit (recommended for most users)
chezmoi edit ~/.bashrc
chezmoi edit --apply ~/.bashrc  # Apply after editing
chezmoi edit --watch ~/.bashrc  # Auto-apply on save
Benefits:
  • Automatically handles encryption/decryption
  • Works with target paths (not source paths)
  • Syntax highlighting works correctly
  • Can auto-apply changes with --apply
  • Integrates with git auto-commit/push
Option 2: Edit in source directory
chezmoi cd  # Open shell in source directory
vim dot_bashrc  # Edit directly
chezmoi diff  # Preview changes
chezmoi apply  # Apply if happy
Option 3: Edit target, then re-add
vim ~/.bashrc  # Edit in place
chezmoi re-add  # Update source state
Option 4: Edit target, then merge
vim ~/.bashrc
chezmoi merge ~/.bashrc  # Resolve differences
Choose the workflow that fits your style!
chezmoi’s filename convention (like dot_bashrc, private_dot_ssh) is a deliberate design choice with important benefits.The criticism:
  • Filenames are verbose and unusual
  • Not all file permissions can be represented
  • Everything is in a single directory
The reasoning:
  1. Metadata in filenames is universal
    • Almost all programs store metadata in filenames (the extension)
    • chezmoi extends this to prefixes (attributes)
  2. Transparency and clarity
    • dot_ makes it obvious which files are managed
    • Files starting with . are ignored by chezmoi (for version control)
    • No special whitelists needed for .git, .gitignore, etc.
  3. Simplicity and atomicity
    • Each file’s metadata is stored with the file
    • Adding/removing a file touches only that file
    • Changing attributes is a simple rename
    • No need to parse/update a central config file
  4. Version control friendly
    • Changes to metadata are simple git operations
    • Easy to see what changed in git history
    • Comments and formatting are never lost
Supported permissions:chezmoi’s attributes support the most common permission combinations:
  • 0o644, 0o755, 0o600, 0o700, 0o444, 0o555, 0o400, 0o500
  • Directories: 0o755, 0o700, 0o500
In practice, these cover 99% of dotfile use cases.The directory issue:Yes, all root-level dotfiles appear in the source root. Mitigate this with .chezmoiroot:
echo "home" > ~/.local/share/chezmoi/.chezmoiroot
Now your dotfiles live in the home/ subdirectory, keeping the repo root clean.Backwards compatibility:chezmoi has many users, so the filename convention must remain stable. Any changes would need to:
  1. Be fully backwards-compatible
  2. Fix a genuine real-world problem
  3. Work across all operating systems
  4. Not add significant complexity
chezmoi deliberately uses a single source of truth - one branch in one git repo. This is an opinionated design choice to avoid complexity and ambiguity.Why single source?Multiple sources create problems:
  1. Ambiguous user interface:
    • chezmoi add ~/.bashrc - which source should this go to?
    • How does the user specify their preference?
  2. Overlapping targets:
    • What if two sources both want to set $EDITOR in .bashrc?
    • How do you handle mutually exclusive configs (vim vs emacs)?
  3. Dependencies between sources:
    • Should shell completions be with the app or the shell?
    • Hard to maintain clean separation
How chezmoi handles variation:Instead of multiple sources, use:
  • Templates for minor differences
  • .chezmoiignore to exclude files on certain machines
  • Password managers for secrets (not stored in repo)
  • Externals to pull in third-party dotfiles
If you really need multiple sources:Option 1: Multiple apply commands
chezmoi-apply() {
    chezmoi apply --config ~/.config/chezmoi-home/chezmoi.toml \
                  --source ~/.local/share/chezmoi-home && \
    chezmoi apply --config ~/.config/chezmoi-work/chezmoi.toml \
                  --source ~/.local/share/chezmoi-work
}
Option 2: Combine sources before applying
#!/bin/bash
combined_source="$(mktemp -d)"
trap 'rm -rf -- "${combined_source}"' INT TERM

for source in $HOME/.dotfiles/*; do
    cp -r "${source}"/* "${combined_source}"
done

chezmoi apply --source "${combined_source}"
Option 3: Nested chezmoi Use a run_ script to invoke a second chezmoi instance. See felipecrs/dotfiles for an example.
This is a technical limitation, not a design choice.The problem: A program cannot change the working directory of its parent process. When you run chezmoi cd, it’s running as a child process of your shell - it can only change its own directory, not your shell’s.The workaround:Create a shell function instead:
# Add to ~/.bashrc or ~/.zshrc
chezmoi-cd() {
    cd $(chezmoi source-path)
}
Or as an alias:
alias ccd='cd $(chezmoi source-path)'
Now typing chezmoi-cd or ccd changes your current shell’s directory.
The promptString, promptBool, and similar functions only work during chezmoi init because prompting during normal operations would be disruptive.The problem:chezmoi executes templates for many commands:
  • chezmoi apply
  • chezmoi diff
  • chezmoi status
  • Many others
If templates could prompt interactively, you’d have to answer questions every time you run any command. This would quickly become tiresome.The solution:Prompt once during initialization:
.chezmoi.toml.tmpl
{{- $email := promptString "email" -}}
{{- $work := promptBool "work machine" -}}

[data]
    email = {{ $email | quote }}
    work = {{ $work }}
Then use the values in other templates:
dot_gitconfig.tmpl
[user]
    email = {{ .email }}
Re-prompting:If you need to change answers:
chezmoi init  # Prompts again
You can use full system management tools for dotfiles, but chezmoi is purpose-built for this specific use case.chezmoi advantages:
  1. Simplicity:
    • Single binary, no dependencies
    • Small, focused feature set
    • Easy to learn (not a full configuration management system)
  2. Easy installation:
    • Copy one binary - done
    • No scripting runtime required
    • No packages to install
    • No system services needed
    • No root access required
  3. Runs everywhere:
    • ARM-based Linux systems
    • Windows desktops
    • Lightweight containers
    • FreeBSD VMs
    • Any platform with a binary available
  4. User focus:
    • Designed for personal configurations
    • No need to learn system administration concepts
    • Quick to get started
When to use system management tools:Use Ansible/Chef/Puppet/Salt when:
  • You need to manage system configuration (not just dotfiles)
  • You’re managing multiple users or servers
  • You need complex orchestration
  • You already know these tools
Hybrid approach:You can use both! Let chezmoi manage dotfiles, and call system management tools from scripts:
run_once_configure_system.sh
#!/bin/bash
# Let Ansible handle system configuration
ansible-playbook ~/.local/share/chezmoi/ansible/playbook.yml
Keep your Ansible playbooks in .chezmoiignore so they don’t pollute your home directory.
Technically yes, but this is strongly discouraged for anything beyond simple cases.chezmoi is designed for:
  • Managing personal dotfiles in your home directory
  • Running without root access
  • User-level configuration
chezmoi is NOT designed for:
  • System-wide configuration files
  • Managing /etc/
  • Multi-user setups
Simple cases that work:Use a run_ script to handle a few files:
run_after_copy_system_file.sh
#!/bin/bash
# Copy a file to /etc (requires sudo)
sudo cp ~/.local/etc/hosts /etc/hosts
Or create a symlink:
run_after_link_system_file.sh
#!/bin/bash
sudo ln -sf ~/config/app.conf /etc/app/app.conf
For anything more complex:Use proper system configuration management tools:These tools are designed for system-wide configuration and handle:
  • Package management
  • Service configuration
  • Multi-user setups
  • Privilege escalation
  • System state management
You can call these from chezmoi scripts, keeping your system configs in .chezmoiignore.
chezmoi was inspired by Puppet, a powerful system configuration management tool.Why not just use Puppet?Puppet is excellent for its intended use case (system administration), but it’s overkill for personal dotfiles:
  • Requires Ruby and many dependencies
  • Needs system services running
  • Requires root access to install
  • Has a steep learning curve
  • Designed for managing servers, not personal configs
What chezmoi borrowed from Puppet:
  • The concept of desired state vs. current state
  • Idempotent operations
  • Declarative configuration
  • Dry-run mode (diff before apply)
What chezmoi does differently:
  • Single binary with no dependencies
  • User-focused (no root required)
  • Simplified feature set
  • Cross-platform support
  • Designed specifically for dotfiles
The future:chezmoi will always focus on personal dotfile management. If your needs grow beyond that (managing multiple machines, system configuration, etc.), switch to a full system configuration management tool like Puppet, Ansible, Chef, or Salt.

Build docs developers (and LLMs) love