README.md (26098B)
1 # The author's laptop — NixDaemon's reference machine 2 3 This is the manual for `modules/hosts/laptop/` (`nixosConfigurations.nixos`): 4 one specific PCSpecialist Valeon II 17 with its fan fix, NVIDIA setup, private 5 dotfiles checkout and sops secrets. **It will not build for anyone else** — it 6 decrypts secrets with the author's age key and links a private dotfiles repo. 7 To install NixDaemon on your own machine, use the generic host instead: 8 [docs/install.md](../../../docs/install.md). 9 10 Personal values (name, email, GPG key, location) are in one file, 11 [`_identity.nix`](./_identity.nix). `$VAULT` below is the author's notes vault. 12 13 One flake, one machine: the TongFang GM7RGxM (Ryzen 9 6900HX, Radeon 680M, 14 RTX 3070 Ti, 2560×1440@240). Everything the machine is comes from here: 15 the kernel modules that keep the dead GPU fan from throttling the CPU, the 16 NVIDIA setup for Hyprland, the greeter, the compositor's Lua config and 17 keybinds, Caelestia as bar/launcher/lock, kitty with tmux-style keys, zsh 18 through the dotfiles checkout, the general tools, and the secrets. Built from 19 the vault's `04Tools/NixDaemon-Migration/` material on 2026-10-07. 20 21 The companion repo is `daemon-sec-dotfiles` (private, same account): 22 home-manager links every dotfile from its checkout (`~/git/daemon-sec-dotfiles`) 23 into `$HOME`, so editing the checkout edits the live config. 24 25 ## Structure 26 27 ```text 28 NixDaemon/ 29 ├── flake.nix inputs: nixpkgs (unstable), flake-parts, import-tree, wrapper-modules, home-manager, 30 │ hyprland, caelestia-shell, caelestia-cli, llm-agents, sops-nix, nvf 31 │ outputs = flake-parts.lib.mkFlake { inherit inputs; } (import-tree ./modules) 32 ├── .sops.yaml, secrets/ sops-nix: the age recipient and the encrypted secrets file 33 ├── scripts/wrap.sh turns a plain module file into a flake-parts module (how the tree below was made) 34 └── modules/ every *.nix here is a flake-parts module; paths containing /_ are skipped 35 ├── parts.nix systems; the home-manager and wrapper-modules flake modules 36 ├── hosts/laptop/ the machine — flake.nixosModules.laptop-* and the nixosConfiguration 37 │ ├── default.nix flake.nixosConfigurations.nixos = nixosSystem { modules = [ self.nixosModules.laptop ]; } 38 │ ├── configuration.nix self.nixosModules.laptop: imports every module below by name; daemon.desktop.* switches; 39 │ │ boot, users (zsh login shell), greetd/tuigreet, audio, fonts, portals, nix-ld, LocalSend port 40 │ ├── hardware.nix laptop-hardware (nixos-generate-config output, unchanged) 41 │ ├── fan-throttle-guard.nix laptop-fan-throttle-guard: vault gpu-fan-fix/, unchanged; fanfix + stability_guard.py beside it 42 │ ├── fan-extras.nix laptop-fan-extras: the performance power profile 43 │ ├── uniwill-laptop.nix laptop-uniwill: the `uniwill` hwmon the guard reads (uniwill-laptop/_package.nix, sources) 44 │ ├── nvidia.nix laptop-nvidia: open kernel module, panel on the dGPU, colon-free DRM names for Hyprland 45 │ ├── ssd.nix laptop-ssd: Samsung 980 crypttab + /mnt/ssd 46 │ ├── nix-settings.nix laptop-nix-settings: flakes, hyprland.cachix.org, nh + weekly clean, nvd, nom 47 │ ├── toolbox.nix laptop-toolbox: envfs, ~/.local/bin first on PATH, padx udev rule 48 │ ├── sops.nix laptop-sops: secrets/secrets.yaml → /run/secrets 49 │ ├── fan-cli.nix laptop-fan-cli: fan-ec, passwordless sudo for wheel 50 │ └── fan-reference/ the Arch-era captures and their README 51 ├── features/ shared NixOS features, by name 52 │ ├── workstation.nix workstation: Claude Code, Claude desktop, Obsidian, gh, glab 53 │ ├── home-manager.nix home-manager: HM as a NixOS module, users.daemonsec = self.homeModules.daemonsec 54 │ └── desktop/ 55 │ ├── options.nix desktop-options: daemon.desktop.hyprland.enable / daemon.desktop.niri.enable (both default true) 56 │ ├── hyprland.nix desktop-hyprland: programs.hyprland (uwsm), the GTK portal — gated 57 │ ├── niri.nix packages.niri (wrapper-modules: config.kdl from Nix, binds, Rosé Pine) + desktop-niri — gated 58 │ └── noctalia.nix packages.noctalia (wrapper-modules: settings.json from Nix, Rosé Pine "Rosepine" scheme) 59 │ └── pentest/ the offensive toolkit — one NixOS module per category, all toggleable 60 │ ├── default.nix nixosModules.pentest: imports every category below by name 61 │ ├── options.nix daemon.pentest.enable + the options no category owns 62 │ ├── _sets.nix mkCategory: one package list -> gated module + devShell + smoke check 63 │ ├── _aliases.nix suffix-free script aliases, collision-guarded (impacket's net/split/ping) 64 │ ├── _impacket.nix impacket + its aliases, shared by python.nix and ad.nix 65 │ ├── _overlay.nix the nixpkgs fixes the toolkit needs (python 3.12 anyio), each dated 66 │ ├── _pkgs/ pinned downloads: default.nix (SharpCollection, PEASS, mimikatz, scripts) + assets.nix (the release table: potatoes, nanodump, SharpHound CE, kerbrute, static nmap/socat…) 67 │ ├── nixpkgs.nix one package set for the system and for the flake's own checks 68 │ ├── core.nix recon.nix ad.nix web.nix pivot.nix crack.nix shells.nix 69 │ ├── wordlists.nix python.nix bloodhound.nix gui.nix payloads.nix paths.nix 70 │ ├── dfir.nix reversing.nix cloud.nix mobile.nix (off by default) 71 │ ├── wireless.nix radio.nix hardware.nix (off; needs hardware) 72 │ ├── c2.nix database.nix osint.nix social.nix (off by default) 73 │ ├── vpn.nix htbvpn: the HTB tunnel as a systemd template unit 74 │ ├── time.nix htb-time: conflict-aware clock skew for Kerberos 75 │ ├── htb.nix htbtarget / htbtime: the box you are on, shared across terminals 76 │ ├── boxes.nix htbbox: per-box tree + box.json + writeup.md (_htbbox.py) 77 │ ├── paths.nix ~/pentesting + the $privesc/$potatoes/$ligolo… vars + htbpaths 78 │ ├── casts.nix htbcast: asciinema recordings as raw write-up material 79 │ ├── devshells.nix nix develop #pentest, and the all-category collision check 80 │ └── update.nix pentest-update: move the _pkgs pins forward, deliberately 81 └── home/ flake.homeModules.* — the user's home 82 ├── default.nix homeModules.daemonsec: imports every module below by name 83 ├── hyprland.nix Lua config wiring, helper scripts, polkit, cliphist — only with daemon.desktop.hyprland 84 ├── caelestia.nix programs.caelestia: shell.json, the CLI with both Rosé Pine schemes — same gate 85 ├── terminal.nix kitty: DMMono Nerd Font, Rosé Pine dark, tmux-style ctrl+a keys, Neovim copy mode 86 ├── shell.nix zsh wiring (ZDOTDIR → dotfiles, fzf bindings, completions), tmux plugins, secretspec 87 ├── dotfiles.nix every dotfile from ~/git/daemon-sec-dotfiles as an out-of-store symlink 88 ├── tools.nix toolbox runtime closure, python env, the general CLI tools, `ns` (package search) 89 ├── cheats.nix the cheat cards: `nix-cheat` and `gpg-cheat` (cheats/*.md) 90 ├── sops.nix sops-nix for the user; sops, age, ssh-to-age 91 ├── neovim.nix nvf: Neovim with a small Nix-built plugin set, Rosé Pine 92 ├── prompt.nix starship and fastfetch 93 ├── fan.nix `fan`: status and watch without root; max/auto with the clamp watchdog 94 ├── htb-shell.nix $TARGET/$BOX in every terminal (zsh precmd) and in the prompt 95 ├── ssh.nix, gpg.nix, git.nix keys from sops, ~/.ssh/config, gpg.conf, git identity and signing 96 ├── media.nix mpd, rmpc, mpv 97 ├── yazi.nix, gtk.nix yazi with previews and Rosé Pine; Yaru-purple icons, cursor, prefer-dark 98 ├── hypr/*.lua omarchy (shim) · core · looknfeel · defaults · bindings · lid · caelestia 99 ├── kitty/, caelestia/, cheats/, gpg/, rmpc/, mpv/, yazi/ the data those modules read 100 ``` 101 102 ## What runs 103 104 | Layer | Choice | Where | 105 |---|---|---| 106 | Boot, login | systemd-boot · greetd + tuigreet (remembers user and session) | modules/hosts/laptop/configuration.nix | 107 | Compositor | Hyprland 0.56 under uwsm, configured in Lua; springy overshoot animations, square corners, blur | modules/home/hypr/, modules/home/hyprland.nix | 108 | Shell UI | Caelestia Shell: bar, launcher, dashboard, sidebar, lock, OSD, notifications. Rosé Pine dark, framed bar, 340 px panels | modules/home/caelestia.nix, modules/home/caelestia/ | 109 | Second desktop | Niri + Noctalia Shell (Rosé Pine "Rosepine"), both as wrapped packages: `nix run ~/NixDaemon#niri` / `#noctalia`. Pick the session in tuigreet; `daemon.desktop.{hyprland,niri}.enable` in configuration.nix drop one | modules/features/desktop/ | 110 | Terminal | kitty, DMMono Nerd Font, Rosé Pine dark, `ctrl+a` tmux-style prefix, copy mode in Neovim | modules/home/terminal.nix | 111 | Shell | zsh as login shell; config = the dotfiles' `~/.dotfiles` tree (autosuggestions, syntax highlighting, fzf-tab, zoxide, atuin). Prompt and fetch are Nix-managed | modules/home/shell.nix, prompt.nix | 112 | Dotfiles | symlinked from `~/git/daemon-sec-dotfiles/home` | modules/home/dotfiles.nix | 113 | Editor | Neovim via nvf: treesitter, LSP, blink completion, telescope, oil, gitsigns, which-key, Rosé Pine | modules/home/neovim.nix | 114 | Tools | uv, nodejs, btop, yazi, lazygit, tmux, ripgrep/fd/fzf/bat/eza, delta, tldr, LocalSend, … | modules/home/tools.nix | 115 | Secrets | sops-nix (age) for the repo; secretspec (keyring) for projects | modules/hosts/laptop/sops.nix, modules/home/sops.nix, shell.nix | 116 | GPU | NVIDIA open module, panel on the RTX; Aquamarine told the GPUs by colon-free udev symlinks | modules/hosts/laptop/nvidia.nix | 117 | Fan | `fan-throttle-guard`: 3.2 GHz floor, EC auto fan, `uniwill` hwmon from a 6.19 driver. `fan` command: status, watch, max/auto with a clamp watchdog | modules/hosts/laptop/fan-*.nix, uniwill-laptop/, modules/home/fan.nix | 118 | Pentest | 23 toggleable categories (`daemon.pentest.<category>.enable`, every one listed in `configuration.nix`): recon, AD, web, pivoting, cracking, shells, wordlists, payloads, BloodHound, GUI on; DFIR, reversing, wireless, radio (SDR/BT/RFID), hardware (JTAG/flash/CAN), C2, database, cloud, OSINT, social, mobile off. Tools go to `environment.systemPackages`, so `sudo nmap -sS` works. Every category carries a smoke check: `nix flake check` | modules/features/pentest/ | 119 | HTB workflow | `htbvpn up/down/list` (systemd template unit), `htbtarget` (shared across terminals via zsh precmd; writes `/etc/hosts` for Kerberos), `htbtime` (clock skew, restores exactly what it changed), `htbbox new <name> <ip> <os> <difficulty> [hosts]` (positional any-order, or flags, or gum prompts; scaffolds recon/enum/creds/loot/exploit/serve/casts + `box.json` + `writeup.md`; also `htbbox use/set/host/cred/flag/note/ports/json`), `htbcast` (asciinema v3 session recording → `txt` transcript for an agent, `gif` preview via agg), `payload-serve` (binds the tunnel only, refuses when the VPN is down), `pentest-cheat` | modules/features/pentest/{vpn,time,htb,boxes}.nix | 120 | Arsenal | `~/pentesting/` with permanent `$privesc $potatoes $creds $ad $ligolo $fscan $nmapbin $shells …` vars and `htbpaths` to navigate. ligolo-ng/chisel/fscan/pspy cross-compiled from source for every OS/arch; mimikatz (2 builds), the full potato family, nanodump, SharpHound CE, SharpCollection, static nmap/socat, kerbrute, PEASS — pinned by hash | modules/features/pentest/{payloads,paths}.nix, _pkgs/ | 121 | Nix | flakes, Hyprland cache, `nh` with weekly `clean all --keep 5 --keep-since 14d` | modules/hosts/laptop/nix-settings.nix | 122 123 ## Setting it up 124 125 ### Day to day (this machine) 126 127 ```sh 128 nh os switch # build, nvd diff, sudo, activate; = sudo nixos-rebuild switch --flake ~/NixDaemon#nixos 129 nh os boot # same, but activate on next boot (kernel / driver changes) 130 nix-cheat # the full card: rebuild, remote, nh, home, search, update, rollback, clean, … 131 nix-cheat nh # one section 132 ns kitty # fuzzy search nixpkgs + NixOS/home-manager options, with descriptions 133 pentest-cheat # the offensive toolkit card: htb, recon, ad, pivot, transfer, crack, web, dfir 134 pentest-cheat ad # one section 135 nix flake check # every pentest category's smoke check, plus the VM tests 136 nix develop ~/NixDaemon#pentest # the whole toolkit without installing it 137 ``` 138 139 home-manager is a NixOS module here, so one rebuild does both; there is no 140 separate `home-manager switch`. New files must be `git add`ed before nix sees 141 them (the repo is jj, colocated with git; `nix-cheat repo`). 142 143 ### From the repo, without a checkout 144 145 The repo is private, so the reference is the ssh form: 146 147 ```sh 148 REPO='git+ssh://git@gitlab.com/DAEMON-404/NixDaemon.git' 149 sudo nixos-rebuild switch --flake "$REPO#nixos" 150 nh os switch "$REPO" 151 nix flake show "$REPO" 152 ``` 153 154 ### Fresh install 155 156 1. Boot the NixOS live ISO, partition and mount at `/mnt`; generate 157 `hardware-configuration.nix` with `nixos-generate-config --root /mnt` and 158 compare it with `modules/hosts/laptop/hardware.nix` (UUIDs). 159 2. `git clone git@gitlab.com:DAEMON-404/NixDaemon.git && cd NixDaemon`, paste 160 the generated file's body into `modules/hosts/laptop/hardware.nix` (inside 161 the `flake.nixosModules.laptop-hardware =` wrapper). Do not drop a raw 162 `hardware-configuration.nix` into `modules/`: import-tree would load it as a 163 flake-parts module and evaluation would fail. 164 3. `sudo nixos-install --flake .#nixos`, reboot, log in at tuigreet, pick 165 **Hyprland (UWSM)** once. 166 4. Clone the dotfiles to `~/git/daemon-sec-dotfiles` (the links in 167 `modules/home/dotfiles.nix` point there) and the toolbox to `~/.local/bin`. 168 5. Restore the age key to `~/.config/sops/age/keys.txt` and copy it for the 169 system (see Secrets), then the Samsung SSD key (below). 170 171 ### The staged migration this repo was built for (2026-10-07, done) 172 173 History, kept as a record. Stage A (`#bootstrap`, built from `nixpkgs-stable`) 174 no longer exists: the dendritic rewrite of 2026-10-08 removed it, so none of 175 the `#bootstrap` commands below work any more. 176 177 **Stage A: fan fix now, on the GNOME install.** Small switch (fan module, 178 driver, toolbox prerequisites, Hyprland cache). The new kernel modules only 179 load from the booted system, hence the reboot. 180 181 ```sh 182 sudo nixos-rebuild switch --flake ~/NixDaemon#bootstrap && sudo reboot # or: nh os switch -H bootstrap 183 ``` 184 185 First-boot check (vault README and gpu-fan-fix/README.md): 186 187 ```sh 188 fanfix status # cap 3200 MHz · boost 1 · profile performance · fan line present 189 sudo fanfix fan status # fan-abnormal=1 is expected; universal-fan-ctrl / custom-tables show the live EC path 190 fanfix test 30 # all-core stress: expect 0 throttle events, peak < 75 °C 191 systemctl status motherboard-stability fanfix-fan fanfix-performance-profile 192 cat /run/motherboard-stability/status.json # limit_mhz 3200, thermal_stage 0, board_gpu_c and main_fan_rpm present 193 ``` 194 195 `fanfix status` will say "cap is not persisted": on NixOS the floor is the 196 `systemd.tmpfiles.rules` line in the module, not `/etc/tmpfiles.d/99-cpu-freq-cap.conf`. 197 Treat `fanfix install` / `uninstall` / `fan setup` as no-ops here; change 198 `capKhz` in the module instead (gpu-fan-fix README). `fanfix-fan` is expected 199 inactive: its manual fan mode makes the EC clamp all cores to 399 MHz under 200 load; EC auto fan with the 3.2 GHz floor passed `fanfix test 30` at 61 °C. 201 202 **Stage B: the desktop.** 203 204 ```sh 205 sudo nixos-rebuild boot --flake ~/NixDaemon#nixos && sudo reboot # or: nh os boot 206 ``` 207 208 tuigreet appears on tty1; pick `Hyprland (UWSM)` once, it is remembered. 209 Then the keybind diff against the vault capture: 210 211 ```sh 212 hyprctl binds -j | python3 -I -c 'import json,sys 213 M={1:"SHIFT",4:"CTRL",8:"ALT",64:"SUPER"} 214 for x in json.load(sys.stdin): 215 print(x.get("submap",""),"|","+".join(n for v,n in sorted(M.items()) if x["modmask"]&v),"|",x["key"],"|",x.get("description",""))' | sort > /tmp/binds.new 216 cut -d'|' -f1-4 $VAULT/04Tools/NixDaemon-Migration/shortcuts/keybinds.txt | sort | diff - /tmp/binds.new 217 ``` 218 219 Expected differences: the keycode binds (workspaces, resize, bar panels, 220 group windows) show `code:0` in the capture and an empty key here; the keys 221 caelestia.lua takes over carry their Caelestia descriptions; the stock 222 Obsidian and YouTube lines are gone because vault-open and bakx own those 223 keys; the two webcam-overlay binds were not carried (keycodes unknown). 224 225 `hosts/bootstrap/` and the `nixpkgs-stable` input were deleted on 2026-10-08. 226 227 **Samsung SSD key** (vault samsung-ssd.md, section 2; needs the gpg passphrase): 228 229 ```sh 230 cd $VAULT/04Tools/NixDaemon-Migration 231 sudo mkdir -p -m 700 /etc/secrets 232 gpg -d --pinentry-mode loopback ssd.key.gpg | sudo tee /etc/secrets/ssd.key >/dev/null 233 sudo chmod 400 /etc/secrets/ssd.key 234 sudo systemctl restart systemd-cryptsetup@ssd.service mnt-ssd.mount # or just reboot 235 ``` 236 237 Until then the drive stays locked; both units are `nofail`, so boot is 238 unaffected. The sops way: `sops set secrets/secrets.yaml '["ssd.key"]' "\"$(gpg -d ssd.key.gpg)\""`, 239 then `sops.secrets."ssd.key".path = "/etc/secrets/ssd.key";` in modules/hosts/laptop/sops.nix. 240 241 ## The shell 242 243 zsh is the login shell (modules/hosts/laptop/configuration.nix) and its configuration is 244 the dotfiles checkout's `home/.dotfiles` tree, reached through a Nix-managed 245 `~/.zshenv` that sets `ZDOTDIR=~/.dotfiles` (modules/home/shell.nix). The 246 plugins (autosuggestions, syntax highlighting, zsh-completions, fzf-tab, 247 history-substring-search, you-should-use) are the copies vendored in that 248 tree; starship, zoxide, atuin and fzf come from nixpkgs. Edit 249 `~/git/daemon-sec-dotfiles/home/.dotfiles/config/*.zsh` and open a new shell. 250 251 Things the shell modules want that this build provides: `~/.fzf.zsh` (fzf's 252 key bindings from the store, core.zsh only knows the Arch paths), the tool 253 configs linked into `~/.config` by dotfiles.nix (bat theme, atuin, crossfetch 254 for the splash animation, cheats, eza, btop, yazi, lazygit, carapace, and the 255 rest of the checkout's .config; the starship prompt and the fastfetch card are 256 Nix-managed in modules/home/prompt.nix), `~/.tmux.conf` with 257 its plugins from nixpkgs behind a TPM stand-in, and the binaries modern.zsh 258 aliases (btop, dust, duf, procs, delta, tldr, hyperfine, glow, onefetch, 259 lazygit, yazi, neovim). Not carried: `mise` (its downloaded runtimes 260 duplicate nixpkgs; `nix-ld` is on so `uv`'s managed Pythons work), and the 261 repo's git config (it turns on commit signing with a key that is not on this 262 machine; `~/.gitconfig` stays). 263 264 ## The dotfiles 265 266 `modules/home/dotfiles.nix` mirrors `~/git/daemon-sec-dotfiles/home/` into 267 `$HOME` with out-of-store symlinks: editing the checkout edits the live 268 config, and a rebuild is only needed to add or remove a path in the list. 269 The header of that file names what is deliberately not linked (hypr and 270 kitty are Nix-managed, the omarchy trees, the systemd units, mimeapps, 271 git's signing config, the bash rc files, `.claude`/`.codex`, the toolbox 272 `bin` directories) and why. 273 274 ## The toolbox 275 276 `~/.local/bin` is the vault's `bin/` copied flat and `git init`ed (remote 277 `gitlab` → `DAEMON-404/daemon-bin`, not pushed). NixOS puts it first on PATH 278 and envfs resolves the `#!/bin/bash` and `#!/usr/bin/python3` shebangs. 279 `install.sh` there reports the environment. Notes: 280 281 - `dropterm`, `winsnap`, `vault-open`, `lid-control` call 282 `hyprctl dispatch 'hl.dsp…'`: that is Hyprland 0.56's Lua dispatch syntax, 283 so they work unchanged. 284 - `winsnap` looks for an `omarchy-bar` layer to avoid the bar; Caelestia's 285 layers are `caelestia-*`, so snaps ignore the bar's reserved edge for now. 286 - `lid-control` still calls a few `omarchy-*` helpers (tolerated: they fail 287 quietly); `clipboard-backup` and `omarchy-menu-tmux-keybindings` are bound 288 but not in the carried `bin/`. 289 - The cheat popups (`omarchy-menu-kitty`, …) pipe into `omarchy-menu-select`, 290 provided here as a fuzzel wrapper (modules/home/hyprland.nix). `nix-cheat` 291 and `gpg-cheat` are this repo's own cards, in the same style. 292 293 ## Secrets 294 295 Two tools. **sops-nix** keeps secrets *in this repo*, encrypted with age 296 (`.sops.yaml` names the recipient, `secrets/secrets.yaml` holds the values) 297 and decrypts them at activation: `/run/secrets/NAME` for the system 298 (modules/hosts/laptop/sops.nix), `~/.config/sops-nix/secrets/NAME` for the user 299 (modules/home/sops.nix). The age key is `~/.config/sops/age/keys.txt`, 300 created on 2026-10-08 and **not in the repo**; back it up (vault) and give 301 the system its copy once: 302 303 ```sh 304 sudo install -D -m 600 -o root -g root ~/.config/sops/age/keys.txt /var/lib/sops-nix/key.txt 305 ``` 306 307 Edit with `sops secrets/secrets.yaml`, declare with `sops.secrets.NAME = { };`, 308 rebuild. `nix-cheat secrets` has the commands. 309 310 What the file holds today: `ssh_id_ed25519` (the SSH private key, used by 311 modules/home/ssh.nix), `gpg_main_secret` (the armored GPG secret key, still 312 under its own passphrase, imported by modules/home/gpg.nix on first 313 activation), and `example`. So a fresh install needs exactly one secret 314 restored by hand, the age key; ssh, gpg and git then come up from the flake. 315 316 **secretspec** is for a project's runtime secrets: declared next to the 317 project in `secretspec.toml`, values in the system keyring 318 (`~/.config/secretspec/config.toml`: provider `keyring`, profile `default`; 319 gnome-keyring is unlocked at login by PAM). `secretspec init`, `secretspec 320 add NAME`, `secretspec check`, `secretspec run -- cmd`. 321 322 ## Look and keys 323 324 - **Caelestia in Rosé Pine dark** (main), translucent over blur, with its 325 framed bar: a 10 px border with 25 px rounded inner corners, clock and 326 tray in pills, filled occupied workspaces, the Nix snowflake as the logo. 327 Sidebar, utilities and notification panels are narrower than stock 328 (`modules/home/caelestia/shell-tokens.json`). A Dawn mapping is registered too: 329 `caelestia scheme set -n rose-pine -f rose-pine-dawn`. 330 - **Bar shows the program**, not the window title: a small patch to the 331 shell's ActiveWindow component (`modules/home/caelestia/active-window-program-name.patch`, 332 applied in caelestia.nix) makes compact mode use the desktop entry's name 333 for the window class. The shell compiles locally because of it. 334 - **More shell**: desktop clock on the wallpaper (bottom right), audio 335 visualiser along the bottom while something plays, weather on the 336 dashboard (location in `_identity.nix`), audio and microphone status icons, lock screen over 337 the wallpaper, a toast on track change, vim keys in the launcher, and 338 idle: lock after 15 min, screen off after 20 (audio or an inhibitor holds 339 both off). 340 - **Springy windows**: `modules/home/hypr/looknfeel.lua` carries the dotfiles' 341 animation rice (overshoot curves on move/resize/open, shadows, blur 342 tuning, drag snapping, swallow, 3-finger workspace swipe, 4-finger-up 343 fullscreen). Loaded after core.lua. 344 - **kitty, tmux-style** (`ctrl+a` prefix; table in modules/home/terminal.nix): 345 `c` tab, `-`/`|` splits, `hjkl` panes, `z` zoom, `[` copy mode in Neovim 346 (`v` select, `y` copy, Enter copy and leave, `q`), `]` paste, `1..9` tabs, 347 `ctrl+a ctrl+a` sends a real ctrl+a to the shell. 348 - `CTRL+SUPER+SPACE` opens the Caelestia launcher in its wallpaper grid 349 (helper `wallpaper-picker`); `>wallpaper name` filters. The directory is 350 `paths.wallpaperDir` in modules/home/caelestia.nix. 351 - Keys to try first: SUPER+RETURN terminal, SUPER+SPACE launcher, 352 SUPER+ESCAPE session menu, SUPER+K keybindings list, SUPER+M window mode, 353 SUPER+` dropdown terminal, PRINT screenshot. 354 355 ## Why `uniwill-laptop` is built here 356 357 `stability_guard.py` reads the `uniwill` hwmon (board GPU temperature, main 358 fan rpm) and falls back to a permanent 1.8 GHz ceiling without it. The driver 359 was merged upstream in Linux 6.19; nixpkgs' 6.18 kernel predates it and the 360 7.2 kernel config leaves its Kconfig submenu off. `modules/hosts/laptop/uniwill-laptop/` 361 holds the v6.19 sources and builds them as an out-of-tree module against 362 whatever kernel is selected (verified on 6.18.55). Revisit when the default 363 NixOS kernel ships it. 364 365 ## Parked for the owner 366 367 - **ANSI green**: Rosé Pine puts pine (#31748f) in the green slot; the rule 368 says pine is never ink. kitty uses foam (#9ccfd8) for color2/color10 369 meanwhile; one variable in modules/home/terminal.nix. 370 - **Display manager**: greetd + tuigreet chosen (text greeter, remembers 371 user and session). sddm would be a one-file swap. 372 - **GPU / MUX**: configured for what the firmware presents, the panel on the 373 RTX 3070 Ti (discrete). The hybrid alternative is a commented block in 374 nvidia.nix; it only applies after changing the MUX in the BIOS. 375 - **Hostname** stays `nixos` (the installer's). The flake output is also `nixos`. 376 - Stock Omarchy keys whose program is still not installed (spotify, 377 1password, signal) show a notification saying so. Add packages to 378 modules/home/tools.nix when wanted. 379 380 --- 381 382 <p align="center">☧ · <a href="https://rosepinetheme.com/">Rosé Pine</a> all the way down · built with Claude Code</p>