initial commit

This commit is contained in:
2026-03-24 19:07:42 +01:00
commit 7a2f92fd98
112 changed files with 12548 additions and 0 deletions

132
README.md Normal file
View File

@@ -0,0 +1,132 @@
# SaugOS
A dev-focused NixOS configuration for older laptops, distilled from [ZaneyOS](https://gitlab.com/Zaney/zaneyos). Uses the **Niri** scrolling tiling Wayland compositor with Catppuccin Mocha theming, Waybar, and a curated set of development tools.
## What's Included
- **Niri** window manager with full keybindings, window rules, and waybar integration
- **Neovim** (via nvf) with LSP, Treesitter, Telescope — full IDE setup
- **VS Code**, **Ghostty**, **Kitty**, **Tmux**
- **Zsh** with Powerlevel10k, Oh-My-Zsh, syntax highlighting
- **Yazi** file manager, **lazygit**, **bat**, **eza**, **fzf**, **zoxide**
- **Stylix** system-wide theming (Catppuccin Mocha, JetBrains Mono)
- **TLP** + **thermald** for laptop power management
- **Docker** for containerized development
- **Rofi** launcher, **swaync** notifications, **wlogout**
- No gaming packages, no NVIDIA drivers, lightweight kernel
## Requirements
- A NixOS installation (25.11+) with flakes enabled
- x86_64 system with Intel or AMD integrated graphics (or a VM)
- The repo must live at `~/zaneyos/SaugOS` (or update `modules/core/nh.nix`)
## Installation
### 1. Clone into position
```bash
cd ~/zaneyos # parent repo
cd SaugOS
```
### 2. Configure your host
Copy the default host template for your machine:
```bash
cp -r hosts/default hosts/<your-hostname>
```
Edit `hosts/<your-hostname>/variables.nix` to set your preferences:
- `gitUsername` / `gitEmail` — your identity
- `terminal` — default terminal (`ghostty`, `kitty`, `alacritty`, `wezterm`)
- `browser` — default browser
- `keyboardLayout` — keyboard layout (`us`, `de`, etc.)
- `clock24h` — 24-hour clock format
- `stylixImage` — wallpaper/theme source image
- Toggle `tmuxEnable`, `vscodeEnable`, `ghosttyEnable`, etc.
### 3. Generate hardware config
```bash
sudo nixos-generate-config --show-hardware-config > hosts/<your-hostname>/hardware.nix
```
### 4. Update flake.nix
Edit `flake.nix` and set the `host` and `profile` variables:
```nix
host = "<your-hostname>";
profile = "intel"; # or "amd" or "vm"
```
### 5. Build and switch
```bash
# Stage files so the flake can see them
git add -A
# Build the system
sudo nixos-rebuild switch --flake .#<profile>
```
Where `<profile>` is `intel`, `amd`, or `vm`.
### After first boot
The included CLI tool `saugcli` handles ongoing management:
```bash
saugcli rebuild # Rebuild and switch
saugcli rebuild-boot # Rebuild for next boot
saugcli update # Update flake inputs + rebuild
saugcli cleanup # Remove old generations
saugcli diag # Generate hardware report
saugcli trim # SSD TRIM
saugcli update-host # Auto-detect and set host/profile in flake.nix
saugcli add-host <name> # Add a new host from the default template
```
Options for `rebuild`/`update`:
- `--dry` / `-n` — preview without applying
- `--ask` / `-a` — confirmation prompts
- `--cores N` — limit CPU cores (useful on low-resource machines)
- `--verbose` / `-v` — detailed output
## Profiles
| Profile | GPU | Use Case |
|---------|-----|----------|
| `intel` | Intel integrated | Most older laptops |
| `amd` | AMD integrated | AMD-based laptops |
| `vm` | VirtIO/VMware | Virtual machines |
## Key Files
| File | Purpose |
|------|---------|
| `flake.nix` | Inputs, outputs, host/profile selection |
| `hosts/<host>/variables.nix` | Per-machine settings (control panel) |
| `hosts/<host>/hardware.nix` | Hardware scan output |
| `hosts/<host>/host-packages.nix` | Machine-specific packages |
| `modules/core/packages.nix` | System-wide packages |
| `modules/home/niri/binds.nix` | Keybindings |
| `modules/home/scripts/saugcli.nix` | CLI management tool |
## Default Keybindings (Niri)
| Key | Action |
|-----|--------|
| `Super + Return` | Open terminal |
| `Super + D` | Rofi app launcher |
| `Super + Q` | Close window |
| `Super + 1-9` | Switch workspace |
| `Super + Shift + 1-9` | Move window to workspace |
| `Super + H/J/K/L` | Focus left/down/up/right |
| `Super + Shift + H/L` | Move column left/right |
| `Super + F` | Maximize column |
| `Super + Shift + F` | Fullscreen |
| `Super + Print` | Screenshot (region) |

652
flake.lock generated Normal file
View File

@@ -0,0 +1,652 @@
{
"nodes": {
"base16": {
"inputs": {
"fromYaml": "fromYaml"
},
"locked": {
"lastModified": 1755819240,
"narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=",
"owner": "SenchoPens",
"repo": "base16.nix",
"rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6",
"type": "github"
},
"original": {
"owner": "SenchoPens",
"repo": "base16.nix",
"type": "github"
}
},
"base16-fish": {
"flake": false,
"locked": {
"lastModified": 1765809053,
"narHash": "sha256-XCUQLoLfBJ8saWms2HCIj4NEN+xNsWBlU1NrEPcQG4s=",
"owner": "tomyun",
"repo": "base16-fish",
"rev": "86cbea4dca62e08fb7fd83a70e96472f92574782",
"type": "github"
},
"original": {
"owner": "tomyun",
"repo": "base16-fish",
"rev": "86cbea4dca62e08fb7fd83a70e96472f92574782",
"type": "github"
}
},
"base16-helix": {
"flake": false,
"locked": {
"lastModified": 1760703920,
"narHash": "sha256-m82fGUYns4uHd+ZTdoLX2vlHikzwzdu2s2rYM2bNwzw=",
"owner": "tinted-theming",
"repo": "base16-helix",
"rev": "d646af9b7d14bff08824538164af99d0c521b185",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "base16-helix",
"type": "github"
}
},
"base16-vim": {
"flake": false,
"locked": {
"lastModified": 1732806396,
"narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=",
"owner": "tinted-theming",
"repo": "base16-vim",
"rev": "577fe8125d74ff456cf942c733a85d769afe58b7",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "base16-vim",
"rev": "577fe8125d74ff456cf942c733a85d769afe58b7",
"type": "github"
}
},
"firefox-gnome-theme": {
"flake": false,
"locked": {
"lastModified": 1764873433,
"narHash": "sha256-1XPewtGMi+9wN9Ispoluxunw/RwozuTRVuuQOmxzt+A=",
"owner": "rafaelmardojai",
"repo": "firefox-gnome-theme",
"rev": "f7ffd917ac0d253dbd6a3bf3da06888f57c69f92",
"type": "github"
},
"original": {
"owner": "rafaelmardojai",
"repo": "firefox-gnome-theme",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1751685974,
"narHash": "sha256-NKw96t+BgHIYzHUjkTK95FqYRVKB8DHpVhefWSz/kTw=",
"ref": "refs/heads/main",
"rev": "549f2762aebeff29a2e5ece7a7dc0f955281a1d1",
"revCount": 92,
"type": "git",
"url": "https://git.lix.systems/lix-project/flake-compat.git"
},
"original": {
"type": "git",
"url": "https://git.lix.systems/lix-project/flake-compat.git"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nvf",
"nixpkgs"
]
},
"locked": {
"lastModified": 1769996383,
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"stylix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1767609335,
"narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "250481aafeb741edfe23d29195671c19b36b6dca",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"fromYaml": {
"flake": false,
"locked": {
"lastModified": 1731966426,
"narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=",
"owner": "SenchoPens",
"repo": "fromYaml",
"rev": "106af9e2f715e2d828df706c386a685698f3223b",
"type": "github"
},
"original": {
"owner": "SenchoPens",
"repo": "fromYaml",
"type": "github"
}
},
"gnome-shell": {
"flake": false,
"locked": {
"host": "gitlab.gnome.org",
"lastModified": 1767737596,
"narHash": "sha256-eFujfIUQDgWnSJBablOuG+32hCai192yRdrNHTv0a+s=",
"owner": "GNOME",
"repo": "gnome-shell",
"rev": "ef02db02bf0ff342734d525b5767814770d85b49",
"type": "gitlab"
},
"original": {
"host": "gitlab.gnome.org",
"owner": "GNOME",
"ref": "gnome-49",
"repo": "gnome-shell",
"type": "gitlab"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1774274588,
"narHash": "sha256-dnHvv5EMUgTzGZmA+3diYjQU2O6BEpGLEOgJ1Qe9LaY=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "cf9686ba26f5ef788226843bc31fda4cf72e373b",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-25.11",
"repo": "home-manager",
"type": "github"
}
},
"mnw": {
"locked": {
"lastModified": 1770419553,
"narHash": "sha256-b1XqsH7AtVf2dXmq2iyRr2NC1yG7skY7Z6N2MpWHlK4=",
"owner": "Gerg-L",
"repo": "mnw",
"rev": "2aaffa8030d0b262176146adbb6b0e6374ce2957",
"type": "github"
},
"original": {
"owner": "Gerg-L",
"repo": "mnw",
"type": "github"
}
},
"ndg": {
"inputs": {
"nixpkgs": [
"nvf",
"nixpkgs"
]
},
"locked": {
"lastModified": 1768214250,
"narHash": "sha256-hnBZDQWUxJV3KbtvyGW5BKLO/fAwydrxm5WHCWMQTbw=",
"owner": "feel-co",
"repo": "ndg",
"rev": "a6bd3c1ce2668d096e4fdaaa03ad7f03ba1fbca8",
"type": "github"
},
"original": {
"owner": "feel-co",
"ref": "refs/tags/v2.6.0",
"repo": "ndg",
"type": "github"
}
},
"niri": {
"inputs": {
"niri-stable": "niri-stable",
"niri-unstable": "niri-unstable",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable",
"xwayland-satellite-stable": "xwayland-satellite-stable",
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
},
"locked": {
"lastModified": 1774283383,
"narHash": "sha256-3aCfmL8hOcdIl783LTnK+lHcjMGCnc+2zQ98xUyefCU=",
"owner": "sodiboo",
"repo": "niri-flake",
"rev": "8a583029606cf072cc01c7e2f4298cc75a7ada28",
"type": "github"
},
"original": {
"owner": "sodiboo",
"repo": "niri-flake",
"type": "github"
}
},
"niri-stable": {
"flake": false,
"locked": {
"lastModified": 1756556321,
"narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=",
"owner": "YaLTeR",
"repo": "niri",
"rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294",
"type": "github"
},
"original": {
"owner": "YaLTeR",
"ref": "v25.08",
"repo": "niri",
"type": "github"
}
},
"niri-unstable": {
"flake": false,
"locked": {
"lastModified": 1773130184,
"narHash": "sha256-3bwx4WqCB06yfQIGB+OgIckOkEDyKxiTD5pOo4Xz2rI=",
"owner": "YaLTeR",
"repo": "niri",
"rev": "b07bde3ee82dd73115e6b949e4f3f63695da35ea",
"type": "github"
},
"original": {
"owner": "YaLTeR",
"repo": "niri",
"type": "github"
}
},
"nix-flatpak": {
"locked": {
"lastModified": 1767983141,
"narHash": "sha256-7ZCulYUD9RmJIDULTRkGLSW1faMpDlPKcbWJLYHoXcs=",
"owner": "gmodena",
"repo": "nix-flatpak",
"rev": "440818969ac2cbd77bfe025e884d0aa528991374",
"type": "github"
},
"original": {
"owner": "gmodena",
"ref": "latest",
"repo": "nix-flatpak",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1774244481,
"narHash": "sha256-4XfMXU0DjN83o6HWZoKG9PegCvKvIhNUnRUI19vzTcQ=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "4590696c8693fea477850fe379a01544293ca4e2",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1774244481,
"narHash": "sha256-4XfMXU0DjN83o6HWZoKG9PegCvKvIhNUnRUI19vzTcQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4590696c8693fea477850fe379a01544293ca4e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1774106199,
"narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "6c9a78c09ff4d6c21d0319114873508a6ec01655",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1771008912,
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "a82ccc39b39b621151d6732718e3e250109076fa",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1767799921,
"narHash": "sha256-r4GVX+FToWVE2My8VVZH4V0pTIpnu2ZE8/Z4uxGEMBE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d351d0653aeb7877273920cd3e823994e7579b0b",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nur": {
"inputs": {
"flake-parts": [
"stylix",
"flake-parts"
],
"nixpkgs": [
"stylix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1767886815,
"narHash": "sha256-pB2BBv6X9cVGydEV/9Y8+uGCvuYJAlsprs1v1QHjccA=",
"owner": "nix-community",
"repo": "NUR",
"rev": "4ff84374d77ff62e2e13a46c33bfeb73590f9fef",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "NUR",
"type": "github"
}
},
"nvf": {
"inputs": {
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"mnw": "mnw",
"ndg": "ndg",
"nixpkgs": "nixpkgs_2",
"systems": "systems"
},
"locked": {
"lastModified": 1774370747,
"narHash": "sha256-yjVgtiGCf0/nH8bp8tPhZrkGAQ575QImTLyndA7GYTA=",
"owner": "notashelf",
"repo": "nvf",
"rev": "795711598394281a0a7a912765c18d8a8611a85f",
"type": "github"
},
"original": {
"owner": "notashelf",
"repo": "nvf",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"niri": "niri",
"nix-flatpak": "nix-flatpak",
"nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable",
"nvf": "nvf",
"stylix": "stylix",
"zen-browser": "zen-browser"
}
},
"stylix": {
"inputs": {
"base16": "base16",
"base16-fish": "base16-fish",
"base16-helix": "base16-helix",
"base16-vim": "base16-vim",
"firefox-gnome-theme": "firefox-gnome-theme",
"flake-parts": "flake-parts_2",
"gnome-shell": "gnome-shell",
"nixpkgs": "nixpkgs_3",
"nur": "nur",
"systems": "systems_2",
"tinted-foot": "tinted-foot",
"tinted-kitty": "tinted-kitty",
"tinted-schemes": "tinted-schemes",
"tinted-tmux": "tinted-tmux",
"tinted-zed": "tinted-zed"
},
"locked": {
"lastModified": 1774194089,
"narHash": "sha256-SCczWhr8y8aaXVHG+gOGcRahNb0BU1Z5zYZuv9W/nA8=",
"owner": "danth",
"repo": "stylix",
"rev": "7c34241d80ea64dd2039bb3a786fb66b4c6261d9",
"type": "github"
},
"original": {
"owner": "danth",
"ref": "release-25.11",
"repo": "stylix",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"tinted-foot": {
"flake": false,
"locked": {
"lastModified": 1726913040,
"narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=",
"owner": "tinted-theming",
"repo": "tinted-foot",
"rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "tinted-foot",
"rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
"type": "github"
}
},
"tinted-kitty": {
"flake": false,
"locked": {
"lastModified": 1735730497,
"narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=",
"owner": "tinted-theming",
"repo": "tinted-kitty",
"rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "tinted-kitty",
"type": "github"
}
},
"tinted-schemes": {
"flake": false,
"locked": {
"lastModified": 1767817087,
"narHash": "sha256-eGE8OYoK6HzhJt/7bOiNV2cx01IdIrHL7gXgjkHRdNo=",
"owner": "tinted-theming",
"repo": "schemes",
"rev": "bd99656235aab343e3d597bf196df9bc67429507",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "schemes",
"type": "github"
}
},
"tinted-tmux": {
"flake": false,
"locked": {
"lastModified": 1767489635,
"narHash": "sha256-e6nnFnWXKBCJjCv4QG4bbcouJ6y3yeT70V9MofL32lU=",
"owner": "tinted-theming",
"repo": "tinted-tmux",
"rev": "3c32729ccae99be44fe8a125d20be06f8d7d8184",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "tinted-tmux",
"type": "github"
}
},
"tinted-zed": {
"flake": false,
"locked": {
"lastModified": 1767488740,
"narHash": "sha256-wVOj0qyil8m+ouSsVZcNjl5ZR+1GdOOAooAatQXHbuU=",
"owner": "tinted-theming",
"repo": "base16-zed",
"rev": "11abb0b282ad3786a2aae088d3a01c60916f2e40",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "base16-zed",
"type": "github"
}
},
"xwayland-satellite-stable": {
"flake": false,
"locked": {
"lastModified": 1755491097,
"narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=",
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"rev": "388d291e82ffbc73be18169d39470f340707edaa",
"type": "github"
},
"original": {
"owner": "Supreeeme",
"ref": "v0.7",
"repo": "xwayland-satellite",
"type": "github"
}
},
"xwayland-satellite-unstable": {
"flake": false,
"locked": {
"lastModified": 1773622265,
"narHash": "sha256-wToKwH7IgWdGLMSIWksEDs4eumR6UbbsuPQ42r0oTXQ=",
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"rev": "a879e5e0896a326adc79c474bf457b8b99011027",
"type": "github"
},
"original": {
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"type": "github"
}
},
"zen-browser": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1773722260,
"narHash": "sha256-U8MsSiqqYZHR3oKE+cCZ2AJt3b4LcXs+oQuNLipaO78=",
"owner": "youwen5",
"repo": "zen-browser-flake",
"rev": "0e6e43342fb3e9a3439fafa777d8cdf98e4ffc49",
"type": "github"
},
"original": {
"owner": "youwen5",
"repo": "zen-browser-flake",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

63
flake.nix Normal file
View File

@@ -0,0 +1,63 @@
{
description = "SaugOS - Dev-focused NixOS for older laptops";
inputs = {
home-manager = {
url = "github:nix-community/home-manager/release-25.11";
inputs.nixpkgs.follows = "nixpkgs";
};
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
nvf.url = "github:notashelf/nvf";
stylix.url = "github:danth/stylix/release-25.11";
nix-flatpak.url = "github:gmodena/nix-flatpak?ref=latest";
niri = {
url = "github:sodiboo/niri-flake";
inputs.nixpkgs.follows = "nixpkgs";
};
zen-browser = {
url = "github:youwen5/zen-browser-flake";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
nixpkgs,
home-manager,
nix-flatpak,
niri,
...
}@inputs:
let
system = "x86_64-linux";
host = "default";
profile = "intel";
username = "benno";
mkNixosConfig = gpuProfile: nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs username host profile;
pkgs-unstable = import inputs.nixpkgs-unstable {
inherit system;
config.allowUnfree = true;
};
};
modules = [
{ nixpkgs.hostPlatform = system; }
./profiles/${gpuProfile}
nix-flatpak.nixosModules.nix-flatpak
niri.nixosModules.niri
];
};
in
{
nixosConfigurations = {
amd = mkNixosConfig "amd";
intel = mkNixosConfig "intel";
vm = mkNixosConfig "vm";
};
};
}

View File

@@ -0,0 +1,6 @@
{ ... }: {
imports = [
./hardware.nix
./host-packages.nix
];
}

View File

@@ -0,0 +1,35 @@
# Do not modify this file! It was generated by 'nixos-generate-config'
# Replace with actual hardware scan output for the target laptop.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{
device = "/dev/disk/by-uuid/CHANGEME";
fsType = "ext4";
};
fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/CHANGEME";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@@ -0,0 +1,29 @@
{
pkgs,
pkgs-unstable,
inputs,
...
}: {
environment.systemPackages = with pkgs; [
# Communication
pkgs-unstable.signal-desktop
element-desktop
# Browser
inputs.zen-browser.packages."x86_64-linux".default
# Screen locking (niri)
swaylock
swayidle
# Dev tools
nodejs
python3
gnumake
gcc
# Security
gnupg
kdePackages.kleopatra
];
}

View File

@@ -0,0 +1,57 @@
{
# Git Configuration
gitUsername = "Benno Lorenz";
gitEmail = "benno@benno-lorenz.com";
# Desktop Environment — Niri (scrolling tiling WM)
desktopEnvironment = "niri";
# Display Manager
# `tui` for text login, `sddm` for graphical GUI
displayManager = "sddm";
# Bundled application toggles
tmuxEnable = true;
alacrittyEnable = false;
weztermEnable = false;
ghosttyEnable = true;
vscodeEnable = true;
helixEnable = false;
doomEmacsEnable = false;
# Monitor settings (adjust per-machine)
extraMonitorSettings = "
";
# Waybar settings
clock24h = true;
# Default browser (must be installed separately in host-packages.nix)
browser = "zen";
# Default terminal emulator
terminal = "ghostty";
# Keyboard layout
keyboardLayout = "de";
keyboardVariant = "";
consoleKeyMap = "de";
# NFS support
enableNFS = false;
# Printing support
printEnable = false;
# Thunar GUI file manager (Yazi is default)
thunarEnable = true;
# Stylix theme image — sets the system color palette
stylixImage = ../../wallpapers/Amagi.jpeg;
# Waybar style
waybarChoice = ../../modules/home/waybar/waybar-curved.nix;
# Network host ID (needed for zfs, otherwise leave as-is)
hostId = "5ab03f50";
}

20
modules/core/boot.nix Normal file
View File

@@ -0,0 +1,20 @@
{ pkgs, pkgs-unstable, config, ... }:
{
boot = {
# Use standard LTS kernel — lighter for older laptops than zen
kernelPackages = pkgs.linuxPackages_latest;
loader.systemd-boot.enable = true;
loader.efi.canTouchEfiVariables = true;
# Appimage Support
binfmt.registrations.appimage = {
wrapInterpreterInShell = false;
interpreter = "${pkgs.appimage-run}/bin/appimage-run";
recognitionType = "magic";
offset = 0;
mask = ''\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff'';
magicOrExtension = ''\x7fELF....AI\x02'';
};
plymouth.enable = true;
};
}

34
modules/core/default.nix Normal file
View File

@@ -0,0 +1,34 @@
{
inputs,
host,
...
}:
let
vars = import ../../hosts/${host}/variables.nix;
in
{
imports = [
./boot.nix
./flatpak.nix
./fonts.nix
./hardware.nix
./network.nix
./nfs.nix
./nh.nix
./packages.nix
./printing.nix
(if vars.displayManager == "tui" then ./greetd.nix else ./sddm.nix)
./security.nix
./services.nix
./stylix.nix
./syncthing.nix
./system.nix
./thunar.nix
./user.nix
./virtualisation.nix
./wayland.nix
./xserver.nix
(if vars.desktopEnvironment == "niri" then ./swaylock.nix else null)
inputs.stylix.nixosModules.stylix
];
}

13
modules/core/flatpak.nix Normal file
View File

@@ -0,0 +1,13 @@
{ pkgs, ... }: {
xdg.portal = {
enable = true;
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
};
services = {
flatpak = {
enable = true;
packages = [ ];
update.onActivation = true;
};
};
}

26
modules/core/fonts.nix Normal file
View File

@@ -0,0 +1,26 @@
{ pkgs, ... }:
{
fonts = {
packages = with pkgs; [
dejavu_fonts
fira-code
fira-code-symbols
font-awesome
ibm-plex
inter
jetbrains-mono
material-icons
maple-mono.NF
nerd-fonts.im-writing
nerd-fonts.blex-mono
noto-fonts
noto-fonts-color-emoji
noto-fonts-cjk-sans
powerline-fonts
roboto
roboto-mono
symbola
terminus_font
];
};
}

12
modules/core/greetd.nix Normal file
View File

@@ -0,0 +1,12 @@
{ pkgs, username, ... }: {
services.greetd = {
enable = true;
vt = 3;
settings = {
default_session = {
user = username;
command = "${pkgs.tuigreet}/bin/tuigreet --time --cmd niri-session";
};
};
};
}

10
modules/core/hardware.nix Normal file
View File

@@ -0,0 +1,10 @@
{ pkgs, ... }:
{
hardware = {
graphics.enable = true;
enableRedistributableFirmware = true;
bluetooth.enable = true;
bluetooth.powerOnBoot = true;
};
local.hardware-clock.enable = false;
}

37
modules/core/network.nix Normal file
View File

@@ -0,0 +1,37 @@
{
pkgs,
host,
options,
...
}: let
inherit (import ../../hosts/${host}/variables.nix) hostId;
in {
assertions = [
{
assertion = builtins.match "^[[:alnum:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$" host != null;
message = "Invalid hostname '${host}'.";
}
];
networking = {
hostName = "${host}";
hostId = hostId;
networkmanager.enable = true;
timeServers = options.networking.timeServers.default ++ ["pool.ntp.org"];
nameservers = ["1.1.1.1#one.one.one.one" "1.0.0.1#one.one.one.one"];
firewall = {
enable = true;
allowedTCPPorts = [ 22 80 443 8080 ];
};
};
services.resolved = {
enable = true;
dnssec = "true";
domains = ["~."];
fallbackDns = ["1.1.1.1#one.one.one.one" "1.0.0.1#one.one.one.one"];
dnsovertls = "true";
};
environment.systemPackages = with pkgs; [networkmanagerapplet];
}

10
modules/core/nfs.nix Normal file
View File

@@ -0,0 +1,10 @@
{ host, ... }:
let
inherit (import ../../hosts/${host}/variables.nix) enableNFS;
in
{
services = {
rpcbind.enable = enableNFS;
nfs.server.enable = enableNFS;
};
}

15
modules/core/nh.nix Normal file
View File

@@ -0,0 +1,15 @@
{ pkgs, username, ... }: {
programs.nh = {
enable = true;
clean = {
enable = true;
extraArgs = "--keep-since 7d --keep 5";
};
flake = "/home/${username}/zaneyos/SaugOS";
};
environment.systemPackages = with pkgs; [
nix-output-monitor
nvd
];
}

60
modules/core/packages.nix Normal file
View File

@@ -0,0 +1,60 @@
{
pkgs,
inputs,
...
}:
{
programs = {
neovim = {
enable = true;
defaultEditor = true;
};
firefox.enable = false;
dconf.enable = true;
seahorse.enable = true;
fuse.userAllowOther = true;
mtr.enable = true;
gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
};
nixpkgs.config.allowUnfree = true;
environment.systemPackages = with pkgs; [
appimage-run
brightnessctl
cliphist
docker-compose
duf
dysk
eza
ffmpeg
file-roller
gedit
greetd.tuigreet
htop
eog
inxi
killall
libnotify
lm_sensors
lshw
mesa-demos
ncdu
nixfmt-rfc-style
pavucontrol
pciutils
pkg-config
playerctl
ripgrep
socat
unrar
unzip
usbutils
uwsm
waypaper
wget
];
}

18
modules/core/printing.nix Normal file
View File

@@ -0,0 +1,18 @@
{ host, ... }:
let
inherit (import ../../hosts/${host}/variables.nix) printEnable;
in
{
services = {
printing = {
enable = printEnable;
drivers = [ ];
};
avahi = {
enable = printEnable;
nssmdns4 = true;
openFirewall = true;
};
ipp-usb.enable = printEnable;
};
}

44
modules/core/sddm.nix Normal file
View File

@@ -0,0 +1,44 @@
{
pkgs,
config,
lib,
...
}: let
foreground = config.stylix.base16Scheme.base00;
textColor = config.stylix.base16Scheme.base05;
sddm-astronaut = pkgs.sddm-astronaut.override {
embeddedTheme = "pixel_sakura";
themeConfig = {
FormPosition = "left";
Blur = "4.0";
Background = "${toString config.stylix.image}";
HeaderTextColor = "#${textColor}";
DateTextColor = "#${textColor}";
TimeTextColor = "#${textColor}";
LoginFieldTextColor = "#${textColor}";
PasswordFieldTextColor = "#${textColor}";
UserIconColor = "#${textColor}";
PasswordIconColor = "#${textColor}";
WarningColor = "#${textColor}";
LoginButtonBackgroundColor = "#${config.stylix.base16Scheme.base01}";
SystemButtonsIconsColor = "#${textColor}";
SessionButtonTextColor = "#${textColor}";
VirtualKeyboardButtonTextColor = "#${textColor}";
DropdownBackgroundColor = "#${config.stylix.base16Scheme.base01}";
HighlightBackgroundColor = "#${textColor}";
FormBackgroundColor = "#${config.stylix.base16Scheme.base01}";
};
};
in {
services.displayManager = {
sddm = {
package = pkgs.kdePackages.sddm;
extraPackages = [sddm-astronaut];
enable = true;
wayland.enable = false;
theme = "sddm-astronaut-theme";
};
};
environment.systemPackages = [sddm-astronaut];
}

50
modules/core/security.nix Normal file
View File

@@ -0,0 +1,50 @@
{ pkgs, username, ... }: {
security = {
rtkit.enable = true;
polkit = {
enable = true;
extraConfig = ''
polkit.addRule(function(action, subject) {
if ( subject.isInGroup("users") && (
action.id == "org.freedesktop.login1.reboot" ||
action.id == "org.freedesktop.login1.reboot-multiple-sessions" ||
action.id == "org.freedesktop.login1.power-off" ||
action.id == "org.freedesktop.login1.power-off-multiple-sessions"
))
{ return polkit.Result.YES; }
})
'';
};
pam.services = {
login.enableGnomeKeyring = true;
login.enableKwallet = true;
};
pam.services.hyprlock = {
text = ''
auth sufficient pam_unix.so try_first_pass nullok
auth required pam_deny.so
'';
};
pam.services.swaylock = {
text = ''
auth sufficient pam_unix.so try_first_pass nullok
auth required pam_deny.so
'';
};
sudo.extraRules = [
{
users = [ "${username}" ];
commands = [
{
command = "ALL";
options = [ "NOPASSWD" ];
}
];
}
];
};
}

49
modules/core/services.nix Normal file
View File

@@ -0,0 +1,49 @@
{ profile, ... }: {
services = {
libinput.enable = true;
fstrim.enable = true;
gvfs.enable = true;
openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = true;
KbdInteractiveAuthentication = true;
};
ports = [ 22 ];
};
blueman.enable = true;
tumbler.enable = true;
gnome.gnome-keyring.enable = true;
tailscale.enable = true;
smartd = {
enable =
if profile == "vm"
then false
else true;
autodetect = true;
};
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
# TLP for laptop power management
tlp = {
enable = true;
settings = {
CPU_SCALING_GOVERNOR_ON_AC = "performance";
CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
CPU_ENERGY_PERF_POLICY_ON_AC = "performance";
CPU_ENERGY_PERF_POLICY_ON_BAT = "power";
START_CHARGE_THRESH_BAT0 = 40;
STOP_CHARGE_THRESH_BAT0 = 80;
};
};
thermald.enable = true;
};
}

55
modules/core/stylix.nix Normal file
View File

@@ -0,0 +1,55 @@
{ pkgs, host, ... }:
let
inherit (import ../../hosts/${host}/variables.nix) stylixImage;
in
{
stylix = {
enable = true;
image = stylixImage;
base16Scheme = {
base00 = "24273a"; # base
base01 = "1e2030"; # mantle
base02 = "363a4f"; # surface0
base03 = "494d64"; # surface1
base04 = "5b6078"; # surface2
base05 = "cad3f5"; # text
base06 = "f4dbd6"; # rosewater
base07 = "b7bdf8"; # lavender
base08 = "ed8796"; # red
base09 = "f5a97f"; # peach
base0A = "eed49f"; # yellow
base0B = "a6da95"; # green
base0C = "8bd5ca"; # teal
base0D = "8aadf4"; # blue
base0E = "c6a0f6"; # mauve
base0F = "f0c6c6"; # flamingo
};
polarity = "dark";
opacity.terminal = 1.0;
cursor = {
package = pkgs.bibata-cursors;
name = "Bibata-Modern-Ice";
size = 24;
};
fonts = {
monospace = {
package = pkgs.nerd-fonts.jetbrains-mono;
name = "JetBrains Mono";
};
sansSerif = {
package = pkgs.montserrat;
name = "Montserrat";
};
serif = {
package = pkgs.montserrat;
name = "Montserrat";
};
sizes = {
applications = 12;
terminal = 15;
desktop = 11;
popups = 12;
};
};
};
}

13
modules/core/swaylock.nix Normal file
View File

@@ -0,0 +1,13 @@
{ config, pkgs, host, ... }:
let
vars = import ../../../hosts/${host}/variables.nix;
in
{
services.udev.extraRules = "";
environment.etc."swaylock/config".text = ''
color=${config.lib.stylix.colors.base00}
'';
environment.systemPackages = [ pkgs.swaylock ];
}

View File

@@ -0,0 +1,8 @@
{ username, ... }: {
services.syncthing = {
enable = false;
user = "${username}";
dataDir = "/home/${username}";
configDir = "/home/${username}/.config/syncthing";
};
}

40
modules/core/system.nix Normal file
View File

@@ -0,0 +1,40 @@
{ host, profile, ... }:
let
inherit (import ../../hosts/${host}/variables.nix) consoleKeyMap;
in
{
nix = {
settings = {
download-buffer-size = 200000000;
auto-optimise-store = true;
experimental-features = [
"nix-command"
"flakes"
];
substituters = [ "https://niri.cachix.org" ];
trusted-public-keys = [ "niri.cachix.org-1:Wv0OmO7PsuocRKzfDoJ3mulSl7Z+BN0JISU3WYj9E84=" ];
};
};
time.timeZone = "Europe/Berlin";
i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "de_DE.UTF-8";
LC_IDENTIFICATION = "de_DE.UTF-8";
LC_MEASUREMENT = "de_DE.UTF-8";
LC_MONETARY = "de_DE.UTF-8";
LC_NAME = "de_DE.UTF-8";
LC_NUMERIC = "de_DE.UTF-8";
LC_PAPER = "de_DE.UTF-8";
LC_TELEPHONE = "de_DE.UTF-8";
LC_TIME = "de_DE.UTF-8";
};
environment.variables = {
NIXOS_OZONE_WL = "1";
SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS = "0";
SAUGOS_VERSION = "1.0";
SAUGOS = "true";
};
console.keyMap = "${consoleKeyMap}";
system.stateVersion = "23.11";
}

18
modules/core/thunar.nix Normal file
View File

@@ -0,0 +1,18 @@
{ host, pkgs, ... }:
let
inherit (import ../../hosts/${host}/variables.nix) thunarEnable;
in
{
programs = {
thunar = {
enable = thunarEnable;
plugins = with pkgs.xfce; [
thunar-archive-plugin
thunar-volman
];
};
};
environment.systemPackages = with pkgs; [
ffmpegthumbnailer
];
}

45
modules/core/user.nix Normal file
View File

@@ -0,0 +1,45 @@
{ pkgs
, inputs
, username
, host
, profile
, pkgs-unstable
, ...
}:
let
inherit (import ../../hosts/${host}/variables.nix) gitUsername;
in
{
imports = [ inputs.home-manager.nixosModules.home-manager ];
home-manager = {
useUserPackages = true;
useGlobalPkgs = false;
backupFileExtension = "backup";
extraSpecialArgs = { inherit inputs username host profile pkgs-unstable; };
users.${username} = {
imports = [
./../home
];
home = {
username = "${username}";
homeDirectory = "/home/${username}";
stateVersion = "23.11";
};
};
};
users.mutableUsers = true;
users.users.${username} = {
isNormalUser = true;
description = "${gitUsername}";
extraGroups = [
"docker"
"libvirtd"
"lp"
"networkmanager"
"wheel"
];
shell = pkgs.zsh;
ignoreShellProgramCheck = true;
};
nix.settings.allowed-users = [ "${username}" ];
}

View File

@@ -0,0 +1,13 @@
{ pkgs, ... }: {
# Docker for container-based dev workflows
virtualisation = {
docker.enable = true;
podman.enable = false;
libvirtd.enable = false;
};
environment.systemPackages = with pkgs; [
lazydocker
docker-client
];
}

32
modules/core/wayland.nix Normal file
View File

@@ -0,0 +1,32 @@
{ host, pkgs, inputs, ... }:
let
vars = import ../../hosts/${host}/variables.nix;
desktopEnvironment = vars.desktopEnvironment or "niri";
in
{
programs.niri = {
enable = desktopEnvironment == "niri";
package = inputs.niri.packages.${pkgs.system}.niri-stable;
};
environment.systemPackages = with pkgs; [
xwayland
xdg-utils
];
xdg.portal = {
enable = true;
extraPortals = with pkgs; [
xdg-desktop-portal-gtk
] ++ (if desktopEnvironment == "niri" then [
xdg-desktop-portal-gnome
] else []);
config = if desktopEnvironment == "niri" then {
common.default = "*";
niri.default = [ "gnome" "gtk" ];
} else {};
};
security.polkit.enable = true;
}

16
modules/core/xserver.nix Normal file
View File

@@ -0,0 +1,16 @@
{ host, ... }:
let
vars = import ../../hosts/${host}/variables.nix;
keyboardLayout = vars.keyboardLayout or "us";
keyboardVariant = vars.keyboardVariant or "";
enableXServer = vars.displayManager == "sddm";
in
{
services.xserver = {
enable = enableXServer;
xkb = {
layout = "${keyboardLayout}";
variant = "${keyboardVariant}";
};
};
}

View File

@@ -0,0 +1,15 @@
{ lib, pkgs, config, ... }:
with lib;
let
cfg = config.drivers.amdgpu;
in
{
options.drivers.amdgpu = {
enable = mkEnableOption "Enable AMD Drivers";
};
config = mkIf cfg.enable {
systemd.tmpfiles.rules = [ "L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}" ];
services.xserver.videoDrivers = [ "amdgpu" ];
};
}

View File

@@ -0,0 +1,9 @@
{ ... }:
{
imports = [
./amd-drivers.nix
./intel-drivers.nix
./local-hardware-clock.nix
./vm-guest-services.nix
];
}

View File

@@ -0,0 +1,20 @@
{ lib, pkgs, config, ... }:
with lib; let
cfg = config.drivers.intel;
in
{
options.drivers.intel = {
enable = mkEnableOption "Enable Intel Graphics Drivers";
};
config = mkIf cfg.enable {
hardware.graphics = {
extraPackages = with pkgs; [
intel-media-driver
intel-vaapi-driver
libva-vdpau-driver
libvdpau-va-gl
];
};
};
}

View File

@@ -0,0 +1,12 @@
{ lib, pkgs, config, ... }:
with lib;
let
cfg = config.local.hardware-clock;
in
{
options.local.hardware-clock = {
enable = mkEnableOption "Change Hardware Clock To Local Time";
};
config = mkIf cfg.enable { time.hardwareClockInLocalTime = true; };
}

View File

@@ -0,0 +1,16 @@
{ lib, pkgs, config, ... }:
with lib;
let
cfg = config.vm.guest-services;
in
{
options.vm.guest-services = {
enable = mkEnableOption "Enable Virtual Machine Guest Services";
};
config = mkIf cfg.enable {
services.qemuGuest.enable = true;
services.spice-vdagentd.enable = true;
services.spice-webdavd.enable = false;
};
}

View File

@@ -0,0 +1,30 @@
{ lib, ... }: {
programs.alacritty =
let
font_family = lib.mkForce "Maple Mono NF";
in
{
enable = true;
settings = {
font = {
normal = {
family = font_family;
style = "Regular";
};
bold = {
family = font_family;
style = "Bold";
};
italic = {
family = font_family;
style = "Italic";
};
bold_italic = {
family = font_family;
style = "Bold Italic";
};
size = 15;
};
};
};
}

22
modules/home/bash.nix Normal file
View File

@@ -0,0 +1,22 @@
{ profile, ... }: {
programs.bash = {
enable = false;
enableCompletion = true;
initExtra = ''
fastfetch
if [ -f $HOME/.bashrc-personal ]; then
source $HOME/.bashrc-personal
fi
'';
shellAliases = {
sv = "sudo nvim";
fr = "nh os switch --hostname ${profile}";
fu = "nh os switch --hostname ${profile} --update";
ncg = "nix-collect-garbage --delete-old && sudo nix-collect-garbage -d && sudo /run/current-system/bin/switch-to-configuration boot";
v = "nvim";
cat = "bat";
".." = "cd ..";
};
};
}

View File

@@ -0,0 +1,20 @@
{ pkgs, ... }: {
home.packages = with pkgs; [ bash ];
home.file."./.bashrc-personal".text = ''
# This file allows you to define your own aliases, functions, etc
# below are just some examples of what you can use this file for
#!/usr/bin/env bash
# Set defaults
#
#export EDITOR="nvim"
#export VISUAL="nvim"
#alias c="clear"
#eval "$(zoxide init bash)"
#eval "$(oh-my-posh init bash --config $HOME/.config/powerlevel10k_rainbow.omp.json)"
'';
}

26
modules/home/bat.nix Normal file
View File

@@ -0,0 +1,26 @@
{ pkgs
, lib
, ...
}: {
programs.bat = {
enable = true;
config = {
pager = "less -FR";
# other styles available and cane be combined
# style = "numbers,changes,headers,rule,grid";
style = "full";
# Bat has other thems as well
# ansi,Catppuccin,base16,base16-256,GitHub,Nord,etc
theme = lib.mkForce "Dracula";
};
extraPackages = with pkgs.bat-extras; [
batman
batpipe
batgrep
];
};
home.sessionVariables = {
MANPAGER = "sh -c 'col -bx | bat -l man -p'";
MANROFFOPT = "-c";
};
}

35
modules/home/bottom.nix Normal file
View File

@@ -0,0 +1,35 @@
{ ... }: {
programs.bottom = {
enable = true;
settings = {
enable_gpu = true;
theme = "nord";
flags.group_processes = true;
row = [
{
ratio = 2;
child = [
{ type = "cpu"; }
{ type = "temp"; }
];
}
{
ratio = 2;
child = [
{ type = "network"; }
];
}
{
ratio = 3;
child = [
{
type = "proc";
ratio = 1;
default = true;
}
];
}
];
};
};
}

18
modules/home/btop.nix Normal file
View File

@@ -0,0 +1,18 @@
{ pkgs, ... }: {
programs.btop = {
enable = true;
settings = {
vim_keys = true;
rounded_corners = true;
proc_tree = true;
show_gpu_info = "on";
show_uptime = true;
show_coretemp = true;
cpu_sensor = "auto";
show_disks = true;
only_physical = true;
io_mode = true;
io_graph_combined = false;
};
};
}

62
modules/home/default.nix Normal file
View File

@@ -0,0 +1,62 @@
{ host, ... }:
let
inherit (import ../../hosts/${host}/variables.nix)
alacrittyEnable
desktopEnvironment
ghosttyEnable
tmuxEnable
waybarChoice
weztermEnable
vscodeEnable
helixEnable
doomEmacsEnable
;
in
{
imports = [
./bash.nix
./bashrc-personal.nix
./bat.nix
./btop.nix
./bottom.nix
./eza.nix
./fastfetch
./fzf.nix
./gh.nix
./git.nix
./gtk.nix
./htop.nix
./kitty.nix
./lazygit.nix
./nvf.nix
./rofi
./qt.nix
./scripts
./stylix.nix
./swappy.nix
./swaync.nix
./tealdeer.nix
waybarChoice
./wlogout
./xdg.nix
./yazi
./zoxide.nix
./zsh
]
++ (if desktopEnvironment == "niri" then [ ./niri ] else [ ])
++ (if helixEnable then [ ./evil-helix.nix ] else [ ])
++ (if vscodeEnable then [ ./vscode.nix ] else [ ])
++ (
if doomEmacsEnable then
[
./editors/doom-emacs-install.nix
./editors/doom-emacs.nix
]
else
[ ]
)
++ (if weztermEnable then [ ./wezterm.nix ] else [ ])
++ (if ghosttyEnable then [ ./ghostty.nix ] else [ ])
++ (if tmuxEnable then [ ./tmux.nix ] else [ ])
++ (if alacrittyEnable then [ ./alacritty.nix ] else [ ]);
}

View File

@@ -0,0 +1,78 @@
{ pkgs, ... }:
let
doom-icon = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/jeetelongname/doom-banners/master/splashes/doom/doom-emacs-color2.svg";
sha256 = "1xxi5ra1z8njsqaqiaq96wyn1sc967l42kvjzbji1zrjj8za6bgq";
};
in
{
# 1. Create a script to install Doom Emacs
home.packages = [
(pkgs.writeShellScriptBin "get-doom" ''
#!/usr/bin/env bash
set -e
# --- Icons ---
ICON_CHECK=""
ICON_INFO=""
ICON_ROCKET="🚀"
# --- Helper Functions ---
print_status() {
echo
echo "--- $ICON_INFO $1 ---"
}
print_success() {
echo "--- $ICON_CHECK $1 ---"
}
print_banner() {
echo "==============================="
echo " Doom Emacs Installer $ICON_ROCKET"
echo "==============================="
}
# --- Main Script ---
print_banner
EMACSDIR="$HOME/.emacs.d"
if [ -d "$EMACSDIR" ]; then
print_success "Doom Emacs is already installed."
exit 0
fi
print_status "Cloning Doom Emacs..."
git clone --depth 1 https://github.com/doomemacs/doomemacs "$EMACSDIR"
print_success "Doom Emacs cloned."
print_status "Running Doom install..."
"$EMACSDIR/bin/doom" install
print_success "Doom install complete."
print_status "Running doom sync..."
"$EMACSDIR/bin/doom" sync
print_success "Doom sync complete."
echo
print_success "All done! Doom Emacs is ready to use."
'')
];
# 2. Add the bin directory to the PATH
home.sessionPath = [
"$HOME/.emacs.d/bin"
];
# 3. Create a desktop file
xdg.desktopEntries.doom-emacs = {
name = "Doom Emacs";
comment = "A configuration framework for GNU Emacs";
exec = "emacs";
icon = doom-icon;
terminal = false;
type = "Application";
categories = [ "Development" "TextEditor" ];
};
}

View File

@@ -0,0 +1,162 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
emacs-pgtk
git
lazygit
ripgrep
libtool
cmake
pkg-config
# Spell checking
hunspell
hunspellDicts.en_US
hunspellDicts.en_AU
hunspellDicts.es_ES
# LSP servers
clang-tools # C/C++ LSP
nil # Nix LSP
];
home.file.".doom.d/init.el".text = ''
;;; init.el -*- lexical-binding: t; -*-
(doom!
:completion
(company +auto)
(vertico +icons)
:ui
doom
doom-dashboard
doom-quit
hl-todo
modeline
nav-flash
ophints
(popup +defaults)
(ligatures +extra)
tabs
treemacs
vi-tilde-fringe
window-select
:editor
(evil +everywhere)
file-templates
fold
multiple-cursors
snippets
word-wrap
:emacs
(dired +icons)
electric
(ibuffer +icons)
(undo +tree)
vc
:term
vterm
:checkers
(syntax +flymake)
(spell +flyspell)
grammar
:tools
(eval +overlay)
(lookup +docsets)
lsp
(magit +forge)
pdf
tree-sitter
:lang
bash
(c +lsp)
css
docker
html
(json +lsp)
markdown
(nix +tree-sitter +lsp)
toml
yaml
:config
(default +bindings +smartparens))
'';
home.file.".doom.d/config.el".text = ''
;;; config.el -*- lexical-binding: t; -*-
(setq doom-theme 'doom-one)
(setq display-line-numbers-type 'relative)
(setq nerd-icons-font-family "JetBrainsMono Nerd Font")
;; Git configuration
(after! magit
;; Set default git editor to emacsclient
(setq with-editor-emacsclient-executable "emacsclient")
;; Show word-granularity differences within diff hunks
(setq magit-diff-refine-hunk t)
;; Auto-refresh magit buffers
(setq magit-refresh-status-buffer t))
;; Lazygit integration
(defun my/lazygit ()
"Open lazygit in a terminal."
(interactive)
(if (fboundp 'vterm)
(let ((default-directory (magit-toplevel)))
(vterm "*lazygit*")
(vterm-send-string "lazygit")
(vterm-send-return))
(async-shell-command "lazygit" "*lazygit*")))
;; LSP configuration
(after! lsp-mode
(setq lsp-signature-auto-activate t
lsp-signature-render-documentation t
lsp-completion-provider :company-capf
lsp-idle-delay 0.1))
;; Nix LSP (nil) configuration
(with-eval-after-load 'lsp-nix-nil
(setq lsp-nix-nil-auto-eval-inputs t))
;; Company completion settings
(after! company
(setq company-idle-delay 0.2
company-minimum-prefix-length 1
company-tooltip-align-annotations t
company-require-match 'never))
;; Spell checking configuration
(after! ispell
(setq ispell-program-name "hunspell")
(setq ispell-local-dictionary "en_US")
(setq ispell-local-dictionary-alist
'(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_US") nil utf-8))))
;; Git keybindings
(map! :leader
(:prefix-map ("g" . "git")
:desc "Magit status" "g" #'magit-status
:desc "Magit dispatch" "d" #'magit-dispatch
:desc "Magit file dispatch" "f" #'magit-file-dispatch
:desc "Magit blame" "b" #'magit-blame-addition
:desc "Git time machine" "t" #'git-timemachine-toggle
:desc "Lazygit" "l" #'my/lazygit
:desc "Git stage file" "s" #'magit-stage-file
:desc "Git unstage file" "u" #'magit-unstage-file))
'';
home.file.".doom.d/packages.el".text = ''
;;; packages.el -*- lexical-binding: t; -*-
;; Git-related packages
(package! git-timemachine)
'';
}

View File

@@ -0,0 +1,89 @@
{ pkgs, ... }:
let
enableEvilHelix = true; # Set to true to enable the configuration
in
{
home.packages = with pkgs; (
if enableEvilHelix
then [
evil-helix
cmake-language-server
jsonnet-language-server
luaformatter
lua-language-server
marksman
taplo
nil
jq-lsp
vscode-langservers-extracted
bash-language-server
awk-language-server
vscode-extensions.llvm-vs-code-extensions.vscode-clangd
clang-tools
docker-compose-language-service
docker-compose
docker-language-server
typescript-language-server
]
else [ ]
);
home.file.".config/helix/languages.toml".text =
if enableEvilHelix
then ''
[language-server.nil]
command = "nil"
[language-server.lua]
command = "lua-language-server"
[language-server.json]
command = "vscode-json-languageserver"
[language-server.markdown]
command = "marksman"
''
else "";
home.file.".config/helix/config.toml".text =
if enableEvilHelix
then ''
theme = "catppuccin_mocha"
#theme = "ao"
[editor]
evil = true
end-of-line-diagnostics = "hint"
auto-pairs = true
mouse = true
middle-click-paste = true
shell = ["zsh", "-c"]
line-number = "absolute"
auto-completion = true
path-completion = true
auto-info = true
color-modes = true
popup-border = "all"
clipboard-provider = "wayland"
indent-heuristic = "hybrid"
[editor.statusline]
left = ["mode", "spinner"]
center = ["file-absolute-path", "total-line-numbers", "read-only-indicator", "file-modification-indicator"]
right = ["diagnostics", "selections", "position", "file-encoding", "file-line-ending", "file-type"]
separator = ""
mode.normal = "NORMAL"
mode.insert = "INSERT"
mode.select = "SELECT"
[editor.lsp]
enable = true
display-messages = true
display-progress-messages = true
[editor.inline-diagnostics]
cursor-line = "hint"
other-lines = "hint"
''
else "";
}

30
modules/home/eza.nix Normal file
View File

@@ -0,0 +1,30 @@
# Eza is a ls replacement
{
programs.eza = {
enable = true;
icons = "auto";
enableBashIntegration = true;
enableZshIntegration = true;
enableFishIntegration = true;
git = true;
extraOptions = [
"--group-directories-first"
"--no-quotes"
"--header" # Show header row
"--git-ignore"
"--icons=always"
# "--time-style=long-iso" # ISO 8601 extended format for time
"--classify" # append indicator (/, *, =, @, |)
"--hyperlink" # make paths clickable in some terminals
];
};
# Aliases to make `ls`, `ll`, `la` use eza
home.shellAliases = {
ls = "eza";
lt = "eza --tree --level=2";
ll = "eza -lh --no-user --long";
la = "eza -lah ";
tree = "eza --tree ";
};
}

BIN
modules/home/face.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -0,0 +1,136 @@
{
programs.fastfetch = {
enable = true;
settings = {
display = {
color = {
keys = "35";
output = "95";
};
separator = " ";
};
logo = {
source = ./nixos.png;
type = "kitty-direct";
height = 10;
width = 20;
padding = {
top = 2;
left = 2;
};
};
modules = [
"break"
{
type = "os";
key = "OS";
keyColor = "31";
}
{
type = "command";
key = " SaugOS ";
keyColor = "31";
text = "echo v$" + "{SAUGOS_VERSION}";
}
{
type = "kernel";
key = " ";
keyColor = "31";
}
{
type = "packages";
key = " 󰏖 ";
keyColor = "31";
}
{
type = "shell";
key = " ";
keyColor = "31";
}
"break"
{
type = "wm";
key = "WM ";
keyColor = "32";
}
{
type = "wmtheme";
key = " 󰉼 ";
keyColor = "32";
}
{
type = "icons";
key = " 󰀻 ";
keyColor = "32";
}
{
type = "cursor";
key = " ";
keyColor = "32";
}
{
type = "terminal";
key = " ";
keyColor = "32";
}
{
type = "terminalfont";
key = " ";
keyColor = "32";
}
"break"
{
type = "host";
format = "{5} {1} Type {2}";
key = "PC ";
keyColor = "33";
}
{
type = "cpu";
format = "{1} ({3}) @ {7} GHz";
key = " ";
keyColor = "33";
}
{
type = "gpu";
format = "{1} {2} @ {12} GHz";
key = " 󰢮 ";
keyColor = "33";
}
{
type = "memory";
key = " ";
keyColor = "33";
}
{
type = "disk";
key = " 󰋊 ";
keyColor = "33";
}
{
type = "monitor";
key = " ";
keyColor = "33";
}
{
type = "player";
key = " 󰥠 ";
keyColor = "33";
}
{
type = "media";
key = " 󰝚 ";
keyColor = "33";
}
"break"
{
type = "uptime";
key = " Uptime ";
}
];
};
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

37
modules/home/fzf.nix Normal file
View File

@@ -0,0 +1,37 @@
# Fzf is a general-purpose command-line fuzzy finder.
{ config
, lib
, ...
}:
let
accent = "#" + config.lib.stylix.colors.base0D;
foreground = "#" + config.lib.stylix.colors.base05;
muted = "#" + config.lib.stylix.colors.base03;
in
{
programs.fzf = {
enable = true;
enableZshIntegration = true;
colors = lib.mkForce {
"fg+" = accent;
"bg+" = "-1";
"fg" = foreground;
"bg" = "-1";
"prompt" = muted;
"pointer" = accent;
};
defaultOptions = [
"--margin=1"
"--layout=reverse"
"--border=none"
"--info='hidden'"
"--header=''"
"--prompt='/ '"
"-i"
"--no-bold"
"--bind='enter:execute(nvim {})'"
"--preview='bat --style=numbers --color=always --line-range :500 {}'"
"--preview-window=right:60%:wrap"
];
};
}

6
modules/home/gh.nix Normal file
View File

@@ -0,0 +1,6 @@
{ ... }:
{
programs = {
gh.enable = true;
};
}

100
modules/home/ghostty.nix Normal file
View File

@@ -0,0 +1,100 @@
{ pkgs, ... }:
let
# A recent issue 7/7/2025 w/ghostty causes it to hang or respond slowly
# This is a workaround until a fix is released
myGhostty = pkgs.ghostty.overrideAttrs (_: {
preBuild = ''
shopt -s globstar
sed -i 's/^const xev = @import("xev");$/const xev = @import("xev").Epoll;/' **/*.zig
shopt -u globstar
'';
});
in
{
programs.ghostty = {
enable = true;
package = myGhostty; # to fix a but in current builds of ghostty
#package = pkgs.ghostty;
};
home.file."./.config/ghostty/config".text = ''
#theme = Aura
theme = Dracula
#theme = Aardvark Blue
#theme = GruvboxDarkHard
adjust-cell-height = 10%
window-theme = dark
window-height = 32
window-width = 110
background-opacity = 0.95
background-blur-radius = 60
selection-background = #2d3f76
selection-foreground = #c8d3f5
cursor-style = bar
mouse-hide-while-typing = true
# keybindings
# Copy/Paste
keybind = ctrl+shift+c=copy_to_clipboard
keybind = ctrl+shift+v=paste_from_clipboard
keybind = alt+s>r=reload_config
keybind = alt+s>x=close_surface
keybind = alt+s>n=new_window
# tabs
keybind = alt+s>c=new_tab
keybind = alt+s>shift+l=next_tab
keybind = alt+s>shift+h=previous_tab
keybind = alt+s>comma=move_tab:-1
keybind = alt+s>period=move_tab:1
# quick tab switch
keybind = alt+s>1=goto_tab:1
keybind = alt+s>2=goto_tab:2
keybind = alt+s>3=goto_tab:3
keybind = alt+s>4=goto_tab:4
keybind = alt+s>5=goto_tab:5
keybind = alt+s>6=goto_tab:6
keybind = alt+s>7=goto_tab:7
keybind = alt+s>8=goto_tab:8
keybind = alt+s>9=goto_tab:9
# split
keybind = alt+s>\=new_split:right
keybind = alt+s>-=new_split:down
keybind = alt+s>j=goto_split:bottom
keybind = alt+s>k=goto_split:top
keybind = alt+s>h=goto_split:left
keybind = alt+s>l=goto_split:right
keybind = alt+s>z=toggle_split_zoom
keybind = alt+s>e=equalize_splits
# other
#copy-on-select = clipboard
font-size = 12
#font-family = JetBrainsMono Nerd Font Mono
#font-family-bold = JetBrainsMono NFM Bold
#font-family-bold-italic = JetBrainsMono NFM Bold Italic
#font-family-italic = JetBrainsMono NFM Italic
font-family = BerkeleyMono Nerd Font
#font-family = Iosevka Nerd Font
# font-family = SFMono Nerd Font
title = "GhosTTY"
wait-after-command = false
shell-integration = detect
window-save-state = always
gtk-single-instance = true
unfocused-split-opacity = 0.5
quick-terminal-position = center
shell-integration-features = cursor,sudo
'';
}

31
modules/home/git.nix Normal file
View File

@@ -0,0 +1,31 @@
{ host, ... }:
let
inherit (import ../../hosts/${host}/variables.nix) gitUsername gitEmail;
in
{
programs.git = {
enable = true;
settings = {
user = {
name = gitUsername;
email = gitEmail;
};
push.default = "simple";
credential.helper = "cache --timeout=7200";
init.defaultBranch = "main";
log.decorate = "full";
log.date = "iso";
merge.conflictStyle = "diff3";
alias = {
br = "branch --sort=-committerdate";
co = "checkout";
df = "diff";
com = "commit -a";
gs = "stash";
gp = "pull";
lg = "log --graph --pretty=format:'%Cred%h%Creset - %C(yellow)%d%Creset %s %C(green)(%cr)%C(bold blue) <%an>%Creset' --abbrev-commit";
st = "status";
};
};
};
}

16
modules/home/gtk.nix Normal file
View File

@@ -0,0 +1,16 @@
{ pkgs, ... }:
{
gtk = {
iconTheme = {
name = "Papirus-Dark";
package = pkgs.papirus-icon-theme;
};
gtk3.extraConfig = {
gtk-application-prefer-dark-theme = 1;
};
gtk4.extraConfig = {
gtk-application-prefer-dark-theme = 1;
};
};
}

42
modules/home/htop.nix Normal file
View File

@@ -0,0 +1,42 @@
{ config, ... }: {
programs.htop = {
enable = true;
settings =
{
color_scheme = 6;
cpu_count_from_one = 0;
delay = 15;
fields = with config.lib.htop.fields; [
PID
USER
PRIORITY
NICE
M_SIZE
M_RESIDENT
M_SHARE
STATE
PERCENT_CPU
PERCENT_MEM
TIME
COMM
];
highlight_base_name = 1;
highlight_megabytes = 1;
highlight_threads = 1;
}
// (with config.lib.htop;
leftMeters [
(bar "AllCPUs2")
(bar "Memory")
(bar "Swap")
(text "Zram")
])
// (with config.lib.htop;
rightMeters [
(text "Tasks")
(text "LoadAverage")
(text "Uptime")
(text "Systemd")
]);
};
}

75
modules/home/kitty.nix Normal file
View File

@@ -0,0 +1,75 @@
{ pkgs, ... }: {
programs.kitty = {
enable = true;
package = pkgs.kitty;
settings = {
font_size = 12;
wheel_scroll_min_lines = 1;
window_padding_width = 4;
confirm_os_window_close = 0;
scrollback_lines = 10000;
enable_audio_bell = false;
mouse_hide_wait = 60;
cursor_trail = 1;
tab_fade = 1;
active_tab_font_style = "bold";
inactive_tab_font_style = "bold";
tab_bar_edge = "top";
tab_bar_margin_width = 0;
tab_bar_style = "powerline";
#tab_bar_style = "fade";
enabled_layouts = "splits";
};
extraConfig = ''
# Clipboard
map ctrl+shift+v paste_from_selection
map shift+insert paste_from_selection
# Scrolling
map ctrl+shift+up scroll_line_up
map ctrl+shift+down scroll_line_down
map ctrl+shift+k scroll_line_up
map ctrl+shift+j scroll_line_down
map ctrl+shift+page_up scroll_page_up
map ctrl+shift+page_down scroll_page_down
map ctrl+shift+home scroll_home
map ctrl+shift+end scroll_end
map ctrl+shift+h show_scrollback
# Window management
map alt+n new_window_with_cwd #open in current dir
#map alt+n new_os_window #opens term in $HOME
map alt+w close_window
map ctrl+shift+enter launch --location=hsplit
map ctrl+shift+s launch --location=vsplit
map ctrl+shift+] next_window
map ctrl+shift+[ previous_window
map ctrl+shift+f move_window_forward
map ctrl+shift+b move_window_backward
map ctrl+shift+` move_window_to_top
map ctrl+shift+1 first_window
map ctrl+shift+2 second_window
map ctrl+shift+3 third_window
map ctrl+shift+4 fourth_window
map ctrl+shift+5 fifth_window
map ctrl+shift+6 sixth_window
map ctrl+shift+7 seventh_window
map ctrl+shift+8 eighth_window
map ctrl+shift+9 ninth_window # Tab management
map ctrl+shift+0 tenth_window
map ctrl+shift+right next_tab
map ctrl+shift+left previous_tab
map ctrl+shift+t new_tab
map ctrl+shift+q close_tab
map ctrl+shift+l next_layout
map ctrl+shift+. move_tab_forward
map ctrl+shift+, move_tab_backward
# Miscellaneous
map ctrl+shift+up increase_font_size
map ctrl+shift+down decrease_font_size
map ctrl+shift+backspace restore_font_size
'';
};
}

32
modules/home/lazygit.nix Normal file
View File

@@ -0,0 +1,32 @@
# Lazygit is a simple terminal UI for git commands.
{ config, lib, ... }:
let
accent = "#${config.lib.stylix.colors.base0D}";
muted = "#${config.lib.stylix.colors.base03}";
in
{
programs.lazygit = {
enable = true;
settings = lib.mkForce {
disableStartupPopups = true;
notARepository = "skip";
promptToReturnFromSubprocess = false;
update.method = "never";
git = {
commit.signOff = true;
parseEmoji = true;
};
gui = {
theme = {
activeBorderColor = [ accent "bold" ];
inactiveBorderColor = [ muted ];
};
showListFooter = false;
showRandomTip = false;
showCommandLog = false;
showBottomLine = false;
nerdFontsVersion = "3";
};
};
};
}

193
modules/home/niri/binds.nix Normal file
View File

@@ -0,0 +1,193 @@
{
host,
config,
lib,
...
}: let
inherit (import ../../../hosts/${host}/variables.nix) browser terminal;
in {
programs.niri.settings = {
binds = with config.lib.niri.actions; {
# Terminal & application launcher
"Mod+Return".action.spawn = "${terminal}";
"Mod+D".action.spawn = "fuzzel";
"Mod+R".action.spawn = "rofi-launcher";
# Window management
"Mod+Q".action = close-window;
"Mod+F".action = fullscreen-window;
"Mod+Shift+F".action = maximize-column;
"Mod+Shift+Space".action = toggle-window-floating;
"Mod+Space".action = switch-focus-between-floating-and-tiling;
# Session control
"Mod+Shift+E".action.quit = {skip-confirmation = false;};
"Mod+Shift+Q".action.quit = {skip-confirmation = true;};
"Mod+L" = {
action.spawn = ["swaylock"];
allow-when-locked = true;
};
# Focus windows
"Mod+Left".action = focus-column-left;
"Mod+Right".action = focus-column-right;
"Mod+Up".action = focus-window-up;
"Mod+Down".action = focus-window-down;
"Mod+Home".action = focus-column-first;
"Mod+End".action = focus-column-last;
# Focus monitors
"Mod+Shift+Left".action = focus-monitor-left;
"Mod+Shift+Right".action = focus-monitor-right;
"Mod+Shift+Up".action = focus-monitor-up;
"Mod+Shift+Down".action = focus-monitor-down;
# Move windows within workspace
"Mod+Ctrl+Left".action = move-column-left;
"Mod+Ctrl+Right".action = move-column-right;
"Mod+Ctrl+Up".action = move-window-up;
"Mod+Ctrl+Down".action = move-window-down;
"Mod+Ctrl+W".action = toggle-column-tabbed-display;
"Mod+Ctrl+Home".action = move-column-to-first;
"Mod+Ctrl+End".action = move-column-to-last;
# Move windows to monitors
"Mod+Shift+Ctrl+Left".action = move-column-to-monitor-left;
"Mod+Shift+Ctrl+Right".action = move-column-to-monitor-right;
"Mod+Shift+Ctrl+Up".action = move-column-to-monitor-up;
"Mod+Shift+Ctrl+Down".action = move-column-to-monitor-down;
# Workspaces
"Mod+1".action = {focus-workspace = 1;};
"Mod+2".action = {focus-workspace = 2;};
"Mod+3".action = {focus-workspace = 3;};
"Mod+4".action = {focus-workspace = 4;};
"Mod+5".action = {focus-workspace = 5;};
"Mod+6".action = {focus-workspace = 6;};
"Mod+7".action = {focus-workspace = 7;};
"Mod+8".action = {focus-workspace = 8;};
"Mod+9".action = {focus-workspace = 9;};
"Mod+Page_Down".action = focus-workspace-down;
"Mod+Page_Up".action = focus-workspace-up;
"Mod+Shift+1".action = {move-window-to-workspace = 1;};
"Mod+Shift+2".action = {move-window-to-workspace = 2;};
"Mod+Shift+3".action = {move-window-to-workspace = 3;};
"Mod+Shift+4".action = {move-window-to-workspace = 4;};
"Mod+Shift+5".action = {move-window-to-workspace = 5;};
"Mod+Shift+6".action = {move-window-to-workspace = 6;};
"Mod+Shift+7".action = {move-window-to-workspace = 7;};
"Mod+Shift+8".action = {move-window-to-workspace = 8;};
"Mod+Shift+9".action = {move-window-to-workspace = 9;};
"Mod+Shift+Page_Down".action = move-window-to-workspace-down;
"Mod+Shift+Page_Up".action = move-window-to-workspace-up;
"Mod+Ctrl+1".action = {move-column-to-workspace = 1;};
"Mod+Ctrl+2".action = {move-column-to-workspace = 2;};
"Mod+Ctrl+3".action = {move-column-to-workspace = 3;};
"Mod+Ctrl+4".action = {move-column-to-workspace = 4;};
"Mod+Ctrl+5".action = {move-column-to-workspace = 5;};
"Mod+Ctrl+6".action = {move-column-to-workspace = 6;};
"Mod+Ctrl+7".action = {move-column-to-workspace = 7;};
"Mod+Ctrl+8".action = {move-column-to-workspace = 8;};
"Mod+Ctrl+9".action = {move-column-to-workspace = 9;};
"Mod+Ctrl+Page_Down".action = move-column-to-workspace-down;
"Mod+Ctrl+Page_Up".action = move-column-to-workspace-up;
# Layout & Sizing
"Mod+Plus".action = {set-column-width = "+10%";};
"Mod+Shift+Plus".action = {set-column-width = "+10";};
"Mod+odiaeresis".action = {set-column-width = "-10%";};
"Mod+Shift+odiaeresis".action = {set-column-width = "-10";};
"Mod+Ctrl+Plus".action = {set-window-height = "+10%";};
"Mod+Ctrl+Shift+Plus".action = {set-window-height = "+10";};
"Mod+Ctrl+odiaeresis".action = {set-window-height = "-10%";};
"Mod+Ctrl+Shift+odiaeresis".action = {set-window-height = "-10";};
"Mod+Shift+R".action = reset-window-height;
"Mod+comma".action = switch-preset-column-width;
"Mod+period".action = switch-preset-window-height;
"Mod+M".action = maximize-column;
"Mod+C".action = center-column;
# Overview mode
"Mod+Tab".action = toggle-overview;
"Mod+numbersign".action = show-hotkey-overlay;
# Screenshots
"Print".action.screenshot = {};
"Ctrl+Print".action.screenshot-screen = {};
"Alt+Print".action.screenshot-window = {};
# Media keys
"XF86AudioRaiseVolume" = {
action.spawn = ["wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"];
allow-when-locked = true;
};
"XF86AudioLowerVolume" = {
action.spawn = ["wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"];
allow-when-locked = true;
};
"XF86AudioMute" = {
action.spawn = ["wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"];
allow-when-locked = true;
};
"XF86AudioMicMute" = {
action.spawn = ["wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"];
allow-when-locked = true;
};
# Brightness
"XF86MonBrightnessUp" = {
action.spawn = ["brightnessctl" "set" "10%+"];
allow-when-locked = true;
};
"XF86MonBrightnessDown" = {
action.spawn = ["brightnessctl" "set" "10%-"];
allow-when-locked = true;
};
# Scroll bindings
"Mod+WheelScrollDown" = {
action = focus-workspace-down;
cooldown-ms = 150;
};
"Mod+WheelScrollUp" = {
action = focus-workspace-up;
cooldown-ms = 150;
};
"Mod+WheelScrollRight".action = focus-column-right;
"Mod+WheelScrollLeft".action = focus-column-left;
"Mod+TouchpadScrollDown" = {
action.spawn = ["wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02+"];
cooldown-ms = 150;
};
"Mod+TouchpadScrollUp" = {
action.spawn = ["wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02-"];
cooldown-ms = 150;
};
# Custom applications
"Mod+W".action.spawn = "${browser}";
"Mod+E".action.spawn = "thunar";
"Mod+Ctrl+Escape".action.spawn = "btop";
# Advanced
"Mod+H".action = consume-window-into-column;
"Mod+K".action = expel-window-from-column;
"Mod+Ctrl+H".action = consume-or-expel-window-left;
"Mod+Ctrl+L".action = consume-or-expel-window-right;
"Mod+Shift+T".action = do-screen-transition;
"Mod+O".action = toggle-window-rule-opacity;
"Mod+Shift+Ctrl+T".action = toggle-debug-tint;
"Mod+Escape" = {
action = toggle-keyboard-shortcuts-inhibit;
allow-inhibiting = false;
};
};
};
}

View File

@@ -0,0 +1,8 @@
{ host, ... }:
{
imports = [
./niri.nix
./binds.nix
./windowrules.nix
];
}

117
modules/home/niri/niri.nix Normal file
View File

@@ -0,0 +1,117 @@
{ host, config, pkgs, inputs, ... }:
let
vars = import ../../../hosts/${host}/variables.nix;
extraMonitorSettings = vars.extraMonitorSettings;
keyboardLayout = vars.keyboardLayout or "us";
keyboardVariant = vars.keyboardVariant or "";
stylixImage = vars.stylixImage;
in
{
home.packages = with pkgs; [
swww
grim
slurp
wl-clipboard
swappy
xwayland-satellite
];
home.file = {
"Pictures/Wallpapers" = {
source = ../../../wallpapers;
recursive = true;
};
".face.icon".source = ../face.jpg;
".config/face.jpg".source = ../face.jpg;
};
programs.niri = {
settings = {
input = {
keyboard = {
xkb = {
layout = "${keyboardLayout}";
variant = "${keyboardVariant}";
options = "grp:alt_caps_toggle,caps:super";
};
repeat-delay = 300;
repeat-rate = 50;
};
touchpad = {
tap = true;
natural-scroll = true;
dwt = true;
scroll-factor = 0.8;
};
mouse = {
accel-speed = 0.0;
};
};
layout = {
gaps = 8;
center-focused-column = "never";
border = {
enable = true;
width = 2;
active = {
color = "#${config.lib.stylix.colors.base08}";
};
inactive = {
color = "#${config.lib.stylix.colors.base01}";
};
};
focus-ring = {
enable = false;
};
};
spawn-at-startup = [
{ command = [ "xwayland-satellite" ":1" ]; }
{ command = [ "swww-daemon" ]; }
{ command = [ "waybar" ]; }
{ command = [ "swaync" ]; }
{ command = [ "swww" "img" "${stylixImage}" ]; }
{ command = [ "swayidle" "-w" "before-sleep" "swaylock" ]; }
];
prefer-no-csd = true;
screenshot-path = "~/Pictures/Screenshots/Screenshot-%Y-%m-%d-%H-%M-%S.png";
environment = {
DISPLAY = ":1";
NIXOS_OZONE_WL = "1";
MOZ_ENABLE_WAYLAND = "1";
MOZ_WEBRENDER = "1";
XDG_SESSION_TYPE = "wayland";
WLR_NO_HARDWARE_CURSORS = "1";
QT_QPA_PLATFORM = "wayland";
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
GDK_BACKEND = "wayland,x11";
CLUTTER_BACKEND = "wayland";
};
};
};
systemd.user.targets.niri-shutdown = {
Unit = {
Description = "Shutdown running niri user services";
DefaultDependencies = "no";
StopWhenUnneeded = true;
Conflicts = [
"graphical-session.target"
"graphical-session-pre.target"
];
After = [
"graphical-session.target"
"graphical-session-pre.target"
];
};
};
}

View File

@@ -0,0 +1,55 @@
{ ... }:
{
programs.niri.settings = {
window-rules = [
{
matches = [
{ app-id = "^org.kde.polkit-kde-authentication-agent-1$"; }
];
open-floating = true;
}
{
matches = [
{ app-id = "^pavucontrol$"; }
];
open-floating = true;
}
{
matches = [
{ app-id = "^blueman-manager$"; }
];
open-floating = true;
}
{
matches = [
{ app-id = "^nm-connection-editor$"; }
];
open-floating = true;
}
{
matches = [
{ title = "^Picture-in-Picture$"; }
];
open-floating = true;
}
{
matches = [
{ app-id = "^thunar$"; title = "^File Operation Progress$"; }
];
open-floating = true;
}
{
matches = [
{ app-id = "^firefox$"; title = "^Picture-in-Picture$"; }
];
open-floating = true;
}
{
matches = [
{ app-id = "^rofi$"; }
];
open-floating = true;
}
];
};
}

268
modules/home/nvf.nix Normal file
View File

@@ -0,0 +1,268 @@
{ inputs
, config
, ...
}: {
imports = [ inputs.nvf.homeManagerModules.default ];
programs.nvf = {
enable = true;
settings.vim = {
lsp.enable = true;
vimAlias = true;
viAlias = true;
withNodeJs = true;
lineNumberMode = "relNumber";
enableLuaLoader = true;
preventJunkFiles = true;
options = {
tabstop = 4;
shiftwidth = 2;
wrap = false;
};
clipboard = {
enable = true;
registers = "unnamedplus";
providers = {
wl-copy.enable = true;
xsel.enable = true;
};
};
maps = {
normal = {
"<leader>e" = {
action = "<CMD>Neotree toggle<CR>";
silent = false;
};
};
};
diagnostics = {
enable = true;
config = {
virtual_lines.enable = true;
underline = true;
};
};
keymaps = [
{
key = "jk";
mode = [ "i" ];
action = "<ESC>";
desc = "Exit insert mode";
}
{
key = "<leader>nh";
mode = [ "n" ];
action = ":nohl<CR>";
desc = "Clear search highlights";
}
{
key = "<leader>ff";
mode = [ "n" ];
action = "<cmd>Telescope find_files<cr>";
desc = "Search files by name";
}
{
key = "<leader>lg";
mode = [ "n" ];
action = "<cmd>Telescope live_grep<cr>";
desc = "Search files by contents";
}
{
key = "<leader>fe";
mode = [ "n" ];
action = "<cmd>Neotree toggle<cr>";
desc = "File browser toggle";
}
{
key = "<C-h>";
mode = [ "i" ];
action = "<Left>";
desc = "Move left in insert mode";
}
{
key = "<C-j>";
mode = [ "i" ];
action = "<Down>";
desc = "Move down in insert mode";
}
{
key = "<C-k>";
mode = [ "i" ];
action = "<Up>";
desc = "Move up in insert mode";
}
{
key = "<C-l>";
mode = [ "i" ];
action = "<Right>";
desc = "Move right in insert mode";
}
];
telescope.enable = true;
spellcheck = {
enable = true;
languages = [ "en" ];
programmingWordlist.enable = true;
};
lsp = {
formatOnSave = true;
lspkind.enable = false;
lightbulb.enable = false;
lspsaga.enable = false;
trouble.enable = true;
lspSignature.enable = true;
otter-nvim.enable = false;
nvim-docs-view.enable = false;
};
languages = {
enableFormat = true;
enableTreesitter = true;
enableExtraDiagnostics = true;
nix.enable = true;
clang.enable = true;
zig.enable = true;
python.enable = true;
markdown.enable = true;
ts = {
enable = true;
lsp.enable = true;
format.type = ["prettierd"];
extensions.ts-error-translator.enable = true;
};
html.enable = true;
lua.enable = true;
css = {
enable = true;
format.type = ["prettierd"];
};
typst.enable = true;
rust = {
enable = true;
extensions.crates-nvim.enable = true;
};
};
visuals = {
nvim-web-devicons.enable = true;
nvim-cursorline.enable = true;
cinnamon-nvim.enable = true;
fidget-nvim.enable = true;
highlight-undo.enable = true;
indent-blankline.enable = true;
rainbow-delimiters.enable = true;
};
statusline.lualine = {
enable = true;
theme = "base16";
};
autopairs.nvim-autopairs.enable = true;
autocomplete.nvim-cmp.enable = true;
snippets.luasnip.enable = true;
tabline.nvimBufferline.enable = true;
treesitter.context.enable = false;
binds = {
whichKey.enable = true;
cheatsheet.enable = true;
};
git = {
enable = true;
gitsigns.enable = true;
gitsigns.codeActions.enable = false;
};
projects.project-nvim.enable = true;
dashboard.dashboard-nvim.enable = true;
filetree.neo-tree.enable = true;
notify = {
nvim-notify.enable = true;
nvim-notify.setupOpts.background_colour = "#${config.lib.stylix.colors.base01}";
};
utility = {
preview.markdownPreview.enable = true;
ccc.enable = false;
vim-wakatime.enable = false;
icon-picker.enable = true;
surround.enable = true;
diffview-nvim.enable = true;
motion = {
hop.enable = true;
leap.enable = true;
precognition.enable = false;
};
images = {
image-nvim.enable = false;
};
};
ui = {
borders.enable = true;
noice.enable = true;
colorizer.enable = true;
illuminate.enable = true;
breadcrumbs = {
enable = false;
navbuddy.enable = false;
};
smartcolumn = {
enable = true;
};
fastaction.enable = true;
};
session = {
nvim-session-manager.enable = false;
};
comments = {
comment-nvim.enable = true;
};
luaConfigPost = ''
-- Nix LSP (nil) configuration for auto-eval-inputs
local lspconfig = require('lspconfig')
lspconfig.nil_ls.setup({
settings = {
['nil'] = {
nix = {
auto_eval_inputs = true,
},
},
},
})
-- Auto-update programming wordlist on first startup
vim.api.nvim_create_autocmd("VimEnter", {
callback = function()
-- Check if dirtytalk dict file exists
local dict_path = vim.fn.stdpath('data') .. '/site/spell/programming.utf-8.add'
if vim.fn.filereadable(dict_path) == 0 then
-- Only run if file doesn't exist to avoid repeated downloads
vim.schedule(function()
vim.cmd('DirtytalkUpdate')
end)
end
end,
})
'';
};
};
home.activation = {
dirtytalkUpdate = ''
# Create the spell directory if it doesn't exist
mkdir -p "$HOME/.local/share/nvim/site/spell"
# Try to run DirtytalkUpdate in headless mode with better error handling
if ! ${config.programs.nvf.finalPackage}/bin/nvim --headless -c "DirtytalkUpdate" -c "qa!" 2>/dev/null; then
echo "Note: DirtytalkUpdate will run automatically on first Neovim startup"
fi
'';
};
}

6
modules/home/qt.nix Normal file
View File

@@ -0,0 +1,6 @@
{ lib, ... }: {
qt = {
enable = true;
platformTheme.name = lib.mkForce "qtct";
};
}

View File

@@ -0,0 +1,49 @@
{ ... }: {
home.file.".config/rofi/config-long.rasi".text = ''
@import "~/.config/rofi/config.rasi"
window {
width: 750px;
border-radius: 20px;
}
mainbox {
orientation: vertical;
children: [ "inputbar", "listbox" ];
}
inputbar {
padding: 75px 40px;
background-color: transparent;
background-image: url("~/Pictures/Wallpapers/Rainnight.jpg", width);
text-color: @foreground;
children: [ "textbox-prompt-colon", "entry" ];
}
textbox-prompt-colon {
padding: 12px 20px;
border-radius: 100%;
background-color: @bg-alt;
text-color: @foreground;
}
entry {
expand: true;
padding: 12px 16px;
border-radius: 100%;
background-color: @bg-alt;
text-color: @foreground;
}
button {
padding: 12px;
border-radius: 100%;
}
element {
spacing: 10px;
padding: 12px;
border-radius: 100%;
}
textbox {
padding: 12px;
border-radius: 100%;
}
error-message {
border-radius: 0px;
}
'';
}

View File

@@ -0,0 +1,6 @@
{ ... }: {
imports = [
./config-long.nix
./rofi.nix
];
}

208
modules/home/rofi/rofi.nix Normal file
View File

@@ -0,0 +1,208 @@
{ pkgs
, config
, ...
}: {
programs = {
rofi = {
enable = true;
package = pkgs.rofi;
extraConfig = {
modi = "drun,filebrowser,run";
show-icons = true;
icon-theme = "Papirus";
font = "JetBrainsMono Nerd Font Mono 12";
drun-display-format = "{icon} {name}";
display-drun = " Apps";
display-run = " Run";
display-filebrowser = " File";
};
theme =
let
inherit (config.lib.formats.rasi) mkLiteral;
in
{
"*" = {
bg = mkLiteral "#${config.stylix.base16Scheme.base00}";
bg-alt = mkLiteral "#${config.stylix.base16Scheme.base09}";
foreground = mkLiteral "#${config.stylix.base16Scheme.base01}";
selected = mkLiteral "#${config.stylix.base16Scheme.base08}";
active = mkLiteral "#${config.stylix.base16Scheme.base0B}";
text-selected = mkLiteral "#${config.stylix.base16Scheme.base00}";
text-color = mkLiteral "#${config.stylix.base16Scheme.base05}";
border-color = mkLiteral "#${config.stylix.base16Scheme.base0F}";
urgent = mkLiteral "#${config.stylix.base16Scheme.base0E}";
};
"window" = {
transparency = "real";
width = mkLiteral "1000px";
location = mkLiteral "center";
anchor = mkLiteral "center";
fullscreen = false;
x-offset = mkLiteral "0px";
y-offset = mkLiteral "0px";
cursor = "default";
enabled = true;
border-radius = mkLiteral "15px";
background-color = mkLiteral "@bg";
};
"mainbox" = {
enabled = true;
spacing = mkLiteral "0px";
orientation = mkLiteral "horizontal";
children = map mkLiteral [
"imagebox"
"listbox"
];
background-color = mkLiteral "transparent";
};
"imagebox" = {
padding = mkLiteral "20px";
background-color = mkLiteral "transparent";
background-image = mkLiteral ''url("~/Pictures/Wallpapers/Rainnight.jpg", height)'';
orientation = mkLiteral "vertical";
children = map mkLiteral [
"inputbar"
"dummy"
"mode-switcher"
];
};
"listbox" = {
spacing = mkLiteral "20px";
padding = mkLiteral "20px";
background-color = mkLiteral "transparent";
orientation = mkLiteral "vertical";
children = map mkLiteral [
"message"
"listview"
];
};
"dummy" = {
background-color = mkLiteral "transparent";
};
"inputbar" = {
enabled = true;
spacing = mkLiteral "10px";
padding = mkLiteral "10px";
border-radius = mkLiteral "10px";
background-color = mkLiteral "@bg-alt";
text-color = mkLiteral "@foreground";
children = map mkLiteral [
"textbox-prompt-colon"
"entry"
];
};
"textbox-prompt-colon" = {
enabled = true;
expand = false;
str = "";
background-color = mkLiteral "inherit";
text-color = mkLiteral "inherit";
};
"entry" = {
enabled = true;
background-color = mkLiteral "inherit";
text-color = mkLiteral "inherit";
cursor = mkLiteral "text";
placeholder = "Search";
placeholder-color = mkLiteral "inherit";
};
"mode-switcher" = {
enabled = true;
spacing = mkLiteral "20px";
background-color = mkLiteral "transparent";
text-color = mkLiteral "@foreground";
};
"button" = {
padding = mkLiteral "15px";
border-radius = mkLiteral "10px";
background-color = mkLiteral "@bg-alt";
text-color = mkLiteral "inherit";
cursor = mkLiteral "pointer";
};
"button selected" = {
background-color = mkLiteral "@selected";
text-color = mkLiteral "@foreground";
};
"listview" = {
enabled = true;
columns = 1;
lines = 8;
cycle = true;
dynamic = true;
scrollbar = false;
layout = mkLiteral "vertical";
reverse = false;
fixed-height = true;
fixed-columns = true;
spacing = mkLiteral "10px";
background-color = mkLiteral "transparent";
text-color = mkLiteral "@foreground";
cursor = "default";
};
"element" = {
enabled = true;
spacing = mkLiteral "15px";
padding = mkLiteral "8px";
border-radius = mkLiteral "10px";
background-color = mkLiteral "transparent";
text-color = mkLiteral "@text-color";
cursor = mkLiteral "pointer";
};
"element normal.normal" = {
background-color = mkLiteral "inherit";
text-color = mkLiteral "@text-color";
};
"element normal.urgent" = {
background-color = mkLiteral "@urgent";
text-color = mkLiteral "@text-color";
};
"element normal.active" = {
background-color = mkLiteral "inherit";
text-color = mkLiteral "@text-color";
};
"element selected.normal" = {
background-color = mkLiteral "@selected";
text-color = mkLiteral "@foreground";
};
"element selected.urgent" = {
background-color = mkLiteral "@urgent";
text-color = mkLiteral "@text-selected";
};
"element selected.active" = {
background-color = mkLiteral "@urgent";
text-color = mkLiteral "@text-selected";
};
"element-icon" = {
background-color = mkLiteral "transparent";
text-color = mkLiteral "inherit";
size = mkLiteral "36px";
cursor = mkLiteral "inherit";
};
"element-text" = {
background-color = mkLiteral "transparent";
text-color = mkLiteral "inherit";
cursor = mkLiteral "inherit";
vertical-align = mkLiteral "0.5";
horizontal-align = mkLiteral "0.0";
};
"message" = {
background-color = mkLiteral "transparent";
};
"textbox" = {
padding = mkLiteral "15px";
border-radius = mkLiteral "10px";
background-color = mkLiteral "@bg-alt";
text-color = mkLiteral "@foreground";
vertical-align = mkLiteral "0.5";
horizontal-align = mkLiteral "0.0";
};
"error-message" = {
padding = mkLiteral "15px";
border-radius = mkLiteral "20px";
background-color = mkLiteral "@bg";
text-color = mkLiteral "@foreground";
};
};
};
};
}

View File

@@ -0,0 +1,26 @@
{ pkgs
, username
, profile
, ...
}: {
home.packages = [
(import ./hm-find.nix { inherit pkgs; })
(import ./note.nix { inherit pkgs; })
(import ./note-from-clipboard.nix { inherit pkgs; })
(import ./rofi-launcher.nix { inherit pkgs; })
(import ./screenshootin.nix { inherit pkgs; })
(import ./squirtle.nix { inherit pkgs; })
(import ./task-waybar.nix { inherit pkgs; })
(import ./wallsetter.nix {
inherit pkgs;
inherit username;
})
(import ./web-search.nix { inherit pkgs; })
(import ./saugcli.nix {
inherit pkgs profile;
backupFiles = [
".config/mimeapps.list.backup"
];
})
];
}

View File

@@ -0,0 +1,60 @@
{ pkgs }:
pkgs.writeShellScriptBin "hm-find" ''
#!/usr/bin/env bash
# Script Metadata
#===============================================
# This script searches recent journalctl entries for Home Manager errors
# It identifies backup files that prevent rebuilds and allows removal.
# Author: Don Williams
# Creation Date: May 6th, 2025
# Revision History:
#-----------------------------------------------
# 0.1 - 5/6/25 - Initial version
# 0.2 - 5/7/25 - Improved messaging, added log directory check
# Display WARNING message
echo "==============================================="
echo " WARNING "
echo "==============================================="
echo "*** This script is experimental! ***"
echo "It will attempt to find old backup files that are preventing Home Manager from rebuilding."
echo "If conflicting files are found, you will be prompted to remove them."
echo "A log of any deletions will be stored in \$HOME/hm-logs."
echo "==============================================="
# Define the time range (default: last 30 minutes)
TIME_RANGE="30m"
LOG_DIR="$HOME/hm-logs"
LOG_FILE="$LOG_DIR/hm-cleanup-$(date +'%Y-%m-%d_%H-%M-%S').log"
# Ensure the log directory exists
if [ ! -d "$LOG_DIR" ]; then
echo "Creating log directory: $LOG_DIR"
mkdir -p "$LOG_DIR"
fi
# Search journal logs for backup conflicts and extract file paths
FILES=$(journalctl --since "-$TIME_RANGE" -xe | grep hm-activate | awk -F "'|'" '/would be clobbered by backing up/ {print $2}')
# Check if any files were found
if [ -z "$FILES" ]; then
echo "No conflicting backup files found in the last $TIME_RANGE."
exit 0
fi
# Display found backup files
echo "🚨 The following backup files are preventing Home Manager from rebuilding:"
echo "$FILES" | tr ' ' '\n'
# Ask for user confirmation before deletion
read -p " Do you want to remove these files? (y/N): " confirm
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
echo "🗑 Deleting files..." | tee -a "$LOG_FILE"
echo "$FILES" | xargs rm -v | tee -a "$LOG_FILE"
echo " Cleanup completed at $(date)" | tee -a "$LOG_FILE"
else
echo " No files were removed." | tee -a "$LOG_FILE"
fi
''

View File

@@ -0,0 +1,20 @@
{ pkgs, ... }:
pkgs.writeShellScriptBin "note-from-clipboard" ''
#!/usr/bin/env bash
# Check clipboard content type
clipboard_type=$(${pkgs.wl-clipboard}/bin/wl-paste --list-types | head -n 1)
if [[ "$clipboard_type" == "text/plain"* ]]; then
# It's text, let's create a note
${pkgs.wl-clipboard}/bin/wl-paste | note
if [ $? -eq 0 ]; then
${pkgs.libnotify}/bin/notify-send -t 3000 "📝 Note Created" "Clipboard content added as a new note."
else
${pkgs.libnotify}/bin/notify-send -t 5000 -u critical " Note Creation Failed" "There was an error creating the note."
fi
else
# It's not text, so we do nothing and notify the user
${pkgs.libnotify}/bin/notify-send -t 4000 -u low "📋 Note Skipped" "Clipboard does not contain text."
fi
''

View File

@@ -0,0 +1,244 @@
{ pkgs, ... }:
pkgs.writeShellScriptBin "note" ''
# Colors for nice output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
GRAY='\033[0;37m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# XDG-compliant notes directory and file
NOTES_DIR="$HOME/.local/share/notes"
NOTES_FILE="$NOTES_DIR/notes.txt"
# Create notes directory if it doesn't exist
mkdir -p "$NOTES_DIR"
# Function to display usage
show_usage() {
echo -e "''${BOLD}''${BLUE}📝 Note Manager''${NC}"
echo -e "''${GRAY}Usage:''${NC}"
echo -e " ''${CYAN}note''${NC} ''${YELLOW}<text>''${NC} - Add a new note"
echo -e " ''${CYAN}note''${NC} - Display all notes"
echo -e " ''${CYAN}note del''${NC} ''${YELLOW}<number>''${NC} - Delete note by number"
echo -e " ''${CYAN}note clear''${NC} - Clear all notes"
echo -e " ''${CYAN}echo 'text' | note''${NC} - Add note from stdin"
echo -e " ''${CYAN}cat file | note''${NC} - Add file contents as note"
echo ""
echo -e "''${GRAY}Examples:''${NC}"
echo -e " ''${GREEN}note call plumber tomorrow''${NC}"
echo -e " ''${GREEN}cat todo.txt | note''${NC}"
echo -e " ''${GREEN}note del 3''${NC}"
}
# Function to add a note
add_note() {
local note_text="$1"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local date_only=$(date '+%Y-%m-%d')
# Create notes file if it doesn't exist
touch "$NOTES_FILE"
# Get next note number
local note_num=1
if [ -f "$NOTES_FILE" ] && [ -s "$NOTES_FILE" ]; then
note_num=$(grep -E "^#[0-9]+" "$NOTES_FILE" | sed 's/^#\([0-9]*\).*/\1/' | sort -n | tail -1)
note_num=$((note_num + 1))
fi
# Add the note with proper formatting
{
echo "#$note_num [$timestamp]"
echo "$note_text"
echo ""
} >> "$NOTES_FILE"
echo -e "''${GREEN}''${NC} Note #$note_num added ''${GRAY}($date_only)''${NC}"
}
# Function to display all notes
display_notes() {
if [ ! -f "$NOTES_FILE" ] || [ ! -s "$NOTES_FILE" ]; then
echo -e "''${YELLOW}📝 No notes found''${NC}"
echo -e "''${GRAY}Use ''${CYAN}note <text>''${GRAY} to add your first note''${NC}"
return
fi
echo -e "''${BOLD}''${BLUE}📝 Your Notes''${NC}"
echo -e "''${GRAY}📁 $NOTES_FILE''${NC}"
echo -e "''${GRAY}$(printf '%.0s' {1..50})''${NC}"
local in_note=false
local note_content=""
while IFS= read -r line; do
# Check if line starts with # followed by numbers and space and [
if echo "$line" | grep -q "^#[0-9][0-9]* \["; then
# Print previous note content if exists
if [ "$in_note" = true ] && [ -n "$note_content" ]; then
echo -e "$note_content"
echo ""
fi
# Extract note number and timestamp
local num=$(echo "$line" | sed 's/^#\([0-9]*\) \[.*/\1/')
local timestamp=$(echo "$line" | sed 's/^#[0-9]* \[\(.*\)\]/\1/')
local date_part=$(echo "$timestamp" | cut -d' ' -f1)
local time_part=$(echo "$timestamp" | cut -d' ' -f2)
echo -e "''${BOLD}''${CYAN}#$num''${NC} ''${GRAY}[$date_part ''${YELLOW}$time_part''${GRAY}]''${NC}"
in_note=true
note_content=""
elif [ -n "$line" ] && [ "$in_note" = true ]; then
# Accumulate note content
if [ -z "$note_content" ]; then
note_content="''${WHITE}$line''${NC}"
else
note_content="$note_content\n''${WHITE}$line''${NC}"
fi
elif [ -z "$line" ] && [ "$in_note" = true ]; then
# End of current note
if [ -n "$note_content" ]; then
echo -e "$note_content"
echo ""
fi
in_note=false
note_content=""
fi
done < "$NOTES_FILE"
# Print last note if file doesn't end with empty line
if [ "$in_note" = true ] && [ -n "$note_content" ]; then
echo -e "$note_content"
echo ""
fi
local total_notes=$(grep -c "^#[0-9]" "$NOTES_FILE")
echo -e "''${GRAY}$(printf '%.0s' {1..50})''${NC}"
echo -e "''${GRAY}Total: ''${BOLD}$total_notes''${NC} ''${GRAY}notes''${NC}"
}
# Function to delete a note
delete_note() {
local note_num="$1"
if [ ! -f "$NOTES_FILE" ] || [ ! -s "$NOTES_FILE" ]; then
echo -e "''${RED}''${NC} No notes found"
return 1
fi
if ! echo "$note_num" | grep -q "^[0-9][0-9]*$"; then
echo -e "''${RED}''${NC} Invalid note number: $note_num"
return 1
fi
# Check if note exists
if ! grep -q "^#$note_num " "$NOTES_FILE"; then
echo -e "''${RED}''${NC} Note #$note_num not found"
return 1
fi
# Create temporary file without the specified note
local temp_file=$(mktemp)
local skip_lines=false
while IFS= read -r line; do
if echo "$line" | grep -q "^#[0-9][0-9]* "; then
local current_num=$(echo "$line" | sed 's/^#\([0-9]*\) .*/\1/')
if [ "$current_num" = "$note_num" ]; then
skip_lines=true
continue
else
skip_lines=false
fi
fi
if [ "$skip_lines" = false ]; then
echo "$line" >> "$temp_file"
elif [ -z "$line" ]; then
# Stop skipping when we hit an empty line (end of note)
skip_lines=false
fi
done < "$NOTES_FILE"
mv "$temp_file" "$NOTES_FILE"
echo -e "''${GREEN}''${NC} Note #$note_num deleted"
}
# Function to clear all notes
clear_notes() {
if [ ! -f "$NOTES_FILE" ] || [ ! -s "$NOTES_FILE" ]; then
echo -e "''${YELLOW}📝 No notes to clear''${NC}"
return
fi
local total_notes=$(grep -c "^#[0-9]" "$NOTES_FILE")
echo -e "''${YELLOW}''${NC} This will delete all $total_notes notes. Are you sure? ''${GRAY}[y/N]''${NC}"
read -r confirmation
if echo "$confirmation" | grep -qi "^y"; then
> "$NOTES_FILE"
echo -e "''${GREEN}''${NC} All notes cleared"
else
echo -e "''${BLUE}''${NC} Operation cancelled"
fi
}
# Main script logic
main() {
# Check if input is being piped
if [ ! -t 0 ]; then
# Read from stdin (pipe)
local piped_content=""
while IFS= read -r line; do
if [ -z "$piped_content" ]; then
piped_content="$line"
else
piped_content="$piped_content"$'\n'"$line"
fi
done
if [ -n "$piped_content" ]; then
add_note "$piped_content"
else
echo -e "''${RED}''${NC} No input received from pipe"
exit 1
fi
return
fi
# Handle command line arguments
case "$1" in
"")
display_notes
;;
"del")
if [ -z "$2" ]; then
echo -e "''${RED}''${NC} Please specify note number to delete"
echo -e "''${GRAY}Usage: ''${CYAN}note del <number>''${NC}"
exit 1
fi
delete_note "$2"
;;
"clear")
clear_notes
;;
"help"|"--help"|"-h")
show_usage
;;
*)
# Everything else is treated as note content
add_note "$*"
;;
esac
}
main "$@"
''

View File

@@ -0,0 +1,8 @@
{ pkgs }:
pkgs.writeShellScriptBin "rofi-launcher" ''
# check if rofi is already running
if pidof rofi > /dev/null; then
pkill rofi
fi
rofi -show drun
''

View File

@@ -0,0 +1,438 @@
{ pkgs
, profile
, backupFiles ? [ ".config/mimeapps.list.backup" ]
, ...
}:
let
backupFilesString = pkgs.lib.strings.concatStringsSep " " backupFiles;
in
pkgs.writeShellScriptBin "saugcli" ''
#!${pkgs.bash}/bin/bash
set -euo pipefail
# --- Configuration ---
PROJECT="zaneyos/SaugOS"
PROFILE="${profile}"
BACKUP_FILES_STR="${backupFilesString}"
VERSION="1.0.0"
FLAKE_NIX_PATH="$HOME/$PROJECT/flake.nix"
read -r -a BACKUP_FILES <<< "$BACKUP_FILES_STR"
# --- Helper Functions ---
verify_hostname() {
local current_hostname
local flake_hostname
current_hostname="$(hostname)"
if [ -f "$FLAKE_NIX_PATH" ]; then
flake_hostname=$(${pkgs.gnugrep}/bin/grep -E '^[[:space:]]*host[[:space:]]*=' "$FLAKE_NIX_PATH" | ${pkgs.gnused}/bin/sed 's/.*=[[:space:]]*"\([^"]*\)".*/\1/')
if [ -z "$flake_hostname" ]; then
echo "Error: Could not find 'host' variable in $FLAKE_NIX_PATH" >&2
exit 1
fi
if [ "$current_hostname" != "$flake_hostname" ]; then
echo "Error: Hostname mismatch!" >&2
echo " Current hostname: '$current_hostname'" >&2
echo " Flake.nix host: '$flake_hostname'" >&2
echo "" >&2
echo "Hint: Run 'saugcli update-host' to automatically update flake.nix" >&2
echo " or manually edit $FLAKE_NIX_PATH" >&2
exit 1
fi
else
echo "Error: Flake.nix not found at $FLAKE_NIX_PATH" >&2
exit 1
fi
local folder="$HOME/$PROJECT/hosts/$current_hostname"
if [ ! -d "$folder" ]; then
echo "Error: Matching host not found in $PROJECT, Missing folder: $folder" >&2
exit 1
fi
}
print_help() {
echo "SaugOS CLI Utility -- version $VERSION"
echo ""
echo "Usage: saugcli [command] [options]"
echo ""
echo "Commands:"
echo " cleanup - Clean up old system generations."
echo " diag - Create a system diagnostic report (~diag.txt)."
echo " list-gens - List user and system generations."
echo " rebuild - Rebuild the NixOS system configuration."
echo " rebuild-boot - Rebuild and set as boot default (activates on next restart)."
echo " trim - Trim filesystems to improve SSD performance."
echo " update - Update the flake and rebuild the system."
echo " update-host - Auto set host and profile in flake.nix."
echo " (Opt: saugcli update-host [hostname] [profile])"
echo " add-host - Add a new host configuration."
echo " del-host - Delete a host configuration."
echo ""
echo "Options for rebuild, rebuild-boot, and update commands:"
echo " --dry, -n - Show what would be done without doing it"
echo " --ask, -a - Ask for confirmation before proceeding"
echo " --cores N - Limit build to N cores (useful for low-resource machines)"
echo " --verbose, -v - Show verbose output"
echo " --no-nom - Don't use nix-output-monitor"
echo ""
echo " help - Show this help message."
}
handle_backups() {
if [ ''${#BACKUP_FILES[@]} -eq 0 ]; then
return
fi
for file_path in "''${BACKUP_FILES[@]}"; do
full_path="$HOME/$file_path"
if [ -f "$full_path" ]; then
echo "Removing stale backup file: $full_path"
rm "$full_path"
fi
done
}
detect_gpu_profile() {
local detected_profile=""
local has_intel=false
local has_amd=false
local has_vm=false
if ${pkgs.pciutils}/bin/lspci &> /dev/null; then
if ${pkgs.pciutils}/bin/lspci | ${pkgs.gnugrep}/bin/grep -qi 'vga\|3d'; then
while read -r line; do
if echo "$line" | ${pkgs.gnugrep}/bin/grep -qi 'amd'; then
has_amd=true
elif echo "$line" | ${pkgs.gnugrep}/bin/grep -qi 'intel'; then
has_intel=true
elif echo "$line" | ${pkgs.gnugrep}/bin/grep -qi 'virtio\|vmware'; then
has_vm=true
fi
done < <(${pkgs.pciutils}/bin/lspci | ${pkgs.gnugrep}/bin/grep -i 'vga\|3d')
if "$has_vm"; then
detected_profile="vm"
elif "$has_amd"; then
detected_profile="amd"
elif "$has_intel"; then
detected_profile="intel"
fi
fi
else
echo "Warning: lspci command not found. Cannot auto-detect GPU profile." >&2
fi
echo "$detected_profile"
}
parse_nh_args() {
local args_string=""
local options_selected=()
shift
while [[ $# -gt 0 ]]; do
case $1 in
--dry|-n)
args_string="$args_string --dry"
options_selected+=("dry run mode (showing what would be done)")
shift
;;
--ask|-a)
args_string="$args_string --ask"
options_selected+=("confirmation prompts enabled")
shift
;;
--cores)
if [[ -n $2 && $2 =~ ^[0-9]+$ ]]; then
args_string="$args_string -- --cores $2"
options_selected+=("limited to $2 CPU cores")
shift 2
else
echo "Error: --cores requires a numeric argument" >&2
exit 1
fi
;;
--verbose|-v)
args_string="$args_string --verbose"
options_selected+=("verbose output enabled")
shift
;;
--no-nom)
args_string="$args_string --no-nom"
options_selected+=("nix-output-monitor disabled")
shift
;;
--)
shift
args_string="$args_string -- $*"
options_selected+=("additional arguments: $*")
break
;;
-*)
echo "Warning: Unknown flag '$1' - passing through to nh" >&2
args_string="$args_string $1"
options_selected+=("unknown flag '$1' passed through")
shift
;;
*)
echo "Error: Unexpected argument '$1'" >&2
exit 1
;;
esac
done
if [[ ''${#options_selected[@]} -gt 0 ]]; then
echo "Options selected:" >&2
for option in "''${options_selected[@]}"; do
echo " $option" >&2
done
echo >&2
fi
echo "$args_string"
}
# --- Main Logic ---
if [ "$#" -eq 0 ]; then
echo "Error: No command provided." >&2
print_help
exit 1
fi
case "$1" in
cleanup)
echo "Warning! This will remove old generations of your system."
read -p "How many generations to keep (default: all)? " keep_count
if [ -z "$keep_count" ]; then
read -p "This will remove all but the current generation. Continue (y/N)? " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
${pkgs.nh}/bin/nh clean all -v
else
echo "Cleanup cancelled."
fi
else
read -p "This will keep the last $keep_count generations. Continue (y/N)? " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
${pkgs.nh}/bin/nh clean all -k "$keep_count" -v
else
echo "Cleanup cancelled."
fi
fi
LOG_DIR="$HOME/saugcli-cleanup-logs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/saugcli-cleanup-$(${pkgs.coreutils}/bin/date +%Y-%m-%d_%H-%M-%S).log"
echo "Cleaning up old log files..." >> "$LOG_FILE"
${pkgs.findutils}/bin/find "$LOG_DIR" -type f -mtime +3 -name "*.log" -delete >> "$LOG_FILE" 2>&1
echo "Cleanup process logged to $LOG_FILE"
;;
diag)
echo "Generating system diagnostic report..."
${pkgs.inxi}/bin/inxi --full > "$HOME/diag.txt"
echo "Diagnostic report saved to $HOME/diag.txt"
;;
help)
print_help
;;
list-gens)
echo "--- User Generations ---"
${pkgs.nix}/bin/nix-env --list-generations | ${pkgs.coreutils}/bin/cat || echo "Could not list user generations."
echo ""
echo "--- System Generations ---"
${pkgs.nix}/bin/nix profile history --profile /nix/var/nix/profiles/system | ${pkgs.coreutils}/bin/cat || echo "Could not list system generations."
;;
rebuild)
verify_hostname
handle_backups
extra_args=$(parse_nh_args "$@")
echo "Starting NixOS rebuild for host: $(${pkgs.nettools}/bin/hostname)"
if eval "${pkgs.nh}/bin/nh os switch --hostname '$PROFILE' $extra_args"; then
echo "Rebuild finished successfully"
else
echo "Rebuild Failed" >&2
exit 1
fi
;;
rebuild-boot)
verify_hostname
handle_backups
extra_args=$(parse_nh_args "$@")
echo "Starting NixOS rebuild (boot) for host: $(${pkgs.nettools}/bin/hostname)"
echo "Note: Configuration will be activated on next reboot"
if eval "${pkgs.nh}/bin/nh os boot --hostname '$PROFILE' $extra_args"; then
echo "Rebuild-boot finished successfully"
echo "New configuration set as boot default - restart to activate"
else
echo "Rebuild-boot Failed" >&2
exit 1
fi
;;
trim)
echo "Running 'sudo fstrim -v /' may take a few minutes and impact system performance."
read -p "Enter (y/Y) to run now or enter to exit (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Running fstrim..."
sudo ${pkgs.util-linux}/bin/fstrim -v /
echo "fstrim complete."
else
echo "Trim operation cancelled."
fi
;;
update)
verify_hostname
handle_backups
extra_args=$(parse_nh_args "$@")
echo "Updating flake and rebuilding system for host: $(${pkgs.nettools}/bin/hostname)"
if eval "${pkgs.nh}/bin/nh os switch --hostname '$PROFILE' --update $extra_args"; then
echo "Update and rebuild finished successfully"
else
echo "Update and rebuild Failed" >&2
exit 1
fi
;;
update-host)
target_hostname=""
target_profile=""
if [ "$#" -eq 3 ]; then
target_hostname="$2"
target_profile="$3"
elif [ "$#" -eq 1 ]; then
echo "Attempting to auto-detect hostname and GPU profile..."
target_hostname=$(${pkgs.nettools}/bin/hostname)
target_profile=$(detect_gpu_profile)
if [ -z "$target_profile" ]; then
echo "Error: Could not auto-detect a specific GPU profile. Please provide it manually." >&2
echo "Usage: saugcli update-host [hostname] [profile]" >&2
exit 1
fi
echo "Auto-detected Hostname: $target_hostname"
echo "Auto-detected Profile: $target_profile"
else
echo "Error: Invalid number of arguments for 'update-host'." >&2
echo "Usage: saugcli update-host [hostname] [profile]" >&2
exit 1
fi
echo "Updating $FLAKE_NIX_PATH..."
if ${pkgs.gnused}/bin/sed -i "s/^[[:space:]]*host[[:space:]]*=[[:space:]]*\".*\"/ host = \"$target_hostname\"/" "$FLAKE_NIX_PATH"; then
echo "Successfully updated host to: $target_hostname"
else
echo "Error: Failed to update host in $FLAKE_NIX_PATH" >&2
exit 1
fi
if ${pkgs.gnused}/bin/sed -i "s/^[[:space:]]*profile[[:space:]]*=[[:space:]]*\".*\"/ profile = \"$target_profile\"/" "$FLAKE_NIX_PATH"; then
echo "Successfully updated profile to: $target_profile"
else
echo "Error: Failed to update profile in $FLAKE_NIX_PATH" >&2
exit 1
fi
echo "Flake.nix updated successfully!"
;;
add-host)
hostname=""
profile_arg=""
if [ "$#" -ge 2 ]; then
hostname="$2"
fi
if [ "$#" -eq 3 ]; then
profile_arg="$3"
fi
if [ -z "$hostname" ]; then
read -p "Enter the new hostname: " hostname
fi
if [ -d "$HOME/$PROJECT/hosts/$hostname" ]; then
echo "Error: Host '$hostname' already exists." >&2
exit 1
fi
echo "Copying default host configuration..."
${pkgs.coreutils}/bin/cp -r "$HOME/$PROJECT/hosts/default" "$HOME/$PROJECT/hosts/$hostname"
detected_profile=""
if [[ -n "$profile_arg" && "$profile_arg" =~ ^(intel|amd|vm)$ ]]; then
detected_profile="$profile_arg"
else
echo "Detecting GPU profile..."
detected_profile=$(detect_gpu_profile)
echo "Detected GPU profile: $detected_profile"
read -p "Is this correct? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Nn]$ ]]; then
read -p "Enter the correct profile (intel, amd, vm): " new_profile
while [[ ! "$new_profile" =~ ^(intel|amd|vm)$ ]]; do
echo "Invalid profile. Please enter one of the following: intel, amd, vm"
read -p "Enter the correct profile: " new_profile
done
detected_profile=$new_profile
fi
fi
echo "Setting profile to '$detected_profile'..."
${pkgs.gnused}/bin/sed -i "s/profile = .*/profile = \"$detected_profile\";/" "$HOME/$PROJECT/hosts/$hostname/default.nix"
read -p "Generate new hardware.nix? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Generating hardware.nix..."
sudo nixos-generate-config --show-hardware-config > "$HOME/$PROJECT/hosts/$hostname/hardware.nix"
echo "hardware.nix generated."
fi
echo "Adding new host to git..."
${pkgs.git}/bin/git -C "$HOME/$PROJECT" add .
echo "hostname: $hostname added"
;;
del-host)
hostname=""
if [ "$#" -eq 2 ]; then
hostname="$2"
else
read -p "Enter the hostname to delete: " hostname
fi
if [ ! -d "$HOME/$PROJECT/hosts/$hostname" ]; then
echo "Error: Host '$hostname' does not exist." >&2
exit 1
fi
read -p "Are you sure you want to delete the host '$hostname'? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Deleting host '$hostname'..."
${pkgs.coreutils}/bin/rm -rf "$HOME/$PROJECT/hosts/$hostname"
${pkgs.git}/bin/git -C "$HOME/$PROJECT" add .
echo "hostname: $hostname removed"
else
echo "Deletion cancelled."
fi
;;
*)
echo "Error: Invalid command '$1'" >&2
print_help
exit 1
;;
esac
''

