Modular, context-aware and aspect-oriented dendritic Nix configurations. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ den.oeiuwq.com
configurations den dendritic nix aspect oriented
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

remove agents file it was outdated

-561
-561
AGENTS_EXAMPLE.md
··· 1 - # AGENTS.md — Den AI Agent Guide 2 - 3 - > **For AI coding agents helping users adopt and use Den.** 4 - > Den is an aspect-oriented, context-driven Dendritic Nix configuration framework. 5 - > Read this document fully before generating any Den configuration. 6 - 7 - --- 8 - 9 - ## 1. Mandatory Source Consultation 10 - 11 - **Always read the source on an as-needed basis.** Do not guess at API shapes or option names. Instead, look them up directly in the repository. The following directories are your primary references: 12 - 13 - | Directory | What it contains | 14 - |-----------|-----------------| 15 - | `./docs/src/content/docs/` | Full user-facing documentation (explanation, guides, reference, tutorials) | 16 - | `./nix/` | Core Den library (`parametric`, `canTake`, `take`, `__findFile`, context types, etc.) | 17 - | `./modules/` | OS framework (schema options, aspect definition, batteries, context wiring, output) | 18 - | `./templates/ci/modules/` | **Every Den feature as a fully isolated, executable nix-unit test** | 19 - 20 - The CI test suite at `./templates/ci/modules/features/` is the **most authoritative** working-code reference. Every test is a self-contained, evaluated Nix expression that demonstrates exactly how a feature behaves. Read the relevant test file whenever you need a code example. 21 - 22 - **Key source files to consult on demand:** 23 - 24 - - `docs/src/content/docs/explanation/core-principles.mdx` — Design philosophy 25 - - `docs/src/content/docs/explanation/aspects.mdx` — Aspect & functor pattern 26 - - `docs/src/content/docs/explanation/parametric.mdx` — Parametric dispatch mechanics 27 - - `docs/src/content/docs/explanation/context-pipeline.mdx` — Host → user → home pipeline 28 - - `docs/src/content/docs/explanation/context-system.mdx` — `den.ctx` architecture 29 - - `docs/src/content/docs/explanation/library-vs-framework.mdx` — Using Den without NixOS 30 - - `docs/src/content/docs/reference/lib.mdx` — Full `den.lib` API 31 - - `docs/src/content/docs/reference/ctx.mdx` — Full `den.ctx` API 32 - - `docs/src/content/docs/reference/schema.mdx` — `den.hosts`, `den.homes`, `den.schema` 33 - - `docs/src/content/docs/reference/aspects.mdx` — `den.aspects`, `den.provides`, `den.ful` 34 - - `docs/src/content/docs/reference/batteries.mdx` — All `den.provides.*` batteries 35 - - `docs/src/content/docs/reference/output.mdx` — Flake output generation 36 - - `docs/src/content/docs/guides/` — Practical cookbooks (batteries, custom classes, namespaces, migration, debugging) 37 - - `nix/lib/default.nix` — Library entrypoint (all sub-modules listed) 38 - - `modules/options.nix` — `den.hosts`, `den.homes`, `den.schema` option declarations 39 - - `modules/config.nix` — How hosts and homes are instantiated into flake outputs 40 - - `modules/aspects/provides/` — All built-in battery implementations 41 - 42 - --- 43 - 44 - ## 2. Den in One Paragraph 45 - 46 - Den is built on [`flake-aspects`](https://github.com/vic/flake-aspects). It inverts the traditional host-centric Nix model: **aspects** (features) are the primary unit of organization. Each aspect declares its behavior per Nix *class* (`nixos`, `darwin`, `homeManager`, `hjem`, `maid`, `user`, custom…). Hosts simply include the aspects they need. A **context pipeline** (`den.ctx`) transforms host/user/home declarations into fully resolved Nix module system inputs. Parametric dispatch (via `builtins.functionArgs` introspection) means a function requiring `{ host, user }` is silently skipped in a `{ host }`-only context — no `mkIf`, no `enable` flags needed to gate context-sensitive configuration. 47 - 48 - --- 49 - 50 - ## 3. Core Concepts 51 - 52 - ### 3.1 Aspects 53 - 54 - An aspect is an attrset containing: 55 - - **Owned configs**: keys named after Nix classes (`nixos`, `darwin`, `homeManager`, `hjem`, `maid`, `user`, `os`, or any custom class). Values are plain attrset modules or function modules (`{ pkgs, ... }: { }`). 56 - - **`includes`**: a list of other aspects, static attrsets, or parametric functions to include as dependencies. 57 - - **`provides`**: named sub-aspects scoped to this aspect, accessible via `den.aspects.foo.provides.bar` or the shorthand `den.aspects.foo._.bar`. 58 - 59 - Read: `docs/src/content/docs/explanation/aspects.mdx`, `docs/src/content/docs/guides/configure-aspects.mdx` 60 - CI examples: `templates/ci/modules/features/parametric.nix`, `templates/ci/modules/features/top-level-parametric.nix`, `templates/ci/modules/features/auto-parametric.nix` 61 - 62 - ### 3.2 Parametric Dispatch 63 - 64 - Den uses `builtins.functionArgs` to inspect a function's declared arguments. A function is included only when all its **required** (non-default) arguments are present in the current context: 65 - 66 - - `{ host, ... }` → matches `{ host }`, `{ host, user }`, etc. (atLeast) 67 - - `{ host, user }` → matches only when both are present 68 - - `{ home }` → matches only standalone home contexts 69 - - `{ class, aspect-chain }` → static aspect (evaluated during resolution, not per-context) 70 - 71 - `den.lib.parametric` wraps an aspect with this dispatch logic. `den.lib.canTake`, `den.lib.take.atLeast`, `den.lib.take.exactly` are the underlying primitives. 72 - 73 - Read: `docs/src/content/docs/explanation/parametric.mdx`, `docs/src/content/docs/reference/lib.mdx` 74 - CI examples: `templates/ci/modules/features/parametric.nix` 75 - 76 - **Parametric variants:** 77 - 78 - | Constructor | Behavior | 79 - |---|---| 80 - | `den.lib.parametric` | Owned + statics + atLeast function includes | 81 - | `den.lib.parametric.atLeast` | Only function includes matching atLeast | 82 - | `den.lib.parametric.exactly` | Only function includes matching exactly | 83 - | `den.lib.parametric.fixedTo attrs aspect` | Always uses given attrs as context | 84 - | `den.lib.parametric.expands attrs aspect` | Extends received context with attrs | 85 - 86 - **Context shortcuts** (built on `take.exactly` + `fixedTo`): 87 - - `den.lib.perHost aspect` — runs only in `{ host }` contexts 88 - - `den.lib.perUser aspect` — runs only in `{ host, user }` contexts 89 - - `den.lib.perHome aspect` — runs only in `{ home }` contexts 90 - 91 - CI example: `templates/ci/modules/features/perUser-perHost.nix` 92 - 93 - ### 3.3 Aspects are Auto-Generated 94 - 95 - Den automatically creates a parametric aspect for every declared host, user, and home. You do not need to declare `den.aspects.igloo` from scratch — you just extend it. Any module file may contribute to any aspect. 96 - 97 - Read: `docs/src/content/docs/guides/configure-aspects.mdx` 98 - 99 - ### 3.4 `includes` Three Kinds 100 - 101 - 1. **Static plain attrset**: `{ nixos.foo = 1; }` — always included unconditionally. 102 - 2. **Static leaf** `{ class, aspect-chain }: ...` — evaluated once during resolution. 103 - 3. **Parametric function** `{ host, user, ... }: ...` — evaluated per context, only when argument requirements are met. 104 - 105 - > **Anti-pattern**: Avoid anonymous inline functions in `includes`. Use named aspects instead — this produces better error traces and more readable code. 106 - 107 - --- 108 - 109 - ## 4. Declaring Hosts, Users, and Homes 110 - 111 - ### 4.1 Hosts 112 - 113 - ```nix 114 - den.hosts.x86_64-linux.laptop.users.alice = {}; 115 - den.hosts.aarch64-darwin.mac.users.alice = {}; 116 - ``` 117 - 118 - Host options (all have defaults): 119 - 120 - | Option | Default | Description | 121 - |--------|---------|-------------| 122 - | `name` | attrset key | Config name | 123 - | `hostName` | `name` | Network hostname | 124 - | `system` | parent key | Platform | 125 - | `class` | auto from system | `"nixos"` or `"darwin"` | 126 - | `aspect` | `name` | Primary aspect name | 127 - | `instantiate` | class-dependent | OS builder function | 128 - | `intoAttr` | class-dependent | Flake output path | 129 - | `users` | `{}` | User declarations | 130 - | `*` | from `den.schema.host` | Schema-defined options | 131 - | `*` | | Freeform attributes (read from aspects via `host.myAttr`) | 132 - 133 - Read: `docs/src/content/docs/guides/declare-hosts.mdx`, `docs/src/content/docs/reference/schema.mdx` 134 - CI examples: `templates/ci/modules/features/host-options.nix` 135 - 136 - ### 4.2 Users 137 - 138 - ```nix 139 - den.hosts.x86_64-linux.laptop.users.alice = { 140 - classes = [ "homeManager" "hjem" ]; 141 - userName = "alice"; # optional, defaults to key 142 - }; 143 - ``` 144 - 145 - User options: 146 - 147 - | Option | Default | Description | 148 - |--------|---------|-------------| 149 - | `name` | attrset key | User config name | 150 - | `userName` | `name` | System account name | 151 - | `aspect` | `name` | Primary aspect | 152 - | `classes` | `[ "homeManager" ]` | Home environment classes | 153 - | `*` | from `den.schema.user` | Schema options | 154 - | `*` | | Freeform (accessible via `user.myAttr`) | 155 - 156 - CI examples: `templates/ci/modules/features/user-classes.nix`, `templates/ci/modules/features/host-options.nix` 157 - 158 - ### 4.3 Standalone Homes 159 - 160 - ```nix 161 - den.homes.x86_64-linux.alice = {}; # → homeConfigurations.alice 162 - den.homes.x86_64-linux."alice@laptop" = {}; # bound to hostname "laptop" 163 - ``` 164 - 165 - When `"alice@laptop"` is declared **and** `den.hosts.x86_64-linux.laptop` exists, the standalone home automatically receives `osConfig` pointing to the NixOS configuration. 166 - 167 - Home options: `name`, `userName`, `system`, `class` (`"homeManager"`), `aspect`, `pkgs`, `instantiate`, `intoAttr`. 168 - 169 - Read: `docs/src/content/docs/guides/home-manager.mdx`, `docs/src/content/docs/guides/declare-hosts.mdx` 170 - CI examples: `templates/ci/modules/features/homes.nix`, `templates/ci/modules/features/special-args-custom-instantiate.nix` 171 - 172 - --- 173 - 174 - ## 5. Configuring Aspects 175 - 176 - ### 5.1 Owned Configs 177 - 178 - Class-keyed configs directly in the aspect. Can be attrset or function modules. 179 - 180 - ### 5.2 `den.default` 181 - 182 - A special aspect applied to **all** hosts, users, and homes: 183 - 184 - ```nix 185 - den.default = { 186 - nixos.system.stateVersion = "25.11"; 187 - homeManager.home.stateVersion = "25.11"; 188 - includes = [ den.provides.define-user den.provides.inputs' ]; 189 - }; 190 - ``` 191 - 192 - > Owned configs in `den.default` are deduplicated across pipeline stages. Parametric functions in `den.default.includes` run at every stage — use `den.lib.perHost` / `den.lib.perUser` to restrict. 193 - 194 - CI examples: `templates/ci/modules/features/default-includes.nix`, `templates/ci/modules/features/context/den-default.nix` 195 - 196 - ### 5.3 `provides` (Sub-Aspects) 197 - 198 - ```nix 199 - den.aspects.tools.provides.editors = { 200 - homeManager.programs.helix.enable = true; 201 - }; 202 - # Used as: 203 - den.aspects.alice.includes = [ den.aspects.tools._.editors ]; 204 - ``` 205 - 206 - `provides` can also be parametric functions. 207 - 208 - CI examples: `templates/ci/modules/features/provides-parametric.nix` 209 - 210 - --- 211 - 212 - ## 6. Schema Base Modules 213 - 214 - `den.schema.{conf,host,user,home}` provides shared meta-configuration (typed options with defaults) applied to every entity of the given kind. These are **not aspects** — they define metadata that aspects can later read from `host.*` / `user.*` / `home.*`. 215 - 216 - ```nix 217 - den.schema.host = { host, lib, ... }: { 218 - options.hardened = lib.mkEnableOption "hardened profile"; 219 - config.hardened = lib.mkDefault true; 220 - }; 221 - den.schema.user = { user, lib, ... }: { 222 - config.classes = lib.mkDefault [ "homeManager" ]; 223 - }; 224 - den.schema.conf = { lib, ... }: { 225 - options.org = lib.mkOption { default = "myorg"; }; 226 - }; 227 - ``` 228 - 229 - - `den.schema.conf` → applied to host, user, and home 230 - - `den.schema.host` → all hosts (imports `conf`) 231 - - `den.schema.user` → all users (imports `conf`) 232 - - `den.schema.home` → all homes (imports `conf`) 233 - 234 - Read: `docs/src/content/docs/reference/schema.mdx` 235 - CI examples: `templates/ci/modules/features/schema-base-modules.nix` 236 - 237 - --- 238 - 239 - ## 7. Context Pipeline (`den.ctx`) 240 - 241 - ### 7.1 Built-in Pipeline 242 - 243 - ``` 244 - den.hosts.x86_64-linux.laptop 245 - → den.ctx.host { host } 246 - → _.host (fixedTo { host } → aspects.laptop) 247 - → _.user (atLeast { host, user } → aspects.laptop) 248 - → into.user (per user) → den.ctx.user { host, user } 249 - → _.user (fixedTo { host, user } → aspects.alice) 250 - → into.hm-host (if HM enabled and has HM users) 251 - → into.hjem-host (if hjem enabled and has hjem users) 252 - → into.maid-host (if maid enabled and has maid users) 253 - → into.wsl-host (if host.wsl.enable = true) 254 - ``` 255 - 256 - Read: `docs/src/content/docs/explanation/context-pipeline.mdx`, `docs/src/content/docs/explanation/context-system.mdx`, `docs/src/content/docs/reference/ctx.mdx` 257 - CI examples: `templates/ci/modules/features/context/` 258 - 259 - ### 7.2 Context Type Anatomy 260 - 261 - Each `den.ctx.<name>` has: 262 - - `description` — human readable 263 - - `_` / `provides` — map of provider functions, each taking context data and returning aspect fragments 264 - - `into` — map of transformation functions producing new context values 265 - - `includes` — aspect includes injected at this pipeline stage 266 - - `modules` — additional modules merged into the resolved output 267 - 268 - ### 7.3 Built-in Context Types 269 - 270 - | Context | Data | Purpose | 271 - |---------|------|---------| 272 - | `den.ctx.host` | `{ host }` | One per declared host | 273 - | `den.ctx.user` | `{ host, user }` | One per user per host | 274 - | `den.ctx.home` | `{ home }` | One per standalone home | 275 - | `den.ctx.hm-host` | `{ host }` | Activates HM OS module | 276 - | `den.ctx.hm-user` | `{ host, user }` | Forwards `homeManager` class | 277 - | `den.ctx.wsl-host` | `{ host }` | WSL activation | 278 - | `den.ctx.hjem-host` / `hjem-user` | `{ host }` / `{ host, user }` | hjem integration | 279 - | `den.ctx.maid-host` / `maid-user` | `{ host }` / `{ host, user }` | nix-maid integration | 280 - 281 - ### 7.4 Custom Context Types 282 - 283 - You can define entirely new `den.ctx.<name>` entries and wire them into the pipeline via `den.ctx.host.into.<name>`. See `templates/ci/modules/features/context/custom-ctx.nix` and the `templates/microvm` template for real examples. 284 - 285 - CI examples: `templates/ci/modules/features/context/custom-ctx.nix`, `templates/ci/modules/features/context/cross-provider.nix` 286 - 287 - ### 7.5 Extending `den.ctx` with `includes` 288 - 289 - Batteries and users extend `den.ctx.user.includes` or `den.ctx.host.includes` to inject behavior at that pipeline stage: 290 - 291 - ```nix 292 - den.ctx.user.includes = [ den._.mutual-provider ]; 293 - ``` 294 - 295 - --- 296 - 297 - ## 8. Batteries (`den.provides.*` / `den._.*`) 298 - 299 - `den.provides` and `den._` are aliases. All batteries live in `modules/aspects/provides/`. Always consult the source file for a battery to understand its exact behavior. 300 - 301 - Read: `docs/src/content/docs/guides/batteries.mdx`, `docs/src/content/docs/reference/batteries.mdx` 302 - Source: `modules/aspects/provides/` 303 - 304 - ### System Batteries 305 - 306 - | Battery | Usage | Effect | 307 - |---------|-------|--------| 308 - | `den._.define-user` | `den.default.includes = [ den._.define-user ]` | Creates `users.users.<name>` on OS + `home.username`/`home.homeDirectory` in HM | 309 - | `den._.hostname` | `den.default.includes = [ den._.hostname ]` | Sets `networking.hostName` on NixOS/Darwin/WSL from `host.hostName` | 310 - | `den._.primary-user` | `den.aspects.alice.includes = [ den._.primary-user ]` | Adds `wheel`/`networkmanager` groups (NixOS), sets `system.primaryUser` (Darwin), `wsl.defaultUser` (WSL) | 311 - | `den._.user-shell` | `den.aspects.alice.includes = [ (den._.user-shell "fish") ]` | Sets login shell at OS and HM levels | 312 - | `den._.mutual-provider` | `den.ctx.user.includes = [ den._.mutual-provider ]` | Enables bidirectional host↔user config via `provides.*` | 313 - | `den._.tty-autologin` | `den.aspects.laptop.includes = [ (den._.tty-autologin "alice") ]` | Enables TTY1 autologin (NixOS) | 314 - | `den._.wsl` | (auto-activated) | WSL activation; creates `wsl` forwarding class | 315 - | `den._.os-user` | (auto-enabled) | Forwards `user` class to `users.users.<userName>` on OS | 316 - | `den._.os-class` | (auto-enabled) | Forwards `os` class to both `nixos` and `darwin` | 317 - | `den._.forward` | see §9 | Creates custom Nix classes by forwarding | 318 - | `den._.import-tree` | see migration | Auto-imports directories of non-dendritic modules | 319 - | `den._.unfree` | `den.aspects.laptop.includes = [ (den._.unfree [ "nvidia-x11" ]) ]` | Allows specific unfree packages | 320 - 321 - CI examples: `templates/ci/modules/features/batteries/` 322 - 323 - ### Flake-Parts Batteries 324 - 325 - | Battery | Effect | 326 - |---------|--------| 327 - | `den._.inputs'` | Exposes system-specialized `inputs'` as module arg | 328 - | `den._.self'` | Exposes system-specialized `self'` as module arg | 329 - 330 - CI example: `templates/ci/modules/features/batteries/flake-parts.nix` 331 - 332 - --- 333 - 334 - ## 9. Home Environments 335 - 336 - Den supports multiple home environment classes. All are opt-in per user (via `user.classes`) or globally via `den.schema.user`. 337 - 338 - ### Enabling 339 - 340 - ```nix 341 - # Per user 342 - den.hosts.x86_64-linux.laptop.users.alice.classes = [ "homeManager" "hjem" ]; 343 - 344 - # Global default 345 - den.schema.user.classes = lib.mkDefault [ "homeManager" ]; 346 - ``` 347 - 348 - ### `homeManager` Class 349 - 350 - - Requires `inputs.home-manager` in flake inputs. 351 - - The `homeManager` key in aspects forwards to `home-manager.users.<userName>`. 352 - - Override HM module per host: `host.home-manager.module = inputs.home-manager-unstable.nixosModules.home-manager`. 353 - 354 - ### `hjem` Class 355 - 356 - - Requires `inputs.hjem`. 357 - - Users with `"hjem"` in `classes` get `hjem.users.<userName>` populated. 358 - - Enable globally: `den.schema.host.hjem.enable = true`. 359 - 360 - ### `maid` Class 361 - 362 - - Requires `inputs.nix-maid`. 363 - - Host class must be `"nixos"`. 364 - - Forwards into `users.users.<name>.maid`. 365 - 366 - ### `user` Class (Built-in) 367 - 368 - - Always available. 369 - - Forwards to `users.users.<userName>` on the OS. 370 - - Replaces verbose `den.aspects.alice.nixos.users.users.alice.*` with `den.aspects.alice.user.*`. 371 - 372 - ### `os` Class (Built-in) 373 - 374 - - Forwards to both `nixos` and `darwin` simultaneously. 375 - - Useful for cross-platform settings that apply to all OS types. 376 - 377 - CI examples: `templates/ci/modules/features/hjem-class.nix`, `templates/ci/modules/features/maid-class.nix`, `templates/ci/modules/features/os-class.nix`, `templates/ci/modules/features/os-user-class.nix` 378 - 379 - Read: `docs/src/content/docs/guides/home-manager.mdx` 380 - 381 - --- 382 - 383 - ## 10. Mutual Providers 384 - 385 - Enable bidirectional host↔user configuration using `den._.mutual-provider`: 386 - 387 - ```nix 388 - den.ctx.user.includes = [ den._.mutual-provider ]; 389 - 390 - # User → specific host 391 - den.aspects.alice.provides.laptop.nixos.programs.emacs.enable = true; 392 - 393 - # User → all hosts it lives on 394 - den.aspects.alice.provides.to-hosts = { host, ... }: { ... }; 395 - 396 - # Host → specific user 397 - den.aspects.laptop.provides.alice.homeManager.programs.vim.enable = true; 398 - 399 - # Host → all its users 400 - den.aspects.laptop.provides.to-users = { user, ... }: { ... }; 401 - 402 - # Or more tersely with the `_` shorthand: 403 - den.aspects.laptop._.to-users.homeManager.programs.direnv.enable = true; 404 - ``` 405 - 406 - Read: `docs/src/content/docs/guides/mutual.mdx` 407 - CI examples: `templates/ci/modules/features/user-host-mutual-config.nix` 408 - 409 - --- 410 - 411 - ## 11. Custom Nix Classes (`den._.forward`) 412 - 413 - `den.provides.forward` creates new Nix classes by forwarding aspect content into a target submodule path on an existing class. This is how all built-in home integrations (`homeManager`, `hjem`, `maid`) and the `user` class are implemented. 414 - 415 - Parameters: 416 - 417 - | Parameter | Description | 418 - |-----------|-------------| 419 - | `each` | List of items to iterate over | 420 - | `fromClass` | Custom class name to read from | 421 - | `intoClass` | Target class to write into | 422 - | `intoPath` | Target attribute path in target class | 423 - | `fromAspect` | The aspect to read the custom class from | 424 - | `guard` | (optional) Only forward when predicate returns true — use `lib.optionalAttrs` for option existence, `lib.mkIf` for config values | 425 - | `adaptArgs` | (optional) Transform module arguments before forwarding | 426 - | `adapterModule` | (optional) Custom submodule type for the forwarded submodule | 427 - 428 - Source: `modules/aspects/provides/forward.nix` 429 - Read: `docs/src/content/docs/guides/custom-classes.mdx` 430 - CI examples: `templates/ci/modules/features/forward-alias-class.nix`, `templates/ci/modules/features/forward-from-custom-class.nix`, `templates/ci/modules/features/guarded-forward.nix` 431 - 432 - ### Guarded Forwarding 433 - 434 - The `guard` function allows conditional class activation: 435 - 436 - - `guard = { options, ... }: options ? environment.persistance` — forward only when the option exists 437 - - `guard = { config, ... }: _item: lib.mkIf config.programs.vim.enable` — forward only when a config value is true 438 - 439 - CI example: `templates/ci/modules/features/guarded-forward.nix` 440 - 441 - --- 442 - 443 - ## 12. Namespaces 444 - 445 - Namespaces create scoped aspect libraries under `den.ful.<name>`, sharable across flakes. 446 - 447 - ```nix 448 - # Create/export namespace 449 - imports = [ (inputs.den.namespace "myns" true) ]; # true = export to flake.denful.myns 450 - 451 - # Create local-only namespace 452 - imports = [ (inputs.den.namespace "myns" false) ]; 453 - 454 - # Import from upstream flakes 455 - imports = [ (inputs.den.namespace "myns" [ inputs.team-config ]) ]; 456 - ``` 457 - 458 - After importing: 459 - - `den.ful.myns` — the namespace attrset 460 - - `myns` — module argument alias to `den.ful.myns` 461 - - `flake.denful.myns` — flake output (if exported) 462 - 463 - Each namespace has its own independent `aspects`, `ctx`, and `schema` sub-namespaces. 464 - 465 - Read: `docs/src/content/docs/guides/namespaces.mdx`, `docs/src/content/docs/reference/aspects.mdx` 466 - CI examples: `templates/ci/modules/features/namespaces.nix`, `templates/ci/modules/features/namespace-schemas.nix`, `templates/ci/modules/features/namespace-provider.nix` 467 - 468 - Source: `nix/lib/namespace.nix` 469 - 470 - --- 471 - 472 - ## 13. Angle Brackets Syntax 473 - 474 - Enable optional syntactic sugar via `__findFile`: 475 - 476 - ```nix 477 - { den, ... }: { 478 - _module.args.__findFile = den.lib.__findFile; 479 - } 480 - ``` 481 - 482 - Resolution rules (in order): 483 - 1. `<den.x.y>` → `config.den.x.y` 484 - 2. `<aspect>` → `config.den.aspects.aspect` 485 - 3. `<aspect/sub>` → `config.den.aspects.aspect.provides.sub` 486 - 4. `<namespace>` → `config.den.ful.namespace` 487 - 5. `<namespace/path>` → nested `provides` traversal 488 - 489 - The `/` separator maps to `.provides.` in the lookup path. 490 - 491 - To use angle brackets in a specific file, add `__findFile` to the module arguments attrset. 492 - 493 - Read: `docs/src/content/docs/guides/angle-brackets.mdx` 494 - Source: `nix/lib/den-brackets.nix` 495 - CI examples: `templates/ci/modules/features/angle-brackets.nix` 496 - 497 - --- 498 - 499 - ## 14. `den.lib` API 500 - 501 - Full reference: `docs/src/content/docs/reference/lib.mdx` 502 - Source: `nix/lib/default.nix` 503 - 504 - | Function | Purpose | 505 - |----------|---------| 506 - | `den.lib.parametric` | Wrap aspect with context-aware dispatch (atLeast) | 507 - | `den.lib.parametric.atLeast` | Same as `parametric` | 508 - | `den.lib.parametric.exactly` | Match only when required args exactly equal context | 509 - | `den.lib.parametric.fixedTo attrs aspect` | Apply aspect with fixed context | 510 - | `den.lib.parametric.expands attrs aspect` | Extend context with attrs before dispatch | 511 - | `den.lib.parametric.withOwn` | Low-level constructor | 512 - | `den.lib.canTake params fn` | Check if fn's required args are satisfied (atLeast) | 513 - | `den.lib.canTake.atLeast params fn` | Same as above | 514 - | `den.lib.canTake.exactly params fn` | Exact parameter match check | 515 - | `den.lib.take.atLeast fn ctx` | Call fn ctx if canTake.atLeast, else `{}` | 516 - | `den.lib.take.exactly fn ctx` | Call fn ctx if canTake.exactly, else `{}` | 517 - | `den.lib.perHost aspect` | Restrict to `{ host }` contexts | 518 - | `den.lib.perUser aspect` | Restrict to `{ host, user }` contexts | 519 - | `den.lib.perHome aspect` | Restrict to `{ home }` contexts | 520 - | `den.lib.statics aspect ctx` | Extract only static includes | 521 - | `den.lib.owned aspect` | Extract owned configs (no includes/functor) | 522 - | `den.lib.isFn value` | True if value is function or has `__functor` | 523 - | `den.lib.isStatic fn` | True if fn accepts `{ class, aspect-chain }` | 524 - | `den.lib.__findFile` | Angle bracket resolver | 525 - | `den.lib.aspects` | Full flake-aspects API (`resolve`, `merge`, types) | 526 - 527 - --- 528 - 529 - ## 15. Den as a Pure Library (Non-OS Domains) 530 - 531 - Den's `den.lib` is domain-agnostic. It can configure any Nix module system (Terranix, NixVim, system-manager, NVF, MicroVM, custom). The OS framework (`modules/`) is entirely optional. 532 - 533 - Import without the framework: 534 - ```nix 535 - # Use the nixModule for any module system 536 - denModule = (import inputs.den.outPath).nixModule inputs; 537 - ev = lib.evalModules { modules = [ denModule <your-module> ]; }; 538 - ``` 539 - 540 - Or call the library directly: 541 - ```nix 542 - den-lib = import inputs.den.outPath { inherit lib config inputs; }; 543 - ``` 544 - 545 - The library module has empty `den.ctx` and `den.aspects` — you populate them for your custom domain. 546 - 547 - Read: `docs/src/content/docs/explanation/library-vs-framework.mdx` 548 - CI example: `templates/ci/modules/features/den-as-lib.nix` 549 - 550 - --- 551 - 552 - ## 16. Flake Output Generation 553 - 554 - Den wires into `flake.nixosConfigurations`, `flake.darwinConfigurations`, `flake.homeConfigurations` automatically via `modules/config.nix`. 555 - 556 - - Each host calls `host.instantiate { modules = [ host.mainModule { nixpkgs.hostPlatform = host.system; } ]; }`. 557 - - `host.instantiate` defaults: `inputs.nixpkgs.lib.nixosSystem` (nixos), `inputs.darwin.lib.darwinSystem` (darwin). 558 - - Override `instantiate` to use a different builder or add `specialArgs`. 559 - - Override `intoAttr` to place output at a custom flake path (set to `[]` to suppress output entirely — used for microvm guests). 560 - 561 - Read: `docs/src/content/docs