From b16707b2ab5320cd31e9cc9332b37806bf5c0eac Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 28 Jun 2026 06:48:07 +0200 Subject: [PATCH] feat(modules): users, scripts, menus, fastfetch, walker, cache, colors, bootstrap Co-Authored-By: Claude Opus 4.8 --- modules/cache.nix | 45 +++ modules/colors.nix | 165 +++++++++ modules/fastfetch.nix | 221 ++++++++++++ modules/home-manager-bootstrap.nix | 69 ++++ modules/menus.nix | 534 ++++++++++++++++++++++++++++ modules/partitioning.sh | 540 +++++++++++++++++++++++++++++ modules/scripts.nix | 373 ++++++++++++++++++++ modules/users.nix | 124 +++++++ modules/walker.nix | 450 ++++++++++++++++++++++++ 9 files changed, 2521 insertions(+) create mode 100644 modules/cache.nix create mode 100644 modules/colors.nix create mode 100644 modules/fastfetch.nix create mode 100644 modules/home-manager-bootstrap.nix create mode 100644 modules/menus.nix create mode 100755 modules/partitioning.sh create mode 100644 modules/scripts.nix create mode 100644 modules/users.nix create mode 100644 modules/walker.nix diff --git a/modules/cache.nix b/modules/cache.nix new file mode 100644 index 0000000..5ef19c8 --- /dev/null +++ b/modules/cache.nix @@ -0,0 +1,45 @@ +# Binary cache configuration. +# +# Substituters and trusted public keys for cache.nixos.org and +# nix-community, plus a stub for the aiolabs cache (uncomment when +# configured). Imported by every host that wants pre-built artifacts +# instead of compiling from source. +# +# Why this exists as its own module: the optimize-deploys/unified flake +# notes that host1/host3/host2 share ~90% of derivations, so the second +# and third deploys would be near-instant once a cache is set up. Same +# applies for the dev box rebuilds. Rather than scatter substituter +# configuration across every host, define it once. +# +# Pushing to the cache is one Makefile target (`make cache`) — see the +# top-level Makefile. + +{ ... }: + +{ + nix.settings = { + substituters = [ + "https://cache.nixos.org" + "https://nix-community.cachix.org" + # Uncomment when the aiolabs cache is configured. + # "https://aiolabs-nix.cachix.org" + ]; + + trusted-public-keys = [ + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + # Add the aiolabs cache public key here once we generate it: + # cachix authtoken + # cachix create aiolabs-nix + # The public key is shown after `cachix create`. + # "aiolabs-nix.cachix.org-1:..." + ]; + + # Allow more substituters at runtime via `--option extra-substituters` + # without editing this file. Useful for one-off testing. + trusted-substituters = [ + "https://cache.nixos.org" + "https://nix-community.cachix.org" + ]; + }; +} diff --git a/modules/colors.nix b/modules/colors.nix new file mode 100644 index 0000000..1397bb6 --- /dev/null +++ b/modules/colors.nix @@ -0,0 +1,165 @@ +{ + config, + pkgs, + lib, + inputs, + ... +}: + +let + inherit (lib) + mkIf + mkMerge + optionals + optionalString + ; + cfg = config.omni; + + # Function to generate colors from wallpaper using imagemagick + generateColorsFromWallpaper = + wallpaperPath: + pkgs.writeShellScriptBin "generate-colors" '' + #!/usr/bin/env bash + + # Extract dominant colors from wallpaper using imagemagick + colors=$(${pkgs.imagemagick}/bin/convert "${wallpaperPath}" -resize 1x1 -format "%[pixel:u]" info:) + + # Generate a simple color scheme based on the dominant color + # This is a simplified approach - ideally would use a more sophisticated algorithm + echo "# Generated color scheme from wallpaper: ${wallpaperPath}" + echo "# Dominant color: $colors" + + # For now, we'll use predefined schemes that match common wallpaper types + # In a real implementation, this would analyze the image and generate appropriate colors + ''; + + # Default color schemes for common wallpaper types + fallbackColorSchemes = { + dark = inputs.nix-colors.colorSchemes.tokyo-night-dark or null; + light = inputs.nix-colors.colorSchemes.tokyo-night-light or null; + blue = inputs.nix-colors.colorSchemes.nord or null; + purple = inputs.nix-colors.colorSchemes.catppuccin-mocha or null; + green = inputs.nix-colors.colorSchemes.gruvbox-dark-medium or null; + }; + + # Select color scheme based on wallpaper or user preference + selectedColorScheme = + if cfg.colorScheme != null then + cfg.colorScheme + else if cfg.wallpaper != null && cfg.features.autoColors then + # TODO: Implement actual color analysis + # For now, use a sensible default based on theme + fallbackColorSchemes.${cfg.theme} or fallbackColorSchemes.dark + else + # Use theme-based color scheme + fallbackColorSchemes.${cfg.theme} or fallbackColorSchemes.dark; + +in +{ + config = mkIf (cfg.enable or true) (mkMerge [ + # User-specific configuration using shared helpers + ({ + home-manager.users.${cfg.user} = mkIf (selectedColorScheme != null) { + colorScheme = selectedColorScheme; + + # Add packages for color management + home.packages = + with pkgs; + [ + imagemagick # For color extraction from images + ] + ++ optionals (cfg.features.customThemes or false || cfg.features.wallpaperEffects or false) [ + # Additional packages for advanced color analysis + python3Packages.pillow # For more sophisticated image analysis + python3Packages.colorthief # For extracting color palettes + ] + ++ optionals (cfg.wallpaper != null) [ + # Generate wallpaper setter script that respects colors + (pkgs.writeShellScriptBin "set-omni-wallpaper" '' + WALLPAPER_PATH="${cfg.wallpaper}" + + echo "Setting wallpaper: $WALLPAPER_PATH" + + # Set wallpaper with awww + if command -v awww &> /dev/null; then + awww img "$WALLPAPER_PATH" --transition-type wipe --transition-angle 30 --transition-step 90 + else + echo "awww not found, please install awww for wallpaper support" + fi + + # Optionally generate new colors from wallpaper + ${optionalString (cfg.features.wallpaperEffects or false) '' + echo "Generating colors from wallpaper..." + # This would trigger a system rebuild with new colors + # For now, just notify the user + echo "Note: Automatic color generation requires system rebuild" + echo "Consider adding this wallpaper to your configuration and rebuilding" + ''} + '') + ]; + }; + }) + + # System-level configuration + { + + # System-level packages for color management + environment.systemPackages = with pkgs; [ + # Color utilities + imagemagick + + # Wallpaper utilities + awww # Wayland wallpaper daemon + + # Script to help users set up automatic colors + (writeShellScriptBin "omni-setup-colors" '' + #!/usr/bin/env bash + + echo "Omnixient Color Setup" + echo "==================" + echo "" + echo "Current configuration:" + echo " Theme: ${cfg.theme}" + echo " Preset: ${if cfg.preset != null then cfg.preset else "none"}" + echo " Custom Themes: ${if cfg.features.customThemes or false then "enabled" else "disabled"}" + echo " Wallpaper Effects: ${ + if cfg.features.wallpaperEffects or false then "enabled" else "disabled" + }" + echo " Wallpaper: ${if cfg.wallpaper != null then toString cfg.wallpaper else "not set"}" + echo " Color Scheme: ${if cfg.colorScheme != null then "custom" else "theme-based"}" + echo "" + + ${optionalString (!(cfg.features.wallpaperEffects or false)) '' + echo "To enable automatic color generation:" + echo " 1. Set omni.features.wallpaperEffects = true; in your configuration" + echo " 2. Set omni.wallpaper = /path/to/your/wallpaper.jpg;" + echo " 3. Rebuild your system with: omni-rebuild" + echo "" + ''} + + ${optionalString ((cfg.features.wallpaperEffects or false) && cfg.wallpaper == null) '' + echo "Wallpaper effects are enabled but no wallpaper is set." + echo "Set omni.wallpaper = /path/to/your/wallpaper.jpg; in your configuration." + echo "" + ''} + + echo "Available nix-colors schemes:" + echo " - tokyo-night-dark, tokyo-night-light" + echo " - catppuccin-mocha, catppuccin-latte" + echo " - gruvbox-dark-medium, gruvbox-light-medium" + echo " - nord" + echo " - everforest-dark-medium" + echo " - rose-pine, rose-pine-dawn" + echo "" + echo "To use a specific scheme:" + echo ' omni.colorScheme = inputs.nix-colors.colorSchemes.SCHEME_NAME;' + '') + ]; + + # Export color information for other modules to use + environment.variables = mkIf (selectedColorScheme != null) { + OMNI_COLOR_SCHEME = selectedColorScheme.slug or "unknown"; + }; + } + ]); +} diff --git a/modules/fastfetch.nix b/modules/fastfetch.nix new file mode 100644 index 0000000..02549e1 --- /dev/null +++ b/modules/fastfetch.nix @@ -0,0 +1,221 @@ +{ + config, + pkgs, + lib, + ... +}: + +# Fastfetch system information display for Omnixient +# Beautiful system information with Omnixient branding + +let + inherit (lib) mkIf; + cfg = config.omni; + omni = config.omni.lib; +in +{ + config = mkIf (cfg.enable or true) { + # Add fastfetch and convenience scripts to system packages + environment.systemPackages = + (with pkgs; [ + fastfetch + ]) + ++ [ + # Convenience scripts + (omni.makeScript "omni-info" "Show Omnixient system information" '' + fastfetch --config /etc/omni/fastfetch/config.jsonc + '') + + (omni.makeScript "omni-about" "Show Omnixient about screen" '' + clear + cat /etc/omni/branding/about.txt + echo + echo "Theme: ${cfg.theme}" + echo "Preset: ${cfg.preset or "custom"}" + echo "User: ${cfg.user}" + echo "NixOS Version: $(nixos-version)" + echo + echo "Visit: https://github.com/TheArctesian/omnixy" + '') + ]; + + # Create Omnixient branding directory + environment.etc."omni/branding/logo.txt".text = '' + + ███████╗███╗ ███╗███╗ ██╗██╗██╗ ██╗██╗ ██╗ + ██╔════╝████╗ ████║████╗ ██║██║╚██╗██╔╝╚██╗ ██╔╝ + ██║ ██╔████╔██║██╔██╗ ██║██║ ╚███╔╝ ╚████╔╝ + ██║ ██║╚██╔╝██║██║╚██╗██║██║ ██╔██╗ ╚██╔╝ + ███████╗██║ ╚═╝ ██║██║ ╚████║██║██╔╝ ██╗ ██║ + ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝ ╚═╝ + + Declarative NixOS Configuration + ''; + + environment.etc."omni/branding/about.txt".text = '' + ╭─────────────────────────────────────────────────────╮ + │ │ + │ ██████╗ ███╗ ███╗███╗ ██╗██╗██╗ ██╗██╗ ██╗│ + │ ██╔═══██╗████╗ ████║████╗ ██║██║╚██╗██╔╝╚██╗ ██╔╝│ + │ ██║ ██║██╔████╔██║██╔██╗ ██║██║ ╚███╔╝ ╚████╔╝ │ + │ ██║ ██║██║╚██╔╝██║██║╚██╗██║██║ ██╔██╗ ╚██╔╝ │ + │ ╚██████╔╝██║ ╚═╝ ██║██║ ╚████║██║██╔╝ ██╗ ██║ │ + │ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝ ╚═╝ │ + │ │ + │ 🚀 Declarative • 🎨 Beautiful • ⚡ Fast │ + │ │ + ╰─────────────────────────────────────────────────────╯ + ''; + + # Create fastfetch configuration + environment.etc."omni/fastfetch/config.jsonc".text = '' + { + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "type": "file", + "source": "/etc/omni/branding/about.txt", + "color": { + "1": "cyan", + "2": "blue" + }, + "padding": { + "top": 1, + "right": 4, + "left": 2 + } + }, + "modules": [ + "break", + { + "type": "custom", + "format": "\u001b[90m┌─────────────────── Hardware ───────────────────┐" + }, + { + "type": "host", + "key": " 󰌢 Host", + "keyColor": "cyan" + }, + { + "type": "cpu", + "key": " 󰻠 CPU", + "keyColor": "cyan" + }, + { + "type": "gpu", + "key": " 󰍛 GPU", + "keyColor": "cyan" + }, + { + "type": "memory", + "key": " 󰍛 Memory", + "keyColor": "cyan" + }, + { + "type": "disk", + "key": " 󰋊 Disk (/)", + "keyColor": "cyan" + }, + { + "type": "custom", + "format": "\u001b[90m├─────────────────── Software ───────────────────┤" + }, + { + "type": "os", + "key": " 󰣇 OS", + "keyColor": "blue" + }, + { + "type": "kernel", + "key": " 󰌽 Kernel", + "keyColor": "blue" + }, + { + "type": "de", + "key": " 󰧨 DE", + "keyColor": "blue" + }, + { + "type": "wm", + "key": " 󰖸 WM", + "keyColor": "blue" + }, + { + "type": "wmtheme", + "key": " 󰏘 Theme", + "keyColor": "blue" + }, + { + "type": "shell", + "key": " 󰆍 Shell", + "keyColor": "blue" + }, + { + "type": "terminal", + "key": " 󰆍 Terminal", + "keyColor": "blue" + }, + { + "type": "custom", + "format": "\u001b[90m├─────────────────── Omnixient ─────────────────────┤" + }, + { + "type": "custom", + "format": " 󰣇 Theme: ${cfg.theme}", + "keyColor": "magenta" + }, + { + "type": "custom", + "format": " 󰣇 Preset: ${cfg.preset or "custom"}", + "keyColor": "magenta" + }, + { + "type": "custom", + "format": " 󰣇 User: ${cfg.user}", + "keyColor": "magenta" + }, + { + "type": "packages", + "key": " 󰏖 Packages", + "keyColor": "magenta" + }, + { + "type": "custom", + "format": "\u001b[90m└─────────────────────────────────────────────────┘" + }, + "break" + ] + } + ''; + + # Convenience scripts are now consolidated above + + # Add to user environment + home-manager.users.${config.omni.user} = { + # Set XDG config dir for fastfetch + xdg.configFile."fastfetch/config.jsonc".source = + config.environment.etc."omni/fastfetch/config.jsonc".source; + + # Add shell aliases + programs.bash.shellAliases = { + neofetch = "omni-info"; + screenfetch = "omni-info"; + sysinfo = "omni-info"; + about = "omni-about"; + }; + + programs.zsh.shellAliases = { + neofetch = "omni-info"; + screenfetch = "omni-info"; + sysinfo = "omni-info"; + about = "omni-about"; + }; + + programs.fish.shellAliases = { + neofetch = "omni-info"; + screenfetch = "omni-info"; + sysinfo = "omni-info"; + about = "omni-about"; + }; + }; + }; +} diff --git a/modules/home-manager-bootstrap.nix b/modules/home-manager-bootstrap.nix new file mode 100644 index 0000000..d819a30 --- /dev/null +++ b/modules/home-manager-bootstrap.nix @@ -0,0 +1,69 @@ +# modules/home-manager-bootstrap.nix +# +# Pre-create the directory tree that the home-manager activation +# script expects to exist on a fresh first boot. Without these +# rules, `home-manager-user.service` crashes in (at least) three +# different places — each one only visible after fixing the +# previous — making first-boot of any clean install fail with a +# misleading error. +# +# This module is imported by both: +# - lib/mksystem.nix (for normal hosts), and +# - iso.nix (for the live ISO), +# so the bootstrap is consistent across both code paths. It is +# intentionally a separate module rather than inlined in mksystem +# so the ISO — which bypasses mksystem — does not silently miss +# the fix. +# +# Reads `config.omni.user`, which is the canonical "main user" +# option set by modules/core.nix. Does nothing if that option is +# unset (e.g. during a flake check that does not set up users). +# +# The bugs this fixes: +# +# 1. The "find a profile dir" check in +# home-manager-generation/activate (around line 90 of the +# generated script) needs $HOME/.local/state/nix/profiles +# OR /nix/var/nix/profiles/per-user/$USER to exist. The +# nix-daemon only creates the per-user dir lazily on the +# user's first nix command, so on a fresh boot neither path +# exists. Symptom: "Could not find suitable profile +# directory" → service fails. +# +# 2. After (1) is fixed, `nix-store --realise ... --add-root +# $HOME/.local/state/home-manager/gcroots/new-home` fails +# because the activate script declares `hmGcrootsDir` but +# never `mkdir -p`s it. nix-store will not create parent +# dirs for --add-root. Symptom: silent exit, status 1, no +# error in journal. +# +# 3. After (2) is fixed, `linkGeneration` fails with +# "Permission denied" creating `~/.local/share/dev-env/...`. +# modules/lib.nix declares `d /home/$USER/.local/share/ +# omni ...` and systemd-tmpfiles auto-creates the missing +# intermediate `.local/share` parent as root:root, which +# then blocks the user-running activation. Pinning the +# `.local/share` parent here keeps it user-owned regardless +# of declaration order. +# +# tmpfiles `d` rules do not recursively create parents, so each +# level of the tree is spelled out explicitly. + +{ config, lib, ... }: + +let + user = config.omni.user or null; +in +{ + config = lib.mkIf (user != null) { + systemd.tmpfiles.rules = [ + "d /nix/var/nix/profiles/per-user/${user} 0755 ${user} users -" + "d /nix/var/nix/gcroots/per-user/${user} 0755 ${user} users -" + "d /home/${user}/.local 0755 ${user} users -" + "d /home/${user}/.local/share 0755 ${user} users -" + "d /home/${user}/.local/state 0755 ${user} users -" + "d /home/${user}/.local/state/home-manager 0755 ${user} users -" + "d /home/${user}/.local/state/home-manager/gcroots 0755 ${user} users -" + ]; + }; +} diff --git a/modules/menus.nix b/modules/menus.nix new file mode 100644 index 0000000..8f3b94c --- /dev/null +++ b/modules/menus.nix @@ -0,0 +1,534 @@ +{ + config, + pkgs, + lib, + ... +}: + +# Interactive menu system for Omnixient +# Terminal-based menus for system management and productivity + +let + inherit (lib) mkIf mkDefault; + cfg = config.omni; + omni = config.omni.lib; +in +{ + config = mkIf (cfg.enable or true) { + # Interactive menu scripts + environment.systemPackages = [ + # Main Omnixient menu + (omni.makeScript "omni-menu" "Interactive Omnixient system menu" '' + #!/bin/bash + + # Colors for terminal output + RED='\033[0;31m' + GREEN='\033[0;32m' + YELLOW='\033[1;33m' + BLUE='\033[0;34m' + PURPLE='\033[0;35m' + CYAN='\033[0;36m' + WHITE='\033[1;37m' + NC='\033[0m' # No Color + + show_header() { + clear + echo -e "''${CYAN}" + echo " ███████╗███╗ ███╗███╗ ██╗██╗██╗ ██╗██╗ ██╗" + echo " ██╔════╝████╗ ████║████╗ ██║██║╚██╗██╔╝╚██╗ ██╔╝" + echo " ██║ ██╔████╔██║██╔██╗ ██║██║ ╚███╔╝ ╚████╔╝" + echo " ██║ ██║╚██╔╝██║██║╚██╗██║██║ ██╔██╗ ╚██╔╝" + echo " ███████╗██║ ╚═╝ ██║██║ ╚████║██║██╔╝ ██╗ ██║" + echo " ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝ ╚═╝" + echo -e "''${NC}" + echo -e "''${WHITE} 🚀 Declarative • 🎨 Beautiful • ⚡ Fast''${NC}" + echo + echo -e "''${BLUE}═══════════════════════════════════════════════════════''${NC}" + echo -e "''${WHITE} Theme: ''${YELLOW}${cfg.theme}''${WHITE} │ User: ''${GREEN}${cfg.user}''${WHITE} │ Preset: ''${PURPLE}${cfg.preset or "custom"}''${NC}" + echo -e "''${BLUE}═══════════════════════════════════════════════════════''${NC}" + echo + } + + show_main_menu() { + show_header + echo -e "''${WHITE}🎛️ Main Menu''${NC}" + echo + echo -e "''${GREEN}1.''${NC} 📦 System Management" + echo -e "''${GREEN}2.''${NC} 🎨 Theme & Appearance" + echo -e "''${GREEN}3.''${NC} ⚙️ Configuration" + echo -e "''${GREEN}4.''${NC} 🔧 Development Tools" + echo -e "''${GREEN}5.''${NC} 📊 System Information" + echo -e "''${GREEN}6.''${NC} 🛠️ Maintenance & Utilities" + echo -e "''${GREEN}7.''${NC} 📋 Help & Documentation" + echo + echo -e "''${RED}0.''${NC} Exit" + echo + echo -ne "''${CYAN}Select an option: ''${NC}" + } + + show_system_menu() { + show_header + echo -e "''${WHITE}📦 System Management''${NC}" + echo + echo -e "''${GREEN}1.''${NC} 🔄 Update System" + echo -e "''${GREEN}2.''${NC} 🔨 Rebuild Configuration" + echo -e "''${GREEN}3.''${NC} 🧪 Test Configuration" + echo -e "''${GREEN}4.''${NC} 🧹 Clean System" + echo -e "''${GREEN}5.''${NC} 📊 Service Status" + echo -e "''${GREEN}6.''${NC} 💾 Create Backup" + echo -e "''${GREEN}7.''${NC} 🔍 Search Packages" + echo + echo -e "''${YELLOW}8.''${NC} ← Back to Main Menu" + echo + echo -ne "''${CYAN}Select an option: ''${NC}" + } + + show_theme_menu() { + show_header + echo -e "''${WHITE}🎨 Theme & Appearance''${NC}" + echo + echo -e "''${WHITE}Current Theme: ''${YELLOW}${cfg.theme}''${NC}" + echo + echo -e "''${GREEN}Available Themes:''${NC}" + echo -e "''${GREEN}1.''${NC} 🌃 tokyo-night - Dark theme with vibrant colors" + echo -e "''${GREEN}2.''${NC} 🎀 catppuccin - Pastel theme with modern aesthetics" + echo -e "''${GREEN}3.''${NC} 🟤 gruvbox - Retro theme with warm colors" + echo -e "''${GREEN}4.''${NC} ❄️ nord - Arctic theme with cool colors" + echo -e "''${GREEN}5.''${NC} 🌲 everforest - Green forest theme" + echo -e "''${GREEN}6.''${NC} 🌹 rose-pine - Cozy theme with muted colors" + echo -e "''${GREEN}7.''${NC} 🌊 kanagawa - Japanese-inspired theme" + echo -e "''${GREEN}8.''${NC} ☀️ catppuccin-latte - Light catppuccin variant" + echo -e "''${GREEN}9.''${NC} ⚫ matte-black - Minimalist dark theme" + echo -e "''${GREEN}a.''${NC} 💎 osaka-jade - Jade green accent theme" + echo -e "''${GREEN}b.''${NC} ☕ ristretto - Coffee-inspired warm theme" + echo + echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu" + echo + echo -ne "''${CYAN}Select theme or option: ''${NC}" + } + + show_config_menu() { + show_header + echo -e "''${WHITE}⚙️ Configuration''${NC}" + echo + echo -e "''${GREEN}1.''${NC} 📝 Edit Main Configuration" + echo -e "''${GREEN}2.''${NC} 🪟 Edit Hyprland Configuration" + echo -e "''${GREEN}3.''${NC} 🎨 Edit Theme Configuration" + echo -e "''${GREEN}4.''${NC} 📦 Edit Package Configuration" + echo -e "''${GREEN}5.''${NC} 🔒 Security Settings" + echo -e "''${GREEN}6.''${NC} 📂 Open Configuration Directory" + echo -e "''${GREEN}7.''${NC} 🔗 View Git Status" + echo + echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu" + echo + echo -ne "''${CYAN}Select an option: ''${NC}" + } + + show_dev_menu() { + show_header + echo -e "''${WHITE}🔧 Development Tools''${NC}" + echo + echo -e "''${GREEN}1.''${NC} 💻 Open Terminal" + echo -e "''${GREEN}2.''${NC} 📝 Open Code Editor" + echo -e "''${GREEN}3.''${NC} 🌐 Open Browser" + echo -e "''${GREEN}4.''${NC} 📁 Open File Manager" + echo -e "''${GREEN}5.''${NC} 🚀 Launch Applications" + echo -e "''${GREEN}6.''${NC} 🐙 Git Operations" + echo + echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu" + echo + echo -ne "''${CYAN}Select an option: ''${NC}" + } + + show_info_menu() { + show_header + echo -e "''${WHITE}📊 System Information''${NC}" + echo + echo -e "''${GREEN}1.''${NC} 🖥️ System Overview" + echo -e "''${GREEN}2.''${NC} 💻 Hardware Information" + echo -e "''${GREEN}3.''${NC} 📈 Performance Monitor" + echo -e "''${GREEN}4.''${NC} 🔧 Service Status" + echo -e "''${GREEN}5.''${NC} 💾 Disk Usage" + echo -e "''${GREEN}6.''${NC} 🌐 Network Information" + echo -e "''${GREEN}7.''${NC} 📊 Omnixient About" + echo + echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu" + echo + echo -ne "''${CYAN}Select an option: ''${NC}" + } + + show_maintenance_menu() { + show_header + echo -e "''${WHITE}🛠️ Maintenance & Utilities''${NC}" + echo + echo -e "''${GREEN}1.''${NC} 🧹 System Cleanup" + echo -e "''${GREEN}2.''${NC} 🔄 Restart Services" + echo -e "''${GREEN}3.''${NC} 📋 View Logs" + echo -e "''${GREEN}4.''${NC} 💾 Backup Configuration" + echo -e "''${GREEN}5.''${NC} 🔧 System Diagnostics" + echo -e "''${GREEN}6.''${NC} 🖼️ Screenshot Tools" + echo + echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu" + echo + echo -ne "''${CYAN}Select an option: ''${NC}" + } + + show_help_menu() { + show_header + echo -e "''${WHITE}📋 Help & Documentation''${NC}" + echo + echo -e "''${GREEN}1.''${NC} 📖 Omnixient Commands" + echo -e "''${GREEN}2.''${NC} 🔑 Keyboard Shortcuts" + echo -e "''${GREEN}3.''${NC} 🌐 Open GitHub Repository" + echo -e "''${GREEN}4.''${NC} 📧 Report Issue" + echo -e "''${GREEN}5.''${NC} ℹ️ About Omnixient" + echo + echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu" + echo + echo -ne "''${CYAN}Select an option: ''${NC}" + } + + handle_system_menu() { + case "$1" in + 1) echo -e "''${GREEN}Updating system...''${NC}"; omni-update ;; + 2) echo -e "''${GREEN}Rebuilding configuration...''${NC}"; omni-rebuild ;; + 3) echo -e "''${GREEN}Testing configuration...''${NC}"; omni-test ;; + 4) echo -e "''${GREEN}Cleaning system...''${NC}"; omni-clean ;; + 5) echo -e "''${GREEN}Checking service status...''${NC}"; omni-services status ;; + 6) echo -e "''${GREEN}Creating backup...''${NC}"; omni-backup ;; + 7) + echo -ne "''${CYAN}Enter package name to search: ''${NC}" + read -r package + if [ -n "$package" ]; then + omni-search "$package" + fi + ;; + 8) return 0 ;; + *) echo -e "''${RED}Invalid option!''${NC}" ;; + esac + echo + echo -ne "''${YELLOW}Press Enter to continue...''${NC}" + read -r + } + + handle_theme_menu() { + case "$1" in + 1) omni-theme tokyo-night ;; + 2) omni-theme catppuccin ;; + 3) omni-theme gruvbox ;; + 4) omni-theme nord ;; + 5) omni-theme everforest ;; + 6) omni-theme rose-pine ;; + 7) omni-theme kanagawa ;; + 8) omni-theme catppuccin-latte ;; + 9) omni-theme matte-black ;; + a|A) omni-theme osaka-jade ;; + b|B) omni-theme ristretto ;; + 0) return 0 ;; + *) echo -e "''${RED}Invalid option!''${NC}" ;; + esac + echo + echo -ne "''${YELLOW}Press Enter to continue...''${NC}" + read -r + } + + handle_config_menu() { + case "$1" in + 1) omni-config main ;; + 2) omni-config hyprland ;; + 3) omni-config theme ;; + 4) omni-config packages ;; + 5) + echo -e "''${CYAN}Security Settings:''${NC}" + echo -e "''${WHITE}1. Security Status 2. Fingerprint Setup 3. FIDO2 Setup''${NC}" + echo -ne "''${CYAN}Select: ''${NC}" + read -r security_choice + case "$security_choice" in + 1) omni-security status ;; + 2) omni-fingerprint setup ;; + 3) omni-fido2 setup ;; + esac + ;; + 6) cd /etc/nixos && ''${TERMINAL:-ghostty} ;; + 7) cd /etc/nixos && git status ;; + 0) return 0 ;; + *) echo -e "''${RED}Invalid option!''${NC}" ;; + esac + echo + echo -ne "''${YELLOW}Press Enter to continue...''${NC}" + read -r + } + + handle_dev_menu() { + case "$1" in + 1) ''${TERMINAL:-ghostty} ;; + 2) code ;; + 3) ''${BROWSER:-firefox} ;; + 4) thunar ;; + 5) walker ;; + 6) + echo -e "''${CYAN}Git Operations:''${NC}" + echo -e "''${WHITE}1. Status 2. Log 3. Commit 4. Push''${NC}" + echo -ne "''${CYAN}Select: ''${NC}" + read -r git_choice + cd /etc/nixos + case "$git_choice" in + 1) git status ;; + 2) git log --oneline -10 ;; + 3) echo -ne "''${CYAN}Commit message: ''${NC}"; read -r msg; git add -A && git commit -m "$msg" ;; + 4) git push ;; + esac + ;; + 0) return 0 ;; + *) echo -e "''${RED}Invalid option!''${NC}" ;; + esac + echo + echo -ne "''${YELLOW}Press Enter to continue...''${NC}" + read -r + } + + handle_info_menu() { + case "$1" in + 1) omni-sysinfo ;; + 2) omni-hardware ;; + 3) htop ;; + 4) omni-services status ;; + 5) df -h && echo && du -sh /nix/store ;; + 6) ip addr show ;; + 7) omni-about ;; + 0) return 0 ;; + *) echo -e "''${RED}Invalid option!''${NC}" ;; + esac + echo + echo -ne "''${YELLOW}Press Enter to continue...''${NC}" + read -r + } + + handle_maintenance_menu() { + case "$1" in + 1) omni-clean ;; + 2) + echo -ne "''${CYAN}Enter service name: ''${NC}" + read -r service + if [ -n "$service" ]; then + omni-services restart "$service" + fi + ;; + 3) + echo -ne "''${CYAN}Enter service name for logs: ''${NC}" + read -r service + if [ -n "$service" ]; then + omni-services logs "$service" + fi + ;; + 4) omni-backup ;; + 5) echo -e "''${GREEN}Running diagnostics...''${NC}"; journalctl -p 3 -xb ;; + 6) grim -g "$(slurp)" - | satty -f - --output-filename ~/Pictures/Screenshots/screenshot_$(date +'%Y-%m-%d-%H%M%S.png') ;; + 0) return 0 ;; + *) echo -e "''${RED}Invalid option!''${NC}" ;; + esac + echo + echo -ne "''${YELLOW}Press Enter to continue...''${NC}" + read -r + } + + handle_help_menu() { + case "$1" in + 1) + echo -e "''${WHITE}Omnixient Commands:''${NC}" + echo -e "''${GREEN}omni-menu''${NC} - This interactive menu" + echo -e "''${GREEN}omni-info''${NC} - System information display" + echo -e "''${GREEN}omni-about''${NC} - About screen" + echo -e "''${GREEN}omni-theme''${NC} - Switch themes" + echo -e "''${GREEN}omni-rebuild''${NC} - Rebuild configuration" + echo -e "''${GREEN}omni-update''${NC} - Update system" + echo -e "''${GREEN}omni-clean''${NC} - Clean system" + echo -e "''${GREEN}omni-search''${NC} - Search packages" + ;; + 2) + echo -e "''${WHITE}Hyprland Keyboard Shortcuts:''${NC}" + echo -e "''${GREEN}Super + Return''${NC} - Open terminal" + echo -e "''${GREEN}Super + R''${NC} - Open launcher" + echo -e "''${GREEN}Super + Q''${NC} - Close window" + echo -e "''${GREEN}Super + F''${NC} - Fullscreen" + echo -e "''${GREEN}Super + 1-0''${NC} - Switch workspaces" + ;; + 3) ''${BROWSER:-firefox} https://github.com/TheArctesian/omnixy ;; + 4) ''${BROWSER:-firefox} https://github.com/TheArctesian/omnixy/issues ;; + 5) omni-about ;; + 0) return 0 ;; + *) echo -e "''${RED}Invalid option!''${NC}" ;; + esac + echo + echo -ne "''${YELLOW}Press Enter to continue...''${NC}" + read -r + } + + # Main menu loop + while true; do + show_main_menu + read -r choice + + case "$choice" in + 1) + while true; do + show_system_menu + read -r sub_choice + handle_system_menu "$sub_choice" + [ "$?" -eq 0 ] && break + done + ;; + 2) + while true; do + show_theme_menu + read -r sub_choice + handle_theme_menu "$sub_choice" + [ "$?" -eq 0 ] && break + done + ;; + 3) + while true; do + show_config_menu + read -r sub_choice + handle_config_menu "$sub_choice" + [ "$?" -eq 0 ] && break + done + ;; + 4) + while true; do + show_dev_menu + read -r sub_choice + handle_dev_menu "$sub_choice" + [ "$?" -eq 0 ] && break + done + ;; + 5) + while true; do + show_info_menu + read -r sub_choice + handle_info_menu "$sub_choice" + [ "$?" -eq 0 ] && break + done + ;; + 6) + while true; do + show_maintenance_menu + read -r sub_choice + handle_maintenance_menu "$sub_choice" + [ "$?" -eq 0 ] && break + done + ;; + 7) + while true; do + show_help_menu + read -r sub_choice + handle_help_menu "$sub_choice" + [ "$?" -eq 0 ] && break + done + ;; + 0|q|Q) + echo -e "''${GREEN}Goodbye! 👋''${NC}" + exit 0 + ;; + *) + echo -e "''${RED}Invalid option! Press Enter to continue...''${NC}" + read -r + ;; + esac + done + '') + + # Quick theme selector + (omni.makeScript "omni-theme-picker" "Quick theme picker with preview" '' + #!/bin/bash + + # Colors + CYAN='\033[0;36m' + WHITE='\033[1;37m' + GREEN='\033[0;32m' + YELLOW='\033[1;33m' + RED='\033[0;31m' + NC='\033[0m' + + themes=( + "tokyo-night:🌃:Dark theme with vibrant colors" + "catppuccin:🎀:Pastel theme with modern aesthetics" + "gruvbox:🟤:Retro theme with warm colors" + "nord:❄️ :Arctic theme with cool colors" + "everforest:🌲:Green forest theme" + "rose-pine:🌹:Cozy theme with muted colors" + "kanagawa:🌊:Japanese-inspired theme" + "catppuccin-latte:☀️ :Light catppuccin variant" + "matte-black:⚫:Minimalist dark theme" + "osaka-jade:💎:Jade green accent theme" + "ristretto:☕:Coffee-inspired warm theme" + ) + + clear + echo -e "''${CYAN}🎨 Omnixient Theme Picker''${NC}" + echo -e "''${WHITE}Current Theme: ''${YELLOW}${cfg.theme}''${NC}" + echo + echo -e "''${WHITE}Available Themes:''${NC}" + echo + + for i in "''${!themes[@]}"; do + IFS=':' read -ra theme_info <<< "''${themes[$i]}" + theme_name="''${theme_info[0]}" + theme_icon="''${theme_info[1]}" + theme_desc="''${theme_info[2]}" + + printf "''${GREEN}%2d.''${NC} %s %-15s - %s\n" "$((i+1))" "$theme_icon" "$theme_name" "$theme_desc" + done + + echo + echo -e "''${RED} 0.''${NC} Cancel" + echo + echo -ne "''${CYAN}Select theme (1-''${#themes[@]}): ''${NC}" + read -r choice + + if [[ "$choice" -ge 1 && "$choice" -le "''${#themes[@]}" ]]; then + IFS=':' read -ra theme_info <<< "''${themes[$((choice-1))]}" + selected_theme="''${theme_info[0]}" + + echo -e "''${GREEN}Switching to ''${selected_theme}...''${NC}" + omni-theme "$selected_theme" + elif [[ "$choice" == "0" ]]; then + echo -e "''${YELLOW}Cancelled.''${NC}" + else + echo -e "''${RED}Invalid selection!''${NC}" + exit 1 + fi + '') + ]; + + # Shell aliases for easy access + home-manager.users.${config.omni.user} = { + programs.bash.shellAliases = { + menu = "omni-menu"; + themes = "omni-theme-picker"; + rebuild = mkDefault "omni-rebuild"; + update = mkDefault "omni-update"; + info = "omni-info"; + clean = mkDefault "omni-clean"; + }; + + programs.zsh.shellAliases = { + menu = "omni-menu"; + themes = "omni-theme-picker"; + rebuild = mkDefault "omni-rebuild"; + update = mkDefault "omni-update"; + info = "omni-info"; + clean = mkDefault "omni-clean"; + }; + + programs.fish.shellAliases = { + menu = "omni-menu"; + themes = "omni-theme-picker"; + rebuild = mkDefault "omni-rebuild"; + update = mkDefault "omni-update"; + info = "omni-info"; + clean = mkDefault "omni-clean"; + }; + }; + }; +} diff --git a/modules/partitioning.sh b/modules/partitioning.sh new file mode 100755 index 0000000..413a7ae --- /dev/null +++ b/modules/partitioning.sh @@ -0,0 +1,540 @@ +#!/usr/bin/env bash +# Omnixient Disk Partitioning Module +# Comprehensive partitioning with LUKS encryption support +# Follows NixOS Installation Guide recommendations + +set -e + +# Color setup for output +setup_colors() { + RED=$(printf '\033[38;2;247;118;142m') + GREEN=$(printf '\033[38;2;158;206;106m') + YELLOW=$(printf '\033[38;2;224;175;104m') + CYAN=$(printf '\033[38;2;125;207;255m') + BLUE=$(printf '\033[38;2;122;162;247m') + PURPLE=$(printf '\033[38;2;187;154;247m') + FG=$(printf '\033[38;2;192;202;245m') + BOLD=$(printf '\033[1m') + DIM=$(printf '\033[2m') + RESET=$(printf '\033[0m') +} + +setup_colors + +# Utility functions +log_info() { + echo -e "${CYAN}[INFO]${RESET} $1" +} + +log_success() { + echo -e "${GREEN}[✓]${RESET} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${RESET} $1" >&2 +} + +log_warn() { + echo -e "${YELLOW}[WARN]${RESET} $1" +} + +# VM Detection +detect_vm() { + if systemd-detect-virt >/dev/null 2>&1; then + local virt_type=$(systemd-detect-virt) + if [ "$virt_type" != "none" ]; then + log_info "Running in virtualized environment: $virt_type" + return 0 + fi + fi + return 1 +} + +# List available disks +list_disks() { + log_info "Available disks:" + echo + lsblk -d -n -o NAME,SIZE,TYPE,MODEL | while read -r name size type model; do + # Include both sd* and vd* devices + if [[ "$name" =~ ^(sd|vd|nvme) ]]; then + echo " ${CYAN}/dev/$name${RESET} - $size - $model" + # Show existing partitions if any + lsblk /dev/$name -n -o NAME,SIZE,FSTYPE,MOUNTPOINT 2>/dev/null | tail -n +2 | while read -r part psize fstype mount; do + echo " └─ $part - $psize - ${fstype:-none} ${mount:+(mounted: $mount)}" + done + fi + done + echo +} + +# Disk selection with VM support +select_disk() { + list_disks + + local selected_disk="" + while [ -z "$selected_disk" ]; do + read -p "${CYAN}Enter disk device (e.g., /dev/sda, /dev/vda, /dev/nvme0n1): ${RESET}" disk_input + + # Normalize input + if [[ ! "$disk_input" =~ ^/dev/ ]]; then + disk_input="/dev/$disk_input" + fi + + # Validate disk exists + if [ -b "$disk_input" ]; then + # Confirm destructive operation + echo + log_warn "WARNING: All data on $disk_input will be destroyed!" + read -p "${YELLOW}Type 'yes' to confirm: ${RESET}" confirm + if [ "$confirm" = "yes" ]; then + selected_disk="$disk_input" + else + log_info "Disk selection cancelled" + fi + else + log_error "Device $disk_input does not exist or is not a block device" + fi + done + + echo "$selected_disk" +} + +# Partition scheme selection +select_partition_scheme() { + echo + log_info "Select partition scheme:" + echo " 1) Automatic - Standard layout with optional encryption" + echo " 2) Manual - Use existing partitions" + echo " 3) Custom - Interactive partitioning" + echo + + local scheme="" + while [ -z "$scheme" ]; do + read -p "${CYAN}Choice (1-3): ${RESET}" choice + case $choice in + 1) scheme="automatic";; + 2) scheme="manual";; + 3) scheme="custom";; + *) log_error "Invalid choice";; + esac + done + + echo "$scheme" +} + +# Detect boot mode (UEFI or BIOS) +detect_boot_mode() { + if [ -d /sys/firmware/efi/efivars ]; then + echo "uefi" + else + echo "bios" + fi +} + +# Automatic partitioning with LUKS support +automatic_partition() { + local disk="$1" + local encrypt="${2:-false}" + local boot_mode=$(detect_boot_mode) + + log_info "Starting automatic partitioning on $disk" + log_info "Boot mode: $boot_mode" + + # Wipe disk + log_info "Wiping disk..." + wipefs -af "$disk" >/dev/null 2>&1 + sgdisk -Z "$disk" >/dev/null 2>&1 + + # Create partition table + if [ "$boot_mode" = "uefi" ]; then + log_info "Creating GPT partition table..." + parted -s "$disk" mklabel gpt + + # Create partitions + log_info "Creating EFI partition..." + parted -s "$disk" mkpart ESP fat32 1MiB 512MiB + parted -s "$disk" set 1 esp on + + log_info "Creating boot partition..." + parted -s "$disk" mkpart primary ext4 512MiB 1GiB + + log_info "Creating root partition..." + parted -s "$disk" mkpart primary 1GiB 100% + + # Wait for kernel to recognize partitions + partprobe "$disk" + sleep 2 + + # Determine partition naming + if [[ "$disk" =~ nvme ]]; then + local efi_part="${disk}p1" + local boot_part="${disk}p2" + local root_part="${disk}p3" + else + local efi_part="${disk}1" + local boot_part="${disk}2" + local root_part="${disk}3" + fi + else + log_info "Creating MBR partition table..." + parted -s "$disk" mklabel msdos + + log_info "Creating boot partition..." + parted -s "$disk" mkpart primary ext4 1MiB 512MiB + parted -s "$disk" set 1 boot on + + log_info "Creating root partition..." + parted -s "$disk" mkpart primary 512MiB 100% + + # Wait for kernel to recognize partitions + partprobe "$disk" + sleep 2 + + # Determine partition naming + if [[ "$disk" =~ nvme ]]; then + local boot_part="${disk}p1" + local root_part="${disk}p2" + else + local boot_part="${disk}1" + local root_part="${disk}2" + fi + fi + + # Setup encryption if requested + if [ "$encrypt" = "true" ]; then + log_info "Setting up LUKS encryption..." + + # Get passphrase + local passphrase="" + local passphrase_confirm="" + while true; do + read -s -p "${CYAN}Enter LUKS passphrase: ${RESET}" passphrase + echo + read -s -p "${CYAN}Confirm passphrase: ${RESET}" passphrase_confirm + echo + + if [ "$passphrase" = "$passphrase_confirm" ]; then + if [ ${#passphrase} -ge 8 ]; then + break + else + log_error "Passphrase must be at least 8 characters" + fi + else + log_error "Passphrases do not match" + fi + done + + # Encrypt root partition + log_info "Encrypting root partition..." + echo -n "$passphrase" | cryptsetup luksFormat --type luks2 "$root_part" - + + log_info "Opening encrypted partition..." + echo -n "$passphrase" | cryptsetup open "$root_part" cryptroot - + + # Update root partition reference + root_part="/dev/mapper/cryptroot" + fi + + # Format partitions + log_info "Formatting partitions..." + + if [ "$boot_mode" = "uefi" ]; then + mkfs.fat -F32 -n ESP "$efi_part" + mkfs.ext4 -L boot "$boot_part" + else + mkfs.ext4 -L boot "$boot_part" + fi + + # Format root - offer filesystem choice + echo + log_info "Select root filesystem:" + echo " 1) ext4 (recommended, stable)" + echo " 2) btrfs (snapshots, compression)" + echo " 3) zfs (advanced features, requires setup)" + echo + + local fs_type="ext4" + read -p "${CYAN}Choice (1-3) [default: 1]: ${RESET}" fs_choice + case $fs_choice in + 2) fs_type="btrfs";; + 3) fs_type="zfs";; + *) fs_type="ext4";; + esac + + case $fs_type in + ext4) + mkfs.ext4 -L nixos "$root_part" + ;; + btrfs) + mkfs.btrfs -L nixos "$root_part" + ;; + zfs) + log_warn "ZFS requires additional setup" + # Create ZFS pool + zpool create -f -o ashift=12 -O compression=lz4 -O xattr=sa -O acltype=posixacl -O mountpoint=none rpool "$root_part" + zfs create -o mountpoint=legacy rpool/root + zfs create -o mountpoint=legacy rpool/home + ;; + esac + + # Mount partitions + log_info "Mounting partitions..." + + # Mount root + if [ "$fs_type" = "zfs" ]; then + mount -t zfs rpool/root /mnt + mkdir -p /mnt/home + mount -t zfs rpool/home /mnt/home + else + mount "$root_part" /mnt + fi + + # Mount boot + mkdir -p /mnt/boot + mount "$boot_part" /mnt/boot + + # Mount EFI if UEFI + if [ "$boot_mode" = "uefi" ]; then + mkdir -p /mnt/boot/efi + mount "$efi_part" /mnt/boot/efi + fi + + # Create swap file + log_info "Creating swap file..." + local ram_size=$(free -g | awk '/^Mem:/{print $2}') + local swap_size=$((ram_size < 8 ? ram_size * 2 : ram_size)) + + if [ "$fs_type" = "btrfs" ]; then + # Btrfs requires special handling for swap + btrfs subvolume create /mnt/swap + truncate -s 0 /mnt/swap/swapfile + chattr +C /mnt/swap/swapfile + fallocate -l ${swap_size}G /mnt/swap/swapfile + else + fallocate -l ${swap_size}G /mnt/swapfile + fi + + chmod 600 /mnt/swapfile + mkswap /mnt/swapfile + swapon /mnt/swapfile + + log_success "Automatic partitioning complete" + + # Return partition information + cat </dev/null; then + log_info "Detected LUKS encrypted partition" + encrypted="true" + read -s -p "${CYAN}Enter passphrase: ${RESET}" passphrase + echo + echo -n "$passphrase" | cryptsetup open "$root_part" cryptroot - + root_part="/dev/mapper/cryptroot" + fi + + # Get boot partition + local boot_part="" + read -p "${CYAN}Enter boot partition (leave empty if combined with root): ${RESET}" boot_part + + # Get EFI partition if UEFI + local efi_part="" + if [ "$(detect_boot_mode)" = "uefi" ]; then + read -p "${CYAN}Enter EFI partition: ${RESET}" efi_part + if [ ! -b "$efi_part" ]; then + log_error "EFI partition required for UEFI systems" + exit 1 + fi + fi + + # Mount partitions + log_info "Mounting partitions..." + mount "$root_part" /mnt + + if [ -n "$boot_part" ]; then + mkdir -p /mnt/boot + mount "$boot_part" /mnt/boot + fi + + if [ -n "$efi_part" ]; then + mkdir -p /mnt/boot/efi + mount "$efi_part" /mnt/boot/efi + fi + + log_success "Manual partition setup complete" +} + +# Custom interactive partitioning +custom_partition() { + local disk="$1" + + log_info "Starting custom partitioning with gdisk/fdisk" + log_warn "This will launch an interactive partitioning tool" + echo + echo "Guidelines:" + echo " - UEFI systems: Create EFI (512MB), boot (512MB), and root partitions" + echo " - BIOS systems: Create boot (512MB) and root partitions" + echo " - Consider leaving space for swap or using a swap file" + echo + read -p "${CYAN}Press Enter to continue...${RESET}" + + # Launch appropriate tool + if command -v gdisk >/dev/null; then + gdisk "$disk" + elif command -v fdisk >/dev/null; then + fdisk "$disk" + else + log_error "No partitioning tool available" + exit 1 + fi + + # After partitioning, guide through formatting + log_info "Partitioning complete. Now format and mount partitions." + manual_partition +} + +# Validate mount points +validate_mounts() { + log_info "Validating mount points..." + + # Check root is mounted + if ! mountpoint -q /mnt; then + log_error "Root filesystem not mounted at /mnt" + return 1 + fi + + # Check boot for UEFI + if [ "$(detect_boot_mode)" = "uefi" ]; then + if ! mountpoint -q /mnt/boot/efi && ! mountpoint -q /mnt/boot; then + log_error "EFI partition not mounted" + return 1 + fi + fi + + log_success "Mount points validated" + return 0 +} + +# Generate hardware configuration +generate_hardware_config() { + log_info "Generating NixOS hardware configuration..." + nixos-generate-config --root /mnt + log_success "Hardware configuration generated" +} + +# Main partitioning flow +main() { + echo + log_info "${BOLD}Omnixient Disk Partitioning Module${RESET}" + echo + + # Check if running as root + if [ "$EUID" -ne 0 ]; then + log_error "This script must be run as root" + exit 1 + fi + + # Detect VM environment + if detect_vm; then + log_info "VM environment detected - looking for vda devices" + fi + + # Check if already mounted + if mountpoint -q /mnt; then + log_warn "/mnt is already mounted" + read -p "${YELLOW}Unmount and continue? (y/N): ${RESET}" unmount + if [ "$unmount" = "y" ]; then + umount -R /mnt 2>/dev/null || true + swapoff -a 2>/dev/null || true + else + log_info "Using existing mount points" + validate_mounts && generate_hardware_config + exit 0 + fi + fi + + # Select partitioning method + local scheme=$(select_partition_scheme) + + case $scheme in + automatic) + local disk=$(select_disk) + + # Ask about encryption + local encrypt="false" + read -p "${CYAN}Enable LUKS encryption? (y/N): ${RESET}" use_encryption + if [ "$use_encryption" = "y" ]; then + encrypt="true" + fi + + automatic_partition "$disk" "$encrypt" + ;; + + manual) + manual_partition + ;; + + custom) + local disk=$(select_disk) + custom_partition "$disk" + ;; + esac + + # Validate and generate config + if validate_mounts; then + generate_hardware_config + + echo + log_success "${BOLD}Partitioning complete!${RESET}" + echo + log_info "Next steps:" + echo " 1. Install Omnixient configuration to /mnt/etc/nixos" + echo " 2. Run nixos-install" + echo " 3. Set root password when prompted" + echo " 4. Reboot into your new system" + echo + + # Save partition info for installer + if [ -n "$PARTITION_INFO" ]; then + echo "$PARTITION_INFO" > /tmp/omni-partition-info + log_info "Partition information saved to /tmp/omni-partition-info" + fi + else + log_error "Mount validation failed" + exit 1 + fi +} + +# Run if executed directly +if [ "${BASH_SOURCE[0]}" = "${0}" ]; then + main "$@" +fi \ No newline at end of file diff --git a/modules/scripts.nix b/modules/scripts.nix new file mode 100644 index 0000000..d235439 --- /dev/null +++ b/modules/scripts.nix @@ -0,0 +1,373 @@ +{ + config, + pkgs, + lib, + ... +}: + +# Essential system utility scripts for Omnixient +# Convenient scripts for system management and productivity + +let + inherit (lib) mkIf; + cfg = config.omni; + omni = config.omni.lib; +in +{ + config = mkIf (cfg.enable or true) { + # System utility scripts + environment.systemPackages = [ + # System information and monitoring + (omni.makeScript "omni-sysinfo" "Show comprehensive system information" '' + echo "╭─────────────────── Omnixient System Info ───────────────────╮" + echo "│" + echo "│ 💻 System: $(hostname) ($(uname -m))" + echo "│ 🐧 OS: NixOS $(nixos-version)" + echo "│ 🎨 Theme: ${cfg.theme}" + echo "│ 👤 User: ${cfg.user}" + echo "│ 🏠 Preset: ${cfg.preset or "custom"}" + echo "│" + echo "│ 🔧 Uptime: $(uptime -p)" + echo "│ 💾 Memory: $(free -h | awk 'NR==2{printf "%.1f/%.1fGB (%.0f%%)", $3/1024/1024, $2/1024/1024, $3*100/$2}')" + echo "│ 💽 Disk: $(df -h / | awk 'NR==2{printf "%s/%s (%s)", $3, $2, $5}')" + echo "│ 🌡️ Load: $(uptime | sed 's/.*load average: //')" + echo "│" + echo "│ 📦 Packages: $(nix-env -qa --installed | wc -l) installed" + echo "│ 🗂️ Generations: $(sudo nix-env -p /nix/var/nix/profiles/system --list-generations | wc -l) total" + echo "│" + echo "╰───────────────────────────────────────────────────────────╯" + '') + + # Quick system maintenance + (omni.makeScript "omni-clean" "Clean system (garbage collect, optimize)" '' + echo "🧹 Cleaning Omnixient system..." + + echo " ├─ Collecting garbage..." + sudo nix-collect-garbage -d + + echo " ├─ Optimizing store..." + sudo nix-store --optimize + + echo " ├─ Clearing user caches..." + rm -rf ~/.cache/thumbnails/* + rm -rf ~/.cache/mesa_shader_cache/* + rm -rf ~/.cache/fontconfig/* + + echo " ├─ Clearing logs..." + sudo journalctl --vacuum-time=7d + + echo " └─ Cleaning complete!" + + # Show space saved + echo + echo "💾 Disk usage:" + df -h / | awk 'NR==2{printf " Root: %s/%s (%s used)\n", $3, $2, $5}' + du -sh /nix/store | awk '{printf " Nix Store: %s\n", $1}' + '') + + # Update system and flake + (omni.makeScript "omni-update" "Update system and flake inputs" '' + echo "📦 Updating Omnixient system..." + + cd /etc/nixos || { echo "❌ Not in /etc/nixos directory"; exit 1; } + + echo " ├─ Updating flake inputs..." + sudo nix flake update + + echo " ├─ Rebuilding system..." + nh os switch /etc/nixos + + echo " └─ Update complete!" + + # Show new generation + echo + echo "🎯 Current generation:" + sudo nix-env -p /nix/var/nix/profiles/system --list-generations | tail -1 + '') + + # Rebuild system configuration + (omni.makeScript "omni-rebuild" "Rebuild NixOS configuration" '' + echo "🔨 Rebuilding Omnixient configuration..." + + cd /etc/nixos || { echo "❌ Not in /etc/nixos directory"; exit 1; } + + # Pull latest changes if the tree is clean + if git diff --quiet && git diff --cached --quiet; then + echo "📥 Pulling latest changes..." + sudo git pull --ff-only || echo "⚠️ Pull failed — continuing with local config" + else + echo "⚠️ Uncommitted changes — skipping pull" + echo " Commit or stash them to pull on next rebuild" + echo + fi + + # Build and switch via nh (Rust nixos-rebuild frontend; elevates itself) + nh os switch /etc/nixos + + if [ $? -eq 0 ]; then + echo "✅ Rebuild successful!" + echo "🎯 Active generation: $(sudo nix-env -p /nix/var/nix/profiles/system --list-generations | tail -1)" + else + echo "❌ Rebuild failed!" + exit 1 + fi + '') + + # Test build without switching + (omni.makeScript "omni-test" "Test build configuration without switching" '' + echo "🧪 Testing Omnixient configuration..." + + cd /etc/nixos || { echo "❌ Not in /etc/nixos directory"; exit 1; } + + # Build without switching + sudo nixos-rebuild build --flake .#omni + + if [ $? -eq 0 ]; then + echo "✅ Build test successful!" + echo " Configuration is valid and ready for deployment" + else + echo "❌ Build test failed!" + echo " Fix configuration errors before rebuilding" + exit 1 + fi + '') + + # Search for packages + (omni.makeScript "omni-search" "Search for NixOS packages" '' + if [ -z "$1" ]; then + echo "Usage: omni-search " + echo "Search for packages in nixpkgs" + exit 1 + fi + + echo "🔍 Searching for packages matching '$1'..." + echo + + # Search in nixpkgs + nix search nixpkgs "$1" | head -20 + + echo + echo "💡 Install with: nix-env -iA nixpkgs." + echo " Or add to your configuration.nix" + '') + + # Theme management + (omni.makeScript "omni-theme" "Switch Omnixient theme" '' + if [ -z "$1" ]; then + echo "🎨 Available Omnixient themes:" + echo " tokyo-night - Dark theme with vibrant colors" + echo " catppuccin - Pastel theme with modern aesthetics" + echo " gruvbox - Retro theme with warm colors" + echo " nord - Arctic theme with cool colors" + echo " everforest - Green forest theme" + echo " rose-pine - Cozy theme with muted colors" + echo " kanagawa - Japanese-inspired theme" + echo " catppuccin-latte - Light catppuccin variant" + echo " matte-black - Minimalist dark theme" + echo " osaka-jade - Jade green accent theme" + echo " ristretto - Coffee-inspired warm theme" + echo + echo "Usage: omni-theme " + echo "Current theme: ${cfg.theme}" + exit 0 + fi + + THEME="$1" + CONFIG_FILE="/etc/nixos/configuration.nix" + + echo "🎨 Switching to theme: $THEME" + + # Validate theme exists + if [ ! -f "/etc/nixos/modules/themes/$THEME.nix" ]; then + echo "❌ Theme '$THEME' not found!" + echo " Available themes listed above" + exit 1 + fi + + # Update configuration.nix + sudo sed -i "s/currentTheme = \".*\";/currentTheme = \"$THEME\";/" "$CONFIG_FILE" + + echo " ├─ Updated configuration..." + echo " ├─ Rebuilding system..." + + # Rebuild with new theme + cd /etc/nixos && nh os switch /etc/nixos + + if [ $? -eq 0 ]; then + echo " ├─ Theme switched successfully!" + echo " └─ Updating Plymouth boot theme..." + + # Update Plymouth theme to match + sudo omni-plymouth-theme "$THEME" 2>/dev/null || echo " (Plymouth theme update may require reboot)" + + echo "✅ Now using theme: $THEME" + echo "💡 Reboot to see the new boot splash screen" + else + echo "❌ Failed to apply theme!" + # Revert change + sudo sed -i "s/currentTheme = \"$THEME\";/currentTheme = \"${cfg.theme}\";/" "$CONFIG_FILE" + exit 1 + fi + '') + + # Hardware information + (omni.makeScript "omni-hardware" "Show detailed hardware information" '' + echo "🖥️ Omnixient Hardware Information" + echo "═══════════════════════════════════" + echo + + echo "💻 System:" + echo " Model: $(cat /sys/class/dmi/id/product_name 2>/dev/null || echo 'Unknown')" + echo " Manufacturer: $(cat /sys/class/dmi/id/sys_vendor 2>/dev/null || echo 'Unknown')" + echo " BIOS: $(cat /sys/class/dmi/id/bios_version 2>/dev/null || echo 'Unknown')" + echo + + echo "🧠 CPU:" + lscpu | grep -E "Model name|Architecture|CPU\(s\)|Thread|Core|MHz" + echo + + echo "💾 Memory:" + free -h + echo + + echo "💽 Storage:" + lsblk -f + echo + + echo "📺 Graphics:" + lspci | grep -i vga + lspci | grep -i 3d + echo + + echo "🔊 Audio:" + lspci | grep -i audio + echo + + echo "🌐 Network:" + ip addr show | grep -E "inet |link/" + '') + + # Service management + (omni.makeScript "omni-services" "Manage Omnixient services" '' + case "$1" in + "status") + echo "📊 Omnixient Service Status" + echo "═══════════════════════" + + services=( + "display-manager" + "networkmanager" + "pipewire" + "bluetooth" + "hypridle" + ) + + for service in "''${services[@]}"; do + status=$(systemctl is-active $service 2>/dev/null || echo "inactive") + case $status in + "active") icon="✅" ;; + "inactive") icon="❌" ;; + *) icon="⚠️ " ;; + esac + printf " %s %s: %s\n" "$icon" "$service" "$status" + done + ;; + "restart") + if [ -z "$2" ]; then + echo "Usage: omni-services restart " + exit 1 + fi + echo "🔄 Restarting $2..." + sudo systemctl restart "$2" + ;; + "logs") + if [ -z "$2" ]; then + echo "Usage: omni-services logs " + exit 1 + fi + journalctl -u "$2" -f + ;; + *) + echo "📋 Omnixient Service Management" + echo + echo "Usage: omni-services [service]" + echo + echo "Commands:" + echo " status - Show status of key services" + echo " restart - Restart a service" + echo " logs - View service logs" + ;; + esac + '') + + # Quick configuration editing + (omni.makeScript "omni-config" "Quick access to configuration files" '' + case "$1" in + "main"|"") + echo "📝 Opening main configuration..." + ''${EDITOR:-nano} /etc/nixos/configuration.nix + ;; + "hyprland") + echo "📝 Opening Hyprland configuration..." + ''${EDITOR:-nano} /etc/nixos/modules/desktop/hyprland.nix + ;; + "theme") + echo "📝 Opening theme configuration..." + ''${EDITOR:-nano} /etc/nixos/modules/themes/${cfg.theme}.nix + ;; + "packages") + echo "📝 Opening package configuration..." + ''${EDITOR:-nano} /etc/nixos/modules/packages.nix + ;; + *) + echo "📝 Omnixient Configuration Files" + echo + echo "Usage: omni-config " + echo + echo "Targets:" + echo " main - Main configuration.nix file" + echo " hyprland - Hyprland window manager config" + echo " theme - Current theme configuration" + echo " packages - Package configuration" + echo + echo "Files will open in: ''${EDITOR:-nano}" + ;; + esac + '') + + # Backup and restore + (omni.makeScript "omni-backup" "Backup Omnixient configuration" '' + BACKUP_DIR="$HOME/omni-backups" + TIMESTAMP=$(date +%Y%m%d_%H%M%S) + BACKUP_FILE="$BACKUP_DIR/omni_$TIMESTAMP.tar.gz" + + echo "💾 Creating Omnixient configuration backup..." + + mkdir -p "$BACKUP_DIR" + + # Create backup archive + sudo tar -czf "$BACKUP_FILE" \ + -C /etc \ + nixos/ \ + --exclude=nixos/hardware-configuration.nix + + # Also backup user configs that matter + if [ -d "$HOME/.config" ]; then + tar -czf "$BACKUP_DIR/userconfig_$TIMESTAMP.tar.gz" \ + -C "$HOME" \ + .config/hypr/ \ + .config/waybar/ \ + .config/mako/ \ + .config/walker/ 2>/dev/null || true + fi + + echo "✅ Backup created:" + echo " System: $BACKUP_FILE" + echo " User: $BACKUP_DIR/userconfig_$TIMESTAMP.tar.gz" + echo + echo "📊 Backup size:" + du -sh "$BACKUP_DIR"/*"$TIMESTAMP"* | sed 's/^/ /' + '') + ]; + }; +} diff --git a/modules/users.nix b/modules/users.nix new file mode 100644 index 0000000..223d11e --- /dev/null +++ b/modules/users.nix @@ -0,0 +1,124 @@ +{ + config, + pkgs, + lib, + settings, + ... +}: + +let + cfg = config.omni; +in +{ + # User account configuration + users.users.${cfg.user} = { + isNormalUser = true; + description = "Omnixient User"; + extraGroups = [ + "wheel" + "networkmanager" + "audio" + "video" + "docker" + "libvirtd" + "input" + "dialout" + ]; + shell = pkgs.bash; + + # Set initial password (should be changed on first login) + # pragma: allowlist secret + initialPassword = "omni"; + + # SSH public keys authorized for this account — add yours in settings.nix. + openssh.authorizedKeys.keys = settings.sshKeys; + }; + + # Additional user-related configurations + users = { + # Allow users in wheel group to use sudo + mutableUsers = true; + + # Default shell + defaultUserShell = pkgs.bash; + }; + + # Security settings for users + security.pam.services = { + # Enable fingerprint authentication + login.fprintAuth = false; + sudo.fprintAuth = false; + + # Enable U2F authentication (for YubiKey etc.) + login.u2fAuth = false; + sudo.u2fAuth = false; + }; + + # Home directory encryption (optional) + # security.pam.enableEcryptfs = true; + + # Automatic login (disable for production) + services.displayManager.autoLogin = { + enable = false; + user = cfg.user; + }; + + # User environment + environment.systemPackages = with pkgs; [ + # User management tools + shadow # provides passwd, useradd, etc. + + # Session management + systemd # provides loginctl + + # User info + bsd-finger + idutils + ]; + + # User-specific services + systemd.user.services = { + # Example: Syncthing for the user + # syncthing = { + # description = "Syncthing for ${cfg.user}"; + # wantedBy = [ "default.target" ]; + # serviceConfig = { + # ExecStart = "${pkgs.syncthing}/bin/syncthing serve --no-browser --no-restart --logflags=0"; + # Restart = "on-failure"; + # RestartSec = 10; + # }; + # }; + }; + + # Shell initialization for all users + programs.bash.interactiveShellInit = '' + # User-specific aliases + alias profile='nvim ~/.bashrc' + alias reload='source ~/.bashrc' + + # Safety aliases + alias rm='rm -i' + alias cp='cp -i' + alias mv='mv -i' + + # Directory shortcuts + alias home='cd ~' + alias downloads='cd ~/Downloads' + alias documents='cd ~/Documents' + alias projects='cd ~/Projects' + + # Create standard directories if they don't exist + mkdir -p ~/Downloads ~/Documents ~/Projects ~/Pictures ~/Videos ~/Music + ''; + + # XDG Base Directory specification + environment.variables = { + XDG_CACHE_HOME = "$HOME/.cache"; + XDG_CONFIG_HOME = "$HOME/.config"; + XDG_DATA_HOME = "$HOME/.local/share"; + XDG_STATE_HOME = "$HOME/.local/state"; + }; + + # User quotas (optional) + # fileSystems."/home".options = [ "usrquota" ]; +} diff --git a/modules/walker.nix b/modules/walker.nix new file mode 100644 index 0000000..5e14269 --- /dev/null +++ b/modules/walker.nix @@ -0,0 +1,450 @@ +{ + config, + pkgs, + lib, + ... +}: + +# Walker app launcher configuration for Omnixient +# Modern replacement for Rofi with better Wayland integration + +let + inherit (lib) mkIf; + cfg = config.omni; + omni = { + makeScript = + name: description: script: + pkgs.writeShellScriptBin name '' + #!/usr/bin/env bash + # ${description} + set -euo pipefail + ${script} + ''; + }; +in +{ + config = mkIf (cfg.enable or true) { + # Add convenience scripts to system packages + environment.systemPackages = [ + # Convenience scripts + (omni.makeScript "omni-launcher" "Launch Omnixient app launcher" '' + walker --config ~/.config/walker/config.json --css ~/.config/walker/themes/style.css + '') + + (omni.makeScript "omni-run" "Quick command runner" '' + walker --modules runner --config ~/.config/walker/config.json --css ~/.config/walker/themes/style.css + '') + + (omni.makeScript "omni-apps" "Application launcher" '' + walker --modules applications --config ~/.config/walker/config.json --css ~/.config/walker/themes/style.css + '') + + (omni.makeScript "omni-files" "File finder" '' + walker --modules finder --config ~/.config/walker/config.json --css ~/.config/walker/themes/style.css + '') + ]; + + # Create Walker configuration + environment.etc."omni/walker/config.json".text = builtins.toJSON { + # General configuration + placeholder = "Search applications, files, and more..."; + fullscreen = false; + layer = "overlay"; + modules = [ + { + name = "applications"; + src = "applications"; + transform = "uppercase"; + } + { + name = "runner"; + src = "runner"; + } + { + name = "websearch"; + src = "websearch"; + engines = [ + { + name = "Google"; + url = "https://www.google.com/search?q=%s"; + icon = "web-browser"; + } + { + name = "GitHub"; + url = "https://github.com/search?q=%s"; + icon = "github"; + } + { + name = "NixOS Packages"; + url = "https://search.nixos.org/packages?query=%s"; + icon = "nix-snowflake"; + } + ]; + } + { + name = "finder"; + src = "finder"; + dirs = [ + "/home/${cfg.user}" + "/home/${cfg.user}/Documents" + "/home/${cfg.user}/Downloads" + "/home/${cfg.user}/Desktop" + ]; + } + { + name = "calc"; + src = "calc"; + } + ]; + + # UI Configuration + ui = { + anchors = { + top = false; + left = true; + right = false; + bottom = false; + }; + margin = { + top = 100; + bottom = 0; + left = 100; + right = 0; + }; + width = 600; + height = 500; + show_initial_entries = true; + show_search_text = true; + scroll_height = 300; + }; + + # Search configuration + search = { + delay = 100; + placeholder = "Type to search..."; + force_keyboard_focus = true; + }; + + # List configuration + list = { + height = 200; + always_show = true; + max_entries = 50; + }; + + # Icons + icons = { + theme = "Papirus"; + size = 32; + }; + + # Theming based on current theme + theme = + if cfg.theme == "gruvbox" then + "gruvbox" + else if cfg.theme == "nord" then + "nord" + else if cfg.theme == "catppuccin" then + "catppuccin" + else if cfg.theme == "tokyo-night" then + "tokyo-night" + else + "default"; + }; + + # Create Walker CSS theme files + environment.etc."omni/walker/themes/gruvbox.css".text = '' + * { + color: #ebdbb2; + font-family: "JetBrainsMono Nerd Font", monospace; + font-size: 14px; + } + + #window { + background-color: rgba(40, 40, 40, 0.95); + } + + window { + background-color: rgba(40, 40, 40, 0.95); + border: 2px solid #a89984; + border-radius: 12px; + } + + box { + background-color: rgba(40, 40, 40, 0.95); + } + + #search { + background-color: #3c3836; + border: 1px solid #665c54; + border-radius: 8px; + padding: 8px 12px; + margin: 12px; + color: #ebdbb2; + } + + #search:focus { + border-color: #d79921; + } + + #list { + background-color: rgba(40, 40, 40, 0.95); + padding: 0 12px 12px 12px; + } + + .item { + padding: 8px 12px; + border-radius: 6px; + margin-bottom: 2px; + } + + .item:selected { + background-color: #504945; + color: #fbf1c7; + } + + .item:hover { + background-color: #3c3836; + } + + .item .icon { + margin-right: 12px; + min-width: 32px; + } + + .item .text { + font-weight: normal; + } + + .item .sub { + font-size: 12px; + color: #a89984; + } + ''; + + environment.etc."omni/walker/themes/nord.css".text = '' + * { + color: #eceff4; + background-color: #2e3440; + font-family: "JetBrainsMono Nerd Font", monospace; + font-size: 14px; + } + + window { + background-color: rgba(46, 52, 64, 0.95); + border: 2px solid #4c566a; + border-radius: 12px; + } + + #search { + background-color: #3b4252; + border: 1px solid #4c566a; + border-radius: 8px; + padding: 8px 12px; + margin: 12px; + color: #eceff4; + } + + #search:focus { + border-color: #5e81ac; + } + + #list { + background-color: transparent; + padding: 0 12px 12px 12px; + } + + .item { + padding: 8px 12px; + border-radius: 6px; + margin-bottom: 2px; + } + + .item:selected { + background-color: #434c5e; + color: #eceff4; + } + + .item:hover { + background-color: #3b4252; + } + + .item .icon { + margin-right: 12px; + min-width: 32px; + } + + .item .text { + font-weight: normal; + } + + .item .sub { + font-size: 12px; + color: #81a1c1; + } + ''; + + environment.etc."omni/walker/themes/catppuccin.css".text = '' + * { + color: #cdd6f4; + background-color: #1e1e2e; + font-family: "JetBrainsMono Nerd Font", monospace; + font-size: 14px; + } + + window { + background-color: rgba(30, 30, 46, 0.95); + border: 2px solid #6c7086; + border-radius: 12px; + } + + #search { + background-color: #313244; + border: 1px solid #45475a; + border-radius: 8px; + padding: 8px 12px; + margin: 12px; + color: #cdd6f4; + } + + #search:focus { + border-color: #89b4fa; + } + + #list { + background-color: transparent; + padding: 0 12px 12px 12px; + } + + .item { + padding: 8px 12px; + border-radius: 6px; + margin-bottom: 2px; + } + + .item:selected { + background-color: #45475a; + color: #cdd6f4; + } + + .item:hover { + background-color: #313244; + } + + .item .icon { + margin-right: 12px; + min-width: 32px; + } + + .item .text { + font-weight: normal; + } + + .item .sub { + font-size: 12px; + color: #89dceb; + } + ''; + + environment.etc."omni/walker/themes/tokyo-night.css".text = '' + * { + color: #c0caf5; + background-color: #1a1b26; + font-family: "JetBrainsMono Nerd Font", monospace; + font-size: 14px; + } + + window { + background-color: rgba(26, 27, 38, 0.95); + border: 2px solid #414868; + border-radius: 12px; + } + + #search { + background-color: #24283b; + border: 1px solid #414868; + border-radius: 8px; + padding: 8px 12px; + margin: 12px; + color: #c0caf5; + } + + #search:focus { + border-color: #7aa2f7; + } + + #list { + background-color: transparent; + padding: 0 12px 12px 12px; + } + + .item { + padding: 8px 12px; + border-radius: 6px; + margin-bottom: 2px; + } + + .item:selected { + background-color: #414868; + color: #c0caf5; + } + + .item:hover { + background-color: #24283b; + } + + .item .icon { + margin-right: 12px; + min-width: 32px; + } + + .item .text { + font-weight: normal; + } + + .item .sub { + font-size: 12px; + color: #7dcfff; + } + ''; + + # Add to user environment + home-manager.users.${config.omni.user} = { + # Walker launcher via official home-manager module + programs.walker = { + enable = true; + runAsService = true; + }; + + # Walker config and theme CSS + xdg.configFile."walker/config.json".source = + config.environment.etc."omni/walker/config.json".source; + xdg.configFile."walker/themes/style.css".source = + config.environment.etc."omni/walker/themes/${cfg.theme}.css".source; + + # Add shell aliases + programs.bash.shellAliases = { + launcher = "walker"; + run = "walker --modules runner"; + apps = "walker --modules applications"; + files = "walker --modules finder"; + }; + + programs.zsh.shellAliases = { + launcher = "walker"; + run = "walker --modules runner"; + apps = "walker --modules applications"; + files = "walker --modules finder"; + }; + + programs.fish.shellAliases = { + launcher = "walker"; + run = "walker --modules runner"; + apps = "walker --modules applications"; + files = "walker --modules finder"; + }; + }; + + # Convenience scripts are now consolidated above + }; +}