View File

@@ -0,0 +1,5 @@
{ pkgs }:
pkgs.writeShellScriptBin "screenshootin" ''
grim -g "$(slurp)" - | swappy -f -
''

View File

@@ -0,0 +1,23 @@
{ pkgs }:
pkgs.writeShellScriptBin "squirtle" ''
echo "

  
  
  



 
 
 
 
 
 
 
 
 
 
"
''

View File

@@ -0,0 +1,6 @@
{ pkgs }:
pkgs.writeShellScriptBin "task-waybar" ''
sleep 0.1
${pkgs.swaynotificationcenter}/bin/swaync-client -t &
''

View File

@@ -0,0 +1,24 @@
{ pkgs, ... }:
pkgs.writeShellScriptBin "wallsetter" ''
TIMEOUT=720
for pid in $(pidof -o %PPID -x wallsetter); do
kill $pid
done
if ! [ -d ~/Pictures/Wallpapers ]; then notify-send -t 5000 "~/Pictures/Wallpapers does not exist" && exit 1; fi
if [ $(ls -1 ~/Pictures/Wallpapers | wc -l) -lt 1 ]; then notify-send -t 9000 "The wallpaper folder is expected to have more than 1 image. Exiting Wallsetter." && exit 1; fi
while true; do
while [ "$WALLPAPER" == "$PREVIOUS" ]; do
WALLPAPER=$(find ~/Pictures/Wallpapers -name '*' | awk '!/.git/' | tail -n +2 | shuf -n 1)
done
PREVIOUS=$WALLPAPER
${pkgs.swww}/bin/swww img "$WALLPAPER" --transition-type random --transition-step 1 --transition-fps 60
sleep $TIMEOUT
done
''

