craigtkhill avatar

chezmoi-dotfiles

Manage dotfiles using chezmoi. Use when creating, modifying, or deploying dotfiles, shell functions,

by craigtkhill|Open Source

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:

  1. 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 status
    

    Empty output → proceed. Any output → re-add every drifted file immediately (paths from chezmoi status are 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"; done
    

    The pre-commit hook blocks commits when home directory files differ from the chezmoi source. Never wait to be asked or reminded.

  2. Navigate to chezmoi source directory

    cd ~/.local/share/chezmoi
    
  3. 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/chezmoi or use chezmoi edit <target-path>
  4. Apply changes to home directory

    chezmoi apply
    # or for specific file:
    chezmoi apply ~/.config/fish/functions/myfile.fish
    
  5. Commit and push to GitHub

    cd ~/.local/share/chezmoi
    git add .
    git commit -m "your message"
    git push origin main
    
  6. Verify it's managed

    chezmoi managed | grep myfile
    

Common Commands

  • chezmoi status - Show what has changed
  • chezmoi diff - Show detailed differences
  • chezmoi managed - List all managed files
  • chezmoi apply - Apply changes from dotfiles to home directory
  • chezmoi apply --force - Force apply, overriding conflicts
  • chezmoi add <file> - Add a file to chezmoi tracking
  • chezmoi 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:

  1. Copy to ~/.config/fish/functions/
  2. Functions are immediately available (fish auto-loads them)
  3. 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:

  1. Check Homebrew version: brew info <tool> --json | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['versions']['stable'])"
  2. 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'])"
  3. If versions are equal → Brewfile
  4. If Cargo is newer → Cargofile
  5. 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-fixer rewrite files in the working tree on failure, silently re-creating drift against home. Always chezmoi apply && chezmoi status (must be empty) before retrying.

DON'T: Trust what's staged after a failed commit attempt

  • A prior git add -A can leave unrelated files staged, bundling them into your next, supposedly-separate commit. Run git diff --cached --stat and confirm only intended paths before committing.

DON'T: Write the commit message before your final check of what's staged

  • A hook or chezmoi apply running between staging and committing can change the staged diff, making an earlier-drafted message stale. Run git diff --cached --stat immediately before git commit and confirm it still matches the message — if not, stop and reconcile before committing.

DO: Edit in ~/.local/share/chezmoi → Apply → Commit → Push