Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 configctl package scaffold
  • add initial configctl script
  • expose configctl from the Dubnium flake packages
  • install configctl on 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