View File

@@ -0,0 +1,47 @@
{ pkgs }:
pkgs.writeShellScriptBin "web-search" ''
# check if rofi is already running
if pidof rofi > /dev/null; then
pkill rofi
fi
declare -A URLS
URLS=(
["🌎 Search"]="https://search.brave.com/search?q="
[" Unstable Packages"]="https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query="
["🎞 YouTube"]="https://www.youtube.com/results?search_query="
["🦥 Arch Wiki"]="https://wiki.archlinux.org/title/"
["🐃 Gentoo Wiki"]="https://wiki.gentoo.org/index.php?title="
)
# List for rofi
gen_list() {
for i in "''${!URLS[@]}"
do
echo "$i"
done
}
main() {
# Pass the list to rofi
platform=$( (gen_list) | ${pkgs.rofi}/bin/rofi -dmenu -config ~/.config/rofi/config-long.rasi )
if [[ -n "$platform" ]]; then
query=$( (echo ) | ${pkgs.rofi}/bin/rofi -dmenu -config ~/.config/rofi/config-long.rasi )
if [[ -n "$query" ]]; then
url=''${URLS[$platform]}$query
xdg-open "$url"
else
exit
fi
else
exit
fi
}
main
exit 0
''

14
modules/home/stylix.nix Normal file
View File

@@ -0,0 +1,14 @@
_: {
stylix.targets = {
waybar.enable = false;
rofi.enable = false;
hyprland.enable = false;
hyprlock.enable = true;
swaylock.enable = true;
ghostty.enable = true;
qt = {
enable = true;
platform = "qtct";
};
};
}

16
modules/home/swappy.nix Normal file
View File

@@ -0,0 +1,16 @@
{ username, ... }: {
home.file = {
".config/swappy/config".text = ''
[Default]
save_dir=/home/${username}/Pictures/Screenshots
save_filename_format=swappy-%Y%m%d-%H%M%S.png
show_panel=false
line_size=5
text_size=20
text_font=Ubuntu
paint_mode=brush
early_exit=true
fill_shape=false
'';
};
}

311
modules/home/swaync.nix Normal file
View File

@@ -0,0 +1,311 @@
{ config, ... }: {
services.swaync = {
enable = true;
settings = {
positionX = "right";
positionY = "top";
layer = "overlay";
control-center-margin-top = 10;
control-center-margin-bottom = 10;
control-center-margin-right = 10;
control-center-margin-left = 10;
notification-icon-size = 64;
notification-body-image-height = 100;
notification-body-image-width = 200;
timeout = 10;
timeout-low = 5;
timeout-critical = 0;
fit-to-screen = false;
control-center-width = 500;
control-center-height = 1025;
notification-window-width = 500;
keyboard-shortcuts = true;
image-visibility = "when-available";
transition-time = 200;
hide-on-clear = false;
hide-on-action = true;
script-fail-notify = true;
widget-config = {
title = {
text = "Notification Center";
clear-all-button = true;
button-text = "󰆴 Clear All";
};
dnd = {
text = "Do Not Disturb";
};
label = {
max-lines = 1;
text = "Notification Center";
};
mpris = {
image-size = 96;
image-radius = 7;
};
volume = {
label = "󰕾";
};
backlight = {
label = "󰃟";
};
};
widgets = [
"title"
"mpris"
"volume"
"backlight"
"dnd"
"notifications"
];
};
style = ''
* {
font-family: JetBrainsMono Nerd Font Mono;
font-weight: bold;
}
.control-center .notification-row:focus,
.control-center .notification-row:hover {
opacity: 0.9;
background: #${config.lib.stylix.colors.base00}
}
.notification-row {
outline: none;
margin: 10px;
padding: 0;
}
.notification {
background: transparent;
padding: 0;
margin: 0px;
}
.notification-content {
background: #${config.lib.stylix.colors.base00};
padding: 10px;
border-radius: 5px;
border: 2px solid #${config.lib.stylix.colors.base0D};
margin: 0;
}
.notification-default-action {
margin: 0;
padding: 0;
border-radius: 5px;
}
.close-button {
background: #${config.lib.stylix.colors.base08};
color: #${config.lib.stylix.colors.base00};
text-shadow: none;
padding: 0;
border-radius: 5px;
margin-top: 5px;
margin-right: 5px;
}
.close-button:hover {
box-shadow: none;
background: #${config.lib.stylix.colors.base0D};
transition: all .15s ease-in-out;
border: none
}
.notification-action {
border: 2px solid #${config.lib.stylix.colors.base0D};
border-top: none;
border-radius: 5px;
}
.notification-default-action:hover,
.notification-action:hover {
color: #${config.lib.stylix.colors.base0B};
background: #${config.lib.stylix.colors.base0B}
}
.notification-default-action {
border-radius: 5px;
margin: 0px;
}
.notification-default-action:not(:only-child) {
border-bottom-left-radius: 7px;
border-bottom-right-radius: 7px
}
.notification-action:first-child {
border-bottom-left-radius: 10px;
background: #${config.lib.stylix.colors.base00}
}
.notification-action:last-child {
border-bottom-right-radius: 10px;
background: #${config.lib.stylix.colors.base00}
}
.inline-reply {
margin-top: 8px
}
.inline-reply-entry {
background: #${config.lib.stylix.colors.base00};
color: #${config.lib.stylix.colors.base05};
caret-color: #${config.lib.stylix.colors.base05};
border: 1px solid #${config.lib.stylix.colors.base09};
border-radius: 5px
}
.inline-reply-button {
margin-left: 4px;
background: #${config.lib.stylix.colors.base00};
border: 1px solid #${config.lib.stylix.colors.base09};
border-radius: 5px;
color: #${config.lib.stylix.colors.base05}
}
.inline-reply-button:disabled {
background: initial;
color: #${config.lib.stylix.colors.base03};
border: 1px solid transparent
}
.inline-reply-button:hover {
background: #${config.lib.stylix.colors.base00}
}
.body-image {
margin-top: 6px;
background-color: #${config.lib.stylix.colors.base05};
border-radius: 5px
}
.summary {
font-size: 16px;
font-weight: 700;
background: transparent;
color: rgba(158, 206, 106, 1);
text-shadow: none
}
.time {
font-size: 16px;
font-weight: 700;
background: transparent;
color: #${config.lib.stylix.colors.base05};
text-shadow: none;
margin-right: 18px
}
.body {
font-size: 15px;
font-weight: 400;
background: transparent;
color: #${config.lib.stylix.colors.base05};
text-shadow: none
}
.control-center {
background: #${config.lib.stylix.colors.base00};
border: 2px solid #${config.lib.stylix.colors.base0C};
border-radius: 5px;
}
.control-center-list {
background: transparent
}
.control-center-list-placeholder {
opacity: .5
}
.floating-notifications {
background: transparent
}
.blank-window {
background: alpha(black, 0)
}
.widget-title {
color: #${config.lib.stylix.colors.base0B};
background: #${config.lib.stylix.colors.base00};
padding: 5px 10px;
margin: 10px 10px 5px 10px;
font-size: 1.5rem;
border-radius: 5px;
}
.widget-title>button {
font-size: 1rem;
color: #${config.lib.stylix.colors.base05};
text-shadow: none;
background: #${config.lib.stylix.colors.base00};
box-shadow: none;
border-radius: 5px;
}
.widget-title>button:hover {
background: #${config.lib.stylix.colors.base08};
color: #${config.lib.stylix.colors.base00};
}
.widget-dnd {
background: #${config.lib.stylix.colors.base00};
padding: 5px 10px;
margin: 10px 10px 5px 10px;
border-radius: 5px;
font-size: large;
color: #${config.lib.stylix.colors.base0B};
}
.widget-dnd>switch {
border-radius: 5px;
/* border: 1px solid #${config.lib.stylix.colors.base0B}; */
background: #${config.lib.stylix.colors.base0B};
}
.widget-dnd>switch:checked {
background: #${config.lib.stylix.colors.base08};
border: 1px solid #${config.lib.stylix.colors.base08};
}
.widget-dnd>switch slider {
background: #${config.lib.stylix.colors.base00};
border-radius: 5px
}
.widget-dnd>switch:checked slider {
background: #${config.lib.stylix.colors.base00};
border-radius: 5px
}
.widget-label {
margin: 10px 10px 5px 10px;
}
.widget-label>label {
font-size: 1rem;
color: #${config.lib.stylix.colors.base05};
}
.widget-mpris {
color: #${config.lib.stylix.colors.base05};
padding: 5px 10px;
margin: 10px 10px 5px 10px;
border-radius: 5px;
}
.widget-mpris > box > button {
border-radius: 5px;
}
.widget-mpris-player {
padding: 5px 10px;
margin: 10px
}
.widget-mpris-title {
font-weight: 700;
font-size: 1.25rem
}
.widget-mpris-subtitle {
font-size: 1.1rem
}
.widget-menubar>box>.menu-button-bar>button {
border: none;
background: transparent
}
.topbar-buttons>button {
border: none;
background: transparent
}
.widget-volume {
background: #${config.lib.stylix.colors.base01};
padding: 5px;
margin: 10px 10px 5px 10px;
border-radius: 5px;
font-size: x-large;
color: #${config.lib.stylix.colors.base05};
}
.widget-volume>box>button {
background: #${config.lib.stylix.colors.base0B};
border: none
}
.per-app-volume {
background-color: #${config.lib.stylix.colors.base00};
padding: 4px 8px 8px;
margin: 0 8px 8px;
border-radius: 5px;
}
.widget-backlight {
background: #${config.lib.stylix.colors.base01};
padding: 5px;
margin: 10px 10px 5px 10px;
border-radius: 5px;
font-size: x-large;
color: #${config.lib.stylix.colors.base05}
}
'';
};
}

