Unified Nix flake for macOS hosts, Home Manager user configuration, and reusable module building blocks.
This repository is still tailored to George's machines, user profile, and workflows today. Ongoing work is focused on separating those personal defaults into reusable framework primitives and a standalone library of modules.
- Primary focus is
nix-darwinplus Home Manager. - Active Darwin hosts:
argusandzeus(work profile enabled), plusrocinante(personal profile). - Active Home Manager output:
homeConfigurations.george. - Exported systems:
aarch64-darwin,aarch64-linux,x86_64-linux. - NixOS modules are exported, but there are currently no
nixosConfigurationsdefined.
darwin/: host entrypoints.home/: user configuration (home/george).modules/: reusable modules (common,darwin,nixos,home).packages/: custom package outputs (axiom-cli,codex-desktop,conductor,droid,gogcli,homebrew-zsh-completion,linear-cli,nix-manipulator,scratch,sculptor,sublime-kdl,superset,toad).overlays/: package overrides and source pinning.lib/: Python libraries for update tooling and Nix model/schema helpers.nixcfg.py: Typer CLI exposed throughnix run .#nixcfg -- ....
-
Install vanilla Nix using the official multi-user installer:
curl -L https://nixos.org/nix/install | sh -s -- --daemonThen either open a new terminal or load the daemon profile in the current shell:
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh -
Clone this repository to
~/.config/nixcfg. -
Bootstrap nix-darwin with the intended host selected explicitly (the pre-switch macOS hostname is not yet declarative):
cd ~/.config/nixcfg sudo /nix/var/nix/profiles/default/bin/nix \ --extra-experimental-features 'nix-command flakes' \ run --inputs-from . nix-darwin#darwin-rebuild -- \ switch --flake .#zeus
-
After the first successful switch, use the managed
nhcommand for normal updates:nh darwin switch --no-nom .#zeus
Useful build-only checks:
nix build .#checks.aarch64-darwin.darwin-argus
nix build .#checks.aarch64-darwin.darwin-rocinante
nix build .#checks.aarch64-darwin.darwin-zeus
nix build .#homeConfigurations.george.activationPackage# Enter the dev environment (tooling + pre-commit hooks)
nix develop
# Keep Python tooling in sync for editor/test workflows
uv sync
# Format and evaluate. The default no-build pass checks the current system;
# the all-systems pass is the full purity matrix. Neither may inspect outputs.
nix fmt
nix flake check --no-build --option allow-import-from-derivation false
nix flake check --all-systems --no-build --option allow-import-from-derivation false
nix flake check
# Pre-commit hooks
prek run -a
# Individual quality checks
uv run coverage run -m pytest
uv run coverage report
# Python test suite
uv run pytest
# Mutation testing with cosmic-ray
uv run cosmic-ray init cosmic-ray.toml .cosmic-ray.sqlite
uv run cosmic-ray exec cosmic-ray.toml .cosmic-ray.sqlite
uv run cr-report .cosmic-ray.sqliteUpdates and package-artifact maintenance are explicit CLI operations; the repository does not track GitHub Actions workflows.
nix run .#nixcfg -- --help
nix run .#nixcfg -- update --help
nix run .#nixcfg -- ci --help
nix run .#nixcfg -- schema --helpnixcfg update prepares changes in an isolated copy of the checkout. Every full
update must build all configured root closures before it changes the checkout.
A root closure contains a system or Home Manager configuration and all its
dependencies. Targeted updates use the same build gate when they change files.
Root discovery follows darwin/*.nix, nixos/*.nix, and home/*/default.nix.
It does not require a separate list of host names.
If a root build fails, the updater leaves the candidate changes outside the checkout. The updater also rejects source changes that invalidate the tested snapshot. It preserves existing user edits and does not activate a system or Home Manager configuration.
Source-derived toolchain metadata comes from the pinned upstream manifests and
locks. Node and pnpm selection must satisfy upstream requirements through the
pinned nixpkgs package set. Mux and Superset use the exact Bun version from
packageManager, with updater-generated runtime hashes. The updater owns these
generated values. Reviewed compatibility pins and platform policy remain
explicit.
This flake can be consumed by another repository as a module framework.
Public API version 2 removes the site-specific nixcfgProfiles exports and
the mkDarwinHost.work policy shortcut. It also stops importing sops-nix
through mkHomeModules. Downstream configurations should import their own
profile modules and, when needed, the sops-nix Home Manager module explicitly.
Cache policy is now opt-in: the common substituter and trusted-key options
default to empty lists. mkDarwinHost also enables the Rosetta builder by
default without consulting ambient CI state; CI and other callers without a
Linux builder must pass enableRosettaBuilder = false explicitly.
-
Exported
darwinModules,nixosModules, andhomeModulesare declared inlib/exports.nix, the canonical module inventory. -
Exported constructors in
lib: -
Downstream-oriented controls:
mkHomesupportsextraSpecialArgsfor downstream-only module argumentsmkSystemsupportsextraSpecialArgs,homeManagerExtraSpecialArgs, andhomeModuleArgsByUser. Darwin systems require at least one user; userless NixOS systems setprimaryUser = null.mkDarwinHostforwardsextraSpecialArgs,homeManagerExtraSpecialArgs, andhomeModuleArgsByUser; it also supportsincludeDefaultUserModule = false,homeModulesByUser, and a customsystem.default.nixand itsmkLibhelper accept an explicitevaluationContextfor update source overrides and fake-hash evaluation. Ambient environment variables do not alter the API.
-
Policy knobs intended to be overridden in downstream repos:
Example downstream pattern:
{
outputs = { nixcfg, ... }: {
darwinConfigurations.my-host = nixcfg.lib.mkDarwinHost {
user = "alice";
includeDefaultUserModule = false;
extraSpecialArgs = {
org = "acme";
};
homeManagerExtraSpecialArgs = {
privateRoot = ./.;
};
homeModuleArgsByUser.alice = {
role = "platform";
};
extraHomeModules = [
nixcfg.homeModules.nixcfgGit
./home/alice.nix
];
extraSystemModules = [
{
nixcfg.common.nix.substituters = [ "https://cache.nixos.org" ];
nixcfg.common.nix.trustedPublicKeys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
];
}
];
};
};
}Site-specific policy (for example cache keys, org profile settings, host/user modules) should live in the consuming repository, while these shared modules stay generic.