ConfigCTL Home Layering Implementation Plan
Purpose
configctl is a generic home-configuration reconciliation CLI.
Dubnium may package and invoke it, but the CLI must not be Dubnium-specific. It should be usable on:
- Dubnium bare metal
- laptops
- WSL
- future NixOS machines
- CI dry-run environments
Dubnium remains responsible for machine policy, runtime modes, services, and local AI infrastructure. configctl owns layered home configuration reconciliation.
Core Model
Per-tool home configuration is organized into ownership layers:
~/.config/<tool>/
├── managed.* # generated by Home Manager/dotfiles; never edit directly
├── local.* # machine-specific; never automatically promoted
├── custom.d/ # user-authored promotion candidates
└── adopted.d/ # fragments already promoted or represented by managed config
Ownership rules:
managed.* -> governed source of truth
local.* -> machine-specific, ignored by promotion
custom.d/* -> promotion candidates
adopted.d/* -> archived/adopted fragments, ignored during normal load
Initial CLI Surface
Implemented commands:
configctl status [tool]
configctl doctor
configctl init <tool>
configctl promote <tool> <fragment>
configctl reconcile [tool]
Phase 0 — Documentation and Skeleton
Status: complete.
Tasks:
- document the per-tool layering contract
- add
configctlpackage scaffold - add initial
configctlscript - expose
configctlfrom the Dubnium flake packages - install
configctlon the workstation target
Phase 1 — Local Layer Initialization
Goal: safe scaffolding of layer directories.
Status: complete.
Commands:
configctl init hypr
configctl init git
configctl init nvim
configctl init zsh
Behavior:
- create
custom.d/ - create
adopted.d/ - create the tool-appropriate
local.*file - do not overwrite existing files
- do not modify managed files
Phase 2 — Status and Doctor
Goal: inspect local layer state without mutating anything.
Status: complete.
configctl status [tool] reports:
- local layer presence
- custom fragment count
- adopted fragment count
- missing expected directories
- unpromoted files in
custom.d/
configctl doctor reports:
- whether essential tools (git, find) are available
- whether the dotfiles repo is found
- whether XDG state/cache/data roots exist
Phase 3 — Promote
Goal: move local configuration fragments into the dotfiles repository.
Status: complete.
configctl promote <tool> <fragment>:
- identifies the fragment in
custom.d/ - copies it to the equivalent path in
external/dotfiles/files/home/ - stages the file in the dotfiles git repository
Promotion remains review-gated via Git (operator must commit and push).
Phase 4 — Reconcile
Goal: detect drift between local overlays and the dotfiles repository.
Status: initial version complete.
configctl reconcile [tool]:
- compares
custom.d/locally with the dotfiles repository - reports files present in dotfiles but missing locally (suggesting a sync or adoption)
Future Phases
- Adoption Manifest: track promoted fragments by hash across machines.
- Governance Integration: link promotion to review workflows.
- Cleanup: automated garbage collection of adopted fragments.
Non-Goals
configctl should not:
- replace Home Manager
- replace Git
- replace NixOS modules
- become Dubnium-specific
- silently promote local configuration
- automatically delete user-authored fragments without an adopted/archive path
- treat runtime state as governed configuration