10
modules/home/tealdeer.nix Normal file
View File

@@ -0,0 +1,10 @@
{ ... }: {
programs.tealdeer = {
enable = true;
settings = {
display.compact = false;
display.use_pager = true;
updates.auto_update = true;
};
};
}

118
modules/home/tmux.nix Normal file
View File

@@ -0,0 +1,118 @@
# Tmux is a terminal multiplexer that allows you to run multiple terminal sessions in a single window.
{ pkgs, ... }: {
programs.tmux = {
enable = true;
mouse = true;
shell = "${pkgs.zsh}/bin/zsh";
prefix = "C-a";
terminal = "kitty";
keyMode = "vi";
extraConfig = ''
set-option -g status-position top
#set -g default-terminal "screen-256color"
set-option -g history-limit 5000
unbind %
unbind '"'
bind-key h select-pane -L
bind-key j select-pane -D
bind-key k select-pane -U
bind-key l select-pane -R
set -gq allow-passthrough on
bind-key x kill-pane # skip "kill-pane 1? (y/n)" prompt
bind-key -n C-Tab next-window
bind-key -n C-S-Tab previous-window
bind-key -n M-Tab new-window
# Start windows and panes index at 1, not 0.
set -g base-index 1
setw -g pane-base-index 1
bind-key "|" split-window -h -c "#{pane_current_path}"
bind-key "\\" split-window -fh -c "#{pane_current_path}"
bind-key "-" split-window -v -c "#{pane_current_path}"
bind-key "_" split-window -fv -c "#{pane_current_path}"
bind -r C-j resize-pane -D 15
bind -r C-k resize-pane -U 15
bind -r C-h resize-pane -L 15
bind -r C-l resize-pane -R 15
# 'c' to new window
bind-key c new-window
# 'n' next window
bind-key n next-window
# 'p' next previous
bind-key n previous-window
unbind r
bind r source-file ~/.config/tmux/tmux.conf
bind -r m resize-pane -Z
bind-key t clock-mode
bind-key q display-panes
bind-key u refresh-client
bind-key o select-pane -t :.+
##### Display Popups #####
bind C-y display-popup \
-d "#{pane_current_path}" \
-w 80% \
-h 80% \
-E "lazygit"
bind C-n display-popup -E 'bash -i -c "read -p \"Session name: \" name; tmux new-session -d -s \$name && tmux switch-client -t \$name"'
bind C-j display-popup -E "tmux list-sessions | sed -E 's/:.*$//' | grep -v \"^$(tmux display-message -p '#S')\$\" | fzf --reverse | xargs tmux switch-client -t"
#bind C-p display-popup -E "ipython"
#bind C-f display-popup \
# -w 80% \
# -h 80% \
# -E 'rmpc'
bind C-r display-popup \
-d "#{pane_current_path}" \
-w 90% \
-h 90% \
-E "yazi"
bind C-z display-popup \
-w 90% \
-h 90% \
-E 'nvim ~/ddubsos/flake.nix'
#bind C-g display-popup -E "bash -i ~/.tmux/scripts/chat-popup.sh"
bind C-t display-popup \
-d "#{pane_current_path}" \
-w 75% \
-h 75% \
-E "zsh"
##### Display Menu #####
bind d display-menu -T "#[align=centre]Dotfiles" -x C -y C \
"SaugOS flake.nix" f "display-popup -E 'nvim ~/zaneyos/SaugOS/flake.nix'" \
"SaugOS packages" p "display-popup -E 'nvim ~/zaneyos/SaugOS/modules/core/packages.nix'" \
"SaugOS keybinds" k "display-popup -E 'nvim ~/zaneyos/SaugOS/modules/home/niri/binds.nix'" \
"SaugOS variables" e "display-popup -E 'nvim ~/zaneyos/SaugOS/hosts/default/variables.nix'" \
"SaugOS windowrules" w "display-popup -E 'nvim ~/zaneyos/SaugOS/modules/home/niri/windowrules.nix'" \
"Exit" q ""
'';
plugins = with pkgs; [
tmuxPlugins.vim-tmux-navigator
tmuxPlugins.sensible
tmuxPlugins.tokyo-night-tmux
];
};
}

