Skip to content

fix(chezmoi): seed data.xdg at init so first apply works on fresh hosts#14

Merged
chagui merged 1 commit into
mainfrom
chagui/chezmoi/bootstrap-config
Apr 22, 2026
Merged

fix(chezmoi): seed data.xdg at init so first apply works on fresh hosts#14
chagui merged 1 commit into
mainfrom
chagui/chezmoi/bootstrap-config

Conversation

@chagui
Copy link
Copy Markdown
Owner

@chagui chagui commented Apr 22, 2026

Summary

Adds a source-root .chezmoi.toml.tmpl that seeds data.xdg.{cache,config,data,state} at chezmoi init time, before the first apply runs. This unblocks templates that reference .xdg.* on a fresh host.

Why

dot_config/chezmoi/private_chezmoi.toml.tmpl already defines [data.xdg], but it's a managed file — it only exists after the first apply. Templates that depend on .xdg.* (currently dot_config/wget/wgetrc.tmpl:1, via {{ .xdg.cache }}) fail on a brand-new machine because the data key isn't populated yet. Classic bootstrap ordering problem: the config that produces the data is itself produced by the thing that needs the data.

Chezmoi resolves this via the source-root .chezmoi.toml.tmpl, which it renders to ~/.config/chezmoi/chezmoi.toml during init — before any apply.

Design notes

The init template is narrow by design: it only seeds [data.xdg]. [diff] and [merge] stay in the managed private_chezmoi.toml.tmpl, which overwrites the init output on the first apply. Rationale: keep the init template limited to what init must provide; let the managed file own everything else so there's a single source of truth post-bootstrap.

For cross-platform behavior, env "XDG_*" | default (joinPath .chezmoi.homeDir ...) respects XDG_* when exported (Linux, or macOS users who set them), otherwise falls back to XDG-spec defaults under \$HOME. This differs from the managed template, which assumes XDG_* is set; the init template can't assume that on a fresh host.

One divergence risk worth calling out: the two templates now both define [data.xdg] with slightly different logic (init has fallbacks, managed does not). If XDG_* is unset at apply time, the managed file will write empty strings and break .xdg.* consumers. Worth a follow-up to unify them — either by giving the managed template the same fallback, or by sourcing XDG_* defaults earlier in the shell env.

dot_config/chezmoi/private_chezmoi.toml.tmpl is a managed file, not an init
template — on a clean host, it can't populate its own config before apply, so
any template that reads .xdg.* (e.g. wgetrc.tmpl) fails with "map has no entry
for key \"xdg\"". Adding a source-root .chezmoi.toml.tmpl makes chezmoi init
render the config before the first apply. Values fall back to XDG-spec defaults
under $HOME when env vars are unset, so it works on macOS and Linux alike.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chagui chagui merged commit 9f8549f into main Apr 22, 2026
1 check passed
@chagui chagui deleted the chagui/chezmoi/bootstrap-config branch April 22, 2026 20:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant