commit 50d930e1ff1e3f5fc3497ad68c7472598da93460
Author: DerGrumpf
Date: Wed Feb 11 11:04:59 2026 +0100
Init
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ae4844e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,271 @@
+# NixOS Starter for Raspberry Pi 4
+
+A declarative NixOS flake setup for Raspberry Pi 4, following a modular configuration structure.
+
+## Directory Structure
+
+```
+rpi-starter/
+├── flake.nix # Main flake configuration and inputs
+├── nixos/
+│ ├── default.nix # Core NixOS system configuration
+│ ├── settings.nix # Localization and system preferences
+│ ├── hardware.nix # RPi 4 hardware-specific settings
+│ └── packages.nix # System-level packages
+├── home/
+│ ├── default.nix # Home Manager entry point
+│ ├── packages.nix # User packages
+│ ├── git.nix # Git configuration
+│ └── shell.nix # Zsh, Tmux, Starship configuration
+└── hosts/
+ └── rpi-4/
+ ├── configuration.nix # Host-specific settings
+ └── shell-functions.sh # Custom shell utilities
+```
+
+## Quick Start
+
+### 1. Flash NixOS to SD Card
+
+```bash
+# Download aarch64 image
+wget https://hydra.nixos.org/build/XXXXX/download/1/nixos-sd-image-aarch64-linux.img.zst
+
+# Flash to SD card (replace sdX with your device)
+zstdcat nixos-sd-image-aarch64-linux.img.zst | sudo dd of=/dev/sdX bs=4M conv=fsync
+```
+
+### 2. Boot and Setup Network
+
+Boot the RPi 4 and find its IP address:
+
+```bash
+arp-scan -l
+ssh root@ # Default password is empty
+```
+
+### 3. Clone Configuration
+
+```bash
+cd /tmp
+git clone nixos-config
+cd nixos-config
+```
+
+### 4. Apply Configuration
+
+```bash
+# Switch to new configuration
+sudo nixos-rebuild switch --flake .#rpi-4
+```
+
+## Customization
+
+### Change Username
+
+Edit `flake.nix`:
+```nix
+primaryUser = "your-username"; # Change from "phil"
+```
+
+### Add System Packages
+
+Edit `nixos/packages.nix`:
+```nix
+environment.systemPackages = with pkgs; [
+ # ... existing packages ...
+ python3
+ nodejs
+];
+```
+
+### Add User Packages
+
+Edit `home/packages.nix`:
+```nix
+home.packages = with pkgs; [
+ # ... existing packages ...
+ poetry
+ nodePackages.pnpm
+];
+```
+
+### Configure Git
+
+Edit `home/git.nix`:
+```nix
+programs.git = {
+ enable = true;
+ userName = "Your Name";
+ userEmail = "your@email.com";
+ # ... more config
+};
+```
+
+### Customize Shell
+
+Edit `home/shell.nix` for Zsh, Tmux, and Starship customizations.
+
+### Add Host-Specific Settings
+
+Edit `hosts/rpi-4/configuration.nix` for RPi 4-specific packages and settings.
+
+## Available Commands
+
+```bash
+# Rebuild and switch to new configuration
+rebuild
+
+# Build without switching
+rebuild-build
+
+# Show system health (disk, memory, CPU, temp)
+sys-health
+
+# SSH into RPi
+ssh-rpi [user] [host]
+
+# Update flake inputs
+flake-update
+
+# Show largest directories
+du-top
+```
+
+To use these commands, source the shell functions:
+
+```bash
+source hosts/rpi-4/shell-functions.sh
+```
+
+Or add to your zsh config to load automatically.
+
+## Configuration Files Overview
+
+### flake.nix
+- Declares inputs (nixpkgs, home-manager, etc.)
+- Defines outputs and system configuration
+- Entry point for the entire setup
+
+### nixos/default.nix
+- Main NixOS system configuration
+- Imports hardware, settings, and packages modules
+- Configures SSH, users, Nix settings
+
+### nixos/hardware.nix
+- RPi 4 bootloader and kernel settings
+- Filesystem and swap configuration
+- RPi 4-specific hardware enablement
+
+### nixos/settings.nix
+- Timezone and locale settings
+- Console keyboard layout
+- General system preferences
+
+### nixos/packages.nix
+- System-level packages available to all users
+
+### home/default.nix
+- Home Manager entry point
+- Imports shell, git, and packages modules
+- Sets home state version
+
+### home/packages.nix
+- User-level packages
+
+### home/git.nix
+- Git configuration (name, email, core settings)
+
+### home/shell.nix
+- Zsh configuration (aliases, keybindings, plugins)
+- Tmux configuration (prefix, keybindings)
+- Starship prompt setup
+- Direnv integration
+
+### hosts/rpi-4/configuration.nix
+- Host-specific package additions
+- RPi 4-specific customizations
+
+### hosts/rpi-4/shell-functions.sh
+- Bash functions for common tasks
+- Can be sourced in shell configs
+
+## Locale and Timezone
+
+Default settings:
+- **Timezone**: Europe/Berlin
+- **Locale**: en_US.UTF-8 (with German regional settings)
+
+Change in `nixos/settings.nix`:
+
+```nix
+time.timeZone = "America/New_York";
+i18n.defaultLocale = "en_US.UTF-8";
+```
+
+## Troubleshooting
+
+### SSH Connection Issues
+- Ensure SSH is enabled in `nixos/default.nix`
+- Check public key is authorized
+- Verify hostname resolves: `ping rpi-4.local`
+
+### Out of Memory
+Increase swap in `nixos/hardware.nix`:
+
+```nix
+swapDevices = [{
+ device = "/swapfile";
+ size = 4096; # Increase to 4GB
+}];
+```
+
+### Package Not Found
+```bash
+# Search for a package
+nix search nixpkgs package-name
+
+# Add to appropriate .nix file and rebuild
+```
+
+### Rebuild Fails
+```bash
+# Update flake inputs
+nix flake update
+
+# Check for errors
+nix flake check
+```
+
+## Useful Nix Commands
+
+```bash
+# Update all inputs to latest versions
+nix flake update
+
+# Check flake for errors
+nix flake check
+
+# Show flake outputs
+nix flake show
+
+# Search for packages
+nix search nixpkgs
+
+# Inspect package
+nix eval -f '' 'hello.meta.description'
+```
+
+## Resources
+
+- [NixOS Manual](https://nixos.org/manual/nixos/stable/)
+- [Home Manager Manual](https://nix-community.github.io/home-manager/)
+- [Nix Flakes Guide](https://nixos.wiki/wiki/Flakes)
+- [RPi NixOS Guide](https://nixos.wiki/wiki/NixOS_on_ARM/Raspberry_Pi)
+
+## Notes
+
+- State version: `24.11` - update if needed
+- Store auto-optimizes weekly and cleans packages older than 30 days
+- Flakes and nix-command are enabled by default
+- Change `primaryUser` from "phil" to your username
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..f20ddec
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,257 @@
+{
+ "nodes": {
+ "flake-compat": {
+ "locked": {
+ "lastModified": 1733328505,
+ "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
+ "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
+ "revCount": 69,
+ "type": "tarball",
+ "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.1.0/01948eb7-9cba-704f-bbf3-3fa956735b52/source.tar.gz"
+ },
+ "original": {
+ "type": "tarball",
+ "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
+ }
+ },
+ "flake-parts": {
+ "inputs": {
+ "nixpkgs-lib": "nixpkgs-lib"
+ },
+ "locked": {
+ "lastModified": 1768135262,
+ "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "flake-parts_2": {
+ "inputs": {
+ "nixpkgs-lib": [
+ "nixvim",
+ "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"
+ }
+ },
+ "home-manager": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1770654520,
+ "narHash": "sha256-mg5WZMIPGsFu9MxSrUcuJUPMbfMsF77el5yb/7rc10k=",
+ "owner": "nix-community",
+ "repo": "home-manager",
+ "rev": "6c4fdbe1ad198fac36c320fd45c5957324a80b8e",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "ref": "master",
+ "repo": "home-manager",
+ "type": "github"
+ }
+ },
+ "nixcord": {
+ "inputs": {
+ "flake-compat": "flake-compat",
+ "flake-parts": "flake-parts",
+ "nixpkgs": "nixpkgs"
+ },
+ "locked": {
+ "lastModified": 1770711111,
+ "narHash": "sha256-fwqwewKc+TGDz593PzfA3YCzZRYdmYDWk6pRTaRNPWg=",
+ "owner": "kaylorben",
+ "repo": "nixcord",
+ "rev": "b3f36f48d83a78653b86b4fe997ff1fccae38c6d",
+ "type": "github"
+ },
+ "original": {
+ "owner": "kaylorben",
+ "repo": "nixcord",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1769089682,
+ "narHash": "sha256-9yA/LIuAVQq0lXelrZPjLuLVuZdm03p8tfmHhnDIkms=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "078d69f03934859a181e81ba987c2bb033eebfc5",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-25.11",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs-lib": {
+ "locked": {
+ "lastModified": 1765674936,
+ "narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
+ "owner": "nix-community",
+ "repo": "nixpkgs.lib",
+ "rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "nixpkgs.lib",
+ "type": "github"
+ }
+ },
+ "nixpkgs_2": {
+ "locked": {
+ "lastModified": 1770537093,
+ "narHash": "sha256-pF1quXG5wsgtyuPOHcLfYg/ft/QMr8NnX0i6tW2187s=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "fef9403a3e4d31b0a23f0bacebbec52c248fbb51",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_3": {
+ "locked": {
+ "lastModified": 1770380644,
+ "narHash": "sha256-P7dWMHRUWG5m4G+06jDyThXO7kwSk46C1kgjEWcybkE=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "ae67888ff7ef9dff69b3cf0cc0fbfbcd3a722abe",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_4": {
+ "locked": {
+ "lastModified": 1770197578,
+ "narHash": "sha256-AYqlWrX09+HvGs8zM6ebZ1pwUqjkfpnv8mewYwAo+iM=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "00c21e4c93d963c50d4c0c89bfa84ed6e0694df2",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixvim": {
+ "inputs": {
+ "flake-parts": "flake-parts_2",
+ "nixpkgs": "nixpkgs_3",
+ "systems": "systems"
+ },
+ "locked": {
+ "lastModified": 1770630823,
+ "narHash": "sha256-5SEmOnJ61vmbap39vzWEsCX5UQ+3Ul8J4mXWKdqSn3w=",
+ "owner": "nix-community",
+ "repo": "nixvim",
+ "rev": "6acc964664ac916c64fe4e394edd467af4d90790",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "nixvim",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "home-manager": "home-manager",
+ "nixcord": "nixcord",
+ "nixpkgs": "nixpkgs_2",
+ "nixvim": "nixvim",
+ "spicetify-nix": "spicetify-nix"
+ }
+ },
+ "spicetify-nix": {
+ "inputs": {
+ "nixpkgs": "nixpkgs_4",
+ "systems": "systems_2"
+ },
+ "locked": {
+ "lastModified": 1770528352,
+ "narHash": "sha256-KO51BALxgLUlhg1CqQgA3Rj8vgAcDvoLxzNLTxD65cc=",
+ "owner": "Gerg-L",
+ "repo": "spicetify-nix",
+ "rev": "9f4ab243968118026f4ff82f7ce41d30319e2bf0",
+ "type": "github"
+ },
+ "original": {
+ "owner": "Gerg-L",
+ "repo": "spicetify-nix",
+ "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"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..1930e8b
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,45 @@
+{
+ description = "NixOS Configuration for Raspberry Pi 4";
+
+ nixConfig = {
+ extra-substituters = [ "https://nix-community.cachix.org" ];
+ extra-trusted-public-keys = [
+ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
+ ];
+
+ http-connections = 4;
+ download-buffer-size = 268435456; # 256MB
+ };
+
+ inputs = {
+ nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
+ home-manager.url = "github:nix-community/home-manager/master";
+ home-manager.inputs.nixpkgs.follows = "nixpkgs";
+ nixvim.url = "github:nix-community/nixvim";
+ nixcord.url = "github:kaylorben/nixcord";
+ spicetify-nix.url = "github:Gerg-L/spicetify-nix";
+ };
+
+ outputs = { self, nixpkgs, home-manager, nixvim, ... }@inputs:
+ let
+ primaryUser = "phil";
+ system = "aarch64-linux";
+ in
+ {
+ nixosConfigurations."rpi-4" = nixpkgs.lib.nixosSystem {
+ inherit system;
+ modules = [
+ ./nixos/default.nix
+ ./nixos/hardware.nix
+ home-manager.nixosModules.home-manager
+ {
+ home-manager.useGlobalPkgs = true;
+ home-manager.useUserPackages = true;
+ home-manager.users.${primaryUser} = import ./home/default.nix;
+ home-manager.extraSpecialArgs = { inherit inputs primaryUser; };
+ }
+ ];
+ specialArgs = { inherit inputs self primaryUser; };
+ };
+ };
+}
diff --git a/home/default.nix b/home/default.nix
new file mode 100644
index 0000000..c5d25ef
--- /dev/null
+++ b/home/default.nix
@@ -0,0 +1,20 @@
+{ primaryUser, inputs, ... }: {
+ imports = [
+ ./packages.nix
+ ./git.nix
+ ./shell.nix
+
+ inputs.nixvim.homeModules.nixvim
+ ./neovim
+ ./python.nix
+
+ ];
+
+ home = {
+ username = primaryUser;
+ stateVersion = "25.11";
+ sessionVariables = {
+ GROQ_API_KEY = "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";
+ };
+ };
+}
diff --git a/home/fastfetch.jsonc b/home/fastfetch.jsonc
new file mode 100644
index 0000000..fa90e1b
--- /dev/null
+++ b/home/fastfetch.jsonc
@@ -0,0 +1,171 @@
+{
+ "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+ "logo": {
+ "type": "kitty-icat",
+ "source": "nixos",
+ // "height": 15,
+ "width": 12,
+ "padding": {
+ "top": 0,
+ "left": 0
+ }
+ },
+ "modules": [
+ "break",
+ {
+ "type": "custom",
+ "format": "\u001b[90m┌──────────────────────Hardware──────────────────────┐"
+ },
+ {
+ "type": "host",
+ "key": " PC",
+ "keyColor": "green"
+ },
+ {
+ "type": "cpu",
+ "key": "│ ├",
+ "keyColor": "green"
+ },
+ {
+ "type": "gpu",
+ "key": "│ ├",
+ "keyColor": "green"
+ },
+ {
+ "type": "disk",
+ "key": "│ ├",
+ "keyColor": "green"
+ },
+ {
+ "type": "memory",
+ "key": "└ └",
+ "keyColor": "green"
+ },
+ {
+ "type": "custom",
+ "format": "\u001b[90m└────────────────────────────────────────────────────┘"
+ },
+ "break",
+ {
+ "type": "custom",
+ "format": "\u001b[90m┌──────────────────────Software──────────────────────┐"
+ },
+ {
+ "type": "os",
+ "key": " OS",
+ "keyColor": "yellow"
+ },
+ {
+ "type": "kernel",
+ "key": "│ ├",
+ "keyColor": "yellow"
+ },
+ {
+ "type": "bios",
+ "key": "│ ├",
+ "keyColor": "yellow"
+ },
+ {
+ "type": "packages",
+ "key": "│ ├",
+ "keyColor": "yellow"
+ },
+ {
+ "type": "shell",
+ "key": "└ └",
+ "keyColor": "yellow"
+ },
+ "break",
+ {
+ "type": "de",
+ "key": " DE",
+ "keyColor": "blue"
+ },
+ {
+ "type": "lm",
+ "key": "│ ├",
+ "keyColor": "blue"
+ },
+ {
+ "type": "wm",
+ "key": "│ ├",
+ "keyColor": "blue"
+ },
+ {
+ "type": "wmtheme",
+ "key": "│ ├",
+ "keyColor": "blue"
+ },
+ {
+ "type": "terminal",
+ "key": "└ └",
+ "keyColor": "blue"
+ },
+ {
+ "type": "custom",
+ "format": "\u001b[90m└────────────────────────────────────────────────────┘"
+ },
+ "break",
+ {
+ "type": "custom",
+ "format": "\u001b[90m┌─────────────────Uptime / Age / DT──────────────────┐"
+ },
+ {
+ "type": "command",
+ "key": " OS Age ",
+ "keyColor": "magenta",
+ "text": "birth_install=$(stat -c %W /); current=$(date +%s); time_progression=$((current - birth_install)); days_difference=$((time_progression / 86400)); echo $days_difference days"
+ },
+ {
+ "type": "uptime",
+ "key": " Uptime ",
+ "keyColor": "magenta"
+ },
+ {
+ "type": "datetime",
+ "key": " DateTime ",
+ "keyColor": "magenta"
+ },
+ {
+ "type": "custom",
+ "format": "\u001b[90m└────────────────────────────────────────────────────┘"
+ },
+ "break",
+ {
+ "type": "custom",
+ "format": "\u001b[90m┌─────────────────────Networking─────────────────────┐"
+ },
+ {
+ "type": "publicip",
+ "key": " Public ",
+ "keyColor": "magenta"
+ },
+ {
+ "type": "localip",
+ "key": " Local ",
+ "keyColor": "magenta"
+ },
+ {
+ "type": "dns",
+ "key": " DNS ",
+ "keyColor": "magenta"
+ },
+ {
+ "type": "netio",
+ "key": " Net I/O ",
+ "keyColor": "magenta"
+ },
+ {
+ "type": "custom",
+ "format": "\u001b[90m└────────────────────────────────────────────────────┘"
+ },
+ {
+ "type": "colors",
+ "paddingLeft": 2,
+ "symbol": "circle"
+ },
+ "break",
+ ]
+}
+
+
diff --git a/home/git.nix b/home/git.nix
new file mode 100644
index 0000000..4ce2355
--- /dev/null
+++ b/home/git.nix
@@ -0,0 +1,21 @@
+{ primaryUser, ... }:
+{
+ programs.git = {
+ enable = true;
+ userName = "DerGrumpf"; # TODO replace
+ userEmail = "p.keier@beyerstedt-it.de"; # TODO replace
+
+ lfs.enable = true;
+
+ ignores = [ "**/.DS_STORE" ];
+
+ extraConfig = {
+ github = {
+ user = primaryUser;
+ };
+ init = {
+ defaultBranch = "main";
+ };
+ };
+ };
+}
diff --git a/home/neovim/alpha.nix b/home/neovim/alpha.nix
new file mode 100644
index 0000000..52357f4
--- /dev/null
+++ b/home/neovim/alpha.nix
@@ -0,0 +1,147 @@
+{ pkgs, ... }: {
+ # Alpha: Start screen/dashboard for Neovim
+ # Shows a custom ASCII art header and quick action buttons on startup.
+ programs.nixvim.plugins.alpha = {
+ enable = true;
+ settings.layout = [
+ {
+ type = "padding";
+ val = 2;
+ }
+ {
+ type = "text";
+ val = [
+ "⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣯⣿⠿⣟⣷⣯⣛⢿⣿⣿⣾⣟⣿⣿⣿⣿⣿⣿⣿⣿⣿"
+ "⣿⣿⣿⣿⣿⣿⣿⡿⣵⣿⡿⣴⣽⡟⣳⢿⢽⣽⣕⣽⢿⡿⣿⣟⣿⣿⣿⣿⣿⣿⣿"
+ "⣿⣿⣿⣷⣿⣿⢟⣫⣿⢟⢟⣾⣾⣿⣿⣞⢳⣻⢞⣎⠿⢞⣊⣿⣞⣿⣿⣿⣿⣿⢽"
+ "⣿⣿⣿⣿⣿⣏⢯⣿⣏⣏⠔⢇⣿⢢⢆⢀⢆⣧⣼⢻⢰⡧⢻⣝⣏⡸⣧⣾⣿⣿⣿"
+ "⣿⣿⣿⣿⡟⣻⣿⣿⡾⡿⡼⢸⡝⣝⡳⢢⣧⢳⣳⢷⡇⣗⢺⡺⣿⡧⣿⣿⣿⢿⢿"
+ "⣿⡿⣿⣼⡼⣿⣿⡗⡧⣧⠁⡝⣧⣳⠅⡾⠈⣎⢮⣧⣿⣿⣗⣷⣻⢷⣏⣼⢏⣺⣿"
+ "⣿⣿⣿⣻⣿⣿⣿⢧⣿⢹⠉⢷⢿⣧⣲⡏⡀⡈⢆⠳⣿⡿⢿⣿⣱⢿⢫⣷⣝⣿⣿"
+ "⣿⣿⣿⡯⡟⣿⣿⢽⣡⠟⢿⣮⠁⠙⠛⠈⡴⢿⣿⡷⣬⣽⢽⠧⣷⡏⣿⡇⣧⣽⣿"
+ "⣿⠟⢻⡧⡇⣿⡇⣇⣆⢄⡜⢃⡀⡀⡀⡀⡀⢎⣁⠁⣸⣗⣸⣿⣧⣼⡿⢹⢿⢾⣿"
+ "⣿⣷⣾⣿⢻⣿⢧⢻⣽⡀⡀⡀⡀⢄⡀⡀⡀⡀⡀⢀⣷⡸⡟⣿⣶⣻⣧⡛⡱⢝⣿"
+ "⣿⣿⣿⣿⢸⡿⢚⡜⣿⣇⡀⡀⡀⡀⡀⡀⡀⡀⠚⢁⢣⣜⡿⣿⡇⢼⣿⠨⣸⣿⣿"
+ "⣿⣄⣿⣗⢾⢻⣧⢿⣾⣿⣦⡀⡀⠑⠚⠉⡀⡀⣤⣿⢨⣿⠗⣻⢣⣿⢹⢈⣽⣿⣿"
+ "⣿⣿⣿⣿⢎⡄⢿⣞⡇⣿⠹⣿⣶⣀⡀⣀⡴⡩⢸⢏⣿⣿⣶⢻⣾⢏⡞⠡⢽⣇⣾"
+ "⣿⣿⣿⣮⣼⢬⣦⢿⣳⣌⠧⡉⠈⣇⣛⣁⣈⣼⣿⡸⠫⠛⠐⠛⠕⣙⣻⣬⣼⣿⣿"
+ "⢟⢿⣿⣿⣿⡢⣃⣪⣭⣡⣤⣶⠟⡿⠿⠿⠿⠛⢁⣿⣿⢩⠉⡀⠈⠓⡝⣿⣿⣿⣿"
+ "⣾⣿⣿⣿⣿⠞⢔⡣⡴⣾⣿⠓⣤⢧⡼⣉⠠⢤⣿⣿⠇⠃⡀⡀⡀⡀⡸⢿⣾⣿⣿"
+ "⣿⣿⣿⡿⣺⡸⢗⢠⣇⣿⣿⠊⠃⡀⠉⡀⢠⣿⣿⠟⡸⡀⡀⡀⡀⡀⣃⣬⠽⠿⣿"
+ "⣿⣿⣿⣿⡇⡏⢸⣿⠟⣽⡇⡀⡀⡀⡀⣴⣟⢭⣾⣿⡇⠎⣠⠒⠉⠈⢀⡀⢨⡋⣿"
+ "⠛⠛⠛⠋⠃⠓⠚⠛⠘⠛⠃⡀⠊⡀⠛⠛⠛⠂⠛⠛⠓⠁⠚⡀⠂⠒⠒⠐⠒⠋⠛"
+ ];
+ opts = {
+ position = "center";
+ hl = "Type";
+ };
+ }
+ {
+ type = "padding";
+ val = 2;
+ }
+ {
+ type = "group";
+ val = [
+ {
+ type = "button";
+ val = "[+] New file";
+ on_press.__raw =
+ "function() vim.cmd[[ene]] vim.cmd[[startinsert]] end";
+ opts = {
+ keymap = [ "n" "e" ":ene startinsert " { } ];
+ shortcut = "e";
+ position = "center";
+ cursor = 3;
+ width = 50;
+ align_shortcut = "right";
+ hl_shortcut = "Keyword";
+ };
+ }
+ {
+ type = "button";
+ val = "[?] Find file";
+ on_press.__raw = "function() vim.cmd[[Telescope find_files]] end";
+ opts = {
+ keymap = [ "n" "f" ":Telescope find_files " { } ];
+ shortcut = "f";
+ position = "center";
+ cursor = 3;
+ width = 50;
+ align_shortcut = "right";
+ hl_shortcut = "Keyword";
+ };
+ }
+ {
+ type = "button";
+ val = "[~] Recent files";
+ on_press.__raw = "function() vim.cmd[[Telescope oldfiles]] end";
+ opts = {
+ keymap = [ "n" "r" ":Telescope oldfiles " { } ];
+ shortcut = "r";
+ position = "center";
+ cursor = 3;
+ width = 50;
+ align_shortcut = "right";
+ hl_shortcut = "Keyword";
+ };
+ }
+ {
+ type = "button";
+ val = "[Y] Yazi";
+ on_press.__raw = "function() require('yazi').yazi() end";
+ opts = {
+ keymap = [ "n" "y" ":Yazi" { } ];
+ shortcut = "y";
+ position = "center";
+ cursor = 3;
+ width = 50;
+ align_shortcut = "right";
+ hl_shortcut = "Keyword";
+ };
+ }
+ {
+ type = "button";
+ val = "[A] Open Prompt";
+ #on_press.__raw = "function() require('yazi').yazi() end";
+ opts = {
+ keymap = [ "n" "a" ":AvanteChatNew" { } ];
+ shortcut = "a";
+ position = "center";
+ cursor = 3;
+ width = 50;
+ align_shortcut = "right";
+ hl_shortcut = "Keyword";
+ };
+ }
+ {
+ type = "button";
+ val = "[X] Quit";
+ on_press.__raw = "function() vim.cmd[[qa]] end";
+ opts = {
+ keymap = [ "n" "q" ":qa" { } ];
+ shortcut = "q";
+ position = "center";
+ cursor = 3;
+ width = 50;
+ align_shortcut = "right";
+ hl_shortcut = "Keyword";
+ };
+ }
+ ];
+ }
+ {
+ type = "padding";
+ val = 2;
+ }
+ {
+ type = "text";
+ val = "Circuits hum in anticipation of your will.";
+ opts = {
+ position = "center";
+ hl = "Comment";
+ };
+ }
+ ];
+ };
+}
diff --git a/home/neovim/avante.nix b/home/neovim/avante.nix
new file mode 100644
index 0000000..edbbf9e
--- /dev/null
+++ b/home/neovim/avante.nix
@@ -0,0 +1,106 @@
+{ pkgs, ... }: {
+ # Avante: AI-powered coding assistant (Cursor-like experience in Neovim)
+ programs.nixvim = {
+
+ plugins = {
+ markdown-preview.enable = true;
+ render-markdown.enable = true;
+ #extraConfigLuaPre = ''
+ # vim.env.GROQ_API_KEY = os.getenv("GROQ_API_KEY")
+ #'';
+ # TODO: Integrate CoPilot https://github.com/settings/copilot/features
+ avante = {
+ enable = true;
+ autoLoad = true;
+ settings = {
+ provider = "groq";
+
+ providers.groq = {
+ __inherited_from = "openai";
+ api_key_name = "GROQ_API_KEY";
+ endpoint = "https://api.groq.com/openai/v1/";
+ model = "groq/compound-mini";
+ disable_tools = true;
+ extra_request_body = {
+ temperature = 1;
+ max_tokens = 8192;
+ tools = null;
+ tool_choice = "none";
+ };
+ };
+
+ # auto_suggestions_provider = "copilot";
+
+ render = { markdown = true; };
+
+ behaviour = {
+ auto_suggestions = false;
+ auto_set_highlight_group = true;
+ auto_set_keymaps = true;
+ auto_apply_diff_after_generation = false;
+ support_paste_from_clipboard = false;
+ };
+
+ mappings = {
+ ask = "aa";
+ edit = "ae";
+ refresh = "ar";
+ diff = {
+ ours = "co";
+ theirs = "ct";
+ all_theirs = "ca";
+ both = "cb";
+ cursor = "cc";
+ next = "]x";
+ prev = "[x";
+ };
+ suggestion = {
+ accept = "";
+ next = "";
+ prev = "";
+ dismiss = "";
+ };
+ jump = {
+ next = "]]";
+ prev = "[[";
+ };
+ submit = {
+ normal = "";
+ insert = "";
+ };
+ sidebar = {
+ switch_windows = "";
+ reverse_switch_windows = "";
+ };
+ };
+
+ hints = { enabled = true; };
+
+ windows = {
+ position = "right";
+ wrap = true;
+ width = 30;
+ sidebar_header = {
+ align = "center";
+ rounded = true;
+ };
+ };
+
+ highlights = {
+ diff = {
+ current = "DiffText";
+ incoming = "DiffAdd";
+ };
+ };
+
+ diff = {
+ autojump = true;
+ list_opener = "copen";
+ };
+ };
+ };
+
+ extraPackages = with pkgs; [ curl ];
+ };
+ };
+}
diff --git a/home/neovim/catppuccin.nix b/home/neovim/catppuccin.nix
new file mode 100644
index 0000000..98ba46c
--- /dev/null
+++ b/home/neovim/catppuccin.nix
@@ -0,0 +1,34 @@
+{ pkgs, ... }:
+{
+ # Catppuccin: Soothing pastel theme for Neovim
+ # Provides consistent theming across plugins with transparency support.
+ programs.nixvim = {
+ colorschemes.catppuccin = {
+ enable = true;
+ settings = {
+ flavour = "mocha";
+ transparent_background = true;
+ term_colors = true;
+ integrations = {
+ treesitter = true;
+ cmp = true;
+ gitsigns = true;
+ telescope = {
+ enabled = true;
+ };
+ notify = true;
+ mini = {
+ enabled = true;
+ };
+ };
+ };
+ };
+
+ # Custom highlight overrides
+ extraConfigLua = ''
+ local colors = require("catppuccin.palettes").get_palette("mocha")
+ vim.api.nvim_set_hl(0, "LineNr", { fg = colors.text, bg = "NONE" })
+ vim.api.nvim_set_hl(0, "CursorLineNr", { fg = colors.pink, bg = "NONE", bold = true })
+ '';
+ };
+}
diff --git a/home/neovim/conform.nix b/home/neovim/conform.nix
new file mode 100644
index 0000000..271ab5d
--- /dev/null
+++ b/home/neovim/conform.nix
@@ -0,0 +1,33 @@
+{ pkgs, ... }: {
+ # Conform: Code formatter that runs external formatting tools
+ # Automatically formats code on save for consistent style.
+ programs.nixvim = {
+ plugins.conform-nvim = {
+ enable = true;
+
+ settings = {
+ formatters_by_ft = {
+ lua = [ "stylua" ];
+ nix = [ "nixfmt" ];
+ python = [ "black" ];
+ rust = [ "rustfmt" ];
+ rasi = [ "prettierd" ];
+ };
+
+ format_on_save = {
+ timeout_ms = 2000;
+ lsp_fallback = true;
+ };
+ };
+ };
+
+ # Install formatters
+ extraPackages = with pkgs; [
+ stylua
+ nixfmt
+ black
+ rustfmt
+ prettierd
+ ];
+ };
+}
diff --git a/home/neovim/default.nix b/home/neovim/default.nix
new file mode 100644
index 0000000..167adb6
--- /dev/null
+++ b/home/neovim/default.nix
@@ -0,0 +1,94 @@
+{ ... }: {
+ imports = [
+ ./treesitter.nix
+ ./lint.nix
+ ./lsp.nix
+ ./conform.nix
+ ./lualine.nix
+ ./yazi.nix
+ ./toggleterm.nix
+ ./telescope.nix
+ ./catppuccin.nix
+ ./alpha.nix
+ ./avante.nix
+ ./openscad.nix
+ ./molten.nix
+ ./which-key.nix
+ ];
+
+ programs.nixvim = {
+ enable = true;
+ defaultEditor = true;
+
+ # Leader key
+ globals.mapleader = " ";
+
+ plugins.web-devicons.enable = true;
+
+ opts = {
+ number = true; # Show line numbers
+ cursorline = true; # Highlight current line
+ showmode = true; # already in statusline
+ hlsearch = true; # Highlight search result
+ incsearch = true; # Incremental Search
+ tabstop = 4;
+ termguicolors = true; # Enable 24-bit colormode
+ };
+
+ # Clipboard keymaps - yank to system clipboard
+ keymaps = [
+ # Yank operations
+ {
+ mode = "n";
+ key = "y";
+ action = ''"+y'';
+ options.desc = "Yank to clipboard";
+ }
+ {
+ mode = "v";
+ key = "y";
+ action = ''"+y'';
+ options.desc = "Yank to clipboard";
+ }
+ {
+ mode = "n";
+ key = "Y";
+ action = ''"+Y'';
+ options.desc = "Yank line to clipboard";
+ }
+ # Delete operations
+ {
+ mode = "n";
+ key = "d";
+ action = ''"+d'';
+ options.desc = "Delete to clipboard";
+ }
+ {
+ mode = "v";
+ key = "d";
+ action = ''"+d'';
+ options.desc = "Delete to clipboard";
+ }
+ {
+ mode = "n";
+ key = "D";
+ action = ''"+D'';
+ options.desc = "Delete line to clipboard";
+ }
+ # Paste operations
+ {
+ mode = "n";
+ key = "p";
+ action = ''"+p'';
+ options.desc = "Paste from clipboard";
+ }
+ {
+ mode = "v";
+ key = "p";
+ action = ''"+p'';
+ options.desc = "Paste from clipboard";
+ }
+ ];
+ };
+
+}
diff --git a/home/neovim/lint.nix b/home/neovim/lint.nix
new file mode 100644
index 0000000..ac178c6
--- /dev/null
+++ b/home/neovim/lint.nix
@@ -0,0 +1,42 @@
+{ pkgs, ... }:
+{
+ # nvim-lint: Asynchronous linter that runs external linting tools
+ # to find errors and style issues without blocking the editor.
+ # Runs automatically after saving files.
+ programs.nixvim = {
+ plugins.lint = {
+ enable = true;
+
+ # Configure linters for each filetype
+ lintersByFt = {
+ lua = [ "luacheck" ];
+ nix = [ "statix" ]; # Nix static analyzer
+ python = [ "ruff" ];
+ javascript = [ "eslint" ];
+ rust = [ "clippy" ];
+ # rasi has no common linter
+ };
+
+ # Trigger linting after saving a file
+ autoCmd = {
+ event = [ "BufWritePost" ];
+ callback = {
+ __raw = ''
+ function()
+ require('lint').try_lint()
+ end
+ '';
+ };
+ };
+ };
+
+ # Install linter binaries
+ extraPackages = with pkgs; [
+ lua54Packages.luacheck
+ statix
+ ruff
+ nodePackages.eslint
+ clippy
+ ];
+ };
+}
diff --git a/home/neovim/lsp.nix b/home/neovim/lsp.nix
new file mode 100644
index 0000000..3fe2059
--- /dev/null
+++ b/home/neovim/lsp.nix
@@ -0,0 +1,91 @@
+{ pkgs, ... }:
+{
+ # LSP configuration: Language Server Protocol provides IDE features
+ # like autocomplete, go-to-definition, diagnostics, and more.
+ programs.nixvim = {
+ plugins = {
+ # LSP configuration
+ lsp = {
+ enable = true;
+
+ # Language servers for each language
+ servers = {
+ lua_ls = {
+ enable = true;
+ settings = {
+ Lua = {
+ runtime.version = "LuaJIT";
+ diagnostics.globals = [ "vim" ];
+ workspace.library = [ ]; # Populated by nixvim
+ telemetry.enable = false;
+ };
+ };
+ };
+
+ nil_ls.enable = true; # Nix language server
+ rust_analyzer = {
+ enable = true; # Rust language server
+ installCargo = true;
+ installRustc = true;
+ };
+ pylsp.enable = true; # Python language server
+ };
+
+ # Keymaps for LSP actions
+ keymaps = {
+ diagnostic = {
+ "e" = "open_float";
+ "[d" = "goto_prev";
+ "]d" = "goto_next";
+ };
+ lspBuf = {
+ "gd" = "definition";
+ "K" = "hover";
+ "rn" = "rename";
+ "ca" = "code_action";
+ };
+ };
+ };
+
+ # Autocompletion
+ cmp = {
+ enable = true;
+ autoEnableSources = true;
+
+ settings = {
+ snippet.expand = ''
+ function(args)
+ require('luasnip').lsp_expand(args.body)
+ end
+ '';
+
+ mapping = {
+ "" = "cmp.mapping.scroll_docs(-4)";
+ "" = "cmp.mapping.scroll_docs(4)";
+ "" = "cmp.mapping.complete()";
+ "" = "cmp.mapping.abort()";
+ "" = "cmp.mapping.confirm({ select = true })";
+ };
+
+ sources = [
+ { name = "nvim_lsp"; }
+ { name = "luasnip"; }
+ { name = "buffer"; }
+ { name = "path"; }
+ ];
+ };
+ };
+
+ # Snippet engine (required for completion)
+ luasnip.enable = true;
+ };
+
+ # Install LSP servers
+ extraPackages = with pkgs; [
+ lua-language-server
+ nil
+ rust-analyzer
+ python311Packages.python-lsp-server
+ ];
+ };
+}
diff --git a/home/neovim/lualine.nix b/home/neovim/lualine.nix
new file mode 100644
index 0000000..4f85435
--- /dev/null
+++ b/home/neovim/lualine.nix
@@ -0,0 +1,22 @@
+{ pkgs, ... }:
+{
+ # Lualine: Fast and customizable statusline for Neovim
+ # Displays file info, git status, diagnostics, and mode at the bottom of the editor.
+ programs.nixvim.plugins.lualine = {
+ enable = true;
+
+ settings = {
+ options = {
+ theme = "catppuccin";
+ component_separators = {
+ left = "|";
+ right = "|";
+ };
+ section_separators = {
+ left = "";
+ right = "";
+ };
+ };
+ };
+ };
+}
diff --git a/home/neovim/molten.nix b/home/neovim/molten.nix
new file mode 100644
index 0000000..6b816ff
--- /dev/null
+++ b/home/neovim/molten.nix
@@ -0,0 +1,43 @@
+{ pkgs, ... }: {
+ programs.nixvim = {
+ plugins.molten = {
+ enable = true;
+ python3Dependencies = p:
+ with p; [
+ pynvim
+ jupyter-client
+ cairosvg
+ ipython
+ nbformat
+ ipykernel
+ pnglatex
+ plotly
+ kaleido
+ pyperclip
+ ];
+ settings = {
+ kernel_name = "python3";
+ auto_open_output = true;
+ output_win_max_width = 80;
+ output_win_max_height = 20;
+ };
+ };
+
+ keymaps = [
+ {
+ mode = "n";
+ key = "ml";
+ action = "MoltenEvaluateLine";
+ options.desc = "Molten: Evaluate line";
+ options.silent = true;
+ }
+ {
+ mode = "v";
+ key = "mv";
+ action = "MoltenEvaluateVisual";
+ options.desc = "Molten: Evaluate selection";
+ options.silent = true;
+ }
+ ];
+ };
+}
diff --git a/home/neovim/openscad.nix b/home/neovim/openscad.nix
new file mode 100644
index 0000000..b4934ab
--- /dev/null
+++ b/home/neovim/openscad.nix
@@ -0,0 +1,28 @@
+{ pkgs, ... }: {
+ # OpenSCAD: 3D modeling language support with syntax highlighting,
+ # cheatsheet, snippets, offline manual and fuzzy help
+ programs.nixvim = {
+ plugins.openscad = {
+ enable = true;
+ autoLoad = true;
+ settings = {
+ fuzzy_finder = "fzf";
+ auto_open = true;
+ cheatsheet_toggle_key = "os";
+ default_mappings = true;
+ exec_openscad_trig_key = "oo";
+ help_manual_trig_key = "om";
+ help_trig_key = "oh";
+ top_toggle = "oc";
+
+ };
+ };
+
+ # Install OpenSCAD binary for preview/compilation
+ extraPackages = with pkgs; [
+ openscad
+ zathura # PDF viewer for manual
+ fzf
+ ];
+ };
+}
diff --git a/home/neovim/telescope.nix b/home/neovim/telescope.nix
new file mode 100644
index 0000000..1d0e330
--- /dev/null
+++ b/home/neovim/telescope.nix
@@ -0,0 +1,27 @@
+{ pkgs, ... }:
+{
+ # Telescope: Fuzzy finder for files, buffers, grep, and more
+ # Provides fast search and navigation throughout your project.
+ programs.nixvim.plugins.telescope = {
+ enable = true;
+
+ keymaps = {
+ "ff" = {
+ action = "find_files";
+ options.desc = "Telescope find files";
+ };
+ "fg" = {
+ action = "live_grep";
+ options.desc = "Telescope live grep";
+ };
+ "fb" = {
+ action = "buffers";
+ options.desc = "Telescope buffers";
+ };
+ "fh" = {
+ action = "help_tags";
+ options.desc = "Telescope help tags";
+ };
+ };
+ };
+}
diff --git a/home/neovim/toggleterm.nix b/home/neovim/toggleterm.nix
new file mode 100644
index 0000000..3eca8a4
--- /dev/null
+++ b/home/neovim/toggleterm.nix
@@ -0,0 +1,64 @@
+{ pkgs, ... }:
+{
+ # ToggleTerm: Terminal emulator inside Neovim
+ # Provides floating, horizontal, and vertical terminal windows.
+ programs.nixvim.plugins.toggleterm = {
+ enable = true;
+
+ settings = {
+ size = 20;
+ open_mapping = "[[]]";
+ direction = "float";
+ float_opts = {
+ border = "single";
+ width = 200;
+ height = 40;
+ };
+ };
+ };
+
+ programs.nixvim.keymaps = [
+ {
+ mode = "n";
+ key = "h";
+ action.__raw = ''
+ function()
+ require("toggleterm").toggle(1, 10, vim.loop.cwd(), "horizontal")
+ end
+ '';
+ options.desc = "Toggle terminal (horizontal)";
+ }
+ {
+ mode = "n";
+ key = "v";
+ action.__raw = ''
+ function()
+ require("toggleterm").toggle(2, 60, vim.loop.cwd(), "vertical")
+ end
+ '';
+ options.desc = "Toggle terminal (vertical)";
+ }
+ {
+ mode = "n";
+ key = "ft";
+ action.__raw = ''
+ function()
+ require("toggleterm").toggle(3, 20, vim.loop.cwd(), "float")
+ end
+ '';
+ options.desc = "Toggle terminal (float)";
+ }
+ {
+ mode = "t";
+ key = "";
+ action = "ToggleTerm";
+ options.desc = "Toggle terminal";
+ }
+ {
+ mode = "t";
+ key = "";
+ action = "v";
+ options.desc = "Exit terminal and enter visual mode";
+ }
+ ];
+}
diff --git a/home/neovim/treesitter.nix b/home/neovim/treesitter.nix
new file mode 100644
index 0000000..58e174a
--- /dev/null
+++ b/home/neovim/treesitter.nix
@@ -0,0 +1,24 @@
+{ pkgs, ... }:
+{
+
+ # Install language parsers declaratively
+ # Syntax Highlighting
+ programs.nixvim.plugins.treesitter = {
+ enable = true;
+ grammarPackages = with pkgs.vimPlugins.nvim-treesitter.builtGrammars; [
+ lua
+ nix
+ python
+ javascript
+ rust
+ rasi
+ ];
+
+ settings = {
+ highlight = {
+ enable = true;
+ additional_vim_regex_highlighting = false;
+ };
+ };
+ };
+}
diff --git a/home/neovim/which-key.nix b/home/neovim/which-key.nix
new file mode 100644
index 0000000..ade48c6
--- /dev/null
+++ b/home/neovim/which-key.nix
@@ -0,0 +1,94 @@
+{ pkgs, ... }: {
+ # Which-key: Display available keybindings in popup
+ # Shows all possible key combinations after pressing leader or other prefix keys
+ programs.nixvim.plugins.which-key = {
+ enable = true;
+
+ settings = {
+ delay = 500; # Time in ms before popup shows
+
+ icons = {
+ breadcrumb = "»";
+ separator = "➜";
+ group = "+";
+ };
+
+ # Organize keymaps into named groups
+ spec = [
+ # Leader key groups
+ {
+ __unkeyed-1 = "a";
+ group = "Avante AI";
+ icon = "🤖";
+ }
+ {
+ __unkeyed-1 = "f";
+ group = "Find/Files/Terminal";
+ icon = "🔍";
+ }
+ {
+ __unkeyed-1 = "m";
+ group = "Molten (Jupyter)";
+ icon = "📓";
+ }
+ {
+ __unkeyed-1 = "o";
+ group = "OpenSCAD";
+ icon = "🔧";
+ }
+
+ # Bracket navigation groups
+ {
+ __unkeyed-1 = "[";
+ group = "Previous";
+ icon = "⬅️";
+ }
+ {
+ __unkeyed-1 = "]";
+ group = "Next";
+ icon = "➡️";
+ }
+
+ # g prefix groups
+ {
+ __unkeyed-1 = "g";
+ group = "Go/LSP";
+ icon = "🎯";
+ }
+ {
+ __unkeyed-1 = "gr";
+ group = "LSP References/Rename";
+ icon = "🔗";
+ }
+ {
+ __unkeyed-1 = "gc";
+ group = "Comments";
+ icon = "💬";
+ }
+
+ # l prefix
+ {
+ __unkeyed-1 = "l";
+ group = "Live Server";
+ icon = "🌐";
+ }
+
+ # z prefix
+ {
+ __unkeyed-1 = "z";
+ group = "Folds/Spell";
+ icon = "📋";
+ }
+ ];
+
+ # Hide specific mappings to reduce clutter
+ disable = {
+ builtin_keys = {
+ # Hide these default vim keys from which-key
+ i = [ "" "" ];
+ n = [ "" ];
+ };
+ };
+ };
+ };
+}
diff --git a/home/neovim/yazi.nix b/home/neovim/yazi.nix
new file mode 100644
index 0000000..06d6e0a
--- /dev/null
+++ b/home/neovim/yazi.nix
@@ -0,0 +1,41 @@
+{ pkgs, ... }: {
+ # Yazi: Terminal file manager integration for Neovim
+ # Provides a fast, visual way to browse and manage files.
+ programs.nixvim = {
+ # Use extraPlugins to manually load yazi.nvim
+ extraPlugins = with pkgs.vimPlugins; [ yazi-nvim ];
+
+ # Configure yazi after it's loaded
+ extraConfigLua = ''
+ require('yazi').setup({
+ open_for_directories = true,
+ })
+ '';
+
+ keymaps = [
+ {
+ mode = "n";
+ key = "fy";
+ action.__raw = ''
+ function()
+ require('yazi').yazi(nil, vim.loop.cwd())
+ end
+ '';
+ options.desc = "Open Yazi file manager";
+ }
+ {
+ mode = "n";
+ key = "fd";
+ action.__raw = ''
+ function()
+ require('yazi').yazi(nil, vim.fn.expand("%:p:h"))
+ end
+ '';
+ options.desc = "Open Yazi in current file directory";
+ }
+ ];
+
+ # Install yazi terminal program
+ extraPackages = with pkgs; [ yazi ];
+ };
+}
diff --git a/home/packages.nix b/home/packages.nix
new file mode 100644
index 0000000..31c73e4
--- /dev/null
+++ b/home/packages.nix
@@ -0,0 +1,31 @@
+{ pkgs, ... }: {
+ home = {
+ packages = with pkgs; [
+ # dev tools
+ curl
+ wget
+ vim
+ htop
+ tree
+ ripgrep
+ gh # Move to git
+ zoxide # Move to fish
+ unrar
+
+ # programming languages
+ #mise # node, deno, bun, rust, python, etc.
+
+ # PDF Tools
+ pandoc
+ texlive.combined.scheme-full
+ wkhtmltopdf
+
+ # misc
+ nil # move to nixvim
+ biome # move to nixvim
+ nixfmt-rfc-style # move to nixvim
+ yt-dlp
+ ffmpeg
+ ];
+ };
+}
diff --git a/home/python.nix b/home/python.nix
new file mode 100644
index 0000000..be4b85d
--- /dev/null
+++ b/home/python.nix
@@ -0,0 +1,26 @@
+{ pkgs, ... }: {
+ home.packages = with pkgs; [
+ # Python 3.13 (newest stable)
+ python313
+ python313Packages.pip
+ python313Packages.virtualenv
+
+ # Additional useful tools
+ python313Packages.pipx # Install Python apps in isolated environments
+ uv # Fast Python package installer (alternative to pip)
+ ];
+
+ # Set up default Python version
+ home.sessionVariables = { PYTHON = "${pkgs.python313}/bin/python3"; };
+
+ # Shell aliases for convenience
+ programs.zsh.shellAliases = {
+ venv = "python3 -m venv";
+ activate = "source venv/bin/activate";
+ };
+
+ programs.fish.shellAliases = {
+ venv = "python3 -m venv";
+ activate = "source venv/bin/activate.fish";
+ };
+}
diff --git a/home/shell.nix b/home/shell.nix
new file mode 100644
index 0000000..161f883
--- /dev/null
+++ b/home/shell.nix
@@ -0,0 +1,203 @@
+{ pkgs, ... }: {
+ home.packages = with pkgs; [
+ eza # ls replacement
+ fzf # FuzzyFinder
+ tdf # terminal pdf viewer
+ jq # json parser
+ tree
+ fastfetch # system stats
+ tabiew # Table viewer
+ glow # MD Viewer
+
+ llm # LLM in the Terminal
+
+ # Fun stuff
+ lolcat
+ cmatrix
+ ];
+
+ programs.kitty = {
+ enable = true;
+ themeFile = "Catppuccin-Mocha";
+
+ font = {
+ name = "Fira Code Nerd Font";
+ size = 12;
+ };
+
+ settings = {
+ confirm_os_window_close = 0;
+ dynamic_background_opacity = true; # ctrl+shift+a>m/l
+ enable_audio_bell = false;
+ mouse_hide_wait = 3.0;
+ window_padding_width = 10;
+
+ background_opacity = 0.8;
+ background_blur = 5;
+
+ tab_bar_min_tabs = 1;
+ tab_bar_edge = "bottom";
+ tab_bar_style = "custom"; # Should be changed to custom
+ tab_title_template =
+ "{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{title}";
+
+ symbol_map = let
+ mappings = [
+ "U+23FB-U+23FE"
+ "U+2B58"
+ "U+E200-U+E2A9"
+ "U+E0A0-U+E0A3"
+ "U+E0B0-U+E0BF"
+ "U+E0C0-U+E0C8"
+ "U+E0CC-U+E0CF"
+ "U+E0D0-U+E0D2"
+ "U+E0D4"
+ "U+E700-U+E7C5"
+ "U+F000-U+F2E0"
+ "U+2665"
+ "U+26A1"
+ "U+F400-U+F4A8"
+ "U+F67C"
+ "U+E000-U+E00A"
+ "U+F300-U+F313"
+ "U+E5FA-U+E62B"
+ ];
+ in (builtins.concatStringsSep "," mappings) + " Symbols Nerd Font Mono";
+ };
+ };
+
+ programs.yazi = {
+ enable = true;
+ enableBashIntegration = true;
+ enableZshIntegration = true;
+ enableFishIntegration = true;
+
+ settings = { ration = [ 1 3 4 ]; };
+ };
+
+ programs.zsh = {
+ enable = true;
+ enableCompletion = true;
+ autosuggestion.enable = true;
+ syntaxHighlighting.enable = true;
+
+ shellAliases = {
+ ls = "eza";
+ la = "eza -la";
+ f = "fzf";
+ i = "kitty +kitten icat";
+ "nix-switch" =
+ "sudo darwin-rebuild switch --flake ~/.config/nix#cyper-mac";
+ };
+
+ initContent = ''
+ fastfetch
+ ai() {
+ llm -m groq/groq/compound "$@" | glow
+ }
+ '';
+ };
+
+ programs.fish = {
+ enable = true;
+
+ shellAliases = {
+ ls = "eza";
+ la = "eza -la";
+ f = "fzf";
+ i = "kitty +kitten icat";
+ "nix-switch" =
+ "sudo darwin-rebuild switch --flake ~/.config/nix#cyper-mac";
+ };
+
+ interactiveShellInit = ''
+ starship init fish | source
+ fzf --fish | source
+ function fish_greeting
+ fastfetch
+ end
+ '';
+
+ functions.ai = {
+ body = ''
+ llm -m groq/groq/compound $argv | glow
+ '';
+ };
+ };
+
+ programs.starship = {
+ enable = true;
+ settings = {
+ add_newline = true;
+ command_timeout = 500;
+
+ format = ''
+ $username$hostname $directory $git_branch$git_status
+ $character '';
+ right_format = "$cmd_duration";
+
+ username = {
+ style_user = "bold #cba6f7";
+ style_root = "bold #f38ba8";
+ format = "[┌](bold #a6e3a1)[$user]($style)";
+ show_always = true;
+ };
+
+ hostname = {
+ style = "bold #74c7ec";
+ format = "[@](bold #fab387)[$hostname]($style)";
+ ssh_only = false;
+ };
+
+ directory = {
+ style = "bold #a6e3a1";
+ truncation_length = 0;
+ truncation_symbol = "";
+ format = "[⤇ ](bold #f38ba8)[《$path 》]($style)";
+ };
+
+ git_branch = {
+ format = "[⟦$branch⟧]($style)";
+ style = "bold #f9e2af";
+ };
+
+ # Git status module settings
+ git_status = {
+ format =
+ "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](red) ($ahead_behind$stashed)]($style)";
+ style = "bold #a6e3a1";
+ conflicted = "";
+ untracked = "";
+ modified = "";
+ staged = "";
+ renamed = "";
+ deleted = "";
+ };
+
+ # Command duration module
+ cmd_duration = {
+ format = "[$duration]($style)";
+ style = "bold #cdd6f4";
+ min_time = 5000; # Only show if command takes longer than 5 seconds
+ };
+
+ # Character module (prompt symbol)
+ character = {
+ success_symbol = "[└──────⇴ ](bold #a6e3a1)";
+ error_symbol = "[└──────⇴ ](bold #f38ba8)";
+ };
+
+ nix_shell = {
+ format = "[$symbol$state( ($name))]($style)";
+ symbol = "U+02744";
+ style = "bold #89dceb";
+ };
+ };
+ };
+
+ home.file = {
+ ".config/fastfetch/config.jsonc".source = ./fastfetch.jsonc;
+ ".config/tabiew/theme.toml".source = ./tabiew.toml;
+ ".config/kitty/tab_bar.py".source = ./tab_bar.py;
+ };
+}
diff --git a/home/tab_bar.py b/home/tab_bar.py
new file mode 100644
index 0000000..e1bad95
--- /dev/null
+++ b/home/tab_bar.py
@@ -0,0 +1,34 @@
+from datetime import datetime
+from kitty.tab_bar import DrawData, ExtraData, TabBarData, as_rgb
+from kitty.fast_data_types import Screen
+
+
+def draw_tab(
+ draw_data: DrawData,
+ screen: Screen,
+ tab: TabBarData,
+ before: int,
+ max_title_length: int,
+ index: int,
+ is_last: bool,
+ extra_data: ExtraData,
+) -> int:
+
+ # Left side: Current directory or command
+ screen.cursor.fg = as_rgb(int("a6e3a1", 16))
+ screen.cursor.bg = as_rgb(int("1e1e2e", 16))
+
+ # Get the foreground process (command) or use title
+ title = tab.active_fg or tab.title or "shell"
+ screen.draw(f" {title} ")
+
+ # Middle: Nix icon
+ screen.cursor.fg = as_rgb(int("89dceb", 16))
+ screen.draw(" ❄ ")
+
+ # Right: Current time
+ screen.cursor.fg = as_rgb(int("cdd6f4", 16))
+ current_time = datetime.now().strftime("%H:%M")
+ screen.draw(f"{current_time} ")
+
+ return screen.cursor.x
diff --git a/home/tabiew.toml b/home/tabiew.toml
new file mode 100644
index 0000000..514af60
--- /dev/null
+++ b/home/tabiew.toml
@@ -0,0 +1,141 @@
+# Catppuccin Mocha Theme for Tabiew
+# Base colors from Catppuccin Mocha palette
+
+[table_header]
+fg = "#F5E0DC" # Rosewater
+bg = "#181825" # Mantle
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[[table_headers]]
+fg = "#F5C2E7" # Pink
+bg = "#181825" # Mantle
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[[table_headers]]
+fg = "#CBA6F7" # Mauve
+bg = "#181825" # Mantle
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[[table_headers]]
+fg = "#89DCEB" # Sky
+bg = "#181825" # Mantle
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[[rows]]
+fg = "#CDD6F4" # Text
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[rows]]
+fg = "#CDD6F4" # Text
+bg = "#181825" # Mantle
+add_modifier = ""
+sub_modifier = ""
+
+[highlight]
+fg = "#181825" # Mantle
+bg = "#F9E2AF" # Yellow
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[[table_tags]]
+fg = "#181825" # Mantle
+bg = "#F38BA8" # Red
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[[table_tags]]
+fg = "#181825" # Mantle
+bg = "#A6E3A1" # Green
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[block]
+fg = "#FAB387" # Peach
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[block_tag]
+fg = "#181825" # Mantle
+bg = "#FAB387" # Peach
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[text]
+fg = "#CDD6F4" # Text
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[subtext]
+fg = "#9399B2" # Overlay1
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[error]
+fg = "#CDD6F4" # Text
+bg = "#F38BA8" # Red
+add_modifier = "BOLD"
+sub_modifier = ""
+
+[[chart]]
+fg = "#F38BA8" # Red
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[chart]]
+fg = "#FAB387" # Peach (Orange)
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[chart]]
+fg = "#F9E2AF" # Yellow
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[chart]]
+fg = "#A6E3A1" # Green
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[chart]]
+fg = "#94E2D5" # Teal
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[chart]]
+fg = "#89DCEB" # Sky (Cyan)
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[chart]]
+fg = "#89B4FA" # Blue
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[chart]]
+fg = "#CBA6F7" # Mauve (Purple)
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
+[[chart]]
+fg = "#F5C2E7" # Pink
+bg = "#313244" # Surface0
+add_modifier = ""
+sub_modifier = ""
+
diff --git a/hosts/rpi-4/configuration.nix b/hosts/rpi-4/configuration.nix
new file mode 100644
index 0000000..ea4fc71
--- /dev/null
+++ b/hosts/rpi-4/configuration.nix
@@ -0,0 +1,12 @@
+{ config, pkgs, primaryUser, ... }:
+
+{
+ # Host-specific packages
+ environment.systemPackages = with pkgs; [
+# python3
+# nodejs
+ ];
+
+ # Any RPi 4 specific customizations go here
+ networking.hostName = "rpi-4";
+}
diff --git a/nixos/default.nix b/nixos/default.nix
new file mode 100644
index 0000000..177abe0
--- /dev/null
+++ b/nixos/default.nix
@@ -0,0 +1,53 @@
+{ config, pkgs, inputs, self, primaryUser, ... }:
+
+{
+ imports = [
+ ./hardware.nix
+ ./settings.nix
+ ./packages.nix
+ ];
+
+ nixpkgs.config.allowUnfree = true;
+
+ networking = {
+ hostName = "rpi-4";
+ networkmanager.enable = true;
+ };
+
+ # SSH configuration
+ services.openssh = {
+ enable = true;
+ settings.PermitRootLogin = "no";
+ settings.PasswordAuthentication = true;
+ };
+
+ # User configuration
+ users.users.${primaryUser} = {
+ isNormalUser = true;
+ home = "/home/${primaryUser}";
+ description = "Phil";
+ extraGroups = [ "wheel" "networkmanager" ];
+ shell = pkgs.fish;
+ };
+
+ # Shell
+ programs.zsh.enable = true;
+ programs.fish.enable = true;
+
+ # Nix settings
+ nix = {
+ settings = {
+ experimental-features = [ "nix-command" "flakes" ];
+ auto-optimise-store = true;
+ builders = "ssh://phil@192.168.2.40 aarch64-linux";
+ builders-use-substitutes = true;
+ };
+ gc = {
+ automatic = true;
+ dates = "weekly";
+ options = "--delete-older-than 30d";
+ };
+ };
+
+ system.stateVersion = "24.11";
+}
diff --git a/nixos/hardware.nix b/nixos/hardware.nix
new file mode 100644
index 0000000..3dc8862
--- /dev/null
+++ b/nixos/hardware.nix
@@ -0,0 +1,34 @@
+{ config, lib, pkgs, modulesPath, ... }:
+
+{
+ imports = [
+ (modulesPath + "/installer/sd-card/sd-image-aarch64.nix")
+ ];
+
+ # Bootloader
+ boot = {
+ kernelPackages = pkgs.linuxPackages_rpi4;
+ initrd.availableKernelModules = [ "xhci_pci" "usbhid" "usb_storage" ];
+ loader.generic-extlinux-compatible.enable = true;
+ kernelParams = [ "console=ttyS0,115200n8" ];
+ };
+
+ # File systems
+ fileSystems."/" = {
+ device = "/dev/disk/by-label/NIXOS_SD";
+ fsType = "ext4";
+ options = [ "noatime" ];
+ };
+
+ # Swap
+ swapDevices = [{
+ device = "/swapfile";
+ size = 4096;
+ }];
+
+ # RPi 4 specific hardware
+ hardware.enableRedistributableFirmware = true;
+
+ # SD Image
+ image.baseName = "nixos-rpi4";
+}
diff --git a/nixos/packages.nix b/nixos/packages.nix
new file mode 100644
index 0000000..696ed08
--- /dev/null
+++ b/nixos/packages.nix
@@ -0,0 +1,19 @@
+{ config, pkgs, ... }:
+
+{
+ environment.systemPackages = with pkgs; [
+ git
+ curl
+ wget
+ htop
+ neovim
+ tmux
+ ripgrep
+ fd
+ bat
+ eza
+ fzf
+ tree
+ fish
+ ];
+}
diff --git a/nixos/settings.nix b/nixos/settings.nix
new file mode 100644
index 0000000..bab9c20
--- /dev/null
+++ b/nixos/settings.nix
@@ -0,0 +1,21 @@
+{ config, pkgs, ... }:
+
+{
+ # Localization
+ 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";
+ };
+
+ # System settings
+ console.keyMap = "de";
+}