57
modules/home/vscode.nix Normal file
View File

@@ -0,0 +1,57 @@
{ pkgs, pkgs-unstable, lib, ... }: {
nixpkgs.config.allowUnfree = true;
programs.vscode = {
enable = true;
package = pkgs-unstable.vscode;
mutableExtensionsDir = true;
profiles.default = {
enableExtensionUpdateCheck = true;
enableUpdateCheck = true;
extensions = with pkgs-unstable.vscode-extensions; [
bbenoist.nix
jeff-hykin.better-nix-syntax
ms-vscode.cpptools-extension-pack
vscodevim.vim # Vim emulation
mads-hartmann.bash-ide-vscode
tamasfe.even-better-toml
zainchen.json
shd101wyy.markdown-preview-enhanced
# Copilot
github.copilot
github.copilot-chat
# Programming languages
golang.go
ziglang.vscode-zig
ms-python.python
ms-python.vscode-pylance
# Jupyter notebooks
ms-toolsai.jupyter
ms-toolsai.jupyter-keymap
ms-toolsai.jupyter-renderers
# Icons
catppuccin.catppuccin-vsc-icons
];
userSettings = {
"workbench.sideBar.location" = "right";
"workbench.iconTheme" = "catppuccin-macchiato";
"github.copilot.enable" = {
"*" = false;
"plaintext" = false;
"markdown" = false;
"scminput" = false;
};
"workbench.panel.defaultLocation" = "left";
"editor.fontFamily" = lib.mkForce "JetBrainsMono Nerd Font, FiraCode Nerd Font, monospace";
"editor.fontLigatures" = true;
"editor.fontSize" = lib.mkForce 12;
"terminal.integrated.fontFamily" = lib.mkForce "JetBrainsMono Nerd Font, FiraCode Nerd Font, monospace";
};
};
};
}

