Compare commits

...

5 Commits

5 changed files with 215 additions and 25 deletions

166
AGENTS.md Normal file
View File

@@ -0,0 +1,166 @@
# AGENTS.md
## Project Overview
NixOS dotfiles for two hosts using Nix flakes + home-manager:
- **mreow** — Framework 13 AMD AI 300 laptop, niri WM, greetd, swaylock
- **yarn** — Desktop, Jovian-NixOS (Steam deck mode), impermanence, sddm, deploy-rs target
Secrets in `system/secrets/` and `home-manager/secrets/` are encrypted with git-crypt. **Never read or write files in those directories.**
## Build & Deploy Commands
```sh
# Build and apply (default: boot, or pass switch/test/build)
./deploy.sh # nixos-rebuild boot --flake . --use-remote-sudo
./deploy.sh switch # apply immediately
./deploy.sh test # apply without adding boot entry
./deploy.sh build # build only, no activation
# Build a specific host without deploying
nix build .#nixosConfigurations.mreow.config.system.build.toplevel -L
nix build .#nixosConfigurations.yarn.config.system.build.toplevel -L
# Remote deploy to yarn via deploy-rs
deploy .#yarn
# Format all Nix files (uses nixfmt-tree, declared in flake.nix)
nix fmt
# Evaluate without building (quick syntax/type check)
nix eval .#nixosConfigurations.mreow.config.system.build.toplevel --no-build 2>&1 | head -5
nix eval .#nixosConfigurations.yarn.config.system.build.toplevel --no-build 2>&1 | head -5
# Update flake inputs
nix flake update
nix flake update --input-name nixpkgs # update a single input
```
There are no tests. Validation is done by building the system configuration (`nix build -L`).
Always append `-L` to `nix build` for verbose build logs.
If nix complains a file isn't found, `git add` the file first — Nix flakes only see tracked files.
## Repository Structure
```
flake.nix # Root flake: inputs, outputs, host definitions
deploy.sh # Wrapper around nixos-rebuild
system/
common.nix # Shared system config (boot, audio, users, etc.)
system-mreow.nix # Laptop-specific system config
system-yarn.nix # Desktop-specific system config
networking.nix # NetworkManager, DNS
impermanence.nix # Ephemeral root for yarn
disk_mreow.nix / disk_yarn.nix # Disko disk layouts
vm.nix # Virtualization (libvirt, waydroid)
vr.nix / no-rgb.nix / steam.nix # Feature modules
secrets/ # git-crypt encrypted, DO NOT READ
home-manager/
home-mreow.nix # Laptop home-manager entry point
home-yarn.nix # Desktop home-manager entry point
gui.nix # GUI packages + theming (imports no-gui.nix)
no-gui.nix # CLI tools, dev toolchains, git config
desktop.nix # Desktop environment (niri, dunst, swaylock, noctalia)
wallpaper.png # Shared wallpaper
progs/ # One file per program
fish.nix, alacritty.nix, emacs.nix, helix.nix, niri.nix, ...
zen/ # Zen Browser (multi-file: default.nix, ublock.nix, dark-reader.nix)
opencode.nix # AI coding tools config
util/ # Helper derivations (blur.nix, inverse_color.nix)
secrets/ # git-crypt encrypted, DO NOT READ
```
## Import Hierarchy
```
flake.nix
├─ system/system-{host}.nix → common.nix → networking.nix, vm.nix, steam.nix
└─ home-manager/home-{host}.nix → gui.nix → no-gui.nix
→ desktop.nix → niri.nix, dunst.nix, swaylock.nix, noctalia.nix
```
Adding a new program: create `home-manager/progs/myprog.nix`, import it from the appropriate layer (`gui.nix` for GUI apps, `no-gui.nix` for CLI tools, or `home-{host}.nix` for host-specific).
## Nix Code Style
**Formatter**: `nixfmt-tree` — run `nix fmt` before committing. All style below conforms to what nixfmt-tree produces.
### Module Structure
```nix
# Function arguments: destructured attrset, alphabetical-ish, always end with `...`
{ pkgs, lib, inputs, config, ... }:
# Optional let bindings for local values
let
myThing = "value";
in
{
imports = [
./other-module.nix
];
# Configuration here
}
```
### Conventions
- **Indentation**: 2 spaces (enforced by nixfmt-tree)
- **Imports**: relative paths (`./progs/fish.nix`), one per line in a list
- **Package references**: use `lib.getExe pkgs.foo` for bin paths, not `${pkgs.foo}/bin/foo`
- **Package lists**: group thematically with comments, use `with pkgs;` or `lib.concatLists` for multiple groups
- **Unfree packages**: explicitly allowlisted per-file via `nixpkgs.config.allowUnfreePredicate`
- **Comments**: lowercase, informal, `#` style. Use `# BUG!` or `# TODO!` prefixes for known issues
- **No trailing commas**: Nix syntax does not support them
- **Attribute sets**: opening brace on same line, closing brace aligned with the key
- **Overlays**: imported inline within the module that needs them via `nixpkgs.overlays`
- **Special args**: passed through `specialArgs` (system) or `extraSpecialArgs` (home-manager) in flake.nix — includes `inputs`, `username`, `hostname`, `niri-package`, `homeDirectory`, `stateVersion`
### Patterns Used
```nix
# Package path references
lib.getExe pkgs.swaylock # preferred
"${pkgs.avizo}/bin/volumectl" # acceptable when lib.getExe doesn't work
# Conditional/host-specific overrides
lib.mkForce false # override inherited values
lib.mkDefault "value" # set overridable defaults
# Helper derivations (see home-manager/util/)
pkgs.callPackage ../util/blur.nix # for derivations that take { stdenv, ... }:
# Combining package lists
home.packages = with pkgs; lib.concatLists [
[ pkg1 pkg2 ] # group 1
[ pkg3 pkg4 ] # group 2
someList # from let binding
];
```
### Naming
- **Host configs**: `system-{hostname}.nix`, `home-{hostname}.nix`, `disk_{hostname}.nix`
- **Program modules**: `progs/{program-name}.nix` (one program per file)
- **Utility derivations**: `util/{descriptive-name}.nix`
- **Variables**: `snake_case` or `camelCase` (no strict rule, follow local context)
## Key Technical Details
- **nixpkgs channel**: unstable (`nixos-unstable`)
- **Secure boot**: lanzaboote with keys extracted from `system/secrets/secureboot.tar`
- **Disk management**: disko
- **Privilege escalation**: doas (sudo is disabled), shim at `doas-sudo-shim`
- **Shell**: fish (bash redirects to fish via `programs.bash.interactiveShellInit`)
- **Wayland**: niri compositor, xwayland-satellite for X11 compat
- **Desktop shell**: noctalia-shell (bar, launcher, notifications)
- **Git**: GPG signing enabled (`signByDefault = true`), default branch `main`
- **Impermanence** (yarn only): root is ephemeral, `/persistent` holds state, home is bind-mounted
## Agent-Specific Instructions
- If instructed to commit, **disable GPG signing** (`git commit --no-gpg-sign`).
- Use `nix-shell -p <package>` if a tool is not available in the environment.
- For `nix build`, always append `-L` for verbose logs.
- If nix reports a missing file, run `git add <file>` first — flakes only see git-tracked files.
- Do not read files under `system/secrets/` or `home-manager/secrets/`.
- Run `nix fmt` after editing any `.nix` file.
- Validate changes with `nix build .#nixosConfigurations.{host}.config.system.build.toplevel -L`.

