A practical recipe for keeping the authored parts of your AI tools (instructions, skills, agents, commands, prompts, settings) in git while leaving the runtime junk (chat history, project caches, transcripts, telemetry, plugins) out of it.
This guide is written for both humans and agents handed the job "set up dotfile management for my AI tools." Follow it top-to-bottom on a fresh machine, or jump to Adding a new AI tool if chezmoi is already initialized.
Every AI tool colonizes ~/.<tool>/ and writes a mix of:
| Category | Examples | Action |
|---|---|---|
| Authored | CLAUDE.md, settings.json, skills, agents, commands, MCP configs |
track |
| Runtime state | chat history, project transcripts, session logs, telemetry, statsig caches | ignore |
| Reinstallable | plugins, downloaded skills from registries, vendored binaries | ignore |
| Machine-specific | API keys, absolute paths, hostnames | template or encrypt |
A bare git repo in $HOME works but forces you to maintain .gitignore carefully and shares the same secrets across every machine. chezmoi gives you (a) a dedicated source dir so $HOME stays clean, (b) .chezmoiignore evaluated against target paths, (c) Go templates for per-machine values, and (d) age/gpg encryption for secrets — all without leaving git.
# 1. Create an empty private repo somewhere (GitHub, GitLab, self-hosted)
gh repo create <you>/dotfiles --private
# 2. Install chezmoi and clone the repo into the chezmoi source dir
brew install chezmoi # macOS
# sh -c "$(curl -fsLS get.chezmoi.io)" # Linux
chezmoi init https://github.com/<you>/dotfiles.git # clones into ~/.local/share/chezmoi
# 3. Verify
chezmoi cd # drops you into the source dir
chezmoi managed # lists target paths chezmoi will manage (empty on first run)chezmoi init clones the repo and does nothing else. Use chezmoi init --apply <url> only when you trust the repo's contents not to clobber $HOME — on a fresh repo this is fine, on a populated one it's not.
Workflow is the same for every tool:
# 1. Add the authored paths (chezmoi copies them into the source dir with `dot_` prefix)
chezmoi add ~/.<tool>/<file-or-dir> [~/.<tool>/<more>...]
# 2. Add ignore patterns BEFORE re-running `chezmoi add` on a parent dir
$EDITOR ~/.local/share/chezmoi/.chezmoiignore
# 3. Verify
chezmoi managed | grep .<tool> # should list only what you want tracked
chezmoi diff # empty = source matches $HOME
# 4. Commit + push
chezmoi cd
git add . && git commit -m "Track ~/.<tool>" && git pushOrder matters: add ignore patterns before doing chezmoi add ~/.<tool> on a parent directory — chezmoi evaluates .chezmoiignore against target paths at add time. If you accidentally added runtime junk, remove it from the source dir with rm (not chezmoi forget, which only works on currently-managed paths).
What to track vs ignore for the common AI tools as of 2026. Paths assumed under ~/; adjust if a tool is XDG-relocated.
| Track | Ignore |
|---|---|
CLAUDE.md |
projects/, jobs/, todos/, statsig/ |
settings.json |
shell-snapshots/, transcripts/, ide/ |
agents/, hooks/, commands/ |
plugins/ (reinstall via plugin marketplace) |
skills/<authored>/ |
skills/<symlinked-from-outside> |
keybindings.json |
mcp_logs/, run_history, scheduled_tasks.json |
| Track | Ignore |
|---|---|
config.toml, AGENTS.md |
history/, sessions/, cache/ |
skills/, prompts/ |
logs/ |
mcp_servers.json |
*.log, telemetry |
| Track | Ignore |
|---|---|
.aider.conf.yml |
.aider.chat.history.md |
.aider.model.metadata.json (if customized) |
.aider.input.history |
.aider.d/<prompts>/ |
.aider.tags.cache.v3/ |
Same pattern. Look under ~/.<tool>/ for:
config.{json,yaml,toml}→ trackprompts/,rules/,agents/,commands/→ trackhistory/,sessions/,cache/,logs/,telemetry/,index*→ ignore
If in doubt: read once, edit once, then re-check ls -la ~/.<tool>/ — anything that grew without you touching it is runtime state.
# repo meta (lives in the source dir but doesn't belong in $HOME)
README.md
LICENSE
# ----- Claude Code runtime -----
.claude/projects
.claude/jobs
.claude/todos
.claude/statsig
.claude/shell-snapshots
.claude/transcripts
.claude/plugins
.claude/ide
.claude/mcp_logs
.claude/run_history
.claude/scheduled_tasks.json
.claude/skills/*/.aider*
# symlinks pointing outside ~/.claude (target won't exist elsewhere)
.claude/skills/find-skills
# ----- Codex runtime -----
.codex/history
.codex/sessions
.codex/cache
.codex/logs
.codex/*.log
# ----- Aider runtime -----
.aider.chat.history.md
.aider.input.history
.aider.tags.cache.v3
.aider.llm.history
# ----- Generic AI runtime patterns -----
**/cache
**/sessions
**/transcripts
**/telemetry
**/*.logOn every machine after the first:
brew install chezmoi
chezmoi init --apply https://github.com/<you>/dotfiles.git # one command, restores all tracked AI configAfter making edits on machine A:
chezmoi cd && git add . && git commit -m "<change>" && git pushOn machine B:
chezmoi update # pulls the repo and applies the diff to $HOMEchezmoi update = git pull + chezmoi apply. Run it after each remote change. If you've edited a managed file directly in $HOME without going through chezmoi, chezmoi diff will show the drift — re-sync with chezmoi re-add (source ← home) or chezmoi apply (source → home).
Use templates for values that differ per machine (e.g. an API endpoint, a path to a personal vault):
chezmoi add --template ~/.codex/config.toml
$EDITOR $(chezmoi source-path ~/.codex/config.toml)Inside the template, reference {{ .chezmoi.hostname }}, {{ .chezmoi.os }}, {{ .email }}, or custom data from chezmoi edit-config.
For secrets (API keys), use chezmoi encrypt (age-backed by default) and reference the encrypted file from a template — never commit a plaintext key.
- Symlinks pointing outside
~/.<tool>/— chezmoi by default tracks the symlink target. If the target lives in some other dir that isn't on the target machine, the symlink will dangle. Add it to.chezmoiignoreorchezmoi add --followto copy the target content instead. - Plugin / extension directories — these are usually reinstallable from a manifest. Track the manifest (
plugins.json,extensions.json), ignore the unpacked dir. - Top-level files in the source dir become
~/<name>files —README.mdin the source dir would land at~/README.mdon apply unless added to.chezmoiignore. chezmoi addre-runs are not idempotent for changed files — if you edit~/.claude/CLAUDE.md, re-runchezmoi add(orchezmoi re-add) to pull the change into the source dir.chezmoi difftells you when they've drifted.
brew install chezmoi
chezmoi init https://github.com/<you>/dotfiles.git
# Edit ~/.local/share/chezmoi/.chezmoiignore with the patterns above
chezmoi add ~/.claude/CLAUDE.md ~/.claude/skills/<authored-dirs>
chezmoi add ~/.codex/config.toml ~/.codex/skills
# ...repeat per tool
chezmoi managed # sanity check: only authored paths
chezmoi diff # sanity check: empty
chezmoi cd && git add . && git commit -m "Initial AI dotfiles" && git pushThat's the whole loop. Adding the next AI tool is chezmoi add + update .chezmoiignore + commit.