nix-config/AGENTS.md

245 lines
6.8 KiB
Markdown

# AGENTS.md — nix-config
Personal NixOS/nix-darwin configuration using flake-parts, import-tree, home-manager, and nixvim.
---
## Repository Overview
```
flake.nix # Thin entry: delegates to import-tree ./modules
Justfile # Task runner (deploy, dry-run, update, gc, etc.)
modules/
config.nix # flake-parts options schema (flake.modules, flake.globalConfig)
systems.nix # Supported systems list
hosts/
dnsc-machine/ # Only active NixOS host (x86_64-linux)
base/ # macOS system defaults + NixOS locale/boot/user base
<feature>/ # One directory per feature module
default.nix # Always the primary file
_sub-module.nix # Underscore-prefixed for large module splits
```
`import-tree` auto-discovers every `.nix` file under `modules/`**no manual imports list in flake.nix**.
New modules are picked up automatically; just create `modules/<name>/default.nix`.
---
## Build / Validation Commands
There is no CI and no `nix fmt`/`nix flake check` target configured.
| Goal | Command |
|---|---|
| Deploy to host | `just deploy <host>` (`sudo nixos-rebuild switch --flake .#<host>`) |
| Deploy with trace | `just debug <host>` (adds `--show-trace --verbose`) |
| Dry-run build | `just dry <host>` — evaluates the closure without realising it |
| Update all inputs | `just update` (`nix flake update`) |
| Garbage collect | `just gc` (`sudo nix-collect-garbage --delete-old`) |
| Wipe old profiles | `just clean` (removes profiles older than 7 days) |
| NixOS REPL | `just repl` |
**Only active host:** `dnsc-machine`
```
just dry dnsc-machine # fastest sanity check — no sudo required
just deploy dnsc-machine
```
There are no unit tests or `checks` outputs. Validation = dry-run build succeeds + manual deploy.
**Linting tools available** (installed as system packages): `nil` (LSP), `statix` (linter).
Run `statix check .` to lint Nix files for common anti-patterns.
---
## Flake Architecture
```
inputs.flake-parts → mkFlake framework
inputs.import-tree → auto-loads modules/
inputs.nixpkgs → nixpkgs-unstable (channel tarball URL, not github:)
inputs.home-manager → follows nixpkgs
inputs.nix-darwin → LnL7/nix-darwin master
inputs.nixvim → nix-community/nixvim
inputs.helium → custom browser flake
inputs.dms → DankMaterialShell (COSMIC alternative desktop)
```
**Custom flake-parts options** (defined in `modules/config.nix`):
- `flake.modules.nixos.<name>` — NixOS system modules
- `flake.modules.darwin.<name>` — nix-darwin system modules
- `flake.modules.homeManager.<name>` — home-manager user modules
- `flake.globalConfig.{username,fullname,email}` — shared personal values
---
## Module Pattern
Every feature lives in `modules/<feature>/default.nix` and registers itself into the module registry.
Host configs (`modules/hosts/<name>/default.nix`) opt in by listing modules explicitly.
### Standard tri-layer module
```nix
{ inputs, ... }:
{
flake.modules.nixos.<name> =
{ pkgs, ... }:
{
# NixOS system-level config
home-manager.sharedModules = [
inputs.self.modules.homeManager.<name>
];
};
flake.modules.darwin.<name> =
{ pkgs, ... }:
{
# nix-darwin system-level config
home-manager.sharedModules = [
inputs.self.modules.homeManager.<name>
];
};
flake.modules.homeManager.<name> =
{ pkgs, config, ... }:
{
# home-manager user-level config
};
}
```
### System-only module (no HM layer)
```nix
{ ... }:
{
flake.modules.nixos.<name> =
{ pkgs, ... }:
{
# NixOS config only, e.g. bluetooth, printing, gaming
};
}
```
### Sub-module splitting (for large modules like neovim)
```nix
flake.modules.homeManager.neovim =
{ pkgs, ... }:
{
imports = [
./_options.nix
./_lsp.nix
./_formatter.nix
];
};
```
### Host definition pattern
```nix
{ inputs, config, ... }:
let
hostname = "dnsc-machine";
in
{
flake.nixosConfigurations.dnsc-machine = inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = with config.flake.modules.nixos; [
home-manager
base
shell
# ... feature modules by name
{
imports = [ ./_hardware-configuration.nix ];
networking.hostName = hostname;
system.stateVersion = "24.11";
}
];
};
}
```
---
## Code Style
### Formatting
- **2-space indentation** throughout, no tabs
- Opening brace on the same line as the attribute/binding
- Closing brace on its own line
- No trailing commas in attribute sets or lists (standard Nix)
- Multi-line function arguments use the exploded form:
```nix
{
inputs,
config,
...
}:
```
Short arg lists use the inline form: `{ pkgs, ... }:`
### Inline embedded languages
Use language comments to enable editor syntax highlighting inside multiline Nix strings:
```nix
interactiveShellInit = /* fish */ ''
fish_vi_key_bindings insert
'';
extraConfig = /* lua */ ''
vim.opt.number = true
'';
```
### Naming conventions
| Thing | Convention | Example |
|---|---|---|
| Module directories | `kebab-case` | `cli-tools/`, `nvidia-graphics/` |
| Primary module file | `default.nix` | every feature dir |
| Sub-module files | `_kebab-case.nix` (underscore prefix) | `_lsp.nix`, `_formatter.nix` |
| Hardware config | `_hardware-configuration.nix` | matches sub-module style |
| `flake.modules.nixos.*` keys | `kebab-case` | `flake.modules.nixos.cli-tools` |
| `flake.modules.homeManager.*` keys | `kebab-case` name, `homeManager` namespace | `flake.modules.homeManager.shell` |
| `let` bindings | `camelCase` | `hmConfig`, `commonPackages` |
| Host names | `kebab-case` with owner prefix | `dnsc-machine`, `dnsc-server` |
| Fish functions | `snake_case` | `fish_greeting`, `tmux_sessionizer` |
| Fish abbrs | short lowercase | `lg`, `gg`, `g` |
### Attribute ordering
In NixOS/HM options, follow upstream conventions:
- `enable = true;` first
- then primary config attributes
- then nested option sets
### No conditional feature flags
Feature modules do **not** use `mkEnableOption`/`mkIf`. Everything in a module is unconditionally enabled when that module is included in a host's modules list. Opt-in/opt-out happens at the host level by adding or removing the module name.
---
## Adding a New Feature Module
1. Create `modules/<feature>/default.nix`
2. Define `flake.modules.nixos.<feature>` and/or `flake.modules.homeManager.<feature>`
3. To activate on a host, add `<feature>` to the `modules = with config.flake.modules.nixos; [ ... ]` list in the host's `default.nix`
4. No registration in `flake.nix` needed — `import-tree` picks it up automatically
---
## Commit Style
Lowercase, brief, imperative — no conventional-commits prefix required:
```
add bluetooth module
fix cli tools config
remove gtk handling
update nixpkgs input
```