View File

@@ -0,0 +1,275 @@
{ pkgs
, lib
, host
, config
, ...
}:
let
betterTransition = "all 0.3s cubic-bezier(.55,-0.68,.48,1.682)";
inherit (import ../../../hosts/${host}/variables.nix) clock24h;
in
with lib; {
# Configure & Theme Waybar
programs.waybar = {
enable = true;
package = pkgs.waybar;
settings = [
{
layer = "top";
position = "top";
modules-center = [ "niri/workspaces" ];
modules-left = [
"custom/startmenu"
"niri/window"
"pulseaudio"
"cpu"
"memory"
"idle_inhibitor"
];
modules-right = [
"custom/hyprbindings"
"custom/notification"
"custom/exit"
"battery"
"tray"
"clock"
];
"niri/workspaces" = {
format = "{name}";
format-icons = {
default = " ";
active = " ";
urgent = " ";
};
};
"clock" = {
format =
if clock24h == true
then '' {:L%H:%M}''
else '' {:L%I:%M %p}'';
tooltip = true;
tooltip-format = "<big>{:%A, %d.%B %Y }</big>\n<tt><small>{calendar}</small></tt>";
};
"niri/window" = {
max-length = 22;
separate-outputs = false;
rewrite = {
"" = " 🙈 No Windows? ";
};
};
"memory" = {
interval = 5;
format = " {}%";
tooltip = true;
};
"cpu" = {
interval = 5;
format = " {usage:2}%";
tooltip = true;
};
"disk" = {
format = " {free}";
tooltip = true;
};
"network" = {
format-icons = [
"󰤯"
"󰤟"
"󰤢"
"󰤥"
"󰤨"
];
format-ethernet = " {bandwidthDownOctets}";
format-wifi = "{icon} {signalStrength}%";
format-disconnected = "󰤮";
tooltip = false;
};
"tray" = {
spacing = 12;
};
"pulseaudio" = {
format = "{icon} {volume}% {format_source}";
format-bluetooth = "{volume}% {icon} {format_source}";
format-bluetooth-muted = " {icon} {format_source}";
format-muted = " {format_source}";
format-source = " {volume}%";
format-source-muted = "";
format-icons = {
headphone = "";
hands-free = "";
headset = "";
phone = "";
portable = "";
car = "";
default = [
""
""
""
];
};
on-click = "sleep 0.1 && pavucontrol";
};
"custom/exit" = {
tooltip = false;
format = "";
on-click = "sleep 0.1 && wlogout";
};
"custom/startmenu" = {
tooltip = false;
format = "";
# exec = "rofi -show drun";
on-click = "sleep 0.1 && rofi-launcher";
};
"custom/hyprbindings" = {
tooltip = false;
format = "󱕴";
on-click = "sleep 0.1 && list-keybinds";
};
"idle_inhibitor" = {
format = "{icon}";
format-icons = {
activated = "";
deactivated = "";
};
tooltip = "true";
};
"custom/notification" = {
tooltip = false;
format = "{icon} {}";
format-icons = {
notification = "<span foreground='red'><sup></sup></span>";
none = "";
dnd-notification = "<span foreground='red'><sup></sup></span>";
dnd-none = "";
inhibited-notification = "<span foreground='red'><sup></sup></span>";
inhibited-none = "";
dnd-inhibited-notification = "<span foreground='red'><sup></sup></span>";
dnd-inhibited-none = "";
};
return-type = "json";
exec-if = "which swaync-client";
exec = "swaync-client -swb";
on-click = "sleep 0.1 && task-waybar";
escape = true;
};
"battery" = {
states = {
warning = 30;
critical = 15;
};
format = "{icon} {capacity}%";
format-charging = "󰂄 {capacity}%";
format-plugged = "󱘖 {capacity}%";
format-icons = [
"󰁺"
"󰁻"
"󰁼"
"󰁽"
"󰁾"
"󰁿"
"󰂀"
"󰂁"
"󰂂"
"󰁹"
];
on-click = "";
tooltip = false;
};
}
];
style = concatStrings [
''
* {
font-family: JetBrainsMono Nerd Font Mono;
font-size: 16px;
border-radius: 0px;
border: none;
min-height: 0px;
}
window#waybar {
background: rgba(0,0,0,0);
}
#workspaces {
color: #${config.lib.stylix.colors.base00};
background: #${config.lib.stylix.colors.base01};
margin: 4px 4px;
padding: 5px 5px;
border-radius: 16px;
}
#workspaces button {
font-weight: bold;
padding: 0px 5px;
margin: 0px 3px;
border-radius: 16px;
color: #${config.lib.stylix.colors.base00};
background: linear-gradient(45deg, #${config.lib.stylix.colors.base08}, #${config.lib.stylix.colors.base0D});
opacity: 0.5;
transition: ${betterTransition};
}
#workspaces button.active {
font-weight: bold;
padding: 0px 5px;
margin: 0px 3px;
border-radius: 16px;
color: #${config.lib.stylix.colors.base00};
background: linear-gradient(45deg, #${config.lib.stylix.colors.base08}, #${config.lib.stylix.colors.base0D});
transition: ${betterTransition};
opacity: 1.0;
min-width: 40px;
}
#workspaces button:hover {
font-weight: bold;
border-radius: 16px;
color: #${config.lib.stylix.colors.base00};
background: linear-gradient(45deg, #${config.lib.stylix.colors.base08}, #${config.lib.stylix.colors.base0D});
opacity: 0.8;
transition: ${betterTransition};
}
tooltip {
background: #${config.lib.stylix.colors.base00};
border: 1px solid #${config.lib.stylix.colors.base08};
border-radius: 12px;
}
tooltip label {
color: #${config.lib.stylix.colors.base08};
}
#window, #pulseaudio, #cpu, #memory, #idle_inhibitor {
font-weight: bold;
margin: 4px 0px;
margin-left: 7px;
padding: 0px 18px;
background: #${config.lib.stylix.colors.base04};
color: #${config.lib.stylix.colors.base00};
border-radius: 24px 10px 24px 10px;
}
#custom-startmenu {
color: #${config.lib.stylix.colors.base0B};
background: #${config.lib.stylix.colors.base02};
font-size: 28px;
margin: 0px;
padding: 0px 30px 0px 15px;
border-radius: 0px 0px 40px 0px;
}
#custom-hyprbindings, #network, #battery,
#custom-notification, #tray, #custom-exit {
font-weight: bold;
background: #${config.lib.stylix.colors.base0F};
color: #${config.lib.stylix.colors.base00};
margin: 4px 0px;
margin-right: 7px;
border-radius: 10px 24px 10px 24px;
padding: 0px 18px;
}
#clock {
font-weight: bold;
color: #0D0E15;
background: linear-gradient(90deg, #${config.lib.stylix.colors.base0E}, #${config.lib.stylix.colors.base0C});
margin: 0px;
padding: 0px 15px 0px 30px;
border-radius: 0px 0px 0px 40px;
}
''
];
};
}

