
chezmoi-dotfiles
Manage dotfiles using chezmoi. Use when creating, modifying, or deploying dotfiles, shell functions,
Chezmoi Dotfiles Management
This skill helps manage dotfiles using chezmoi in this repository.
Repository Location
All dotfiles are managed in ~/.local/share/chezmoi which is a git repository synced to GitHub at https://github.com/craigtkhill/dotfiles.git.
Critical Workflow
When creating or modifying dotfiles, you MUST follow this exact order:
-
Check for drift before every new task — no exceptions
Run this before starting any new task in this repo, not just once per session — other processes (e.g. Obsidian) edit tracked files live and can create drift mid-session:
chezmoi statusEmpty output → proceed. Any output → re-add every drifted file immediately (paths from
chezmoi statusare home-relative), regardless of whether it's related to the current task:chezmoi status | awk '{print $2}' | while read -r f; do chezmoi re-add ~/"$f"; doneThe pre-commit hook blocks commits when home directory files differ from the chezmoi source. Never wait to be asked or reminded.
-
Navigate to chezmoi source directory
cd ~/.local/share/chezmoi -
Create or edit files using chezmoi naming conventions
- Use
dot_prefix for dotfiles (e.g.,dot_gitconfig→~/.gitconfig) - Preserve directory structure (e.g.,
dot_config/fish/functions/→~/.config/fish/functions/) - You can edit directly in
~/.local/share/chezmoior usechezmoi edit <target-path>
- Use
-
Apply changes to home directory
chezmoi apply # or for specific file: chezmoi apply ~/.config/fish/functions/myfile.fish -
Commit and push to GitHub
cd ~/.local/share/chezmoi git add . git commit -m "your message" git push origin main -
Verify it's managed
chezmoi managed | grep myfile
Common Commands
chezmoi status- Show what has changedchezmoi diff- Show detailed differenceschezmoi managed- List all managed fileschezmoi apply- Apply changes from dotfiles to home directorychezmoi apply --force- Force apply, overriding conflictschezmoi add <file>- Add a file to chezmoi trackingchezmoi re-add <file>- Re-add a tracked file
Fish Shell Specifics
Fish automatically loads functions from ~/.config/fish/functions/. Each function must be in its own file named functionname.fish.
After adding new fish functions:
- Copy to
~/.config/fish/functions/ - Functions are immediately available (fish auto-loads them)
- No need to source or reload
Adding Existing Files to Chezmoi
If you want to add an existing file from your home directory to chezmoi:
chezmoi add ~/.config/fish/functions/myfile.fish
This will copy the file to ~/.local/share/chezmoi with proper naming and make it managed.
Package Manager Policy
Tools are split across two files:
- Brewfile — preferred for macOS. Use when Homebrew version is equal to or newer than Cargo.
- Cargofile — use only when Cargo has a newer version than Homebrew, or when there is no Homebrew equivalent (e.g.
cargo-update).
When adding a new CLI tool:
- Check Homebrew version:
brew info <tool> --json | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['versions']['stable'])" - Check Cargo version:
curl -s https://crates.io/api/v1/crates/<tool> | python3 -c "import sys,json; print(json.load(sys.stdin)['crate']['newest_version'])" - If versions are equal → Brewfile
- If Cargo is newer → Cargofile
- If no Homebrew equivalent → Cargofile
Common Mistakes
❌ DON'T: Edit files directly in ~/.config/fish/ without updating chezmoi
- Changes will be lost when chezmoi applies source files
❌ DON'T: Forget to commit and push changes to GitHub
- Your dotfiles won't be backed up or available on other machines
❌ DON'T: Retry git commit immediately after a hook failure without re-running chezmoi apply
- Hooks like
end-of-file-fixerrewrite files in the working tree on failure, silently re-creating drift against home. Alwayschezmoi apply && chezmoi status(must be empty) before retrying.
❌ DON'T: Trust what's staged after a failed commit attempt
- A prior
git add -Acan leave unrelated files staged, bundling them into your next, supposedly-separate commit. Rungit diff --cached --statand confirm only intended paths before committing.
❌ DON'T: Write the commit message before your final check of what's staged
- A hook or
chezmoi applyrunning between staging and committing can change the staged diff, making an earlier-drafted message stale. Rungit diff --cached --statimmediately beforegit commitand confirm it still matches the message — if not, stop and reconcile before committing.
✅ DO: Edit in ~/.local/share/chezmoi → Apply → Commit → Push