UNPKG

@sebastienrousseau/dotfiles

Version:

The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.

281 lines (226 loc) 13.7 kB
--- title: "RFC: v0.2.503 Repository Reorganisation" status: Accepted — shipping incrementally in this PR authors: ['@sebastienrousseau'] opened: 2026-05-17 accepted: 2026-05-17 target: v0.2.503 --- # RFC: v0.2.503 Repository Reorganisation > **Status: Accepted.** This RFC was opened in this PR and > immediately accepted by the maintainer with explicit decision to > ship the reorganisation incrementally within v0.2.503 rather > than the originally-proposed two-version deprecation window. > Phases land as separate commits on `feat/v0.2.503`; each is > independently atomic and verified by `dot lint` + the existing > test matrix. ## Summary Split the current chezmoi-managed monorepo into a **framework layer** (distributable CLI + library) and a **defaults layer** (user-facing configuration), with the framework layer publishable as a standalone tarball to Homebrew, Scoop, and AUR. Maintain backwards-compatible behaviour for existing users via a one-shot migration script that runs on first apply after upgrade. ## Motivation R4 hard-audit identified the framework/user-config intermingling as the **highest-leverage structural gap** blocking de-facto- framework status (`HARD_AUDIT_2026.md` §8.5 Top-5 adoption gaps). Concrete symptoms: 1. **Distribution stuck at "curl-pipe-bash".** The Homebrew / Scoop / AUR manifests scaffolded in v0.2.503 (`install/{homebrew,scoop,aur}/`) cannot publish until there's a single `bin/dot` tarball — chezmoi's `dot_*` / `executable_*` / `private_*` prefixes force the current layout. Until that's fixed, downstream distros have nothing to package. 2. **New contributor onboarding cost.** Even with the v0.2.503 `STRUCTURE.md`, ~20 chezmoi-prefixed root paths require a concept (the chezmoi naming contract) to navigate. A `bin/` + `lib/` + `defaults/` layout is self-documenting. 3. **Framework forks are blocked.** Anyone wanting to fork the *CLI* without the maintainer's personal configs has to manually delete 80+ tool-specific directories under `dot_config/`. A clean separation makes "fork the framework, apply my own defaults" a one-command flow. 4. **Test surface bleed.** CI runs `chezmoi apply --dry-run` on every PR, exercising both framework templates AND the maintainer's personal defaults. A real consumer running the framework will not exercise the maintainer's `dot_config/aider/` etc. — and yet a regression there blocks CI. The reorganisation is **breaking** for existing user installs: chezmoi tracks deployed files by source path, so moving `bin/dot` to `bin/dot` means the old `~/.local/bin/dot` would be removed before the new path is installed. Mitigation: ship a `migrate-v0.2-to-v0.3.sh` script that runs before the first post-upgrade `chezmoi apply`. ## Detailed design ### Target layout Following the [Debian/aws-cli](https://github.com/Debian/aws-cli) discipline (every top-level path has a clear purpose; contributor orients in <30 seconds): ``` . ├── bin/ # CLI entrypoints │ ├── dot # was bin/dot │ ├── dot-load-benchmark-pty # was bin/dot-load-benchmark-pty │ ├── dot-theme-sync # was bin/dot-theme-sync │ ├── dot-bootstrap # was bin/dot-bootstrap │ └── dot-update # was dot_local/bin/executable_update (renamed) ├── lib/ # Framework library (no chezmoi) │ ├── commands/ # was scripts/dot/commands/ │ ├── ui.sh # was scripts/dot/lib/ui.sh │ ├── utils.sh # was scripts/dot/lib/utils.sh │ ├── platform.sh # was scripts/dot/lib/platform.sh │ ├── log.sh # was scripts/dot/lib/log.sh │ ├── bento.sh # was scripts/dot/lib/bento.sh │ └── secrets_provider.sh # was scripts/lib/secrets_provider.sh ├── share/ # OS-conventional resources │ ├── man/man1/dot.1 # was dot_local/share/man/man1/dot.1 │ ├── completions/ # was dot_local/share/zsh/completions/ │ └── docs/ # was docs/ ├── defaults/ # User-facing default config (was dot_config/, etc.) │ ├── home/ # dotfiles deployed to $HOME (dot_X → .X) │ ├── config/ # dotfiles deployed to $XDG_CONFIG_HOME │ └── tools/ # per-tool configs (mise/, npmrc/, ...) ├── install/ # Distribution + bootstrap │ ├── install.sh # was install.sh (moved one level down) │ ├── homebrew/dot.rb # already at install/homebrew/ in v0.2.503 │ ├── scoop/dot.json # already at install/scoop/ in v0.2.503 │ ├── aur/PKGBUILD # already at install/aur/ in v0.2.503 │ ├── provision/ # was install/provision/ (chezmoi run_onchange_ hooks) │ └── migrate/ # NEW: migrate-v0_2-to-v0_3.sh + rollback ├── tests/ # unchanged ├── examples/ # unchanged ├── tools/ # NEW: ops scripts not shipped to users │ ├── ci/ # was tools/ci/ │ ├── release/ # was tools/release/ │ ├── maintenance/ # was tools/maintenance/ │ ├── docs/ # was tools/docs/ │ └── version-sync.sh # was scripts/version-sync.sh ├── .chezmoiroot # NEW: points at defaults/ ├── README.md ├── LICENSE ├── CHANGELOG.md ├── CLAUDE.md / AGENTS.md / per-harness renders └── (no more dot_X at root) ``` ### chezmoi adaptation `.chezmoiroot` lets chezmoi treat a subdirectory as the source root. With `.chezmoiroot = "defaults"`, chezmoi will look for `defaults/home/dot_zshrc`, `defaults/config/dot_starship.toml`, etc. — and deploy to the normal `~/.zshrc` / `~/.config/starship.toml` paths. This means: - Repo top-level is no longer required to follow chezmoi naming. - `bin/dot` is a plain shell script, not `dot_local/bin/executable_dot`. - `share/man/man1/dot.1` is a plain file, not chezmoi-deployed. - A Homebrew formula can `bin.install 'bin/dot'` directly. ### Migration tool `install/migrate/migrate-v0.2-to-v0.3.sh`: 1. Detect existing chezmoi state at `~/.local/share/chezmoi` / `~/.config/chezmoi/chezmoi.toml`. 2. Read the user's pinned source repo from chezmoi.toml; if it's `sebastienrousseau/dotfiles@<v0.2.x>`, warn and confirm. 3. Run `chezmoi diff` and persist the per-file output to `~/.local/state/dotfiles/v0_2_to_v0_3_pre_diff.log` so the user has a record of pre-migration state. 4. Run `chezmoi forget` for paths that are moving (no destructive delete — chezmoi forget only un-tracks). 5. Update `~/.config/chezmoi/chezmoi.toml` to point at the new sourceDir with `.chezmoiroot` honoured. 6. Run `chezmoi apply` — picks up the new layout and re-creates the user's files at their canonical paths. 7. Run `dot doctor` and `dot lint` to verify. The migration is **idempotent** and **safe to abort**: at step 4 the chezmoi state is removed but no user data is deleted. At step 6 chezmoi notices "these files already exist on disk with content matching the source" and is a no-op. ### Library bash-source paths Today `scripts/dot/commands/<cmd>.sh` does: ```bash SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../lib/utils.sh" ``` After reorganisation: ```bash SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../utils.sh" # commands/<cmd>.sh → lib/utils.sh ``` Or, more robustly, drive lookup from a single env var set by `bin/dot`: ```bash : "${DOT_LIB:=$(dirname "$(realpath "$0")")/../lib}" source "$DOT_LIB/utils.sh" ``` The Homebrew formula sets `$DOT_LIB` to `${libexec}/lib` so `bin/dot` finds its library wherever the package manager installed it. ### Distribution surface Once `bin/dot` is standalone: | Channel | Artefact | Verify command | |---------|----------|----------------| | Homebrew tap | `dot-${VERSION}-${OS}-${ARCH}.tar.gz` | `brew install sebastienrousseau/tap/dot && dot version` | | Scoop bucket | `dot.json``dot-${VERSION}-windows-${ARCH}.zip` | `scoop install dot && dot version` | | AUR | `dotfiles-git` PKGBUILD building from source | `paru -S dotfiles-git && dot version` | | `install.sh` | Same SHA256-verified path as today | `bash install.sh` | | Direct tarball | Cosign-signed + SLSA-attested release asset | per `docs/security/VERIFY_RELEASE.md` | The chezmoi-managed `defaults/` subtree is **only** consumed when a user wants the maintainer's opinionated config layer. It's a strict superset: install `dot` standalone for the CLI; layer `defaults/` on top if you want the wallpaper-theming + multi-shell setup. ## Backwards compatibility | Surface | v0.2.x behaviour | v0.2.503 behaviour | Breaking? | |---------|------------------|------------------|-----------| | `~/.local/bin/dot` | Deployed by chezmoi | Replaced by Homebrew/Scoop install, OR symlinked by chezmoi from the new source | Yes — path may move; migration script handles it | | `~/.zshrc` etc | Source-pinned at `dot_zshrc` | Source-pinned at `defaults/home/dot_zshrc`, chezmoi reads via `.chezmoiroot` | No — destination path unchanged | | `dot <cmd>` API | All subcommands work as documented | Same | No | | `scripts/dot/commands/*.sh` consumers | Direct source paths used in user customisations | Path moves to `lib/commands/*.sh` | Yes — affects any user who source'd these directly | | `.chezmoidata.toml` | Repo root | Repo root (unchanged for compatibility with old user `chezmoi init` flows) | No | ### Two-version deprecation window v0.2.503 ships with the migration script and a deprecation warning in `dot doctor`. v0.4.0 removes any v0.2.x shim code. Users who skip v0.2.503 entirely (v0.2.x → v0.4.0) hit a hard error and must run the migration tool from a v0.3.x release manually. ## Alternatives considered ### A) Keep the chezmoi monorepo as-is **Pros**: zero migration cost; works today. **Rejected**: blocks Homebrew/Scoop/AUR publication permanently. The Top-5 adoption gap remains. R4 audit's "9.0/10 internal · 7.5/10 adoption" plateau persists. ### B) Two-repo split (framework + defaults) Publish `dot` framework at `sebastienrousseau/dot` and the maintainer's personal defaults at `sebastienrousseau/dotfiles`. **Pros**: cleanest possible separation. Framework forks trivial. **Rejected (for v0.3)**: requires a second repo, doubles the CI matrix, and forces users to install from two sources. Defer to v0.4 if v0.3 single-repo with `.chezmoiroot` proves insufficient. ### C) Rename current root files only (cosmetic) Just rename `bin/dot``bin/executable_dot` without `.chezmoiroot`. **Rejected**: chezmoi only resolves the `executable_` / `dot_` prefixes for files inside its source root, so moving the prefixed file outside breaks chezmoi-driven install entirely without giving us a standalone tarball. ## Unresolved questions 1. **How does the `defaults/` subtree behave when a user wants to override one default?** Today they edit `dot_config/X.tmpl` directly. Post-reorg, do they: (a) edit `defaults/config/X.tmpl` and live with merge conflicts on framework updates, or (b) use a chezmoi `data` override + template conditional, or (c) maintain a second repo layered atop `defaults/`? 2. **Should `install/migrate/` ship in the regular framework install, or only via a one-shot `https://...migrate.sh` URL?** Bundling it forever increases install size; URL-only requires the user to find and trust the right URL during a stressful upgrade moment. 3. **Does `.chezmoiroot` survive existing user customisations in `~/.config/chezmoi/chezmoi.toml`?** Needs verification on a real upgrade test. 4. **Windows-native `bin/dot`**: standalone PowerShell rewrite, or wrapper that shells to bash via WSL/git-bash? `POWERSHELL_PARITY.md` documents the current stub state. ## Implementation plan | Phase | Scope | Effort | |-------|-------|--------| | 1 | Draft + ratify this RFC. Get user OK. | Done (this PR's draft) | | 2 | Create `defaults/`, `bin/`, `lib/`, `share/`, `tools/` and copy files. Update bash source paths. Add `.chezmoiroot`. | 1 week | | 3 | Write `install/migrate/migrate-v0_2-to-v0_3.sh`. Test against a synthetic v0.2.503-installed environment. | 3 days | | 4 | Update CI: every workflow that references `scripts/`, `dot_local/`, `dot_config/` needs path updates. | 3 days | | 5 | Update every doc that references the old paths. Most are in `docs/manual/`. | 1 day | | 6 | Cut v0.2.999 RC as a deprecation-warning-only release; let real users dry-run the migration. | 1 day + 2-week soak | | 7 | Cut v0.2.503 with the actual reorg + migration tool. | 1 day | | 8 | Publish to Homebrew/Scoop/AUR using `install/{homebrew,scoop,aur}/` scaffolds. | 1 week | | **Total** | | **~5 weeks calendar time** | ## See also - `HARD_AUDIT_2026.md` §8.3 — cross-platform gap analysis. - `HARD_AUDIT_2026.md` §8.5 — Top-5 de-facto adoption gaps. - `STRUCTURE.md` — today's layout (honest about the chezmoi-prefix forcing function). - `GOVERNANCE.md` — RFC process this document follows. - `install/README.md` — distribution-channel publication checklist. - Reference: [Debian/aws-cli](https://github.com/Debian/aws-cli) — clean top-level discipline.