Compare commits

..

6 commits

Author SHA1 Message Date
d6d1f921e2
Add trash-cli with trash alias
Install trash-cli and alias trash to trash-put for safe file deletion.
Also clean up package comments and remove spacedrive-v2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:51:15 +01:00
7156981e57
Add fish shell functions and abbreviations
Add nomad-ui function, --np contextual expansion, and related abbreviations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:51:01 +01:00
2073876eaf
Add Blue Yeti USB reset service for cold-boot fix
The Blue Yeti mic initializes audio endpoints in a broken state on cold boot
because snd-usb-audio loads after device enumeration. This systemd service
toggles USB authorization to force a clean rebind.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:50:47 +01:00
09a71afe84
Update flake inputs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:50:37 +01:00
890767d224
Add CLAUDE.md with project documentation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:50:30 +01:00
dfb6a8e3b6
Rename writeNushellApplication to exclude from import-tree
Prefixing with underscore prevents auto-import while keeping the file available for explicit use.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:50:26 +01:00
7 changed files with 150 additions and 15 deletions

87
CLAUDE.md Normal file
View file

@ -0,0 +1,87 @@
# CLAUDE.md
NixOS + nix-darwin dotfiles managing multiple hosts via a single flake.
Uses **flake-parts**, **import-tree**, **home-manager**, and **agenix** for secrets.
## Hosts
| Host | Platform | Role |
|------|----------|------|
| **endurance** | nixos (x86_64-linux) | Desktop workstation (AMD GPU, Niri compositor) |
| **aepplet** | nixos (x86_64-linux) | Data/compute server |
| **vasa** | darwin (x86_64-darwin) | macOS (minimal config) |
Host configs live in `hosts/{name}/` with `default.nix`, `hardware.nix`, and `disko.nix`.
## Key directories
| Path | What's there |
|------|-------------|
| `flake.nix` | Entry point — all inputs and flake-parts imports |
| `modules/flake/` | Flake-parts modules: host definitions, home-manager wiring, packages, formatter, lib |
| `modules/generic/` | Shared config (nix settings, profiles, base packages) — applies to all platforms |
| `modules/nixos/` | NixOS-specific: system, users, SSH, services (ollama, traefik, beszel, metrics) |
| `modules/nixos/profiles/` | Composable feature profiles: `graphical`, `docker`, `work` |
| `modules/darwin/` | macOS-specific modules |
| `modules/home/` | Home-manager modules shared across hosts (helix, terminal, shell, kitty, GUI) |
| `home/by-host/{name}/` | Per-host home-manager config (programs, services, theming) |
| `home/by-host/{name}/config/` | Auto-imported config modules (dev, shell, git, etc.) |
| `home/by-host/{name}/misc/` | Optional per-host services (launcher, browser, recording) |
| `home/by-host/{name}/niri/` | Niri WM config (keybinds, window rules, autostart) |
| `packages/` | Custom packages (each dir has `package.nix`, auto-discovered) |
| `overlays/` | Nixpkgs overlays (lix, unstable channel packages, custom builds) |
| `secrets/` | Age-encrypted secrets managed by agenix |
## Custom options namespace
This flake uses a `bosun` namespace for composable options:
```nix
bosun.profiles.graphical.enable = true;
bosun.profiles.docker.enable = true;
bosun.profiles.work.enable = true;
bosun.key = "ssh-ed25519 ..."; # Host SSH public key
bosun.secrets.npmrc = { ... }; # Secret definitions
```
Profile definitions are in `modules/generic/profiles.nix`, implementations in `modules/nixos/profiles/`.
## Architecture patterns
- **import-tree** auto-discovers and imports `.nix` files in `modules/flake/`. Files prefixed with `_` are excluded from auto-import.
- **easy-hosts** manages host definitions in `modules/flake/hosts.nix`.
- **Overlays** receive `inputs` and `channels` (multiple nixpkgs instances) via the `withChannels` wrapper in `overlays/default.nix`.
- **Stylix** handles system-wide theming (colors, fonts) from a single config.
- **Lix** is used instead of stock Nix.
## Commands (`just`)
```
just deploy # nixos-rebuild switch / darwin-rebuild switch
just debug # Build with --show-trace --verbose via nom
just repl # nix repl with flake loaded
just shell <name> # Enter a dev shell
just up # Update all flake inputs
just upp <input> # Update a single input
just gc # Garbage collect old generations
just rekey # Rekey all agenix secrets
just edit-secret <f> # Edit an encrypted secret
```
## Where to find settings
| Looking for... | Go to |
|---------------|-------|
| Which hosts exist and their platform | `modules/flake/hosts.nix` |
| Home-manager host assignments | `modules/flake/homes.nix` |
| Nix daemon settings, substituters, gc | `modules/generic/nix.nix` |
| Locale, timezone, stateVersion | `modules/nixos/system.nix` |
| User accounts | `modules/nixos/users.nix` |
| SSH daemon config | `modules/nixos/ssh.nix` |
| Shell config (Fish, Nushell) | `modules/home/common/terminal/shell/` |
| Helix editor config | `modules/home/common/helix/` |
| Kitty terminal | `modules/home/gui/kitty.nix` |
| Desktop programs for endurance | `home/by-host/endurance/config/dev.nix` and `misc/` |
| Niri keybinds & window rules | `home/by-host/endurance/niri/` |
| Available packages | `packages/` (auto-discovered by flake-parts) |
| Secret definitions | `modules/*/secrets.nix` + `secrets/*.age` |

