Skip to content

Context Pipeline

When Den evaluates a host, it walks a pipeline of context transformations:

flowchart TD
  start["den.hosts.x86_64-linux.laptop"] --> host["den.ctx.host {host}"]
  host -->|"_.host"| owned["Owned config: fixedTo {host} aspects.laptop"]
  host -->|"_.user"| userctx["atLeast aspects.laptop {host, user}"]
  host -->|"into.user"| user["den.ctx.user {host, user} (per user)"]
  user -->|"_.user"| userown["fixedTo {host,user} aspects.alice"]
  host -->|"into.hm-host"| hmhost["den.ctx.hm-host {host}"]
  hmhost -->|"import HM module"| hmmod["home-manager OS module"]
  hmhost -->|"into.hm-user"| hmuser["den.ctx.hm-user {host, user}"]
  hmuser -->|"forward homeManager class"| fwd["home-manager.users.alice"]
  1. Host Context

    For each entry in den.hosts.<system>.<name>, Den creates a {host} context. The host context type (den.ctx.host) contributes:

    • _.host — Applies the host’s own aspect with fixedTo { host }, making all owned configs available for the host’s class.
    • _.user — For each user, applies the host’s aspect with atLeast { host, user }, activating parametric includes that need both host and user.
  2. User Context

    into.user maps each host.users entry into a {host, user} context. The user context type (den.ctx.user) contributes:

    • _.user — Applies the user’s own aspect with fixedTo { host, user }.
  3. Derived Contexts

    Batteries register additional into.* transformations on the host context:

    TransitionConditionProduces
    into.hm-hosthost.home-manager.enable && hasHmUsers{host} hm-host
    into.hm-userPer HM-class user on hm-host{host, user} hm-user
    into.wsl-hosthost.class == "nixos" && host.wsl.enable{host} wsl-host
    into.hjem-hosthost.hjem.enable && hasHjemUsers{host} hjem-host
    into.hjem-userPer hjem-class user{host, user} hjem-user
    into.maid-hosthost.nix-maid.enable && hasMaidUsers{host} maid-host
    into.maid-userPer maid-class user{host, user} maid-user

    Each derived context can contribute its own aspect definitions and import the necessary OS-level modules (e.g., home-manager.nixosModules.home-manager).

  4. Deduplication

    dedupIncludes in modules/context/types.nix ensures:

    • First occurrence of a context type uses parametric.fixedTo, which includes owned configs + statics + parametric matches.
    • Subsequent occurrences use parametric.atLeast, which only includes parametric matches (owned/statics already applied).

    This prevents den.default configs from being applied twice when the same aspect appears at multiple pipeline stages.

  5. Home Configurations

    Standalone den.homes entries go through a separate path:

    flowchart TD
      home["den.homes.x86_64-linux.alice"] --> homectx["den.ctx.home {home}"]
      homectx --> resolve["fixedTo {home} aspects.alice"]
      resolve --> hmc["homeConfigurations.alice"]

    Home contexts have no host, so functions requiring { host } are not activated. Functions requiring { home } run instead.

  6. Output

    modules/config.nix collects all hosts and homes, calls host.instantiate (defaults to lib.nixosSystem, darwinSystem, or homeManagerConfiguration depending on class), and places results into flake.nixosConfigurations, flake.darwinConfigurations, or flake.homeConfigurations.

Contribute Community Sponsor