Repository navigation
Conversation
An nvf configuration is a Neovim written as nvf modules, evaluated at every system in force on the selected package set. caisson evaluates nvf's module list with its own `evalModules`, with the special arguments nvf's `neovimConfiguration` passes, on the composed library extended with `lib.nvim` from the same nvf flake. The output `neovim` is published as `packages.<system>.<name>`; the pinned-world suite checks it is the derivation `neovimConfiguration` builds. A NixOS machine, a darwin machine, a home and an hjem configuration install the Neovim of an nvf configuration declared inside them, with the module `nvf-package` of each class. caisson now registers a `default` home-manager module and a `default` hjem module, which import it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A nixvim configuration is a Neovim written as nixvim modules, evaluated at every system in force on the selected package set. caisson makes the evaluation `evalNixvim` makes, `evalModules` over `modules/top-level` with the flake as `flake`, on the composed library extended with the overlay nixvim publishes and with `nixpkgs.pkgs` set to the selected package set. The output `package` is the Neovim; the configuration is published as `nixvimConfigurations.<system>.<name>`, where nixvim's flake publishes its own. The pinned-world suite checks the package is the derivation `evalNixvim` builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every evaluation declared `caisson.modules.<class>.export.enabled` and `caisson.modules.<class>.exported` as options for every registered class. `caisson.modules` is now one option, an attribute set by class of the two settings, so a class no module sets costs nothing to evaluate. The definitions are written as before; a class with no registered module, or a setting other than the two, is refused when the exports are read. `exported` is now a value, so two definitions of it for one class conflict instead of merging. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A topology configuration is the diagram of the NixOS configurations declared inside it. caisson evaluates nix-topology's `topology` modules on the composed library and the selected package set extended with nix-topology's packages, with `nixosConfigurations` set to the machines declared inside it at its system; those machines get nix-topology's NixOS module by default. The configuration named `default` is published as `topology.<system>`, where nix-topology's flake module publishes it. A kubenix configuration is Kubernetes resources written as kubenix modules, evaluated as kubenix's `evalModules` evaluates them, on the composed library extended with kubenix's `upstreamables.nix`. Its `result` is published as `packages.<system>.<name>`. A nixidy configuration is an Argo CD environment, evaluated with nixidy's own `mkEnv` over the composed library, with the namespaces of the composed library added to nixidy's through `libOverlay`. It is published as `nixidyEnvs.<system>.<name>`, which the nixidy CLI reads. The pinned-world suite checks each against its upstream evaluator: the same topology nodes and diagram, the same kubenix result and the same nixidy environment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A configuration with `perSystem` has an evaluation for each system in force; the comments called it "evaluated at a system", which names one of those evaluations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… declared inside a machine A system-manager configuration now acts as the parent of the configurations declared inside it, as a NixOS or darwin machine does. Its new registered `default` module imports: - `home-manager-activation` and `hjem-activation`, the NixOS modules registered a second time for the `systemManager` class. They import the core module of the class they are evaluated in, and the hjem module keeps extra dependencies only where the class declares `system.extraDependencies`. - `nvf-package`, which installs the Neovim of each nvf configuration in `environment.systemPackages`. - `caisson.forChildren` settings that give homes and hjem configurations the `system-manager-parent` module, the `nixos-parent` module under a second name, which reads the nearest NixOS or system-manager machine. system-manager counts as a machine for naming homes (`user@machine`), for the `osConfig` and `utils` an hjem configuration receives, and for the check that leaves out what an inner machine activates. A pinned-world test declares a home, an hjem configuration and an nvf configuration inside a system-manager machine and checks the units, the packages and the published home name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… and the one above it Drift detection was written for one pair: a home inside a NixOS machine compared `/etc/caisson-home-manager/source.json` with the machine it was built for. It is now a property of the framework. An integration whose configurations are activated passes `activation` to `mkModuleConfiguration`: `identity`, the store path of the childless evaluation, and `marker`, the file its activation writes that identity into. NixOS, darwin and system-manager record the system and `/etc/caisson/marker.json`; a home records its activation package and a file in the state directory of its user; an hjem configuration records its manifest file and a file in its directory. A machine `standsAlone`: it is applied on its own host, so it checks nothing above it. `lib.caisson.integrations` gains `activatingAncestorOf`, `markerOf`, `checksMarkerOf` and `driftCheckOf`. Each activating class writes its marker from its `default` module (`activation-marker` for nixos, darwin, systemManager, homeManager and hjem) when a configuration declared inside it checks it. A home runs `driftCheckOf` against the nearest activating configuration above it from the home-manager module `activation-drift`, now part of the home-manager `default` module, so a home inside a darwin or system-manager machine is checked as one inside NixOS is. The NixOS module `home-manager-source-marker` and the home-manager module `nixos-source-marker` are removed. The option `caisson.home-manager.machineDrift.warn` becomes `caisson.drift.warn`, and the marker field `baseSystemOutPath` becomes `identity`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rker A drift marker held the store path of the childless evaluation with its string context dropped, which made it a string that looks like a store path but is not tracked as one. The marker and the check now hold the SHA-256 digest of that store path. Computing it evaluates the childless evaluation and builds nothing, and the digest names no store path, so nothing depends on it and nothing can read it as a path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test of the units that activate the homes dropped the string context of the activation package and of the unit script to search one in the other. It now reads the context of the script, which records the store paths the script refers to, and checks that it holds the activation package of the home and not that of the other home. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit b6f1ff3)
…ates An nvf or nixvim configuration declared inside a machine, a home or an hjem configuration used to be installed into the packages of the configuration above. It now relates to that configuration as a home relates to its machine: it has an activation of its own, which the configuration above runs each time it is activated itself. `lib.caisson.integrations.profileOf` gives such a configuration the outputs `activationPackage` and `profile`. `activate` checks for drift against the nearest configuration above with an activation, and points a Nix profile at the Neovim with `nix-env --profile`, which also makes the profile a garbage-collector root; it adds no generation when the profile already points there. Inside a machine the profile is a profile of the system, `/nix/var/nix/profiles/caisson/<kind>/<name>`; inside a home or an hjem configuration, or at a top, it is a profile of the user, `$HOME/.local/state/caisson/profiles/<kind>/<name>`. The home marker moves under `$HOME/.local/state` as well, since a unit of the machine and a shell may see `$XDG_STATE_HOME` differently. Each class has a `profile-activation` module in its `default` module: - nixos and systemManager: a unit per profile wanted by `multi-user.target`, run as root for a profile of the system, and as the user after `hjem-activate@<user>` for a profile inside an hjem configuration, whose own activation has no step to add; - darwin: steps of `postActivation`, the same way; - homeManager: an activation step after the files are linked and the marker is written, so `home-manager switch`, a switch of the machine and a boot all put the profile back; - hjem: the programs and the variable below. Each also installs `profileShimsOf`: `nvim` (and `vi`, `vim` where the Neovim has them) runs the profile `$CAISSON_NVIM_PROFILE` names, read each time it runs, and the default of the configuration when it is unset. A home or an hjem configuration sets the variable to its own profile, and a shell can `export` another. Where several profiles share the variable, `caisson.profiles.selected` names the default. The modules `nvf-package` of every class and `lib.caisson.nvf.packagesModule` are removed. nvf and nixvim get a `default` module declaring `caisson.drift.warn`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hjem is pronounced with a leading "y" sound, so it takes "a". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The comments of the integrations said a configuration is evaluated at every system in force, and one in the integrations library said a configuration is evaluated at a system. They say it is evaluated per system, once for each system in force. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ly that configuration A tree with a treefmt configuration named `default` now also publishes `checks.<system>.treefmt`, the configuration's `check` over the root of the tree (`root` on `mkLib`), so `nix flake check` fails when the tree is not formatted. A tree without a root, such as a library composed inside a test, publishes no check. Every treefmt configuration used to be an entry for `formatter`, which holds a single value, so a second configuration, under any other name, was refused when the top published. Now only the configuration named `default` is published; one under another name is evaluated, passed up, and found through the manifest. `exportsTo` may be a list of exports, for an integration published in more than one output, and an export may carry `only`, a function of the manifest saying whether the configuration is published there. `exportsOf` replaces `exportsToOf` in the integrations library. The pinned-world test declares a second configuration, `docs`, which the previous integration refused, and checks the check is published over the root and absent without one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Folded into #98, the treefmt PR, where the treefmt integration is introduced: the configuration named |
An error occurred while trying to automatically change base from
fix/system-manager-pkgs
to
main
October 18, 2026 19:25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A tree with a treefmt configuration named
defaultnow publishes two outputs:formatter.<system>nix fmtruns (unchanged)checks.<system>.treefmtcheckover the root of the tree,rootonmkLib, whichnix flake checkbuildsA tree without a root publishes no check. A library composed inside a test is one example.
Second configurations no longer refused. Every treefmt configuration used to become an entry for
formatter, which holds a single value. So a second configuration, under any other name, was refused when the top published, with "this output holds a single value". Now onlydefaultis published. A configuration under another name is evaluated and passed up, and is reachable only through the manifest.exportsTochanges.exportsTomay now be a list of exports, for an integration that publishes in more than one output. An export may carryonly, a function of the manifest that says whether the configuration is published in that output.exportsOfreplacesexportsToOfin the integrations library.Testing
Pinned-world test.
treefmtIsTheFormatterTreefmtNixBuildsnow declares a second configuration,docs. It checks four things:formatterstill holds the wrappermkWrapperbuilds;checks.x86_64-linuxholds onlytreefmt, and it is the configuration'scheckover that root;checksoutput;docsis evaluated, and only the manifest holds it.With the previous integration the suite fails, because
formatter.x86_64-linuxrefusestreefmt docs.Built for real from this branch, the published check succeeds on a formatted tree and fails on an unformatted one, printing the diff for
flake.nix.nix flake checkpasses, including the eval-weight gate, andnix flake check --no-buildpasses in all 18 consumers. TheexportsTochange touches how every integration publishes.Docs: nix-caisson/nix-caisson.github.io, branch
docs/treefmt-check.🤖 Generated with Claude Code