24
flake.lock generated
View file

@ -129,11 +129,11 @@
]
},
"locked": {
"lastModified": 1769920146,
"narHash": "sha256-Co8wpqWe5SWzsx0Fy2Q7+tpnDlvHe+ksX+9Lis4NJFw=",
"lastModified": 1769313163,
"narHash": "sha256-pjYF+adGJBkMLgKFAhnMEMR0818OsCaZAZREYs/baPQ=",
"owner": "nix-community",
"repo": "buildbot-nix",
"rev": "21a138e5230c23fb253559bea63ec0979156aff3",
"rev": "6c0fbf1425279800fd8f02796fdb567599587b7b",
"type": "github"
},
"original": {
@ -1204,11 +1204,11 @@
]
},
"locked": {
"lastModified": 1769939035,
"narHash": "sha256-Fok2AmefgVA0+eprw2NDwqKkPGEI5wvR+twiZagBvrg=",
"lastModified": 1769069492,
"narHash": "sha256-Efs3VUPelRduf3PpfPP2ovEB4CXT7vHf8W+xc49RL/U=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "a8ca480175326551d6c4121498316261cbb5b260",
"rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23",
"type": "github"
},
"original": {
@ -1367,11 +1367,11 @@
]
},
"locked": {
"lastModified": 1769921679,
"narHash": "sha256-twBMKGQvaztZQxFxbZnkg7y/50BW9yjtCBWwdjtOZew=",
"lastModified": 1769314333,
"narHash": "sha256-+Uvq9h2eGsbhacXpuS7irYO7fFlz514nrhPCSTkASlw=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "1e89149dcfc229e7e2ae24a8030f124a31e4f24f",
"rev": "2eb9eed7ef48908e0f02985919f7eb9d33fa758f",
"type": "github"
},
"original": {
@ -1614,11 +1614,11 @@
]
},
"locked": {
"lastModified": 1769691507,
"narHash": "sha256-8aAYwyVzSSwIhP2glDhw/G0i5+wOrren3v6WmxkVonM=",
"lastModified": 1769353635,
"narHash": "sha256-J0G1ACrUK29M0THPAsz429eZX07GmR9Bs/b0pB3N0dQ=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "28b19c5844cc6e2257801d43f2772a4b4c050a1b",
"rev": "f46bb205f239b415309f58166f8df6919fa88377",
"type": "github"
},
"original": {

View file

@ -15,9 +15,10 @@
bottom # System resource monitor
grim # Screenshots
slurp # Region selection
portfolio
pytr
portfolio # Investment management
pytr # TradeRepublic CLI
tabiew # csv viewer
trash-cli # Freedesktop trash management
# Productivity
obsidian # Note taking
@ -26,7 +27,6 @@
onlyoffice-desktopeditors # libreoffice alternative
speedcrunch # GUI calculator app
calibre # eBook Manager
spacedrive-v2
# loupe # Photo viewer
(dokieli.overrideAttrs

View file

@ -198,6 +198,31 @@
# systemd.packages = [pkgs.lact];
# systemd.services.lactd.wantedBy = ["multi-user.target"];
# Blue Yeti (046d:0ab7) initializes its audio endpoints in a broken state on cold boot
# because snd-usb-audio loads ~2s after the device enumerates. Toggling authorized
# forces a USB rebind on a clean device, mimicking unplug/replug.
systemd.services.blue-yeti-reset = {
description = "Reset Blue Yeti USB mic to fix cold-boot initialization";
after = ["systemd-udev-settle.service"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "blue-yeti-reset" ''
for dev in /sys/bus/usb/devices/*/; do
[ -f "$dev/idVendor" ] || continue
vendor=$(cat "$dev/idVendor" 2>/dev/null)
product=$(cat "$dev/idProduct" 2>/dev/null)
if [ "$vendor" = "046d" ] && [ "$product" = "0ab7" ]; then
echo 0 > "$dev/authorized"
sleep 0.5
echo 1 > "$dev/authorized"
break
fi
done
'';
};
};
hardware = {
amdgpu = {
opencl.enable = true;

View file

@ -8,5 +8,6 @@
cat = "bat";
vim = "hx";
vi = "hx";
trash = "trash-put";
};
}

View file

@ -20,6 +20,13 @@ in {
'';
functions = {
nomad-ui = {
description = "Fetches the Nomad management token from alvin and opens the authenticated UI";
body = ''
set -gx NOMAD_TOKEN (ssh root@alvin cat /var/lib/nomad-acl/management.token)
nomad ui -authenticate
'';
};
agx = {
wraps = "ag";
description = "Runs ag on the given string and returns a list of selectable references of the result. The selection is then opened in the editor.";
@ -27,6 +34,17 @@ in {
hx (ag $search $argv[2..] | fzf | cut -d : -f 1,2)
'';
};
__np_expand = {
description = "Expands --np contextually: --pp for bat/cat, --no-pager otherwise";
body = ''
set -l cmd (commandline -po)[1]
if test "$cmd" = bat -o "$cmd" = cat
echo -- --pp
else
echo -- --no-pager
end
'';
};
};
preferAbbrs = true;
@ -52,6 +70,10 @@ in {
position = "anywhere";
expansion = "--color";
};
"--np" = {
position = "anywhere";
function = "__np_expand";
};
};
};
}