Aspect-Oriented
Aspects bundle NixOS, Darwin, home-manager, or custom class config in one composable unit. Includes form a DAG. Provides create sub-aspects. One concern, all platforms.
Den takes the Dendritic pattern to a whole new level, and I cannot imagine going back.
—@adda- Very early Den adopter after using Dendritic flake-parts and Unify. [repo]
I’m super impressed with den so far, I’m excited to try out some new patterns that Unify couldn’t easily do.
—@quasigod- Author of Unify dendritic-framework, on adopting Den. [repo]
Massive work you did here!
—@drupol- Author of “Flipping the Configuration Matrix” Dendritic blog post.
Thanks for the awesome library and the support for non-flakes… it’s positively brilliant!. I really hope this gets wider adoption.
—@vczf- At#den-lib:matrix.orgchannel.
Den is a playground for some very advanced concepts. I’m convinced that some of its ideas will play a role in future Nix areas. In my opinion there are some raw diamonds in Den.
—@Doc-Steve- Author of Dendritic Design Guide
Traditional Nix configurations are host-first. Bluetooth on three machines means three files with duplicated config — one per host, split again across NixOS and home-manager.
# Without Den — duplicated across hosts and module systemshosts/laptop/configuration.nix # hardware.bluetooth.enable = truehosts/laptop/home.nix # services.blueman-applet.enable = truehosts/desktop/configuration.nix # hardware.bluetooth.enable = true (again)hosts/mac/darwin.nix # homebrew.casks = [ "blueutil" ] (different syntax)Den inverts this: aspects are the primary unit. One aspect, all platforms.
# With Den — one aspect configures everythingden.aspects.bluetooth = { nixos.hardware.bluetooth.enable = true; homeManager.services.blueman-applet.enable = true; darwin.homebrew.casks = [ "blueutil" ];};
# Every host that includes it gets bluetooth — across all classesden.aspects.laptop.includes = [ den.aspects.bluetooth ];den.aspects.desktop.includes = [ den.aspects.bluetooth ];Den context args flow automatically — no wrappers, no specialArgs, no infinite recursion:
# Den args and NixOS module args coexist in a single functionden.aspects.laptop.nixos = { host, config, pkgs, ... }: { networking.hostName = host.name;};Den is a library for composing Nix configurations via aspect-oriented programming and a framework for NixOS/Darwin/home-manager built on top.
Under the hood, Den uses a pure algebraic effects pipeline — aspects compile to computations, handlers decide what to do, and a trampoline interprets the result. This gives you extensible policies for entity topology, diagrams of your resolution graph, and custom classes for any Nix module system.
graph LR
H["host stage {host}"] --> U["user stage {host, user} (for each user)"]
U --> HM["aspect provides homeManager/hjeim class"]
H --> OS["aspect provides nixos/darwin class"]flowchart BT
subgraph "**den.aspects.dev-tools**"
n["nixos"]
h["homeManager"]
d["darwin"]
end
n --> server["server (NixOS)"]
n --> laptop["laptop (NixOS)"]
d --> mac["mac (Darwin)"]
h --> laptop
h --> mac
h --> standalone["alice (standalone HM)"]Aspect-Oriented
Aspects bundle NixOS, Darwin, home-manager, or custom class config in one composable unit. Includes form a DAG. Provides create sub-aspects. One concern, all platforms.
Pure Effects Pipeline
Built on algebraic effects via nix-effects. Aspects compile to computations, handlers own resolution strategy. Policies drive entity topology and bind behavior. Everything is extensible.
No Lock-in
Works with flake-parts, without flake-parts, or without flakes at all. Den works with anything configurable through Nix modules — NixOS, Terraform, NixVim, or your own domain.
Sharable Aspects
Namespaces let you publish and consume aspect libraries across flakes or non-flakes. Diagrams visualize your resolution graph for debugging and documentation.
Built on top of den.lib, Den provides a framework with ready-made facilities for
NixOS/nix-Darwin/homes configurations.
flowchart LR Schema["den.hosts / den.homes"] --> Pipeline["den.policies pipeline"] Aspects["den.aspects"] --> Pipeline Batteries["den.provides"] --> Pipeline Pipeline --> Resolve["Resolution"] Resolve --> Out["nixos / darwin / homeConfigurations"]
den.hosts and den.homes declare machines, users, and their properties with den.schema modules and extensible freeform types.den.aspects.* bundles per-class configs (nixos, darwin, homeManager, or any custom class) with .includes and .provides forming a DAG.den.policies fan out from entity kinds ({host} → {host, user}, {home}) and bind behavior. Batteries register derived entity kinds like hm-host, hm-user, wsl-host.nixpkgs.lib.nixosSystem, darwin.lib.darwinSystem, or home-manager.lib.homeManagerConfiguration.