Architecture
This setup is a chezmoi source directory. chezmoi renders templates and copies files into your $HOME.
Repository Layoutโ
home/is the source-of-truth for files that end up in your home directory.home/.chezmoiscripts/contains automation hooks that run during apply.home/.chezmoi.toml.tmpldefines interactive prompts and computed values.home/.chezmoiexternal.tomlpulls a few external assets (git repos/archives).
Documentation Hygieneโ
This repo treats docs/ as part of the configuration:
- If you change dotfiles behavior (anything under
home/that affects commands or workflows), updatedocs/in the same change. - If a change truly has no user-facing impact, record that in the PR/commit context so the docs/code divergence is explicit.
Repo-Only Assets (Not Installed Into $HOME)โ
Some directories in home/ are intentionally ignored by chezmoi and are used as "repo-local data" for scripts.
Ignore rules live in:
Examples in this setup:
home/app_icons/is used by the,apply-app-iconsscript, but it is not installed into$HOME.
Chezmoi Naming Conventions (How Source Maps To Installed Files)โ
Chezmoi uses filename conventions to decide where things land.
Common patterns in this setup:
- Paths under
home/dot_config/map to~/.config/... home/exact_lib/...->~/lib/...for deployed command internalshome/dot_*maps to~/.<name>(for example:home/dot_zsh/->~/.zsh/)- Paths under
home/private_dot_ssh/map to~/.ssh/...(and are treated as private by chezmoi) executable_foo-> installs as an executable file namedfooreadonly_foo-> installs asfoowith0444permissions (read-only); used for config files that should not be modified by external tools at runtimeexact_prefix in a directory name means "exact directory" (chezmoi does not merge it with existing contents)
This is why you may see paths like:
home/dot_config/exact_nvim/exact_lua/in the repo- but
~/.config/nvim/lua/on disk
The Data Flowโ
This setup is intentionally declarative:
- You answer prompts in
home/.chezmoi.toml.tmpl. - Templates in
home/render differently depending on those values. - Hooks in
home/.chezmoiscripts/install / update tools based on the rendered config. - Re-running
chezmoi applyconverges you back to the intended state.
Dynamic AI Context Mergingโ
Because AI tools (like OpenCode and Pi) often rewrite their config files during runtime, rendering templates directly into those files causes conflicts. Instead, this architecture uses Source-Based Merging:
- MCP server definitions share a single canonical registry at
home/.chezmoidata/mcp_servers.yaml. - During
chezmoi apply, the unified scriptrun_onchange_after_07-generate-mcp-configs.sh.tmplcallsscripts/generate_mcp_configs.pyonce and writes the result to Claude Code, Pi, and any other tool that consumes the standardmcpServersJSON shape. - Tools with different MCP schemas (OpenCode, Codex) still derive from the same registry via small inject scripts in
scripts/that transform the canonical registry into the tool-specific config shape.
Models are set directly in each harness config. For the full picture see MCP servers and Tool configs.
Shared Library (scripts/chezmoi_lib.sh)โ
All run_onchange_after_07-merge-* scripts source a shared shell library at scripts/chezmoi_lib.sh for common operations:
| Function | Purpose |
|---|---|
chezmoi_write_if_changed | Atomic string write, skip if content unchanged |
chezmoi_install_if_changed | File copy via install(1), skip if content unchanged |
chezmoi_record_checksum | Record one literal target and sha256 in the manifest |
chezmoi_record_artifact | Record one ownership-aware generated AI artifact |
Two independent runtime ledgers serve different questions:
~/.local/state/chezmoi/managed_configs.tsvis the generic literal whole-file checksum manifest.scripts/managed_config_manifest.pycollapses exact duplicate rows and powers the,doctorConfig Drift section, which joins each row with the artifact ledger below: rows with no artifact and no remaining producer in source retire silently, while artifact-covered rows compare ownership-projected state so app-owned churn stays silent.~/.local/state/chezmoi/generated_artifacts.v1.jsonis the AI-specific effective-state ledger.scripts/generated_artifact_ledger.pyrecords source/transform hashes, ownership projection, target, consumer, and local probe metadata.,doctor aiand the Config Drift section read it, so runtime-owned Codex fields do not create false drift.
Both ledgers are atomic and mode 0600. The AI ledger stores paths and hashes only, never generated config contents or resolved secret values.
To add a new AI tool config, create its source file and a merge script that sources the library โ typically 5โ10 lines of tool-specific logic.
Hooks (Automation)โ
The most important concept for understanding "what happens" is the hook naming:
run_once_before_*runs once before apply work.run_once_after_*runs once after apply work.run_onchange_after_*runs after apply when the tracked inputs change.
Examples in this repo:
| Hook | Purpose |
|---|---|
home/.chezmoiscripts/run_once_before_00-install-xcode.sh | Xcode CLT |
home/.chezmoiscripts/run_once_after_01-install-brew.sh | Homebrew install |
home/.chezmoiscripts/run_once_after_02-install-fish.sh | Fish install |
home/.chezmoiscripts/run_onchange_after_03-install-brew-packages.fish.tmpl | Brew bundle |
home/.chezmoiscripts/run_onchange_after_05-install-mise-runtimes.sh.tmpl | mise runtimes + shims |
home/.chezmoiscripts/run_onchange_after_05-install-uv-versions.sh.tmpl | UV Python versions |
Many hooks embed sha256sum comments that reference template content. The AI/config 07 hooks include every directly or transitively executed local transform, so changing a shared parser, reconciler, or shell helper schedules the affected projection again.
The Reference map lists every hook and helper script and the file each one drives.
External Assetsโ
home/.chezmoiexternal.toml is used for things you want updated regularly but don't want to vendor into your dotfiles repo.
Current externals:
| External | Purpose |
|---|---|
tpm | tmux plugin manager |
EmmyLua.spoon | Hammerspoon Lua annotations |
lowfi data files | Background music tracklists |
bat themes | Syntax highlighting themes |