Skip to content

✨ feat: migrate dotfiles management from rsync bootstrap to chezmoi - #12

Merged
hadees merged 9 commits into
masterfrom
feat/chezmoi-migration
Jul 13, 2026
Merged

✨ feat: migrate dotfiles management from rsync bootstrap to chezmoi#12
hadees merged 9 commits into
masterfrom
feat/chezmoi-migration

Conversation

@hadees

@hadees hadees commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

Phase 1 of the cross-platform plan: the repo becomes a chezmoi source directory. Seven atomic commits — Brewfile addition, pure renames, scaffolding, machine-class templates, docs + bootstrap deprecation, test rework, CI wiring.

What changes

  • Deployed files renamed to chezmoi source naming (dot_zshrc, private_dot_extra.tmpl, bin/executable_has-glyphs, …); repo-level files keep their names and stay undeployed (dot-prefixed = invisible to chezmoi, the rest via .chezmoiignore).
  • A machine class chosen once at init (mac / linux / wsl / ephemeral) drives all gating. Deviation from the approved plan: personal-mac/work-mac collapsed into one mac class — both GitHub identities live on one Mac via includeIf, so the split bought nothing; a class can be added later if a work-only Mac appears.
  • ~/.gitconfig.local comes under management as a template: the mac branch renders byte-identical to the live file (verified); linux gets identity-only with a documented agent-forwarding signing recipe; wsl gets 1Password's official core.sshCommand=ssh.exe pattern. Note this puts name/email/github-user in a public repo — they're already in public commit metadata, but flagging it. ~/.gitconfig-ica (work) stays untracked.
  • ~/.extra switches from op inject to chezmoi's native onepasswordRead templating (mode 0600 via private_); the ephemeral class never deploys it.
  • The deployed global gitignore/gitattributes (referenced by .gitconfig's excludesfile/attributesfile) split from the repo's own copies; the global one no longer carries repo-specific entries.
  • macOS GUI config (iTerm plist, mackup) no longer lands on Linux targets.
  • bootstrap.sh is a deprecated wrapper; dotfiles alias becomes chezmoi apply.

Acceptance gate (from the plan): chezmoi apply --dry-run -v against the live $HOME shows exactly two diffs, both intended (new .extra template header; global gitignore losing repo-only entries). 52 managed targets, mapping audited.

Test plan

  • bats tests — 18/18 locally (full init+apply per machine class in isolated $HOMEs; create_ non-destruction; template render; dot_* parse/source checks)
  • chezmoi execute-template < dot_gitconfig.local.tmpl | diff - ~/.gitconfig.local — identical
  • chezmoi apply --dry-run -v — only the two intended diffs
  • CI green on ubuntu / macos / rocky / wsl
  • Post-merge: chezmoi apply on this Mac, open new shell, signed commit

🤖 Generated with Claude Code

hadees and others added 7 commits July 12, 2026 20:12
First step of the chezmoi migration: the dotfiles manager itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pure git mv, no content changes: leading dots become dot_ prefixes,
.extra.tmpl becomes private_dot_extra.tmpl (0600 target), and bin
scripts gain executable_ prefixes. Repo-level files (.gitignore,
.gitattributes, .github, .macos, tests/, Brewfile, bootstrap.sh) keep
their names — chezmoi ignores dot-prefixed source files natively, and
the rest gets a .chezmoiignore next. .claude/settings.local.json stays
machine-local and undeployed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
.chezmoi.toml.tmpl prompts once for a machine class (mac / linux / wsl /
ephemeral) that drives all per-machine gating, and points macs at the
development clone as the source dir. .chezmoiignore keeps repo-level
files out of $HOME, drops macOS GUI config from Linux targets, and
strips identity/secrets from ephemeral boxes. The deployed global
gitignore/gitattributes (referenced by .gitconfig's excludesfile /
attributesfile) split into dot_-prefixed copies so the repo's own
housekeeping files stay repo-only. bin/subl becomes a symlink_ source
file (chezmoi doesn't support raw symlinks in source state).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- dot_gitconfig.local.tmpl brings ~/.gitconfig.local under management:
  the mac branch renders byte-identical to the live file (verified with
  execute-template | diff); linux gets identity only with a documented
  agent-forwarding signing recipe; wsl adds 1Password's official
  core.sshCommand=ssh.exe pattern. Work identity (~/.gitconfig-ica)
  stays untracked.
- private_dot_extra.tmpl switches from op inject to chezmoi's native
  1Password templating (private_ = mode 0600).
- dot_claude/create_CLAUDE.local.md.tmpl replaces bootstrap's printf;
  create_ preserves the only-write-when-missing semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
README and CLAUDE.md now lead with the chezmoi one-liners (fresh
machine, --one-shot disposable box, development clone) and document the
machine-class system. bootstrap.sh becomes a thin deprecated wrapper
around `chezmoi init --source . --apply`; the dotfiles alias becomes
`chezmoi apply`. Secrets docs switch from op inject to chezmoi's
onepasswordRead. Also fixes the stray ßß in the README title.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
chezmoi.bats does a full init + apply into an isolated $HOME for each
machine class: ephemeral gets shell config and nothing sensitive, linux
gets identity without signing plus a 0600 .extra, wsl gets the ssh.exe
wiring, and create_ semantics are proven non-destructive on re-apply.
shell.bats follows the dot_* renames; extra-tmpl.bats now enforces
Go-template invariants and renders the template for real.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The per-class apply tests need the chezmoi binary. Hosted runners get
the official installer into ~/.local/bin (PATH via GITHUB_PATH); the
Rocky container and WSL distro install to /usr/local/bin as root, with
curl added to their package sets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hadees hadees self-assigned this Jul 13, 2026
hadees and others added 2 commits July 12, 2026 20:28
GitHub's ubuntu runners export XDG_CONFIG_HOME, which chezmoi prefers
over $HOME/.config — so the first test's machineClass=ephemeral config
persisted outside the per-test $TMPHOME and promptStringOnce silently
reused it, making the linux/wsl tests apply the ephemeral class (no
.gitconfig.local) on CI while passing locally and in WSL's clean env.
All chezmoi invocations now go through a helper that pins HOME and
every XDG dir into the test's temp home. Verified locally by running
the suite with a poisoned XDG_CONFIG_HOME.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rocky 9 images ship curl-minimal, which conflicts with the curl package
while already providing the curl binary the chezmoi installer needs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hadees
hadees merged commit e2e973b into master Jul 13, 2026
4 checks passed
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