82
modules/home/wezterm.nix Normal file
View File

@@ -0,0 +1,82 @@
{ pkgs, ... }: {
programs.wezterm = {
enable = true;
package = pkgs.wezterm;
};
home.file."./.config/wezterm/wezterm.lua".text = ''
-- Config from Drew @justaguylinux small mods
local wezterm = require("wezterm")
local config = wezterm.config_builder()
config.enable_wayland = false
-- General appearance and visuals
config.colors = {
tab_bar = {
background = "#00141d", -- col_gray1, your main DWM bar background
active_tab = {
bg_color = "#80bfff", -- col_gray2 (selected tab in bright blue)
fg_color = "#00141d", -- contrast text on active tab
},
inactive_tab = {
bg_color = "#1a1a1a", -- col_gray4 (dark background for inactive tabs)
fg_color = "#FFFFFF", -- col_gray3 (white text on inactive tabs)
},
new_tab = {
bg_color = "#1a1a1a", -- same as inactive
fg_color = "#4fc3f7", -- col_barbie (for the "+" button)
},
},
}
config.window_background_opacity = 0.90
config.color_scheme = "nightfox"
config.font_size = 12
config.font = wezterm.font("FiraCode", { weight = "Regular", italic = false })
config.window_padding = {
left = 10,
right = 10,
top = 10,
bottom = 10,
}
config.use_fancy_tab_bar = true
config.window_frame = {
-- font = wezterm.font({ family = "FiraCode Nerd Font Mono", weight = "Regular" }),
font = wezterm.font({ family = "JetBrainsMono Nerd Font Mono", weight = "Regular" }),
}
config.default_cursor_style = "BlinkingUnderline"
config.cursor_blink_rate = 500
config.term = "xterm-256color"
config.max_fps = 144
config.animation_fps = 30
-- Keybindings using ALT for tabs & splits
config.keys = {
-- Tab management
{ key = "t", mods = "ALT", action = wezterm.action.SpawnTab("CurrentPaneDomain") },
{ key = "w", mods = "ALT", action = wezterm.action.CloseCurrentTab({ confirm = false }) },
{ key = "n", mods = "ALT", action = wezterm.action.ActivateTabRelative(1) },
{ key = "p", mods = "ALT", action = wezterm.action.ActivateTabRelative(-1) },
-- Pane management
{ key = "v", mods = "ALT", action = wezterm.action.SplitVertical({ domain = "CurrentPaneDomain" }) },
{ key = "h", mods = "ALT", action = wezterm.action.SplitHorizontal({ domain = "CurrentPaneDomain" }) },
{ key = "q", mods = "ALT", action = wezterm.action.CloseCurrentPane({ confirm = false }) },
-- Pane navigation (move between panes with ALT + Arrows)
{ key = "LeftArrow", mods = "ALT", action = wezterm.action.ActivatePaneDirection("Left") },
{ key = "RightArrow", mods = "ALT", action = wezterm.action.ActivatePaneDirection("Right") },
{ key = "UpArrow", mods = "ALT", action = wezterm.action.ActivatePaneDirection("Up") },
{ key = "DownArrow", mods = "ALT", action = wezterm.action.ActivatePaneDirection("Down") },
}
return config
'';
}

View File

@@ -0,0 +1,107 @@
{ config, ... }:
{
programs.wlogout = {
enable = true;
layout = [
{
label = "shutdown";
action = "sleep 1; systemctl poweroff";
text = "Shutdown";
keybind = "s";
}
{
"label" = "reboot";
"action" = "sleep 1; systemctl reboot";
"text" = "Reboot";
"keybind" = "r";
}
{
"label" = "logout";
"action" = "sleep 1; hyprctl dispatch exit";
"text" = "Exit";
"keybind" = "e";
}
{
"label" = "suspend";
"action" = "sleep 1; systemctl suspend";
"text" = "Suspend";
"keybind" = "u";
}
{
"label" = "lock";
"action" = "sleep 1; hyprlock";
"text" = "Lock";
"keybind" = "l";
}
{
"label" = "hibernate";
"action" = "sleep 1; systemctl hibernate";
"text" = "Hibernate";
"keybind" = "h";
}
];
style = ''
* {
font-family: "JetBrainsMono NF", FontAwesome, sans-serif;
background-image: none;
transition: 20ms;
}
window {
background-color: rgba(12, 12, 12, 0.1);
}
button {
color: #${config.lib.stylix.colors.base05};
font-size:20px;
background-repeat: no-repeat;
background-position: center;
background-size: 25%;
border-style: solid;
background-color: rgba(12, 12, 12, 0.3);
border: 3px solid #${config.lib.stylix.colors.base05};
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
button:focus,
button:active,
button:hover {
color: #${config.lib.stylix.colors.base0B};
background-color: rgba(12, 12, 12, 0.5);
border: 3px solid #${config.lib.stylix.colors.base0B};
}
#logout {
margin: 10px;
border-radius: 20px;
background-image: image(url("icons/logout.png"));
}
#suspend {
margin: 10px;
border-radius: 20px;
background-image: image(url("icons/suspend.png"));
}
#shutdown {
margin: 10px;
border-radius: 20px;
background-image: image(url("icons/shutdown.png"));
}
#reboot {
margin: 10px;
border-radius: 20px;
background-image: image(url("icons/reboot.png"));
}
#lock {
margin: 10px;
border-radius: 20px;
background-image: image(url("icons/lock.png"));
}
#hibernate {
margin: 10px;
border-radius: 20px;
background-image: image(url("icons/hibernate.png"));
}
'';
};
home.file.".config/wlogout/icons" = {
source = ./icons;
recursive = true;
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

37
modules/home/xdg.nix Normal file
View File

@@ -0,0 +1,37 @@
{ pkgs, host, ... }:
let
vars = import ../../hosts/${host}/variables.nix;
browserDesktop = {
"firefox" = "firefox.desktop";
"brave" = "brave-browser.desktop";
"google-chrome" = "google-chrome.desktop";
"google-chrome-stable" = "google-chrome.desktop";
"chromium" = "chromium-browser.desktop";
"zen" = "zen.desktop";
"floorp" = "floorp.desktop";
"librewolf" = "librewolf.desktop";
"vivaldi" = "vivaldi-stable.desktop";
};
defaultBrowser = browserDesktop.${vars.browser} or "${vars.browser}.desktop";
in
{
xdg = {
enable = true;
mime.enable = true;
mimeApps = {
enable = true;
defaultApplications = {
"text/html" = defaultBrowser;
"x-scheme-handler/http" = defaultBrowser;
"x-scheme-handler/https" = defaultBrowser;
"x-scheme-handler/about" = defaultBrowser;
"x-scheme-handler/unknown" = defaultBrowser;
};
};
portal = {
enable = true;
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
config.common.default = "*";
};
};
}

View File

@@ -0,0 +1,32 @@
{ pkgs, ... }:
let
settings = import ./yazi.nix;
keymap = import ./keymap.nix;
theme = import ./theme.nix;
in
{
programs.yazi = {
enable = true;
enableZshIntegration = true;
enableBashIntegration = true;
enableFishIntegration = true;
shellWrapperName = "yy";
settings = settings;
keymap = keymap;
theme = theme;
plugins = {
lazygit = pkgs.yaziPlugins.lazygit;
full-border = pkgs.yaziPlugins.full-border;
git = pkgs.yaziPlugins.git;
smart-enter = pkgs.yaziPlugins.smart-enter;
};
initLua = ''
require("full-border"):setup()
require("git"):setup()
require("smart-enter"):setup {
open_multi = true,
}
'';
};
}

1201
modules/home/yazi/keymap.nix Normal file

File diff suppressed because it is too large Load Diff

3404
modules/home/yazi/theme.nix Normal file

File diff suppressed because it is too large Load Diff

389
modules/home/yazi/yazi.nix Normal file
View File

@@ -0,0 +1,389 @@
{
settings = {
manager = {
ratio = [ 1 4 3 ];
sort_by = "alphabetical";
sort_sensitive = false;
sort_reverse = false;
sort_dir_first = true;
sort_translit = false;
linemode = "none";
show_hidden = false;
show_symlink = true;
scrolloff = 5;
mouse_events = [ "click" "scroll" ];
title_format = "Yazi: {cwd}";
};
preview = {
wrap = "no";
tab_size = 2;
max_width = 600;
max_height = 900;
cache_dir = "";
image_delay = 30;
image_filter = "triangle";
image_quality = 75;
sixel_fraction = 15;
ueberzug_scale = 1;
ueberzug_offset = [ 0 0 0 0 ];
};
opener = {
edit = [
{
run = ''${"EDITOR:-vi"} "$@"'';
desc = "$EDITOR";
block = true;
for = "unix";
}
{
run = "code %*";
orphan = true;
desc = "code";
for = "windows";
}
{
run = "code -w %*";
block = true;
desc = "code (block)";
for = "windows";
}
];
open = [
{
run = ''xdg-open "$1"'';
desc = "Open";
for = "linux";
}
{
run = ''open "$@"'';
desc = "Open";
for = "macos";
}
{
run = ''start "" "%1"'';
orphan = true;
desc = "Open";
for = "windows";
}
{
run = ''termux-open "$1"'';
desc = "Open";
for = "android";
}
];
reveal = [
{
run = ''xdg-open "$(dirname "$1")"'';
desc = "Reveal";
for = "linux";
}
{
run = ''open -R "$1"'';
desc = "Reveal";
for = "macos";
}
{
run = ''explorer /select,"%1"'';
orphan = true;
desc = "Reveal";
for = "windows";
}
{
run = ''termux-open "$(dirname "$1")"'';
desc = "Reveal";
for = "android";
}
{
run = ''exiftool "$1"; echo "Press enter to exit"; read _'';
block = true;
desc = "Show EXIF";
for = "unix";
}
];
extract = [
{
run = ''ya pub extract --list "$@"'';
desc = "Extract here";
for = "unix";
}
{
run = "ya pub extract --list %*";
desc = "Extract here";
for = "windows";
}
];
play = [
{
run = ''mpv --force-window "$@"'';
orphan = true;
for = "unix";
}
{
run = "mpv --force-window %*";
orphan = true;
for = "windows";
}
{
run = ''mediainfo "$1"; echo "Press enter to exit"; read _'';
block = true;
desc = "Show media info";
for = "unix";
}
];
};
open = {
rules = [
{
name = "*/";
use = [ "edit" "open" "reveal" ];
}
{
mime = "text/*";
use = [ "edit" "reveal" ];
}
{
mime = "image/*";
use = [ "open" "reveal" ];
}
{
mime = "{audio,video}/*";
use = [ "play" "reveal" ];
}
{
mime =
"application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}";
use = [ "extract" "reveal" ];
}
{
mime = "application/{json,ndjson}";
use = [ "edit" "reveal" ];
}
{
mime = "*/javascript";
use = [ "edit" "reveal" ];
}
{
mime = "inode/empty";
use = [ "edit" "reveal" ];
}
{
name = "*";
use = [ "open" "reveal" ];
}
];
};
tasks = {
micro_workers = 10;
macro_workers = 10;
bizarre_retry = 3;
image_alloc = 536870912;
image_bound = [ 0 0 ];
suppress_preload = false;
};
plugin = {
fetchers = [{
id = "mime";
name = "*";
run = "mime";
prio = "high";
}];
spotters = [
{
name = "*/";
run = "folder";
}
{
mime = "text/*";
run = "code";
}
{
mime = "application/{mbox,javascript,wine-extension-ini}";
run = "code";
}
{
mime = "image/{avif,hei?,jxl,svg+xml}";
run = "magick";
}
{
mime = "image/*";
run = "image";
}
{
mime = "video/*";
run = "video";
}
{
name = "*";
run = "file";
}
];
preloaders = [
{
mime = "image/{avif,hei?,jxl,svg+xml}";
run = "magick";
}
{
mime = "image/*";
run = "image";
}
{
mime = "video/*";
run = "video";
}
{
mime = "application/pdf";
run = "pdf";
}
{
mime = "font/*";
run = "font";
}
{
mime = "application/ms-opentype";
run = "font";
}
];
previewers = [
{
name = "*/";
run = "folder";
sync = true;
}
{
mime = "text/*";
run = "code";
}
{
mime = "application/{mbox,javascript,wine-extension-ini}";
run = "code";
}
{
mime = "application/{json,ndjson}";
run = "json";
}
{
mime = "image/{avif,hei?,jxl,svg+xml}";
run = "magick";
}
{
mime = "image/*";
run = "image";
}
{
mime = "video/*";
run = "video";
}
{
mime = "application/pdf";
run = "pdf";
}
{
mime =
"application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}";
run = "archive";
}
{
mime =
"application/{debian*-package,redhat-package-manager,rpm,android.package-archive}";
run = "archive";
}
{
name = "*.{AppImage,appimage}";
run = "archive";
}
{
mime = "application/{iso9660-image,qemu-disk,ms-wim,apple-diskimage}";
run = "archive";
}
{
mime = "application/virtualbox-{vhd,vhdx}";
run = "archive";
}
{
name = "*.{img,fat,ext,ext2,ext3,ext4,squashfs,ntfs,hfs,hfsx}";
run = "archive";
}
{
mime = "font/*";
run = "font";
}
{
mime = "application/ms-opentype";
run = "font";
}
{
mime = "inode/empty";
run = "empty";
}
{
name = "*";
run = "file";
}
];
prepend_fetchers = [
{
id = "git";
name = "*";
run = "git";
}
{
id = "git";
name = "*/";
run = "git";
}
];
};
input = {
cursor_blink = false;
cd_title = "Change directory:";
cd_origin = "top-center";
cd_offset = [ 0 2 50 3 ];
create_title = [ "Create:" "Create (dir):" ];
create_origin = "top-center";
create_offset = [ 0 2 50 3 ];
rename_title = "Rename:";
rename_origin = "hovered";
rename_offset = [ 0 1 50 3 ];
filter_title = "Filter:";
filter_origin = "top-center";
filter_offset = [ 0 2 50 3 ];
find_title = [ "Find next:" "Find previous:" ];
find_origin = "top-center";
find_offset = [ 0 2 50 3 ];
search_title = "Search via {n}:";
search_origin = "top-center";
search_offset = [ 0 2 50 3 ];
shell_title = [ "Shell:" "Shell (block):" ];
shell_origin = "top-center";
shell_offset = [ 0 2 50 3 ];
};
confirm = {
trash_title = "Trash {n} selected file{s}?";
trash_origin = "center";
trash_offset = [ 0 0 70 20 ];
delete_title = "Permanently delete {n} selected file{s}?";
delete_origin = "center";
delete_offset = [ 0 0 70 20 ];
overwrite_title = "Overwrite file?";
overwrite_content = "Will overwrite the following file:";
overwrite_origin = "center";
overwrite_offset = [ 0 0 50 15 ];
quit_title = "Quit?";
quit_content =
"The following tasks are still running, are you sure you want to quit?";
quit_origin = "center";
quit_offset = [ 0 0 50 15 ];
};
pick = {
open_title = "Open with:";
open_origin = "hovered";
open_offset = [ 0 1 50 7 ];
};
which = {
sort_by = "none";
sort_sensitive = false;
sort_reverse = false;
sort_translit = false;
};
};
}

13
modules/home/zoxide.nix Normal file
View File

@@ -0,0 +1,13 @@
_: {
programs = {
zoxide = {
enable = true;
enableZshIntegration = true;
enableBashIntegration = true;
options = [
"--cmd cd"
];
};
};
}

View File

@@ -0,0 +1,63 @@
{ profile
, pkgs
, lib
, ...
}: {
imports = [
./zshrc-personal.nix
];
programs.zsh = {
enable = true;
autosuggestion.enable = true;
syntaxHighlighting = {
enable = true;
highlighters = [ "main" "brackets" "pattern" "regexp" "root" "line" ];
};
historySubstringSearch.enable = true;
history = {
ignoreDups = true;
save = 10000;
size = 10000;
};
oh-my-zsh = {
enable = true;
};
plugins = [
{
name = "powerlevel10k";
src = pkgs.zsh-powerlevel10k;
file = "share/zsh-powerlevel10k/powerlevel10k.zsh-theme";
}
{
name = "powerlevel10k-config";
src = lib.cleanSource ./p10k-config;
file = "p10k.zsh";
}
];
initContent = ''
bindkey "\eh" backward-word
bindkey "\ej" down-line-or-history
bindkey "\ek" up-line-or-history
bindkey "\el" forward-word
if [ -f $HOME/.zshrc-personal ]; then
source $HOME/.zshrc-personal
fi
'';
shellAliases = {
sv = "sudo nvim";
v = "nvim";
c = "clear";
fr = "nh os switch --hostname ${profile}";
fu = "nh os switch --hostname ${profile} --update";
ncg = "nix-collect-garbage --delete-old && sudo nix-collect-garbage -d && sudo /run/current-system/bin/switch-to-configuration boot";
cat = "bat";
man = "batman";
};
};
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More