This commit is contained in:
2026-03-03 16:30:58 +01:00
parent 5f34d32807
commit 6a49646d5e
34 changed files with 1229 additions and 1044 deletions

View File

@@ -1,27 +1,51 @@
# Gemini Context & Project Guidelines
# Den Configuration Framework: Core Concepts & Guidelines
This file serves as persistent contextual memory for the Gemini CLI when working on this NixOS configuration project.
## Overview
This NixOS configuration uses `den`, a declarative pipeline framework that shifts away from static module wiring to a system of **Context Transformation** and **Context-Aware Aspects**.
## Architecture: The `den` Framework
This repository manages NixOS and Home Manager configurations using the `den` framework. The approach here drastically differs from standard NixOS setups.
**Important Resource:** The `den` repository is vendored at `_ref/den/` and its official documentation can be found at `_ref/den/docs`. Use these resources (via `read_file`, `grep_search`, or `list_directory`) anytime you need to gain a deeper understanding of den's internal behavior or available features.
### Core Concepts & Rules
1. **Freeform Schemas over Custom Options:** Do not use legacy Nix module options (`lib.mkOption`, `lib.mkIf`) to define simple user/host properties (like email addresses, domains, or names). Instead, attach properties directly to the host or user definition objects in `hosts/<name>/default.nix` or `users/<name>.nix`. Den's freeform entity schemas will pass these through the context pipeline automatically.
2. **Parametric Aspects:** When a module requires access to host or user variables (like `user.email` or `host.domain`), the aspect MUST be wrapped in `den.lib.parametric`.
* *Example:* `lux.myapp = den.lib.parametric { includes = [ ({ user, ... }: { ... }) ]; };`
3. **Decentralized Host & User Definitions:** Do not centralize host definitions in a single file. Follow the `quasigod` reference structure:
* **Hosts** declare themselves in `modules/hosts/<hostname>/default.nix` (e.g., `den.hosts.x86_64-linux.orion = { ... }`).
* **Users** bind themselves to hosts in their own user files in `modules/users/<username>.nix` (e.g., `den.hosts.x86_64-linux.orion.users.kiri = userAccount // { ... }`).
4. **App Categories & Naming:**
* `/modules/desktop/`: GUI, Wayland, display managers, WMs.
* `/modules/dev/`: Developer tools, terminal, neovim.
* `/modules/apps/`: User-level software (PIM, Bitwarden, MPV, Email). Note: `pim.nix` stands for Personal Information Management and is an app, not a user definition.
* `/modules/services/`: System-level daemons (Caddy, Gitea, Vaultwarden).
* `/modules/profiles/`: Aggregations (like workstation/server).
## 1. Core Principles
* **Aspects (`__functor` pattern):** Configurations are functions of context, not static sets. An aspect (e.g., `{ host, user, ... }: { ... }`) inspects the context it receives and produces configs across domains (`nixos`, `homeManager`, `darwin`) simultaneously.
* **Context (`den.ctx`):** Attribute sets containing data (like `host` or `user`). Contexts are *named* (e.g., `ctx.hm-host` vs `ctx.host`) to provide guarantees (e.g., `hm-host` proves Home Manager detection passed).
* **The Pipeline (`into`):** Data flows through a defined pipeline. One context transforms `into` others (e.g., a single `ctx.host` fans out into multiple `ctx.user` contexts).
* **Providers (`provides`):** Aspects use `provides` to declare sub-aspects or inject configurations across contexts.
### Common Pitfalls & Lessons Learned
* **`home-manager` vs `homeManager`:** When defining class configurations inside a parametric function, the key for Home Manager is strictly `homeManager` (camelCase). Writing `home-manager.programs...` will cause evaluation errors because `home-manager` is not the class name used by the schema.
* **`user` is an Object:** In context parameters (`{ user, ... }:`), `user` is an attribute set, not a string. Do not interpolate it directly as a string (`"${user}"`); use `${user.name}`.
* **Namespace Inclusion:** The project uses the `lux` namespace. When an aspect needs to pull in other aspects, use `with lux; [ ... ]` rather than writing out `den.ful.lux...` repeatedly.
* **Abstracting Paths:** Never hardcode `/home/<username>`. Inside `homeManager` modules, use `config.home.homeDirectory`. Inside `nixos` modules (like SOPS), use `/home/${user.name}` where `user` is provided by the parametric context.
* **Git Status dependency:** When moving, creating, or renaming files (`mv`, `mkdir`), they must be staged in Git (`git add <file>`) before running `nix flake check`, otherwise the flake evaluator will not see the changes and will throw "undefined variable" or "path does not exist" errors.
## 2. Idiomatic Structure
* **Declaration vs. Configuration:** `den.hosts` and `den.homes` declare *what* exists (hosts, architectures, users). `den.aspects` define *how* they are configured.
* **Domain Spanning:** A single aspect file handles all relevant domains (e.g., a `git` aspect defines both `nixos.environment.systemPackages` and `homeManager.programs.git`).
* **Composition:** High-level aspects `include` lower-level aspect functions.
## 3. The Context Pipeline
1. **`ctx.host` `{ host }`:** Resolves the host's primary aspect (`den.aspects.<hostname>`).
2. **`ctx.default` `{ host }`:** Activates global defaults for the host.
3. **`ctx.user` `{ host, user }`:** Fans out to create a context for each user on the host. Resolves user aspects (`den.aspects.<username>`). *Crucially, host aspects can configure users here, and user aspects can configure the host.*
4. **`ctx.default` `{ host, user }`:** Activates global defaults for the user.
5. **`ctx.hm-host` `{ host }`:** If the host supports Home Manager and has HM users, this safely imports the HM module.
6. **`ctx.hm-user` `{ host, user }`:** For HM users, their config is forwarded into the host's `home-manager.users.<name>`.
## 4. Configuration Placement
* **Host Aspect (`den.aspects.<hostname>`):** Hardware, networking, system services. Can define default `homeManager` settings for all its users.
* **User Aspect (`den.aspects.<username>`):** Dotfiles, user packages, shell preferences. Can define required `nixos` settings for every host the user is on.
* **Global Defaults (`den.ctx.default`):** Universal settings (e.g., `stateVersion`, `den._.define-user`). **Note:** Prefer using more specific contexts (like `den.ctx.host` or `den.ctx.user`) over `den.ctx.default` whenever possible. Always write it as `den.ctx.default` rather than `den.default` to make it clear it is a context.
* **Feature Aspects:** Granular aspects included conditionally via `<den/lib> take.exactly` (or `den.lib.take.exactly`).
## 5. Common Pitfalls
* **The "Lax Context" Duplicate Config Bug:** A function like `({ host, ... }: { ... })` in `den.default.includes` runs at both the `ctx.host` and `ctx.user` stages, causing duplicate config errors.
* **Fix:** Use `<den/lib> take.exactly ({ host }: ...)` to run only at the host stage.
* **Missing `parametric` Wrapper:** Custom aspect trees (not auto-created by Den) that fail to forward context to their includes will throw `error: function 'anonymous lambda' called without required argument`.
* **Fix:** Wrap the custom aspect in `<den/lib> parametric`.
* **Home Manager Silent Failures:** If the detection gate fails (wrong OS, missing `"homeManager"` class on user, or missing `inputs.home-manager`), HM configs won't generate.
## 6. Essential Library Functions (`den.lib.*` & Batteries)
* `take.exactly`: Executes only if context matches arguments exactly.
* `take.atLeast`: Executes if context has at least the requested arguments.
* `parametric`: Wrapper to make an aspect forward context to its `includes`.
* `_.forward`: Translates config from one domain (e.g., custom class) to another.
* **Batteries (`den._.*`):** Built-in parametric aspects (e.g., `define-user`, `user-shell`, `tty-autologin`, `unfree`).
## 7. Useful Commands
* **`nix-search-tv`:** Use this command to look up docs for relevant options.
* Examples: `nix-search-tv preview "home-manager/ home.packages"`, `nix-search-tv preview "nixos/ environment.systemPackages"`.
* Prefix with `nixpkgs/` for nixpkgs docs.
* Use `nix-search-tv print` to print all available options and packages (filter output to avoid bloating context).