48
flake.lock generated
View File

@@ -65,11 +65,11 @@
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1773961521,
"narHash": "sha256-enhjd1AcHHU+3RCRdSWVQj6TIqRXkJUbQSFVXzC6xLo=",
"lastModified": 1774106245,
"narHash": "sha256-gB3XhG900wWKDa/dbqgK0wFGRf8u9PQhqN/SvnTZlIM=",
"owner": "sadjow",
"repo": "claude-code-nix",
"rev": "1519be1f77ed017ae4a88916ac54529cef885573",
"rev": "0b01bf3b7cb403ef11f502183b6de55e2aaccf88",
"type": "github"
},
"original": {
@@ -162,11 +162,11 @@
]
},
"locked": {
"lastModified": 1774025049,
"narHash": "sha256-mlXHmmL8lZibp/DytQuHjCfl0iU56qf4uJjlLZFY1Kc=",
"lastModified": 1774110692,
"narHash": "sha256-0JPH7CPdBCxx5IWNXZuqeiTwK8jS5ClT3xIO5brPNhI=",
"owner": "nix-community",
"repo": "emacs-overlay",
"rev": "2f30afcd2ca141e1cf9745439fffcf5fb044dfc8",
"rev": "e7876ebeff5bd7dcb1fcec5222f9f3a6f2ec7d89",
"type": "github"
},
"original": {
@@ -445,11 +445,11 @@
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1774017304,
"narHash": "sha256-4+MRnM772f76dpsXUxVp/2jW68C2wp4766pujWyqzx8=",
"lastModified": 1774104280,
"narHash": "sha256-kQeR1qqTFleJzMWsOttJMWUxMsykcKrUA2ttPIg2O4k=",
"owner": "numtide",
"repo": "llm-agents.nix",
"rev": "bbf9d11b64b8f42df45a8eb5829c9f64fe02cea8",
"rev": "4f6fca6b05c5b59b6bbb442a262596ddf86661e8",
"type": "github"
},
"original": {
@@ -472,11 +472,11 @@
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
},
"locked": {
"lastModified": 1773889880,
"narHash": "sha256-cu23CGP+mD2wKPKaoGM7evZ1dXfjd+cjryqqqx2HloE=",
"lastModified": 1774113359,
"narHash": "sha256-b7/LsPn5uZoFNjGVQ26q+6QPf8Q9IHHmRx+rGLZ8oyY=",
"owner": "sodiboo",
"repo": "niri-flake",
"rev": "63767d4572eb2e3da5e68f68de77d8f2cdeca8dd",
"rev": "1c4a800bbe0c4cbcf99529fd88286a14450261a8",
"type": "github"
},
"original": {
@@ -652,11 +652,11 @@
"noctalia-qs": "noctalia-qs"
},
"locked": {
"lastModified": 1774029401,
"narHash": "sha256-pM4U3rRPs+QUh/qfPFhcpmN2g9Nb91eIro1xcLdEYnA=",
"lastModified": 1774121595,
"narHash": "sha256-+NlTqaXbEwvL23RSCRiWn5jpRPeQPKWoPs753V3+WL4=",
"owner": "noctalia-dev",
"repo": "noctalia-shell",
"rev": "56457b140047e96a7a1e3bae6cf00cb9485d49a1",
"rev": "6b30925fb400c493e21494fb82af92d5b0f6d210",
"type": "github"
},
"original": {
@@ -675,11 +675,11 @@
"treefmt-nix": "treefmt-nix_2"
},
"locked": {
"lastModified": 1773842483,
"narHash": "sha256-oRqz+5AbNKfUWWwN5c83CsSOsUWVGITh0HZg+wX5Q/8=",
"lastModified": 1774059741,
"narHash": "sha256-ObYsrf7XLJDqWVbJ+GWH5JYV/EUc7SVdhGx5r5wWKno=",
"owner": "noctalia-dev",
"repo": "noctalia-qs",
"rev": "3962ff1e0b59ef067c57199d31271ddbf23b29cd",
"rev": "c9beee5c634ec784af128b8e7c56db14012ab17f",
"type": "github"
},
"original": {
@@ -741,11 +741,11 @@
]
},
"locked": {
"lastModified": 1773975983,
"narHash": "sha256-zrRVwdfhDdohANqEhzY/ydeza6EXEi8AG6cyMRNYT9Q=",
"lastModified": 1774062094,
"narHash": "sha256-ba3c+hS7KzEiwtZRGHagIAYdcmdY3rCSWVCyn64rx7s=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "cc80954a95f6f356c303ed9f08d0b63ca86216ac",
"rev": "c807e83cc2e32adc35f51138b3bdef722c0812ab",
"type": "github"
},
"original": {
@@ -944,11 +944,11 @@
]
},
"locked": {
"lastModified": 1773737882,
"narHash": "sha256-P6k0BtT1/idYveVRdcwAZk8By9UjZW8XOMhSoS6wTBY=",
"lastModified": 1774103303,
"narHash": "sha256-ZKsQGY0D4DLe3071/RZSQHLqqmFvsA38PudjEvnPbZI=",
"owner": "0xc000022070",
"repo": "zen-browser-flake",
"rev": "a7f1db35d74faf04e5189b3a32f890186ace5c28",
"rev": "ae52b215dd66f73cb131106b7588f3a983617cee",
"type": "github"
},
"original": {

View File

@@ -82,5 +82,16 @@
(map! :map undo-fu-mode-map "C-?" #'undo-fu-only-redo))
;; Fix SPC p p slowness
(after! projectile
(setq projectile-indexing-method 'alien
projectile-enable-caching nil
projectile-project-search-path '("~/projects/"))
(projectile-discover-projects-in-search-path))
;; Packages are already natively compiled by Nix; JIT recompilation
;; just wastes cycles (and the eln-cache is invalidated on every rebuild anyway)
(setq native-comp-jit-compilation nil)
;; line wrapping
(visual-line-mode t)

View File

@@ -93,6 +93,13 @@ in
"signon.rememberSignons" = false;
"signon.autofillForms" = false;
"signon.management.page.breach-alerts.enabled" = false;
"signon.formlessCapture.enabled" = false;
"signon.privateBrowsingCapture.enabled" = false;
# disable the autocomplete popup on login fields
"signon.firefoxRelay.feature" = "";
"signon.generation.enabled" = false;
# disable passkey/webauthn prompts from the built-in manager
"security.webauthn.enable_conditional_mediation" = false;
};
};
};

View File

@@ -169,7 +169,13 @@
power-profiles-daemon.enable = true;
# geolocation (uses beacondb.net by default)
geoclue2.enable = true;
geoclue2 = {
enable = true;
appConfig.zen-twilight = {
isAllowed = true;
isSystem = false;
};
};
};
# EST