Dotfiles vs Maint¶
Two top-level modules cover everything-about-these-dotfiles:
dotfiles::— what you do to use these dotfilesmaint::— what you do to edit these dotfiles
The split is by subject, not audience. Both modules belong to the same person on a personal dotfiles repo, but they operate on different things — installed state vs repo source.
dotfiles:: — installed state¶
Operations on what's deployed at ~/. Anyone with these dotfiles installed runs them.
| Recipe | When |
|---|---|
just dotfiles update |
Pull new dotfiles + upgrade chezmoi binary. Routine — weekly or after upstream changes. |
just dotfiles apply |
Re-render templates and write changes. Reach for it after editing a managed file via |
chezmoi edit |
|
just dotfiles dry-run |
Preview what apply would change. Safe inspection. |
just dotfiles check-updates |
Compare pinned external plugin tags against latest GitHub releases. Read-only |
| — doesn't change anything. | |
just dotfiles verify |
Health check: binaries on PATH, Brewfile satisfied, shell config present, git hook |
| layer wired. Run after anything that might leave the install in a weird state. |
The top-level just update orchestrator chains these:
That's the routine refresh — every recipe in the chain is a positive lifecycle operation. Nothing destructive.
maint:: — repo source¶
Operations on the dotfiles repo as a thing being edited. You only reach for these when you're changing the framework — adding a recipe, fixing a script, building docs, regenerating the contract spec.
maint::
test:: functional test suites
bats:: shell-script tests (deployed bin/, hook scripts)
contract:: pytest-just contract tests (recipe API)
smoke:: docker-based bootstrap smoke tests
spec:: generates the contract spec.yaml
qa:: quality assurance
hooks:: pre-commit framework infra (install / repair envs)
shellcheck:: rendered template + script linting
docs:: zensical docs site (sync / serve / build / clean)
check health + lint + functional tests (no smoke)
purge destructive teardown — wipes the chezmoi install
The maint::check orchestrator runs everything you'd want before a commit: dotfiles-verify.sh + shellcheck + bats +
contract tests. Smoke tests are excluded — they spin up Docker containers and take minutes; run them deliberately when
you've changed init-flow code.
Where does a new recipe belong?¶
Apply this test:
Does this recipe make sense for someone who has these dotfiles installed but no intent to edit them?
- Yes →
dotfiles::. Routine, positive, operates on installed state. - No →
maint::. Repo-editing work, framework-level operations, testing the source.
Examples worked through:
chezmoi diffwrapper that highlights only managed-file changes — yes, anyone with the install might want to inspect drift. Belongs indotfiles::.- Test runner for a new shellcheck rule set — no, only relevant when editing the repo's scripts. Belongs in
maint::qa::shellcheck(extension). purge— destroys the install. Looks like adotfiles::operation by virtue of touching installed state, but the audience is "someone testing a fresh-install flow" — a maintainer scenario. Lives inmaint::purge.
Why this split, not one combined module?¶
For a personal dotfiles repo (one person), both modules serve the same human. The split has aesthetic cost (one more
top-level entry in just --list) but pays back in:
- Daily
just --listclarity — user-facing recipes aren't buried among test runners and lint tools. - Conceptual map — a contributor (or future-you) can see at a glance what each module is for without reading every recipe.
- Avoids awkward readings —
just maint updatefor the routine dotfiles refresh would parse as "maintenance: update," which misnames a positive lifecycle operation.
The cost is small; the wins are real but small too. The split earns its keep without being load-bearing.