├── wallpapers ├── .gitkeep ├── aishot-2602.jpg └── README.md ├── .gitignore ├── screenshotv4.jpg ├── hosts ├── nixstation │ ├── wallpaper.jpg │ ├── waybar-test.json │ ├── hyprpaper.conf │ ├── scripts │ │ ├── waybar-reboot.sh │ │ ├── launch-communication.sh │ │ ├── waybar-dunst.sh │ │ ├── waybar-launcher.sh │ │ ├── waybar-public-ip.sh │ │ ├── waybar-btc.py │ │ ├── waybar-mpris.sh │ │ ├── hyprlock-btc.sh │ │ ├── waybar-per-monitor.sh │ │ ├── launch-development.sh │ │ ├── waybar-btc-coingecko.sh │ │ ├── waybar-timezones.sh │ │ ├── waybar-clock-tooltip.sh │ │ ├── waybar-clock-multizone.sh │ │ ├── waybar-crypto-cmc.py │ │ ├── waybar-clock.sh │ │ ├── waybar-weather.sh │ │ ├── waybar-brightness.sh │ │ ├── waybar-amd-gpu.sh │ │ ├── rofi-brightness.sh │ │ └── logitech-bluetooth.sh │ ├── waybar-test.css │ ├── waybar-minimal.json │ ├── hypridle.conf │ ├── waybar-simple.css │ ├── hyprlock.conf │ ├── waybar-simple-dp1.json │ ├── waybar-simple-dp2.json │ ├── waybar-simple-hdmi.json │ ├── waybar-simple.json │ ├── fonts.conf │ ├── hyprland.conf │ ├── waybar.css │ ├── waybar-multi.json │ ├── waybar.json │ └── hardware-configuration.nix ├── rvbee │ ├── aesthetic_8_bit_art-wallpaper-3840x2160.jpg │ ├── hyprpaper.conf │ ├── scripts │ │ ├── waybar-reboot.sh │ │ ├── waybar-dunst.sh │ │ ├── waybar-public-ip.sh │ │ ├── waybar-btc.py │ │ ├── waybar-mpris.sh │ │ ├── hyprlock-btc.sh │ │ ├── waybar-btc-coingecko.sh │ │ ├── waybar-crypto-cmc.py │ │ ├── waybar-weather.sh │ │ ├── waybar-brightness.sh │ │ ├── waybar-amd-gpu.sh │ │ └── rofi-brightness.sh │ ├── hypridle.conf │ ├── hyprlock.conf │ ├── hyprland.conf │ ├── hardware-configuration.nix │ ├── waybar.css │ └── waybar.json └── nixbook │ ├── hyprpaper.conf │ ├── scripts │ ├── waybar-reboot.sh │ ├── waybar-dunst.sh │ ├── waybar-public-ip.sh │ ├── waybar-btc.py │ ├── waybar-mpris.sh │ ├── hyprlock-btc.sh │ ├── waybar-btc-coingecko.sh │ ├── waybar-crypto-cmc.py │ ├── waybar-weather.sh │ ├── waybar-brightness.sh │ ├── waybar-amd-gpu.sh │ ├── rofi-power-profile.sh │ ├── rofi-brightness.sh │ └── waybar-wifi.sh │ ├── hypridle.conf │ ├── hyprlock.conf │ ├── hyprland.conf │ ├── hardware-configuration.nix │ ├── waybar.css │ ├── TAILSCALE_SETUP.md │ ├── waybar.json │ └── POWER_MANAGEMENT.md ├── configs ├── hyprpaper-default.conf ├── waybar-scripts │ ├── waybar-reboot.sh │ ├── waybar-dunst.sh │ ├── waybar-public-ip.sh │ ├── waybar-mpris.sh │ ├── waybar-btc-coingecko.sh │ ├── waybar-weather.sh │ ├── waybar-amd-gpu.sh │ └── rofi-brightness.sh ├── hyprland-default.conf ├── hyprland-monitors-nixbook.conf ├── hypridle-default.conf ├── hyprland-monitors-rvbee.conf ├── waybar-default.css ├── hyprlock-default.conf ├── waybar-default.json ├── hyprland-monitors-rvbee-120hz.conf ├── waybar-rvbee.css ├── hyprland-monitors-nixstation.conf └── waybar-rvbee.json ├── modules └── shared │ ├── default.nix │ ├── system.nix │ ├── desktop.nix │ ├── services.nix │ ├── packages.nix │ ├── user.nix │ └── waybar.nix ├── scripts ├── waybar-per-monitor.sh ├── waybar-switch.sh └── setup-monitors.sh ├── ~ └── .local │ └── bin │ └── switch-oh-my-posh-theme ├── flake.nix ├── docs ├── monitor-keybindings.md ├── KITTY_DEFAULT_TERMINAL_SETUP.md ├── KITTY_OH_MY_POSH_SETUP.md ├── CONFIGURATION_GUIDE.md ├── RVBEE_UPDATE_SUMMARY.md └── MIGRATION_PLAN.md └── switch-oh-my-posh-theme.sh /wallpapers/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | result-* 3 | -------------------------------------------------------------------------------- /screenshotv4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisLAS/hyprvibe/HEAD/screenshotv4.jpg -------------------------------------------------------------------------------- /wallpapers/aishot-2602.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisLAS/hyprvibe/HEAD/wallpapers/aishot-2602.jpg -------------------------------------------------------------------------------- /hosts/nixstation/wallpaper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisLAS/hyprvibe/HEAD/hosts/nixstation/wallpaper.jpg -------------------------------------------------------------------------------- /hosts/rvbee/aesthetic_8_bit_art-wallpaper-3840x2160.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisLAS/hyprvibe/HEAD/hosts/rvbee/aesthetic_8_bit_art-wallpaper-3840x2160.jpg -------------------------------------------------------------------------------- /configs/hyprpaper-default.conf: -------------------------------------------------------------------------------- 1 | # Hyprpaper default configuration 2 | splash = false 3 | ipc = true 4 | preload = __WALLPAPER__ 5 | wallpaper = ,__WALLPAPER__ 6 | 7 | 8 | -------------------------------------------------------------------------------- /configs/waybar-scripts/waybar-reboot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | choice=$(printf "No\nYes" | rofi -dmenu -p "Reboot?" -i) 5 | if [[ "${choice:-}" == "Yes" ]]; then 6 | systemctl reboot 7 | fi 8 | 9 | 10 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 38, 5 | "modules-right": ["clock"], 6 | "clock": { 7 | "format": "TIME {:%H:%M}", 8 | "tooltip": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /configs/hyprland-default.conf: -------------------------------------------------------------------------------- 1 | # Hyprvibe default main configuration 2 | # Sources the shared base config. Provide monitors via hyprvibe.hyprland.monitorsFile 3 | 4 | source=~/.config/hypr/hyprland-base.conf 5 | source=~/.config/hypr/hyprland-local.conf 6 | 7 | 8 | -------------------------------------------------------------------------------- /hosts/rvbee/hyprpaper.conf: -------------------------------------------------------------------------------- 1 | # Hyprpaper Configuration 2 | # Enable splash screen 3 | splash = false 4 | 5 | # Enable IPC socket 6 | ipc = true 7 | 8 | # Preload wallpapers 9 | preload = __WALLPAPER__ 10 | 11 | # Set default wallpaper for all monitors 12 | wallpaper = ,__WALLPAPER__ -------------------------------------------------------------------------------- /hosts/nixbook/hyprpaper.conf: -------------------------------------------------------------------------------- 1 | # Hyprpaper Configuration 2 | # Enable splash screen 3 | splash = false 4 | 5 | # Enable IPC socket 6 | ipc = true 7 | 8 | # Preload wallpapers 9 | preload = __WALLPAPER__ 10 | 11 | # Set default wallpaper for all monitors 12 | wallpaper = ,__WALLPAPER__ -------------------------------------------------------------------------------- /hosts/nixstation/hyprpaper.conf: -------------------------------------------------------------------------------- 1 | # Hyprpaper Configuration 2 | # Enable splash screen 3 | splash = false 4 | 5 | # Enable IPC socket 6 | ipc = true 7 | 8 | # Preload wallpapers 9 | preload = __WALLPAPER__ 10 | 11 | # Set default wallpaper for all monitors 12 | wallpaper = ,__WALLPAPER__ -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-reboot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Simple GUI confirm using rofi (already installed) 5 | choice=$(printf "No\nYes" | rofi -dmenu -p "Reboot?" -i) 6 | if [[ "${choice:-}" == "Yes" ]]; then 7 | systemctl reboot 8 | fi 9 | 10 | 11 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-reboot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Simple GUI confirm using rofi (already installed) 5 | choice=$(printf "No\nYes" | rofi -dmenu -p "Reboot?" -i) 6 | if [[ "${choice:-}" == "Yes" ]]; then 7 | systemctl reboot 8 | fi 9 | 10 | 11 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-reboot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Simple GUI confirm using rofi (already installed) 5 | choice=$(printf "No\nYes" | rofi -dmenu -p "Reboot?" -i) 6 | if [[ "${choice:-}" == "Yes" ]]; then 7 | systemctl reboot 8 | fi 9 | 10 | 11 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar-test.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: "DejaVu Sans", sans-serif; 3 | font-size: 14px; 4 | color: #ffffff; 5 | } 6 | 7 | window#waybar { 8 | background: rgba(0, 0, 0, 0.8); 9 | color: #ffffff; 10 | } 11 | 12 | #clock { 13 | padding: 0 10px; 14 | background: transparent; 15 | } 16 | -------------------------------------------------------------------------------- /configs/hyprland-monitors-nixbook.conf: -------------------------------------------------------------------------------- 1 | # Nixbook Monitor Configuration 2 | # Auto-detect primary monitor - adjust as needed for your nixbook 3 | # To find your monitor name: hyprctl monitors 4 | # Example: monitor=eDP-1,1920x1080@60,auto,1 5 | 6 | # Auto-detect (comment out and specify manually if needed) 7 | monitor=,preferred,auto,1 8 | -------------------------------------------------------------------------------- /configs/hypridle-default.conf: -------------------------------------------------------------------------------- 1 | # Hypridle default configuration 2 | listener { 3 | timeout = 2700 4 | on-timeout = hyprctl dispatch dpms off 5 | on-resume = hyprctl dispatch dpms on 6 | } 7 | 8 | general { 9 | lock_cmd = pidof hyprlock || hyprlock 10 | before_sleep_cmd = loginctl lock-session 11 | after_sleep_cmd = hyprctl dispatch dpms on 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /configs/hyprland-monitors-rvbee.conf: -------------------------------------------------------------------------------- 1 | # Rvbee Monitor Configuration (1 monitor) 2 | # This file contains monitor-specific settings for rvbee 3 | 4 | # Monitor configuration for single monitor setup 5 | monitor=,preferred,auto,auto 6 | 7 | # Single monitor specific settings 8 | # No workspace assignments needed for single monitor 9 | # All workspaces will be available on the single monitor 10 | -------------------------------------------------------------------------------- /hosts/nixbook/hypridle.conf: -------------------------------------------------------------------------------- 1 | # hypridle configuration 2 | listener { 3 | # 45 minutes: blank displays via DPMS off 4 | timeout = 2700 5 | on-timeout = hyprctl dispatch dpms off 6 | on-resume = hyprctl dispatch dpms on 7 | } 8 | 9 | general { 10 | lock_cmd = pidof hyprlock || hyprlock 11 | before_sleep_cmd = loginctl lock-session 12 | after_sleep_cmd = hyprctl dispatch dpms on 13 | } 14 | -------------------------------------------------------------------------------- /hosts/rvbee/hypridle.conf: -------------------------------------------------------------------------------- 1 | # hypridle configuration 2 | listener { 3 | # 45 minutes: blank displays via DPMS off 4 | timeout = 2700 5 | on-timeout = hyprctl dispatch dpms off 6 | on-resume = hyprctl dispatch dpms on 7 | } 8 | 9 | general { 10 | lock_cmd = pidof hyprlock || hyprlock 11 | before_sleep_cmd = loginctl lock-session 12 | after_sleep_cmd = hyprctl dispatch dpms on 13 | } 14 | -------------------------------------------------------------------------------- /configs/waybar-default.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: "FiraCode Nerd Font", monospace; 3 | font-size: 12pt; 4 | } 5 | 6 | window#waybar { 7 | background: rgba(22, 22, 30, 0.6); 8 | color: #c0caf5; 9 | } 10 | 11 | #workspaces button.focused { 12 | background: #7aa2f7; 13 | color: #1a1b26; 14 | } 15 | 16 | #clock, #battery, #network, #pulseaudio { 17 | padding: 0 8px; 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 38, 5 | "modules-left": ["hyprland/workspaces"], 6 | "modules-center": [], 7 | "modules-right": ["clock"], 8 | "hyprland/workspaces": { 9 | "disable-scroll": true, 10 | "all-outputs": true, 11 | "format": "{name}" 12 | }, 13 | "clock": { 14 | "format": "{:%H:%M}" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/launch-communication.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Launch Slack and Telegram on right vertical monitor (HDMI-A-1) 5 | # Slack on top half, Telegram on bottom half 6 | 7 | # Focus the right vertical monitor (HDMI-A-1) 8 | hyprctl dispatch focusmonitor HDMI-A-1 9 | 10 | # Launch Slack first 11 | flatpak run com.slack.Slack & 12 | sleep 2 13 | 14 | # Wait for Slack to start, then launch Telegram 15 | flatpak run org.telegram.desktop & 16 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-dunst.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | state="off" 5 | if dunstctl is-paused >/dev/null 2>&1; then 6 | if dunstctl is-paused | grep -qi true; then 7 | state="paused" 8 | else 9 | state="on" 10 | fi 11 | fi 12 | 13 | icon="🔔" 14 | case "$state" in 15 | paused) icon="🔕" ;; 16 | on) icon="🔔" ;; 17 | off) icon="🔔" ;; 18 | esac 19 | 20 | echo "{\"text\": \"$icon\", \"tooltip\": \"Notifications: $state (click to toggle)\"}" 21 | 22 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-dunst.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | state="off" 5 | if dunstctl is-paused >/dev/null 2>&1; then 6 | if dunstctl is-paused | grep -qi true; then 7 | state="paused" 8 | else 9 | state="on" 10 | fi 11 | fi 12 | 13 | icon="🔔" 14 | case "$state" in 15 | paused) icon="🔕" ;; 16 | on) icon="🔔" ;; 17 | off) icon="🔔" ;; 18 | esac 19 | 20 | echo "{\"text\": \"$icon\", \"tooltip\": \"Notifications: $state (click to toggle)\"}" 21 | 22 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-dunst.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | state="off" 5 | if dunstctl is-paused >/dev/null 2>&1; then 6 | if dunstctl is-paused | grep -qi true; then 7 | state="paused" 8 | else 9 | state="on" 10 | fi 11 | fi 12 | 13 | icon="󰂚" 14 | case "$state" in 15 | paused) icon="󰂛" ;; 16 | on) icon="󰂚" ;; 17 | off) icon="󰂚" ;; 18 | esac 19 | 20 | echo "{\"text\": \"$icon\", \"tooltip\": \"Notifications: $state (click to toggle)\"}" 21 | 22 | -------------------------------------------------------------------------------- /configs/waybar-scripts/waybar-dunst.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | state="off" 5 | if dunstctl is-paused >/dev/null 2>&1; then 6 | if dunstctl is-paused | grep -qi true; then 7 | state="paused" 8 | else 9 | state="on" 10 | fi 11 | fi 12 | 13 | icon="🔔" 14 | case "$state" in 15 | paused) icon="🔕" ;; 16 | on) icon="🔔" ;; 17 | off) icon="🔔" ;; 18 | esac 19 | 20 | echo "{\"text\": \"$icon\", \"tooltip\": \"Notifications: $state (click to toggle)\"}" 21 | 22 | 23 | -------------------------------------------------------------------------------- /configs/hyprlock-default.conf: -------------------------------------------------------------------------------- 1 | # Hyprlock default configuration 2 | 3 | background { 4 | path = __WALLPAPER__ 5 | blur_passes = 2 6 | blur_size = 5 7 | color = rgba(0,0,0,0.5) 8 | } 9 | 10 | input-field { 11 | monitor = 12 | size = 300, 45 13 | outline_thickness = 2 14 | dots_spacing = 0.2 15 | fade_on_empty = false 16 | placeholder_text = Password 17 | } 18 | 19 | label { 20 | text = $TIME12 21 | font_size = 34 22 | color = rgba(230,230,230,1.0) 23 | position = 0, -120 24 | halign = center 25 | valign = center 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-launcher.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Kill any existing waybar instances 5 | pkill waybar || true 6 | 7 | # Get the monitor name from the environment variable 8 | MONITOR="${WAYBAR_OUTPUT_NAME:-}" 9 | 10 | # Main monitor (DP-3) gets the full configuration 11 | if [[ "$MONITOR" == "DP-3" ]]; then 12 | waybar -c ~/.config/waybar/config -s ~/.config/waybar/style.css & 13 | else 14 | # All other monitors get the simple configuration 15 | waybar -c ~/.config/waybar/waybar-simple.json -s ~/.config/waybar/style.css & 16 | fi 17 | -------------------------------------------------------------------------------- /configs/waybar-scripts/waybar-public-ip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | get_ip() { 5 | curl -fsS --max-time 2 https://api.ipify.org && return 0 6 | curl -fsS --max-time 2 https://ifconfig.me && return 0 7 | curl -fsS --max-time 2 https://icanhazip.com && return 0 8 | return 1 9 | } 10 | 11 | ip="$(get_ip 2>/dev/null || true)" 12 | if [[ -z "${ip:-}" ]]; then 13 | echo '{"text":"IP: ?","tooltip":"Public IP unavailable"}' 14 | else 15 | ip_trimmed="${ip//$'\n'/}" 16 | echo "{\"text\": \"IP: ${ip_trimmed}\", \"tooltip\": \"Public IP: ${ip_trimmed}\"}" 17 | fi 18 | 19 | 20 | -------------------------------------------------------------------------------- /hosts/nixstation/hypridle.conf: -------------------------------------------------------------------------------- 1 | # hypridle configuration 2 | listener { 3 | # 45 minutes: blank displays via DPMS off - monitor-specific commands 4 | timeout = 2700 5 | on-timeout = hyprctl dispatch dpms off DP-1 && hyprctl dispatch dpms off DP-2 && hyprctl dispatch dpms off DP-3 && hyprctl dispatch dpms off HDMI-A-1 6 | on-resume = hyprctl dispatch dpms on DP-1 && hyprctl dispatch dpms on DP-2 && hyprctl dispatch dpms on DP-3 && hyprctl dispatch dpms on HDMI-A-1 7 | } 8 | 9 | general { 10 | lock_cmd = pidof hyprlock || hyprlock 11 | before_sleep_cmd = loginctl lock-session 12 | after_sleep_cmd = hyprctl dispatch dpms on 13 | } 14 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-public-ip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Try multiple providers to get public IP 5 | get_ip() { 6 | curl -fsS --max-time 2 https://api.ipify.org && return 0 7 | curl -fsS --max-time 2 https://ifconfig.me && return 0 8 | curl -fsS --max-time 2 https://icanhazip.com && return 0 9 | return 1 10 | } 11 | 12 | ip="$(get_ip 2>/dev/null || true)" 13 | if [[ -z "${ip:-}" ]]; 14 | then 15 | echo '{"text":"IP: ?","tooltip":"Public IP unavailable"}' 16 | else 17 | ip_trimmed="${ip//$'\n'/}" 18 | echo "{\"text\": \"IP: ${ip_trimmed}\", \"tooltip\": \"Public IP: ${ip_trimmed}\"}" 19 | fi 20 | 21 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-public-ip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Try multiple providers to get public IP 5 | get_ip() { 6 | curl -fsS --max-time 2 https://api.ipify.org && return 0 7 | curl -fsS --max-time 2 https://ifconfig.me && return 0 8 | curl -fsS --max-time 2 https://icanhazip.com && return 0 9 | return 1 10 | } 11 | 12 | ip="$(get_ip 2>/dev/null || true)" 13 | if [[ -z "${ip:-}" ]]; 14 | then 15 | echo '{"text":"IP: ?","tooltip":"Public IP unavailable"}' 16 | else 17 | ip_trimmed="${ip//$'\n'/}" 18 | echo "{\"text\": \"IP: ${ip_trimmed}\", \"tooltip\": \"Public IP: ${ip_trimmed}\"}" 19 | fi 20 | 21 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-public-ip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Try multiple providers to get public IP 5 | get_ip() { 6 | curl -fsS --max-time 2 https://api.ipify.org && return 0 7 | curl -fsS --max-time 2 https://ifconfig.me && return 0 8 | curl -fsS --max-time 2 https://icanhazip.com && return 0 9 | return 1 10 | } 11 | 12 | ip="$(get_ip 2>/dev/null || true)" 13 | if [[ -z "${ip:-}" ]]; 14 | then 15 | echo '{"text":"IP: ?","tooltip":"Public IP unavailable"}' 16 | else 17 | ip_trimmed="${ip//$'\n'/}" 18 | echo "{\"text\": \"IP: ${ip_trimmed}\", \"tooltip\": \"Public IP: ${ip_trimmed}\"}" 19 | fi 20 | 21 | -------------------------------------------------------------------------------- /configs/waybar-scripts/waybar-mpris.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | status=$(playerctl -p playerctld status 2>/dev/null || echo "Stopped") 5 | case "$status" in 6 | Playing) icon="▶️" ;; 7 | Paused) icon="⏸️" ;; 8 | *) icon="🎵" ;; 9 | esac 10 | 11 | title=$(playerctl -p playerctld metadata title 2>/dev/null || true) 12 | if command -v jq >/dev/null 2>&1; then 13 | esc_title=$(printf '%s' "$title" | jq -Rsa .) 14 | else 15 | esc_title="\"${title//\"/\\\"}\"" 16 | fi 17 | 18 | if [[ -n "$title" ]]; then 19 | printf '{"text":"%s","tooltip":%s}\n' "$icon" "$esc_title" 20 | else 21 | printf '{"text":"%s","tooltip":"MPRIS"}\n' "$icon" 22 | fi 23 | 24 | 25 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar-simple.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: "DejaVu Sans", sans-serif; 3 | font-size: 12px; 4 | color: white; 5 | } 6 | 7 | #workspaces button { 8 | padding: 5px; 9 | background: transparent; 10 | color: white; 11 | } 12 | 13 | #workspaces button.active { 14 | background: #64727D; 15 | } 16 | 17 | #clock { 18 | padding: 5px; 19 | color: white; 20 | } 21 | 22 | #cpu { 23 | padding: 5px; 24 | color: white; 25 | } 26 | 27 | #memory { 28 | padding: 5px; 29 | color: white; 30 | } 31 | 32 | #pulseaudio { 33 | padding: 5px; 34 | color: white; 35 | } 36 | 37 | #network { 38 | padding: 5px; 39 | color: white; 40 | } 41 | 42 | #window { 43 | padding: 5px; 44 | color: white; 45 | } 46 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-btc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import json 3 | import sys 4 | import urllib.request 5 | 6 | # Fetch BTC price (USD) from CoinDesk (no API key) 7 | URL = "https://api.coindesk.com/v1/bpi/currentprice/BTC.json" 8 | 9 | def main(): 10 | try: 11 | with urllib.request.urlopen(URL, timeout=3) as resp: 12 | data = json.load(resp) 13 | rate = data["bpi"]["USD"]["rate_float"] 14 | text = f"₿ {rate:,.0f}" 15 | out = {"text": text, "tooltip": f"BTC/USD: {rate:,.2f}"} 16 | print(json.dumps(out)) 17 | except Exception as e: 18 | print(json.dumps({"text": "₿ ?", "tooltip": f"BTC error: {e}"})) 19 | 20 | if __name__ == "__main__": 21 | sys.exit(main()) 22 | 23 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-btc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import json 3 | import sys 4 | import urllib.request 5 | 6 | # Fetch BTC price (USD) from CoinDesk (no API key) 7 | URL = "https://api.coindesk.com/v1/bpi/currentprice/BTC.json" 8 | 9 | def main(): 10 | try: 11 | with urllib.request.urlopen(URL, timeout=3) as resp: 12 | data = json.load(resp) 13 | rate = data["bpi"]["USD"]["rate_float"] 14 | text = f"₿ {rate:,.0f}" 15 | out = {"text": text, "tooltip": f"BTC/USD: {rate:,.2f}"} 16 | print(json.dumps(out)) 17 | except Exception as e: 18 | print(json.dumps({"text": "₿ ?", "tooltip": f"BTC error: {e}"})) 19 | 20 | if __name__ == "__main__": 21 | sys.exit(main()) 22 | 23 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-btc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import json 3 | import sys 4 | import urllib.request 5 | 6 | # Fetch BTC price (USD) from CoinDesk (no API key) 7 | URL = "https://api.coindesk.com/v1/bpi/currentprice/BTC.json" 8 | 9 | def main(): 10 | try: 11 | with urllib.request.urlopen(URL, timeout=3) as resp: 12 | data = json.load(resp) 13 | rate = data["bpi"]["USD"]["rate_float"] 14 | text = f"₿ {rate:,.0f}" 15 | out = {"text": text, "tooltip": f"BTC/USD: {rate:,.2f}"} 16 | print(json.dumps(out)) 17 | except Exception as e: 18 | print(json.dumps({"text": "₿ ?", "tooltip": f"BTC error: {e}"})) 19 | 20 | if __name__ == "__main__": 21 | sys.exit(main()) 22 | 23 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-mpris.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Prefer playerctld to unify active player selection 5 | status=$(playerctl -p playerctld status 2>/dev/null || echo "Stopped") 6 | case "$status" in 7 | Playing) icon="▶️" ;; 8 | Paused) icon="⏸️" ;; 9 | *) icon="🎵" ;; 10 | esac 11 | 12 | title=$(playerctl -p playerctld metadata title 2>/dev/null || true) 13 | 14 | # Escape tooltip for JSON using jq if available 15 | if command -v jq >/dev/null 2>&1; then 16 | esc_title=$(printf '%s' "$title" | jq -Rsa .) 17 | else 18 | esc_title="\"${title//\"/\\\"}\"" 19 | fi 20 | 21 | if [[ -n "$title" ]]; then 22 | printf '{"text":"%s","tooltip":%s}\n' "$icon" "$esc_title" 23 | else 24 | printf '{"text":"%s","tooltip":"MPRIS"}\n' "$icon" 25 | fi 26 | 27 | 28 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-mpris.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Prefer playerctld to unify active player selection 5 | status=$(playerctl -p playerctld status 2>/dev/null || echo "Stopped") 6 | case "$status" in 7 | Playing) icon="▶️" ;; 8 | Paused) icon="⏸️" ;; 9 | *) icon="🎵" ;; 10 | esac 11 | 12 | title=$(playerctl -p playerctld metadata title 2>/dev/null || true) 13 | 14 | # Escape tooltip for JSON using jq if available 15 | if command -v jq >/dev/null 2>&1; then 16 | esc_title=$(printf '%s' "$title" | jq -Rsa .) 17 | else 18 | esc_title="\"${title//\"/\\\"}\"" 19 | fi 20 | 21 | if [[ -n "$title" ]]; then 22 | printf '{"text":"%s","tooltip":%s}\n' "$icon" "$esc_title" 23 | else 24 | printf '{"text":"%s","tooltip":"MPRIS"}\n' "$icon" 25 | fi 26 | 27 | 28 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-mpris.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Prefer playerctld to unify active player selection 5 | status=$(playerctl -p playerctld status 2>/dev/null || echo "Stopped") 6 | case "$status" in 7 | Playing) icon="▶️" ;; 8 | Paused) icon="⏸️" ;; 9 | *) icon="🎵" ;; 10 | esac 11 | 12 | title=$(playerctl -p playerctld metadata title 2>/dev/null || true) 13 | 14 | # Escape tooltip for JSON using jq if available 15 | if command -v jq >/dev/null 2>&1; then 16 | esc_title=$(printf '%s' "$title" | jq -Rsa .) 17 | else 18 | esc_title="\"${title//\"/\\\"}\"" 19 | fi 20 | 21 | if [[ -n "$title" ]]; then 22 | printf '{"text":"%s","tooltip":%s}\n' "$icon" "$esc_title" 23 | else 24 | printf '{"text":"%s","tooltip":"MPRIS"}\n' "$icon" 25 | fi 26 | 27 | 28 | -------------------------------------------------------------------------------- /configs/waybar-default.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "modules-left": ["hyprland/workspaces", "hyprland/window"], 5 | "modules-center": [], 6 | "modules-right": ["pulseaudio", "network", "battery", "clock"], 7 | "pulseaudio": { 8 | "format": " {volume}%", 9 | "format-muted": " {volume}%", 10 | "on-click": "pavucontrol" 11 | }, 12 | "network": { 13 | "format-wifi": " {essid} {signal}%", 14 | "format-ethernet": " {ip}", 15 | "format-disconnected": "󰖪 offline" 16 | }, 17 | "battery": { 18 | "format": " {capacity}%", 19 | "format-charging": " {capacity}%", 20 | "states": { 21 | "warning": 30, 22 | "critical": 15 23 | } 24 | }, 25 | "clock": { 26 | "format": " %a %b %d %H:%M" 27 | } 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/hyprlock-btc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Use full paths for hyprlock's minimal environment 5 | CURL="/run/current-system/sw/bin/curl" 6 | JQ="/run/current-system/sw/bin/jq" 7 | 8 | URL="https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true" 9 | resp="$("$CURL" -fsS --max-time 3 "$URL" 2>/dev/null || true)" 10 | if [[ -z "$resp" ]]; then 11 | echo "₿ ?" 12 | exit 0 13 | fi 14 | price=$("$JQ" -r '.bitcoin.usd // empty' <<<"$resp" 2>/dev/null || true) 15 | chg=$("$JQ" -r '.bitcoin.usd_24h_change // empty' <<<"$resp" 2>/dev/null || true) 16 | if [[ -z "$price" ]]; then 17 | echo "₿ ?" 18 | exit 0 19 | fi 20 | price_i=$(printf '%.0f' "$price") 21 | chg_s=$(printf '%+.1f' "${chg:-0}") 22 | echo "₿ ${price_i} (${chg_s}%)" 23 | 24 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/hyprlock-btc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Use full paths for hyprlock's minimal environment 5 | CURL="/run/current-system/sw/bin/curl" 6 | JQ="/run/current-system/sw/bin/jq" 7 | 8 | URL="https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true" 9 | resp="$("$CURL" -fsS --max-time 3 "$URL" 2>/dev/null || true)" 10 | if [[ -z "$resp" ]]; then 11 | echo "₿ ?" 12 | exit 0 13 | fi 14 | price=$("$JQ" -r '.bitcoin.usd // empty' <<<"$resp" 2>/dev/null || true) 15 | chg=$("$JQ" -r '.bitcoin.usd_24h_change // empty' <<<"$resp" 2>/dev/null || true) 16 | if [[ -z "$price" ]]; then 17 | echo "₿ ?" 18 | exit 0 19 | fi 20 | price_i=$(printf '%.0f' "$price") 21 | chg_s=$(printf '%+.1f' "${chg:-0}") 22 | echo "₿ ${price_i} (${chg_s}%)" 23 | 24 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/hyprlock-btc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Use full paths for hyprlock's minimal environment 5 | CURL="/run/current-system/sw/bin/curl" 6 | JQ="/run/current-system/sw/bin/jq" 7 | 8 | URL="https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true" 9 | resp="$("$CURL" -fsS --max-time 3 "$URL" 2>/dev/null || true)" 10 | if [[ -z "$resp" ]]; then 11 | echo "₿ ?" 12 | exit 0 13 | fi 14 | price=$("$JQ" -r '.bitcoin.usd // empty' <<<"$resp" 2>/dev/null || true) 15 | chg=$("$JQ" -r '.bitcoin.usd_24h_change // empty' <<<"$resp" 2>/dev/null || true) 16 | if [[ -z "$price" ]]; then 17 | echo "₿ ?" 18 | exit 0 19 | fi 20 | price_i=$(printf '%.0f' "$price") 21 | chg_s=$(printf '%+.1f' "${chg:-0}") 22 | echo "₿ ${price_i} (${chg_s}%)" 23 | 24 | -------------------------------------------------------------------------------- /wallpapers/README.md: -------------------------------------------------------------------------------- 1 | Wallpapers 2 | =========== 3 | 4 | Place shared wallpapers for all hosts here. Recommended usage: 5 | 6 | - Add your image file into this directory and commit it to the repo. 7 | - Point each host's `wallpaperPath` to this file using a Nix path literal, e.g.: 8 | - In `hosts//system.nix`: 9 | - `wallpaperPath = ../../wallpapers/aishot-2602.jpg;` 10 | - This embeds the image into the Nix store and makes it available on all hosts when they build. 11 | 12 | Notes 13 | - Hyprpaper and Hyprlock configs are rendered during activation with this path, so both desktop and lock screen use the same image. 14 | - Update the file name here to change wallpapers across systems in one commit. 15 | - If you want per-host wallpapers, keep different files in this folder and reference the desired one per host. 16 | 17 | 18 | -------------------------------------------------------------------------------- /configs/hyprland-monitors-rvbee-120hz.conf: -------------------------------------------------------------------------------- 1 | # RVBEE Monitor Configuration (targeting 120Hz) 2 | # 3 | # How to use: 4 | # 1) Find your monitor name(s) and supported modes: 5 | # ~/.local/bin/setup-monitors status 6 | # (or: hyprctl monitors) 7 | # 2) Replace MON with your connector name (e.g. DP-1, HDMI-A-1). 8 | # 3) Replace WIDTHxHEIGHT@120 with an actual mode your panel supports at 120Hz 9 | # (e.g. 2560x1440@120 or 1920x1080@120). 10 | # 4) Set position to auto and scale to 1 unless you need otherwise. 11 | # 5) Point RVBEE at this file by changing hyprvibe.hyprland.monitorsFile in 12 | # hosts/rvbee/system.nix from hyprland-monitors-rvbee.conf to this file. 13 | # 14 | # Example: 15 | # monitor=DP-1,2560x1440@120,auto,1 16 | # 17 | # Force-reapply the mode: disable then enable at 144 Hz 18 | monitor=DP-1,disable 19 | monitor=DP-1,2560x1080@144,0x0,1 20 | 21 | 22 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-per-monitor.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Kill any existing waybar instances 5 | pkill waybar || true 6 | 7 | # Wait a moment for waybar to fully terminate 8 | sleep 1 9 | 10 | # Launch waybar for each monitor with different configurations 11 | # Each monitor gets its own specific config file with output field 12 | 13 | # Launch for DP-1 (top monitor) - simple 14 | waybar -c ~/.config/waybar/waybar-simple-dp1.json -s ~/.config/waybar/style.css & 15 | 16 | # Launch for DP-2 (left vertical) - simple 17 | waybar -c ~/.config/waybar/waybar-simple-dp2.json -s ~/.config/waybar/style.css & 18 | 19 | # Launch for DP-3 (main center) - full config 20 | waybar -c ~/.config/waybar/config -s ~/.config/waybar/style.css & 21 | 22 | # Launch for HDMI-A-1 (right vertical) - simple 23 | waybar -c ~/.config/waybar/waybar-simple-hdmi.json -s ~/.config/waybar/style.css & 24 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/launch-development.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Launch development tools on left vertical monitor (DP-2) 5 | # Cursor editor on top half, terminal on bottom half 6 | 7 | # Focus the left vertical monitor 8 | hyprctl dispatch focusmonitor DP-2 9 | 10 | # Launch Cursor editor and position it on top half 11 | cursor & 12 | sleep 2 13 | # Move to DP-2 monitor first, then position 14 | hyprctl dispatch movewindow mon:DP-2 15 | hyprctl dispatch movewindow exact 0 0 16 | hyprctl dispatch resizeactive exact 1440 1280 17 | 18 | # Launch terminal and position it on bottom half 19 | kitty & 20 | sleep 2 21 | # Move to DP-2 monitor first, then position 22 | hyprctl dispatch movewindow mon:DP-2 23 | hyprctl dispatch movewindow exact 0 1280 24 | hyprctl dispatch resizeactive exact 1440 1280 25 | 26 | # Focus back to the main monitor (DP-3) 27 | hyprctl dispatch focusmonitor DP-3 28 | -------------------------------------------------------------------------------- /configs/waybar-scripts/waybar-btc-coingecko.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | URL="https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true" 5 | 6 | resp="$(curl -fsS --max-time 3 "$URL" 2>/dev/null || true)" 7 | if [[ -z "$resp" ]]; then 8 | echo '{"text":"₿ ?","tooltip":"CoinGecko request failed"}' 9 | exit 0 10 | fi 11 | 12 | price=$(jq -r '.bitcoin.usd // empty' <<<"$resp" 2>/dev/null || true) 13 | chg=$(jq -r '.bitcoin.usd_24h_change // empty' <<<"$resp" 2>/dev/null || true) 14 | 15 | if [[ -z "$price" ]]; then 16 | echo '{"text":"₿ ?","tooltip":"No price in response"}' 17 | exit 0 18 | fi 19 | 20 | price_i=$(printf '%.0f' "$price") 21 | chg_s=$(printf '%+.1f' "${chg:-0}") 22 | 23 | text="₿ ${price_i} (${chg_s}%)" 24 | tooltip="BTC/USD: ${price} (${chg_s}% 24h)" 25 | 26 | printf '{"text":"%s","tooltip":"%s"}\n' "$text" "$tooltip" 27 | 28 | 29 | -------------------------------------------------------------------------------- /hosts/rvbee/hyprlock.conf: -------------------------------------------------------------------------------- 1 | # Hyprlock Configuration (declarative) 2 | # Edit this file and rebuild to theme the lock screen. 3 | 4 | # Basic example using your current wallpaper; tweak as desired. 5 | background { 6 | # Path to image; leave empty for solid color 7 | path = __WALLPAPER__ 8 | blur_passes = 2 9 | blur_size = 5 10 | color = rgba(0,0,0,0.5) 11 | } 12 | 13 | input-field { 14 | monitor = 15 | size = 300, 45 16 | outline_thickness = 2 17 | dots_spacing = 0.2 18 | fade_on_empty = false 19 | placeholder_text = Password 20 | } 21 | 22 | label { 23 | text = cmd[60] /home/chrisf/.config/hypr/hyprlock-btc.sh 24 | font_size = 22 25 | color = rgba(230,230,230,1.0) 26 | position = 0, -160 27 | halign = center 28 | valign = center 29 | } 30 | 31 | label { 32 | text = $TIME12 33 | font_size = 34 34 | color = rgba(230,230,230,1.0) 35 | position = 0, -120 36 | halign = center 37 | valign = center 38 | } 39 | 40 | -------------------------------------------------------------------------------- /hosts/nixbook/hyprlock.conf: -------------------------------------------------------------------------------- 1 | # Hyprlock Configuration (declarative) 2 | # Edit this file and rebuild to theme the lock screen. 3 | 4 | # Basic example using your current wallpaper; tweak as desired. 5 | background { 6 | # Path to image; leave empty for solid color 7 | path = __WALLPAPER__ 8 | blur_passes = 2 9 | blur_size = 5 10 | color = rgba(0,0,0,0.5) 11 | } 12 | 13 | input-field { 14 | monitor = 15 | size = 300, 45 16 | outline_thickness = 2 17 | dots_spacing = 0.2 18 | fade_on_empty = false 19 | placeholder_text = Password 20 | } 21 | 22 | label { 23 | text = cmd[60] /home/chrisf/.config/hypr/hyprlock-btc.sh 24 | font_size = 22 25 | color = rgba(230,230,230,1.0) 26 | position = 0, -160 27 | halign = center 28 | valign = center 29 | } 30 | 31 | label { 32 | text = $TIME12 33 | font_size = 34 34 | color = rgba(230,230,230,1.0) 35 | position = 0, -120 36 | halign = center 37 | valign = center 38 | } 39 | 40 | -------------------------------------------------------------------------------- /hosts/nixstation/hyprlock.conf: -------------------------------------------------------------------------------- 1 | # Hyprlock Configuration (declarative) 2 | # Edit this file and rebuild to theme the lock screen. 3 | 4 | # Basic example using your current wallpaper; tweak as desired. 5 | background { 6 | # Path to image; leave empty for solid color 7 | path = __WALLPAPER__ 8 | blur_passes = 2 9 | blur_size = 5 10 | color = rgba(0,0,0,0.5) 11 | } 12 | 13 | input-field { 14 | monitor = 15 | size = 300, 45 16 | outline_thickness = 2 17 | dots_spacing = 0.2 18 | fade_on_empty = false 19 | placeholder_text = Password 20 | } 21 | 22 | label { 23 | text = cmd[60] /home/chrisf/.config/hypr/hyprlock-btc.sh 24 | font_size = 22 25 | color = rgba(230,230,230,1.0) 26 | position = 0, -160 27 | halign = center 28 | valign = center 29 | } 30 | 31 | label { 32 | text = $TIME12 33 | font_size = 34 34 | color = rgba(230,230,230,1.0) 35 | position = 0, -120 36 | halign = center 37 | valign = center 38 | } 39 | 40 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-btc-coingecko.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | URL="https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true" 5 | 6 | resp="$(curl -fsS --max-time 3 "$URL" 2>/dev/null || true)" 7 | if [[ -z "$resp" ]]; then 8 | echo '{"text":"₿ ?","tooltip":"CoinGecko request failed"}' 9 | exit 0 10 | fi 11 | 12 | price=$(jq -r '.bitcoin.usd // empty' <<<"$resp" 2>/dev/null || true) 13 | chg=$(jq -r '.bitcoin.usd_24h_change // empty' <<<"$resp" 2>/dev/null || true) 14 | 15 | if [[ -z "$price" ]]; then 16 | echo '{"text":"₿ ?","tooltip":"No price in response"}' 17 | exit 0 18 | fi 19 | 20 | # Round price to integer; change to 1 decimal with sign 21 | price_i=$(printf '%.0f' "$price") 22 | chg_s=$(printf '%+.1f' "${chg:-0}") 23 | 24 | text="₿ ${price_i} (${chg_s}%)" 25 | tooltip="BTC/USD: ${price} (${chg_s}% 24h)" 26 | 27 | printf '{"text":"%s","tooltip":"%s"}\n' "$text" "$tooltip" 28 | 29 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-btc-coingecko.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | URL="https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true" 5 | 6 | resp="$(curl -fsS --max-time 3 "$URL" 2>/dev/null || true)" 7 | if [[ -z "$resp" ]]; then 8 | echo '{"text":"₿ ?","tooltip":"CoinGecko request failed"}' 9 | exit 0 10 | fi 11 | 12 | price=$(jq -r '.bitcoin.usd // empty' <<<"$resp" 2>/dev/null || true) 13 | chg=$(jq -r '.bitcoin.usd_24h_change // empty' <<<"$resp" 2>/dev/null || true) 14 | 15 | if [[ -z "$price" ]]; then 16 | echo '{"text":"₿ ?","tooltip":"No price in response"}' 17 | exit 0 18 | fi 19 | 20 | # Round price to integer; change to 1 decimal with sign 21 | price_i=$(printf '%.0f' "$price") 22 | chg_s=$(printf '%+.1f' "${chg:-0}") 23 | 24 | text="₿ ${price_i} (${chg_s}%)" 25 | tooltip="BTC/USD: ${price} (${chg_s}% 24h)" 26 | 27 | printf '{"text":"%s","tooltip":"%s"}\n' "$text" "$tooltip" 28 | 29 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-btc-coingecko.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | URL="https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true" 5 | 6 | resp="$(curl -fsS --max-time 3 "$URL" 2>/dev/null || true)" 7 | if [[ -z "$resp" ]]; then 8 | echo '{"text":"󰈁 ?","tooltip":"CoinGecko request failed"}' 9 | exit 0 10 | fi 11 | 12 | price=$(jq -r '.bitcoin.usd // empty' <<<"$resp" 2>/dev/null || true) 13 | chg=$(jq -r '.bitcoin.usd_24h_change // empty' <<<"$resp" 2>/dev/null || true) 14 | 15 | if [[ -z "$price" ]]; then 16 | echo '{"text":"󰈁 ?","tooltip":"No price in response"}' 17 | exit 0 18 | fi 19 | 20 | # Round price to integer; change to 1 decimal with sign 21 | price_i=$(printf '%.0f' "$price") 22 | chg_s=$(printf '%+.1f' "${chg:-0}") 23 | 24 | text="󰈁 ${price_i} (${chg_s}%)" 25 | tooltip="BTC/USD: ${price} (${chg_s}% 24h)" 26 | 27 | printf '{"text":"%s","tooltip":"%s"}\n' "$text" "$tooltip" 28 | 29 | -------------------------------------------------------------------------------- /hosts/nixbook/hyprland.conf: -------------------------------------------------------------------------------- 1 | # Hyprland Configuration for Nixbook 2 | # See https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ 3 | 4 | # Source shared base configuration (use absolute path; ~ is not expanded by Hyprland) 5 | source = /home/chrisf/.config/hypr/hyprland-base.conf 6 | 7 | # Source host-specific monitor configuration 8 | source = /home/chrisf/.config/hypr/hyprland-monitors-nixbook.conf 9 | 10 | # Nixbook-specific overrides and additions can go here 11 | # For example: 12 | # - Machine-specific keybindings 13 | # - Hardware-specific settings 14 | # - Laptop-specific optimizations 15 | 16 | # Fixed geometry for MPV only; OBS is tiled by Hyprland 17 | # MPV identified by app-id or title 18 | windowrulev2 = float, class:^(clip-player)$ 19 | windowrulev2 = size 960 540, class:^(clip-player)$ 20 | windowrulev2 = move 960 0, class:^(clip-player)$ 21 | windowrulev2 = float, title:^.*ClipPlayer.*$ 22 | windowrulev2 = size 960 540, title:^.*ClipPlayer.*$ 23 | windowrulev2 = move 960 0, title:^.*ClipPlayer.*$ -------------------------------------------------------------------------------- /hosts/nixstation/waybar-simple-dp1.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 38, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | "output": "DP-1", 11 | "modules-left": ["hyprland/workspaces", "hyprland/window"], 12 | "modules-center": [], 13 | "modules-right": ["clock"], 14 | "hyprland/workspaces": { 15 | "disable-scroll": true, 16 | "all-outputs": true, 17 | "format": "{name}", 18 | "format-icons": { 19 | "1": "1", 20 | "2": "2", 21 | "3": "3", 22 | "4": "4", 23 | "5": "5", 24 | "6": "6", 25 | "7": "7", 26 | "8": "8", 27 | "9": "9", 28 | "10": "10", 29 | "urgent": "urgent", 30 | "focused": "focused", 31 | "default": "default" 32 | } 33 | }, 34 | "hyprland/window": { 35 | "format": "{}", 36 | "max-length": 50 37 | }, 38 | "clock": { 39 | "format": "󰅐 {:%I:%M %p}", 40 | "tooltip": false 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar-simple-dp2.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 38, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | "output": "DP-2", 11 | "modules-left": ["hyprland/workspaces", "hyprland/window"], 12 | "modules-center": [], 13 | "modules-right": ["clock"], 14 | "hyprland/workspaces": { 15 | "disable-scroll": true, 16 | "all-outputs": true, 17 | "format": "{name}", 18 | "format-icons": { 19 | "1": "1", 20 | "2": "2", 21 | "3": "3", 22 | "4": "4", 23 | "5": "5", 24 | "6": "6", 25 | "7": "7", 26 | "8": "8", 27 | "9": "9", 28 | "10": "10", 29 | "urgent": "urgent", 30 | "focused": "focused", 31 | "default": "default" 32 | } 33 | }, 34 | "hyprland/window": { 35 | "format": "{}", 36 | "max-length": 50 37 | }, 38 | "clock": { 39 | "format": "󰅐 {:%I:%M %p}", 40 | "tooltip": false 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar-simple-hdmi.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 38, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | "output": "HDMI-A-1", 11 | "modules-left": ["hyprland/workspaces", "hyprland/window"], 12 | "modules-center": [], 13 | "modules-right": ["clock"], 14 | "hyprland/workspaces": { 15 | "disable-scroll": true, 16 | "all-outputs": true, 17 | "format": "{name}", 18 | "format-icons": { 19 | "1": "1", 20 | "2": "2", 21 | "3": "3", 22 | "4": "4", 23 | "5": "5", 24 | "6": "6", 25 | "7": "7", 26 | "8": "8", 27 | "9": "9", 28 | "10": "10", 29 | "urgent": "urgent", 30 | "focused": "focused", 31 | "default": "default" 32 | } 33 | }, 34 | "hyprland/window": { 35 | "format": "{}", 36 | "max-length": 50 37 | }, 38 | "clock": { 39 | "format": "󰅐 {:%I:%M %p}", 40 | "tooltip": false 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar-simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 38, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | "output": ["DP-1", "DP-2", "HDMI-A-1"], 11 | "modules-left": ["hyprland/workspaces", "hyprland/window"], 12 | "modules-center": [], 13 | "modules-right": ["clock"], 14 | "hyprland/workspaces": { 15 | "disable-scroll": true, 16 | "all-outputs": true, 17 | "format": "{name}", 18 | "format-icons": { 19 | "1": "1", 20 | "2": "2", 21 | "3": "3", 22 | "4": "4", 23 | "5": "5", 24 | "6": "6", 25 | "7": "7", 26 | "8": "8", 27 | "9": "9", 28 | "10": "10", 29 | "urgent": "urgent", 30 | "focused": "focused", 31 | "default": "default" 32 | } 33 | }, 34 | "hyprland/window": { 35 | "format": "{}", 36 | "max-length": 50 37 | }, 38 | "clock": { 39 | "format": "󰅐 {:%I:%M %p}", 40 | "tooltip": false 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /modules/shared/default.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: 2 | let 3 | cfg = config.hyprvibe; 4 | in { 5 | options.hyprvibe.enable = lib.mkEnableOption "Enable the base Hyprvibe desktop experience"; 6 | 7 | imports = [ 8 | ./packages.nix 9 | ./desktop.nix 10 | ./hyprland.nix 11 | ./waybar.nix 12 | ./shell.nix 13 | ./services.nix 14 | ./system.nix 15 | ./user.nix 16 | ./power.nix 17 | ]; 18 | 19 | config = lib.mkIf cfg.enable { 20 | # Base common experience across hosts 21 | documentation.man.enable = false; 22 | hyprvibe.desktop = { 23 | enable = true; 24 | fonts.enable = true; 25 | }; 26 | hyprvibe.hyprland.enable = true; 27 | hyprvibe.waybar.enable = true; 28 | hyprvibe.shell.enable = true; 29 | hyprvibe.services = { 30 | enable = true; 31 | openssh.enable = true; 32 | }; 33 | hyprvibe.system.enable = true; 34 | hyprvibe.packages = { 35 | enable = true; 36 | base.enable = true; 37 | desktop.enable = true; 38 | }; 39 | }; 40 | } 41 | 42 | 43 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-timezones.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Simple timezone display script for Waybar 4 | # This script outputs just timezone information (no clock display) 5 | 6 | # Get times in different timezones 7 | pacific_time=$(TZ='America/Los_Angeles' date '+%I:%M %p') 8 | central_time=$(TZ='America/Chicago' date '+%I:%M %p') 9 | eastern_time=$(TZ='America/New_York' date '+%I:%M %p') 10 | london_time=$(TZ='Europe/London' date '+%I:%M %p') 11 | utc_time=$(TZ='UTC' date '+%I:%M %p') 12 | 13 | # Get timezone abbreviations 14 | pacific_tz=$(TZ='America/Los_Angeles' date '+%Z') 15 | central_tz=$(TZ='America/Chicago' date '+%Z') 16 | eastern_tz=$(TZ='America/New_York' date '+%Z') 17 | london_tz=$(TZ='Europe/London' date '+%Z') 18 | 19 | # Create tooltip content 20 | tooltip="Time Zones: 21 | Pacific (${pacific_tz}): ${pacific_time} 22 | Central (${central_tz}): ${central_time} 23 | Eastern (${eastern_tz}): ${eastern_time} 24 | London (${london_tz}): ${london_time} 25 | UTC: ${utc_time}" 26 | 27 | # Use jq to properly format JSON 28 | jq -n -c \ 29 | --arg text "TZ" \ 30 | --arg tooltip "$tooltip" \ 31 | '{"text": $text, "tooltip": $tooltip}' 32 | -------------------------------------------------------------------------------- /hosts/rvbee/hyprland.conf: -------------------------------------------------------------------------------- 1 | # Hyprland Configuration for Rvbee 2 | # See https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ 3 | 4 | # Source shared base configuration (use absolute path; ~ is not expanded by Hyprland) 5 | source = /home/chrisf/.config/hypr/hyprland-base.conf 6 | 7 | # Source host-specific monitor configuration 8 | source = /home/chrisf/.config/hypr/hyprland-monitors-rvbee-120hz.conf 9 | 10 | # Enforce 144Hz on login in case early monitor keyword is ignored 11 | exec-once = sh -c "sleep 1 && hyprctl keyword monitor 'DP-1,2560x1080@144,0x0,1'" 12 | 13 | # Rvbee-specific overrides and additions can go here 14 | # For example: 15 | # - Machine-specific keybindings 16 | # - Hardware-specific settings 17 | # - Laptop-specific optimizations 18 | 19 | # Fixed geometry for MPV only; OBS is tiled by Hyprland 20 | # MPV identified by app-id or title 21 | windowrulev2 = float, class:^(clip-player)$ 22 | windowrulev2 = size 960 540, class:^(clip-player)$ 23 | windowrulev2 = move 960 0, class:^(clip-player)$ 24 | windowrulev2 = float, title:^.*ClipPlayer.*$ 25 | windowrulev2 = size 960 540, title:^.*ClipPlayer.*$ 26 | windowrulev2 = move 960 0, title:^.*ClipPlayer.*$ -------------------------------------------------------------------------------- /scripts/waybar-per-monitor.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Per-Monitor Waybar Launcher 4 | # This script launches different waybar configurations for different monitors 5 | 6 | CONFIG_DIR="/home/chrisf/.config/waybar" 7 | FULL_CONFIG="$CONFIG_DIR/config" 8 | SIMPLE_CONFIG="$CONFIG_DIR/simple-config" 9 | STYLE_FILE="$CONFIG_DIR/style.css" 10 | 11 | # Function to launch waybar for a specific monitor 12 | launch_waybar_for_monitor() { 13 | local monitor=$1 14 | local config=$2 15 | 16 | echo "Launching waybar for monitor $monitor with config $config" 17 | 18 | # Launch waybar with specific output 19 | waybar -c "$config" -s "$STYLE_FILE" -o "$monitor" & 20 | } 21 | 22 | # Kill existing waybar instances 23 | pkill waybar 24 | sleep 1 25 | 26 | # Launch waybar for each monitor with appropriate configuration 27 | # Main monitor (DP-3) gets full waybar 28 | launch_waybar_for_monitor "DP-3" "$FULL_CONFIG" 29 | 30 | # Other monitors get simple waybar 31 | launch_waybar_for_monitor "DP-1" "$SIMPLE_CONFIG" 32 | launch_waybar_for_monitor "DP-2" "$SIMPLE_CONFIG" 33 | launch_waybar_for_monitor "HDMI-A-1" "$SIMPLE_CONFIG" 34 | 35 | echo "Per-monitor waybar launched successfully" 36 | -------------------------------------------------------------------------------- /hosts/nixstation/fonts.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | sans-serif 7 | 8 | Ubuntu 9 | Noto Color Emoji 10 | Twemoji 11 | 12 | 13 | 14 | 15 | monospace 16 | 17 | Fira Code 18 | Noto Color Emoji 19 | Twemoji 20 | 21 | 22 | 23 | 24 | 25 | 26 | Noto Color Emoji 27 | 28 | 29 | false 30 | 31 | 32 | 33 | 34 | 35 | 36 | Noto Color Emoji 37 | 38 | 39 | rgb 40 | 41 | 42 | 43 | 44 | 45 | Twemoji 46 | 47 | 48 | rgb 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /modules/shared/system.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, config, ... }: 2 | let 3 | cfg = config.hyprvibe.system; 4 | in { 5 | options.hyprvibe.system = { 6 | enable = lib.mkEnableOption "Enable shared system/kernel performance settings"; 7 | kernelPackages = lib.mkOption { 8 | type = lib.types.nullOr lib.types.unspecified; 9 | default = pkgs.linuxPackages_zen; 10 | description = "Kernel packages to use. Defaults to Zen kernel. Set to null to use system default, or override with pkgs.linuxPackages for regular kernel."; 11 | }; 12 | }; 13 | 14 | config = lib.mkIf cfg.enable { 15 | # Kernel: use Zen by default, but allow per-host override 16 | boot.kernelPackages = cfg.kernelPackages; 17 | 18 | # Trim SSDs weekly (harmless on HDDs) 19 | services.fstrim = { 20 | enable = true; 21 | interval = "weekly"; 22 | }; 23 | 24 | # ZRAM swap with zstd 25 | zramSwap = { 26 | enable = true; 27 | algorithm = "zstd"; 28 | }; 29 | 30 | # Nix store optimizations and GC 31 | nix.settings.auto-optimise-store = true; 32 | nix.gc = { 33 | automatic = true; 34 | dates = "weekly"; 35 | options = "--delete-older-than 30d"; 36 | }; 37 | 38 | # Power management defaults 39 | powerManagement = { 40 | enable = true; 41 | cpuFreqGovernor = "performance"; 42 | }; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-clock-tooltip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Custom tooltip script for Waybar clock module 4 | # This script outputs plain text tooltip content (not JSON) 5 | 6 | # Get current time in local timezone 7 | current_time=$(date '+%I:%M %p') 8 | 9 | # Get times in different timezones 10 | pacific_time=$(TZ='America/Los_Angeles' date '+%I:%M %p') 11 | central_time=$(TZ='America/Chicago' date '+%I:%M %p') 12 | eastern_time=$(TZ='America/New_York' date '+%I:%M %p') 13 | london_time=$(TZ='Europe/London' date '+%I:%M %p') 14 | utc_time=$(TZ='UTC' date '+%I:%M %p') 15 | 16 | # Get timezone abbreviations 17 | pacific_tz=$(TZ='America/Los_Angeles' date '+%Z') 18 | central_tz=$(TZ='America/Chicago' date '+%Z') 19 | eastern_tz=$(TZ='America/New_York' date '+%Z') 20 | london_tz=$(TZ='Europe/London' date '+%Z') 21 | 22 | # Get current date and day of week 23 | current_date=$(date '+%Y-%m-%d') 24 | day_of_week=$(date '+%A') 25 | current_time_24=$(date '+%H:%M:%S') 26 | 27 | # Generate calendar (simple version) 28 | calendar=$(cal | sed 's/^/ /') 29 | 30 | # Create tooltip content 31 | echo "${day_of_week}, ${current_date} | ${current_time_24} 32 | 33 | Time Zones: 34 | ☀️ Pacific (${pacific_tz}): ${pacific_time} 35 | 🌆 Central (${central_tz}): ${central_time} 36 | 🌃 Eastern (${eastern_tz}): ${eastern_time} 37 | 🌍 London (${london_tz}): ${london_time} 38 | 🌐 UTC: ${utc_time} 39 | 40 | Calendar: 41 | ${calendar}" 42 | -------------------------------------------------------------------------------- /modules/shared/desktop.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, config, ... }: 2 | let cfg = config.hyprvibe.desktop; 3 | in { 4 | options.hyprvibe.desktop = { 5 | enable = lib.mkEnableOption "Shared desktop (Wayland env, portals, fonts, GTK/Qt)"; 6 | fonts.enable = lib.mkEnableOption "Install recommended Nerd/base fonts"; 7 | }; 8 | 9 | config = lib.mkIf cfg.enable { 10 | environment.sessionVariables = { 11 | NIXOS_OZONE_WL = "1"; 12 | MOZ_ENABLE_WAYLAND = "1"; 13 | QT_QPA_PLATFORM = "wayland"; 14 | GDK_BACKEND = "wayland"; 15 | XCURSOR_THEME = "Bibata-Modern-Ice"; 16 | XCURSOR_SIZE = "24"; 17 | }; 18 | 19 | # Display manager for Hyprland sessions 20 | services.displayManager.gdm = { 21 | enable = true; 22 | wayland = true; 23 | }; 24 | 25 | xdg.portal = { 26 | enable = true; 27 | xdgOpenUsePortal = true; 28 | extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; 29 | config.common.default = [ "hyprland" "gtk" ]; 30 | }; 31 | 32 | fonts.packages = lib.mkIf cfg.fonts.enable ( 33 | with pkgs; [ 34 | fira-code 35 | fira-code-symbols 36 | nerd-fonts.fira-code 37 | nerd-fonts.hack 38 | nerd-fonts.ubuntu 39 | noto-fonts 40 | noto-fonts-color-emoji 41 | noto-fonts-color-emoji 42 | ubuntu-classic 43 | liberation_ttf 44 | ] 45 | ); 46 | }; 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /hosts/nixbook/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ "kvm-intel" ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | fileSystems."/" = 17 | { device = "/dev/disk/by-uuid/149d9f19-5202-4348-8f4d-ece8cea5d219"; 18 | fsType = "btrfs"; 19 | options = [ "subvol=@" ]; 20 | }; 21 | 22 | fileSystems."/home" = 23 | { device = "/dev/disk/by-uuid/149d9f19-5202-4348-8f4d-ece8cea5d219"; 24 | fsType = "btrfs"; 25 | options = [ "subvol=@home" ]; 26 | }; 27 | 28 | fileSystems."/boot" = 29 | { device = "/dev/disk/by-uuid/8818-3ECD"; 30 | fsType = "vfat"; 31 | options = [ "fmask=0077" "dmask=0077" ]; 32 | }; 33 | 34 | swapDevices = 35 | [ { device = "/dev/disk/by-uuid/9c39a56b-f178-4f24-b3ad-f658a4385331"; } 36 | ]; 37 | 38 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 39 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 40 | } 41 | -------------------------------------------------------------------------------- /configs/waybar-rvbee.css: -------------------------------------------------------------------------------- 1 | /* RVBEE-inspired Waybar theme */ 2 | * { font-family: "FiraCode Nerd Font", "Fira Code", monospace; font-size: 12pt; } 3 | window#waybar { background: rgba(10, 10, 16, 0.75); color: #e6e6e6; border-bottom: 2px solid #00ffd2; } 4 | #workspaces { padding: 0 8px; background: transparent; border: none; margin: 0 4px; } 5 | #workspaces button { padding: 4px 10px; color: #9ae6ff; border: 1px solid transparent; margin: 2px; } 6 | #workspaces button.active { color: #0a0a10; background: linear-gradient(135deg, #00ffd2, #ff00aa); border-color: #00ffd2; } 7 | #workspaces button.urgent { background: #ff0055; color: #fff; } 8 | #workspaces button label { font-weight: 700; font-size: 14pt; } 9 | #clock, #memory, #cpu, #tray, #network, #pulseaudio, #custom-public_ip, #custom-amd_gpu, #custom-weather, #custom-dunst, #window { padding: 0 10px; } 10 | #clock { color: #ffe86b; } 11 | #network { color: #7af7a7; } 12 | #pulseaudio.muted { color: #888; } 13 | #custom-amd_gpu { color: #ff8bd1; } 14 | #custom-weather { color: #7ad1ff; } 15 | #custom-btc { color: #F7931A; } 16 | #window { color: #e6e6e6; } 17 | tooltip { background: #0f0f17; color: #f2f2f2; border: 1px solid #00ffd2; } 18 | .modules-left > widget, .modules-center > widget, .modules-right > widget { background-color: rgba(20, 20, 32, 0.55); border: none; border-radius: 8px; padding: 2px 10px; margin: 2px 4px; } 19 | #cpu { min-width: 8em; } #memory { min-width: 8em; } #network { min-width: 14em; } #pulseaudio { min-width: 8em; } 20 | 21 | 22 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-clock-multizone.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Waybar clock module with multiple timezones 4 | # This script generates a tooltip showing current time in multiple timezones 5 | 6 | # Get current date and time 7 | current_date=$(date '+%Y-%m-%d') 8 | current_time=$(date '+%H:%M:%S') 9 | 10 | # Get times in different timezones 11 | pacific_time=$(TZ='America/Los_Angeles' date '+%I:%M %p') 12 | central_time=$(TZ='America/Chicago' date '+%I:%M %p') 13 | eastern_time=$(TZ='America/New_York' date '+%I:%M %p') 14 | london_time=$(TZ='Europe/London' date '+%I:%M %p') 15 | utc_time=$(TZ='UTC' date '+%I:%M %p') 16 | 17 | # Get timezone abbreviations 18 | pacific_tz=$(TZ='America/Los_Angeles' date '+%Z') 19 | central_tz=$(TZ='America/Chicago' date '+%Z') 20 | eastern_tz=$(TZ='America/New_York' date '+%Z') 21 | london_tz=$(TZ='Europe/London' date '+%Z') 22 | 23 | # Get current day of week 24 | day_of_week=$(date '+%A') 25 | 26 | # Generate calendar (simple version) 27 | calendar=$(cal | sed 's/^/ /') 28 | 29 | # Create the tooltip content 30 | tooltip="${day_of_week}, ${current_date} 31 | ${current_time} 32 | 33 | Time Zones: 34 | 🌅 Pacific (${pacific_tz}): ${pacific_time} 35 | 🌆 Central (${central_tz}): ${central_time} 36 | 🌃 Eastern (${eastern_tz}): ${eastern_time} 37 | 🌍 London (${london_tz}): ${london_time} 38 | 🌐 UTC: ${utc_time} 39 | 40 | Calendar: 41 | ${calendar}" 42 | 43 | # Output the tooltip 44 | echo "$tooltip" 45 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-crypto-cmc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import json 3 | import os 4 | import sys 5 | import urllib.request 6 | 7 | API_KEY = os.environ.get("COINMARKETCAPAPIKEY", "") 8 | SYMBOLS = os.environ.get("CMC_SYMBOLS", "BTC,ETH").split(",") 9 | CURRENCY = os.environ.get("CMC_CURRENCY", "USD") 10 | 11 | URL = ( 12 | "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=" 13 | + ",".join([s.strip().upper() for s in SYMBOLS]) 14 | + "&convert=" 15 | + CURRENCY 16 | ) 17 | 18 | def main(): 19 | if not API_KEY: 20 | print(json.dumps({"text": "CRYPTO?", "tooltip": "Set COINMARKETCAPAPIKEY"})) 21 | return 0 22 | try: 23 | req = urllib.request.Request(URL, headers={"X-CMC_PRO_API_KEY": API_KEY}) 24 | with urllib.request.urlopen(req, timeout=4) as resp: 25 | data = json.load(resp) 26 | parts = [] 27 | tip = [] 28 | for sym in [s.strip().upper() for s in SYMBOLS]: 29 | q = data["data"][sym]["quote"][CURRENCY] 30 | price = q["price"] 31 | change = q["percent_change_24h"] 32 | parts.append(f"{sym} {price:,.0f}") 33 | tip.append(f"{sym}: {price:,.2f} ({change:+.2f}% 24h)") 34 | text = " | ".join(parts) 35 | tooltip = "\n".join(tip) 36 | print(json.dumps({"text": text, "tooltip": tooltip})) 37 | except Exception as e: 38 | print(json.dumps({"text": "CRYPTO?", "tooltip": f"CMC error: {e}"})) 39 | return 0 40 | 41 | if __name__ == "__main__": 42 | sys.exit(main()) 43 | 44 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-crypto-cmc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import json 3 | import os 4 | import sys 5 | import urllib.request 6 | 7 | API_KEY = os.environ.get("COINMARKETCAPAPIKEY", "") 8 | SYMBOLS = os.environ.get("CMC_SYMBOLS", "BTC,ETH").split(",") 9 | CURRENCY = os.environ.get("CMC_CURRENCY", "USD") 10 | 11 | URL = ( 12 | "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=" 13 | + ",".join([s.strip().upper() for s in SYMBOLS]) 14 | + "&convert=" 15 | + CURRENCY 16 | ) 17 | 18 | def main(): 19 | if not API_KEY: 20 | print(json.dumps({"text": "CRYPTO?", "tooltip": "Set COINMARKETCAPAPIKEY"})) 21 | return 0 22 | try: 23 | req = urllib.request.Request(URL, headers={"X-CMC_PRO_API_KEY": API_KEY}) 24 | with urllib.request.urlopen(req, timeout=4) as resp: 25 | data = json.load(resp) 26 | parts = [] 27 | tip = [] 28 | for sym in [s.strip().upper() for s in SYMBOLS]: 29 | q = data["data"][sym]["quote"][CURRENCY] 30 | price = q["price"] 31 | change = q["percent_change_24h"] 32 | parts.append(f"{sym} {price:,.0f}") 33 | tip.append(f"{sym}: {price:,.2f} ({change:+.2f}% 24h)") 34 | text = " | ".join(parts) 35 | tooltip = "\n".join(tip) 36 | print(json.dumps({"text": text, "tooltip": tooltip})) 37 | except Exception as e: 38 | print(json.dumps({"text": "CRYPTO?", "tooltip": f"CMC error: {e}"})) 39 | return 0 40 | 41 | if __name__ == "__main__": 42 | sys.exit(main()) 43 | 44 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-crypto-cmc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import json 3 | import os 4 | import sys 5 | import urllib.request 6 | 7 | API_KEY = os.environ.get("COINMARKETCAPAPIKEY", "") 8 | SYMBOLS = os.environ.get("CMC_SYMBOLS", "BTC,ETH").split(",") 9 | CURRENCY = os.environ.get("CMC_CURRENCY", "USD") 10 | 11 | URL = ( 12 | "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=" 13 | + ",".join([s.strip().upper() for s in SYMBOLS]) 14 | + "&convert=" 15 | + CURRENCY 16 | ) 17 | 18 | def main(): 19 | if not API_KEY: 20 | print(json.dumps({"text": "CRYPTO?", "tooltip": "Set COINMARKETCAPAPIKEY"})) 21 | return 0 22 | try: 23 | req = urllib.request.Request(URL, headers={"X-CMC_PRO_API_KEY": API_KEY}) 24 | with urllib.request.urlopen(req, timeout=4) as resp: 25 | data = json.load(resp) 26 | parts = [] 27 | tip = [] 28 | for sym in [s.strip().upper() for s in SYMBOLS]: 29 | q = data["data"][sym]["quote"][CURRENCY] 30 | price = q["price"] 31 | change = q["percent_change_24h"] 32 | parts.append(f"{sym} {price:,.0f}") 33 | tip.append(f"{sym}: {price:,.2f} ({change:+.2f}% 24h)") 34 | text = " | ".join(parts) 35 | tooltip = "\n".join(tip) 36 | print(json.dumps({"text": text, "tooltip": tooltip})) 37 | except Exception as e: 38 | print(json.dumps({"text": "CRYPTO?", "tooltip": f"CMC error: {e}"})) 39 | return 0 40 | 41 | if __name__ == "__main__": 42 | sys.exit(main()) 43 | 44 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-clock.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Custom Waybar clock module with multi-timezone tooltip 4 | # This script outputs JSON with both text and tooltip 5 | 6 | # Get current time in local timezone 7 | current_time=$(date '+%I:%M %p') 8 | 9 | # Get times in different timezones 10 | pacific_time=$(TZ='America/Los_Angeles' date '+%I:%M %p') 11 | central_time=$(TZ='America/Chicago' date '+%I:%M %p') 12 | eastern_time=$(TZ='America/New_York' date '+%I:%M %p') 13 | london_time=$(TZ='Europe/London' date '+%I:%M %p') 14 | utc_time=$(TZ='UTC' date '+%I:%M %p') 15 | 16 | # Get timezone abbreviations 17 | pacific_tz=$(TZ='America/Los_Angeles' date '+%Z') 18 | central_tz=$(TZ='America/Chicago' date '+%Z') 19 | eastern_tz=$(TZ='America/New_York' date '+%Z') 20 | london_tz=$(TZ='Europe/London' date '+%Z') 21 | 22 | # Get current date and day of week 23 | current_date=$(date '+%Y-%m-%d') 24 | day_of_week=$(date '+%A') 25 | current_time_24=$(date '+%H:%M:%S') 26 | 27 | # Generate calendar (simple version) 28 | calendar=$(cal | sed 's/^/ /') 29 | 30 | # Create tooltip content with proper escaping (simplified HTML) 31 | tooltip="${day_of_week}, ${current_date} | ${current_time_24} 32 | 33 | Time Zones: 34 | Pacific (${pacific_tz}): ${pacific_time} 35 | Central (${central_tz}): ${central_time} 36 | Eastern (${eastern_tz}): ${eastern_time} 37 | London (${london_tz}): ${london_time} 38 | UTC: ${utc_time} 39 | 40 | Calendar: 41 | ${calendar}" 42 | 43 | # Use jq to properly format JSON with escaped newlines (compact output) 44 | jq -n -c \ 45 | --arg text "$current_time" \ 46 | --arg tooltip "$tooltip" \ 47 | '{"text": $text, "tooltip": $tooltip}' 48 | -------------------------------------------------------------------------------- /modules/shared/services.nix: -------------------------------------------------------------------------------- 1 | { lib, config, pkgs, ... }: 2 | let cfg = config.hyprvibe.services; 3 | in { 4 | options.hyprvibe.services = { 5 | enable = lib.mkEnableOption "Shared baseline services (pipewire, flatpak, polkit, sudo)"; 6 | openssh.enable = lib.mkEnableOption "OpenSSH server"; 7 | tailscale.enable = lib.mkEnableOption "Tailscale"; 8 | virt.enable = lib.mkEnableOption "Virtualization (libvirtd)"; 9 | docker.enable = lib.mkEnableOption "Docker"; 10 | }; 11 | 12 | config = lib.mkIf cfg.enable { 13 | services.pipewire = { 14 | enable = true; 15 | alsa.enable = true; 16 | alsa.support32Bit = true; 17 | pulse.enable = true; 18 | jack.enable = true; 19 | }; 20 | services.flatpak.enable = true; 21 | security.polkit.enable = true; 22 | security.rtkit.enable = true; 23 | security.sudo.wheelNeedsPassword = false; 24 | 25 | # Desktop support services common to both hosts 26 | services.udisks2.enable = true; 27 | services.gvfs.enable = true; 28 | services.tumbler.enable = true; 29 | services.blueman.enable = true; 30 | services.avahi = { 31 | enable = true; 32 | nssmdns4 = true; 33 | }; 34 | services.davfs2.enable = true; 35 | services.gnome.gnome-keyring.enable = true; 36 | 37 | services.openssh.enable = lib.mkIf cfg.openssh.enable true; 38 | services.tailscale = lib.mkIf cfg.tailscale.enable { 39 | enable = true; 40 | useRoutingFeatures = "both"; 41 | }; 42 | virtualisation.libvirtd.enable = lib.mkIf cfg.virt.enable true; 43 | virtualisation.docker.enable = lib.mkIf cfg.docker.enable true; 44 | }; 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /configs/waybar-scripts/waybar-weather.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | geo_json=$(curl -fsS --max-time 2 https://ipapi.co/json/ 2>/dev/null || true) 5 | if [[ -z "${geo_json}" ]]; then 6 | echo '{"text":"☁ ?°F","tooltip":"Weather unavailable"}' 7 | exit 0 8 | fi 9 | 10 | city=$(jq -r '.city // empty' <<<"${geo_json}" 2>/dev/null || true) 11 | lat=$(jq -r '.latitude // empty' <<<"${geo_json}" 2>/dev/null || true) 12 | lon=$(jq -r '.longitude // empty' <<<"${geo_json}" 2>/dev/null || true) 13 | 14 | if [[ -z "${lat}" || -z "${lon}" ]]; then 15 | echo '{"text":"☁ ?°F","tooltip":"Weather location unavailable"}' 16 | exit 0 17 | fi 18 | 19 | weather_json=$(curl -fsS --max-time 3 "https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,apparent_temperature,precipitation,weather_code&hourly=temperature_2m&temperature_unit=fahrenheit&timezone=auto" 2>/dev/null || true) 20 | if [[ -z "${weather_json}" ]]; then 21 | echo '{"text":"☁ ?°F","tooltip":"Weather request failed"}' 22 | exit 0 23 | fi 24 | 25 | temp=$(jq -r '.current.temperature_2m // empty' <<<"${weather_json}" 2>/dev/null || true) 26 | appt=$(jq -r '.current.apparent_temperature // empty' <<<"${weather_json}" 2>/dev/null || true) 27 | code=$(jq -r '.current.weather_code // empty' <<<"${weather_json}" 2>/dev/null || true) 28 | 29 | icon="☁" 30 | case "${code}" in 31 | 0) icon="☀" ;; 32 | 1|2|3) icon="⛅" ;; 33 | 45|48) icon="🌫" ;; 34 | 51|53|55) icon="🌦" ;; 35 | 61|63|65) icon="🌧" ;; 36 | 71|73|75) icon="❄" ;; 37 | 80|81|82) icon="🌧" ;; 38 | 95|96|99) icon="⛈" ;; 39 | esac 40 | 41 | text="${icon} ${temp:-?}°F" 42 | tooltip="${city:-Weather}: ${temp:-?}°F (feels ${appt:-?}°F)" 43 | printf '{"text":"%s","tooltip":"%s"}\n' "$text" "$tooltip" 44 | 45 | 46 | -------------------------------------------------------------------------------- /hosts/rvbee/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { 5 | config, 6 | lib, 7 | pkgs, 8 | modulesPath, 9 | ... 10 | }: { 11 | imports = [ 12 | (modulesPath + "/installer/scan/not-detected.nix") 13 | ]; 14 | 15 | boot.initrd.availableKernelModules = ["nvme" "xhci_pci" "usbhid" "usb_storage" "sd_mod"]; 16 | boot.initrd.kernelModules = []; 17 | boot.kernelModules = ["kvm-amd"]; 18 | boot.extraModulePackages = []; 19 | boot.kernelParams = ["amdgpu.securedisplay=0" "preempt=full" "threadirqs"]; 20 | fileSystems."/" = { 21 | device = "/dev/disk/by-uuid/0a78cb30-c575-4884-ba20-c542212f7acb"; 22 | fsType = "btrfs"; 23 | options = ["subvol=@"]; 24 | }; 25 | 26 | fileSystems."/boot" = { 27 | device = "/dev/disk/by-uuid/ECD0-A62C"; 28 | fsType = "vfat"; 29 | options = ["fmask=0022" "dmask=0022"]; 30 | }; 31 | 32 | swapDevices = []; 33 | 34 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 35 | # (the default) this is the recommended approach. When using systemd-networkd it's 36 | # still possible to use this option, but it's recommended to use it in conjunction 37 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 38 | networking.useDHCP = lib.mkDefault true; 39 | # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; 40 | # networking.interfaces.enp4s0f4u1u4u4.useDHCP = lib.mkDefault true; 41 | # networking.interfaces.wlo1.useDHCP = lib.mkDefault true; 42 | 43 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 44 | hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 45 | } 46 | -------------------------------------------------------------------------------- /scripts/waybar-switch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Waybar Configuration Switcher 4 | # This script allows switching between full and simple waybar configurations 5 | 6 | CONFIG_DIR="/home/chrisf/.config/waybar" 7 | FULL_CONFIG="$CONFIG_DIR/config" 8 | SIMPLE_CONFIG="$CONFIG_DIR/simple-config" 9 | 10 | case "${1:-help}" in 11 | "full") 12 | echo "Switching to full waybar configuration..." 13 | pkill waybar 14 | sleep 1 15 | waybar -c "$FULL_CONFIG" -s "$CONFIG_DIR/style.css" & 16 | echo "Full waybar started" 17 | ;; 18 | "simple") 19 | echo "Switching to simple waybar configuration..." 20 | pkill waybar 21 | sleep 1 22 | waybar -c "$SIMPLE_CONFIG" -s "$CONFIG_DIR/style.css" & 23 | echo "Simple waybar started" 24 | ;; 25 | "status") 26 | if pgrep waybar > /dev/null; then 27 | echo "Waybar is running" 28 | if [ -f "$FULL_CONFIG" ] && [ "$(readlink -f "$CONFIG_DIR/config")" = "$(readlink -f "$FULL_CONFIG")" ]; then 29 | echo "Current config: Full" 30 | else 31 | echo "Current config: Simple" 32 | fi 33 | else 34 | echo "Waybar is not running" 35 | fi 36 | ;; 37 | "help"|*) 38 | echo "Usage: $0 " 39 | echo "" 40 | echo "Commands:" 41 | echo " full - Switch to full waybar configuration (all modules)" 42 | echo " simple - Switch to simple waybar configuration (workspaces, window, clock only)" 43 | echo " status - Show current waybar status and configuration" 44 | echo " help - Show this help message" 45 | echo "" 46 | echo "Examples:" 47 | echo " $0 full # Switch to full configuration" 48 | echo " $0 simple # Switch to simple configuration" 49 | ;; 50 | esac 51 | -------------------------------------------------------------------------------- /configs/waybar-scripts/waybar-amd-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | format_output() { 5 | local text tooltip 6 | text="$1" 7 | tooltip="$2" 8 | echo "{\"text\": \"${text}\", \"tooltip\": \"${tooltip}\"}" 9 | } 10 | 11 | card_index="" 12 | for dev in /sys/class/drm/card*/device; do 13 | [[ -e "$dev" ]] || continue 14 | if [[ -r "$dev/vendor" ]] && grep -qi "0x1002" "$dev/vendor"; then 15 | card_index=$(basename "$(dirname "$dev")" | sed 's/card//') 16 | gpu_path="$dev" 17 | break 18 | fi 19 | done 20 | 21 | temp_c=""; power_w=""; util="" 22 | if [[ -n "${gpu_path:-}" && -r "${gpu_path}/hwmon" ]]; then 23 | hwmon_dir=$(readlink -f "${gpu_path}/hwmon"/* 2>/dev/null || true) 24 | if [[ -n "${hwmon_dir}" ]]; then 25 | [[ -r "${hwmon_dir}/temp1_input" ]] && temp_c=$(( $(cat "${hwmon_dir}/temp1_input" 2>/dev/null || echo 0) / 1000 )) 26 | if [[ -r "${hwmon_dir}/power1_average" ]]; then 27 | p_raw=$(cat "${hwmon_dir}/power1_average" 2>/dev/null || echo 0) 28 | power_w=$(awk -v v="${p_raw}" 'BEGIN{ printf "%.1f", v/1000000 }') 29 | fi 30 | fi 31 | fi 32 | 33 | if [[ -n "${gpu_path:-}" && -r "${gpu_path}/gpu_busy_percent" ]]; then 34 | util=$(cat "${gpu_path}/gpu_busy_percent" 2>/dev/null | tr -dc '0-9') 35 | elif [[ -n "${card_index}" && -r "/sys/kernel/debug/dri/${card_index}/amdgpu_pm_info" ]]; then 36 | pm_info=$(cat "/sys/kernel/debug/dri/${card_index}/amdgpu_pm_info" 2>/dev/null || true) 37 | util=$(grep -iE 'GPU load' <<<"${pm_info}" | awk '{print $(NF-1)}' | tr -d '%') 38 | fi 39 | 40 | parts=() 41 | [[ -n "${util}" ]] && parts+=("${util}%") 42 | [[ -n "${temp_c}" ]] && parts+=("${temp_c}°C") 43 | [[ -n "${power_w}" ]] && parts+=("${power_w}W") 44 | 45 | text=""; tooltip="AMD GPU" 46 | if [[ ${#parts[@]} -gt 0 ]]; then text="${parts[*]}"; tooltip="AMD GPU: ${parts[*]}"; fi 47 | format_output "${text}" "${tooltip}" 48 | 49 | 50 | -------------------------------------------------------------------------------- /~/.local/bin/switch-oh-my-posh-theme: -------------------------------------------------------------------------------- 1 | #!/run/current-system/sw/bin/bash 2 | 3 | # Oh My Posh Theme Switcher 4 | # Available themes: default, enhanced, minimal, professional 5 | 6 | THEME_DIR="$HOME/.config/oh-my-posh" 7 | DEFAULT_CONFIG="$THEME_DIR/config.json" 8 | 9 | # Available themes 10 | declare -A THEMES=( 11 | ["default"]="config.json" 12 | ["enhanced"]="config-enhanced.json" 13 | ["minimal"]="config-minimal.json" 14 | ["professional"]="config-professional.json" 15 | ) 16 | 17 | # Function to show usage 18 | show_usage() { 19 | echo "Usage: $0 [theme]" 20 | echo "" 21 | echo "Available themes:" 22 | for theme in "${!THEMES[@]}"; do 23 | echo " $theme" 24 | done 25 | echo "" 26 | echo "Examples:" 27 | echo " $0 enhanced" 28 | echo " $0 minimal" 29 | echo " $0 professional" 30 | echo " $0 default" 31 | } 32 | 33 | # Function to switch theme 34 | switch_theme() { 35 | local theme_name="$1" 36 | local source_file="$THEME_DIR/${THEMES[$theme_name]}" 37 | 38 | if [[ ! -f "$source_file" ]]; then 39 | echo "Error: Theme file '$source_file' not found!" 40 | return 1 41 | fi 42 | 43 | # Create backup of current config 44 | if [[ -f "$DEFAULT_CONFIG" ]]; then 45 | cp "$DEFAULT_CONFIG" "$DEFAULT_CONFIG.bak.$(date +%Y%m%d-%H%M%S)" 46 | fi 47 | 48 | # Copy the selected theme to config.json 49 | cp "$source_file" "$DEFAULT_CONFIG" 50 | 51 | echo "✅ Switched to '$theme_name' theme!" 52 | echo "🔄 Restart your terminal or run 'source ~/.config/fish/conf.d/oh-my-posh.fish' to see changes." 53 | } 54 | 55 | # Main script logic 56 | if [[ $# -eq 0 ]]; then 57 | show_usage 58 | exit 1 59 | fi 60 | 61 | theme="$1" 62 | 63 | if [[ ! ${THEMES[$theme]+_} ]]; then 64 | echo "Error: Unknown theme '$theme'" 65 | echo "" 66 | show_usage 67 | exit 1 68 | fi 69 | 70 | switch_theme "$theme" 71 | -------------------------------------------------------------------------------- /modules/shared/packages.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, config, ... }: 2 | let 3 | cfg = config.hyprvibe.packages; 4 | # Curated common sets derived from overlaps across hosts 5 | basePackages = with pkgs; [ 6 | htop btop tree lsof lshw neofetch nmap zip unzip gnupg curl file jq bat fd fzf ripgrep tldr 7 | whois plocate less eza grc cursor-cli 8 | ]; 9 | desktopPackages = with pkgs; [ 10 | wl-clipboard grim slurp swappy wf-recorder dunst cliphist brightnessctl playerctl pavucontrol 11 | # qt6ct # Temporarily disabled - pulls in qgnomeplatform which has build failure in current nixpkgs 12 | # Core desktop apps 13 | kitty rofi bibata-cursors 14 | # Hyprland companions started by base config 15 | hyprpaper hypridle hyprlock 16 | ]; 17 | devPackages = with pkgs; [ 18 | git gh gitui gcc gnumake cmake binutils patchelf python3 go nodejs_20 yarn imagemagick 19 | ]; 20 | gamingPackages = with pkgs; [ 21 | steam-run lutris moonlight-qt sunshine vulkan-tools 22 | ]; 23 | in { 24 | options.hyprvibe.packages = { 25 | enable = lib.mkEnableOption "Shared package groups"; 26 | base.enable = lib.mkEnableOption "Common CLI utilities"; 27 | desktop.enable = lib.mkEnableOption "Desktop helpers for Wayland sessions"; 28 | dev.enable = lib.mkEnableOption "Developer toolchain"; 29 | gaming.enable = lib.mkEnableOption "Gaming helpers"; 30 | extraPackages = lib.mkOption { 31 | type = with lib.types; listOf package; 32 | default = []; 33 | description = "Additional packages to append to shared packages."; 34 | }; 35 | }; 36 | 37 | config = lib.mkIf cfg.enable { 38 | environment.systemPackages = 39 | (lib.optionals cfg.base.enable basePackages) 40 | ++ (lib.optionals cfg.desktop.enable desktopPackages) 41 | ++ (lib.optionals cfg.dev.enable devPackages) 42 | ++ (lib.optionals cfg.gaming.enable gamingPackages) 43 | ++ cfg.extraPackages; 44 | }; 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-weather.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Get geolocation by IP and then weather in Fahrenheit 5 | # Providers kept simple and low-frequency to avoid rate limits. 6 | 7 | geo_json=$(curl -fsS --max-time 2 https://ipapi.co/json/ 2>/dev/null || true) 8 | if [[ -z "${geo_json}" ]]; then 9 | echo '{"text":"☁ ?°F","tooltip":"Weather unavailable"}' 10 | exit 0 11 | fi 12 | 13 | city=$(jq -r '.city // empty' <<<"${geo_json}" 2>/dev/null || true) 14 | lat=$(jq -r '.latitude // empty' <<<"${geo_json}" 2>/dev/null || true) 15 | lon=$(jq -r '.longitude // empty' <<<"${geo_json}" 2>/dev/null || true) 16 | 17 | if [[ -z "${lat}" || -z "${lon}" ]]; then 18 | echo '{"text":"☁ ?°F","tooltip":"Weather location unavailable"}' 19 | exit 0 20 | fi 21 | 22 | # Use open-meteo free API (no key). Request Fahrenheit units. 23 | weather_json=$(curl -fsS --max-time 3 "https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,apparent_temperature,precipitation,weather_code&hourly=temperature_2m&temperature_unit=fahrenheit&timezone=auto" 2>/dev/null || true) 24 | 25 | if [[ -z "${weather_json}" ]]; then 26 | echo '{"text":"☁ ?°F","tooltip":"Weather request failed"}' 27 | exit 0 28 | fi 29 | 30 | temp=$(jq -r '.current.temperature_2m // empty' <<<"${weather_json}" 2>/dev/null || true) 31 | appt=$(jq -r '.current.apparent_temperature // empty' <<<"${weather_json}" 2>/dev/null || true) 32 | code=$(jq -r '.current.weather_code // empty' <<<"${weather_json}" 2>/dev/null || true) 33 | 34 | icon="☁" 35 | case "${code}" in 36 | 0) icon="☀" ;; 37 | 1|2|3) icon="⛅" ;; 38 | 45|48) icon="🌫" ;; 39 | 51|53|55) icon="🌦" ;; 40 | 61|63|65) icon="🌧" ;; 41 | 71|73|75) icon="❄" ;; 42 | 80|81|82) icon="🌧" ;; 43 | 95|96|99) icon="⛈" ;; 44 | esac 45 | 46 | text="${icon} ${temp:-?}°F" 47 | tooltip="${city:-Weather}: ${temp:-?}°F (feels ${appt:-?}°F)" 48 | 49 | printf '{"text":"%s","tooltip":"%s"}\n' "$text" "$tooltip" 50 | 51 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-weather.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Get geolocation by IP and then weather in Fahrenheit 5 | # Providers kept simple and low-frequency to avoid rate limits. 6 | 7 | geo_json=$(curl -fsS --max-time 2 https://ipapi.co/json/ 2>/dev/null || true) 8 | if [[ -z "${geo_json}" ]]; then 9 | echo '{"text":"☁ ?°F","tooltip":"Weather unavailable"}' 10 | exit 0 11 | fi 12 | 13 | city=$(jq -r '.city // empty' <<<"${geo_json}" 2>/dev/null || true) 14 | lat=$(jq -r '.latitude // empty' <<<"${geo_json}" 2>/dev/null || true) 15 | lon=$(jq -r '.longitude // empty' <<<"${geo_json}" 2>/dev/null || true) 16 | 17 | if [[ -z "${lat}" || -z "${lon}" ]]; then 18 | echo '{"text":"☁ ?°F","tooltip":"Weather location unavailable"}' 19 | exit 0 20 | fi 21 | 22 | # Use open-meteo free API (no key). Request Fahrenheit units. 23 | weather_json=$(curl -fsS --max-time 3 "https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,apparent_temperature,precipitation,weather_code&hourly=temperature_2m&temperature_unit=fahrenheit&timezone=auto" 2>/dev/null || true) 24 | 25 | if [[ -z "${weather_json}" ]]; then 26 | echo '{"text":"☁ ?°F","tooltip":"Weather request failed"}' 27 | exit 0 28 | fi 29 | 30 | temp=$(jq -r '.current.temperature_2m // empty' <<<"${weather_json}" 2>/dev/null || true) 31 | appt=$(jq -r '.current.apparent_temperature // empty' <<<"${weather_json}" 2>/dev/null || true) 32 | code=$(jq -r '.current.weather_code // empty' <<<"${weather_json}" 2>/dev/null || true) 33 | 34 | icon="☁" 35 | case "${code}" in 36 | 0) icon="☀" ;; 37 | 1|2|3) icon="⛅" ;; 38 | 45|48) icon="🌫" ;; 39 | 51|53|55) icon="🌦" ;; 40 | 61|63|65) icon="🌧" ;; 41 | 71|73|75) icon="❄" ;; 42 | 80|81|82) icon="🌧" ;; 43 | 95|96|99) icon="⛈" ;; 44 | esac 45 | 46 | text="${icon} ${temp:-?}°F" 47 | tooltip="${city:-Weather}: ${temp:-?}°F (feels ${appt:-?}°F)" 48 | 49 | printf '{"text":"%s","tooltip":"%s"}\n' "$text" "$tooltip" 50 | 51 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-weather.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Get geolocation by IP and then weather in Fahrenheit 5 | # Providers kept simple and low-frequency to avoid rate limits. 6 | 7 | geo_json=$(curl -fsS --max-time 2 https://ipapi.co/json/ 2>/dev/null || true) 8 | if [[ -z "${geo_json}" ]]; then 9 | echo '{"text":"󰖐 ?°F","tooltip":"Weather unavailable"}' 10 | exit 0 11 | fi 12 | 13 | city=$(jq -r '.city // empty' <<<"${geo_json}" 2>/dev/null || true) 14 | lat=$(jq -r '.latitude // empty' <<<"${geo_json}" 2>/dev/null || true) 15 | lon=$(jq -r '.longitude // empty' <<<"${geo_json}" 2>/dev/null || true) 16 | 17 | if [[ -z "${lat}" || -z "${lon}" ]]; then 18 | echo '{"text":"󰖐 ?°F","tooltip":"Weather location unavailable"}' 19 | exit 0 20 | fi 21 | 22 | # Use open-meteo free API (no key). Request Fahrenheit units. 23 | weather_json=$(curl -fsS --max-time 3 "https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,apparent_temperature,precipitation,weather_code&hourly=temperature_2m&temperature_unit=fahrenheit&timezone=auto" 2>/dev/null || true) 24 | 25 | if [[ -z "${weather_json}" ]]; then 26 | echo '{"text":"󰖐 ?°F","tooltip":"Weather request failed"}' 27 | exit 0 28 | fi 29 | 30 | temp=$(jq -r '.current.temperature_2m // empty' <<<"${weather_json}" 2>/dev/null || true) 31 | appt=$(jq -r '.current.apparent_temperature // empty' <<<"${weather_json}" 2>/dev/null || true) 32 | code=$(jq -r '.current.weather_code // empty' <<<"${weather_json}" 2>/dev/null || true) 33 | 34 | icon="󰖐" 35 | case "${code}" in 36 | 0) icon="󰖙" ;; 37 | 1|2|3) icon="󰖐" ;; 38 | 45|48) icon="󰖑" ;; 39 | 51|53|55) icon="󰖐" ;; 40 | 61|63|65) icon="󰖗" ;; 41 | 71|73|75) icon="󰖘" ;; 42 | 80|81|82) icon="󰖗" ;; 43 | 95|96|99) icon="󰖓" ;; 44 | esac 45 | 46 | text="${icon} ${temp:-?}°F" 47 | tooltip="${city:-Weather}: ${temp:-?}°F (feels ${appt:-?}°F)" 48 | 49 | printf '{"text":"%s","tooltip":"%s"}\n' "$text" "$tooltip" 50 | 51 | -------------------------------------------------------------------------------- /configs/waybar-scripts/rofi-brightness.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | get_percent() { 5 | if ls /sys/class/backlight >/dev/null 2>&1 && [ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]; then 6 | brightnessctl -m | awk -F, '{gsub("%","", $4); print $4}' 2>/dev/null || true 7 | elif command -v ddcutil >/dev/null 2>&1; then 8 | ddcutil getvcp 0x10 --terse 2>/dev/null | awk '{print $(NF-1)}' || true 9 | fi 10 | } 11 | 12 | has_kernel_backlight() { 13 | ls /sys/class/backlight >/dev/null 2>&1 && [ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ] 14 | } 15 | 16 | adjust_kernel() { brightnessctl set "$1" >/dev/null 2>&1 || false; } 17 | 18 | adjust_ddc() { 19 | local req="$1"; local ok=0 20 | while read -r busdev; do 21 | [ -n "$busdev" ] || continue 22 | busnum="${busdev##*-}" 23 | read -r cur max < <(ddcutil --bus "$busnum" getvcp 0x10 --terse 2>/dev/null | awk '{print $(NF-1), $NF}') 24 | cur=${cur:-0}; max=${max:-100} 25 | local target 26 | if [[ "$req" =~ ^[+-] ]]; then target=$(( cur + ${req} )); else target=$req; fi 27 | if [ "$target" -lt 0 ]; then target=0; fi 28 | if [ "$target" -gt "$max" ]; then target=$max; fi 29 | if ddcutil --bus "$busnum" setvcp 0x10 "$target" >/dev/null 2>&1; then ok=1; fi 30 | done < <(ddcutil detect --terse 2>/dev/null | awk '/I2C bus:/ {print $3}') 31 | [ $ok -eq 1 ] 32 | } 33 | 34 | current="$(get_percent || echo "?")" 35 | if ! command -v rofi >/dev/null 2>&1; then 36 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "rofi not found" 37 | exit 1 38 | fi 39 | 40 | choice=$(printf "%s\n" "+5%" "-5%" "25%" "50%" "75%" "100%" | rofi -dmenu -p "Brightness (${current}% )" -i) 41 | if [ -n "${choice:-}" ]; then 42 | if has_kernel_backlight; then adjust_kernel "$choice"; else adjust_ddc "${choice%%%}"; fi 43 | newp=$(get_percent || echo "?") 44 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Set to: $choice (now ${newp}%)" 45 | else 46 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Cancelled" 47 | fi 48 | 49 | 50 | -------------------------------------------------------------------------------- /hosts/nixstation/hyprland.conf: -------------------------------------------------------------------------------- 1 | # Hyprland Configuration for Nixstation 2 | # See https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ 3 | 4 | # Source shared base configuration (Hyprland doesn't expand ~) 5 | source = /home/chrisf/.config/hypr/hyprland-base.conf 6 | 7 | # Source host-specific monitor configuration 8 | source = /home/chrisf/.config/hypr/hyprland-monitors-nixstation.conf 9 | 10 | # Nixstation-specific overrides and additions can go here 11 | # For example: 12 | # - Machine-specific keybindings 13 | # - Hardware-specific settings 14 | # - Performance tweaks for 4-monitor setup 15 | 16 | # Reaper window rules - Fix X11/XWayland window management issues 17 | # Main Reaper window: keep tiled (not floating) so it works with other windows 18 | # This ensures Reaper integrates properly with tiling and doesn't stay on top 19 | windowrulev2 = tile, class:^(reaper)$ 20 | windowrulev2 = windowdance, class:^(reaper)$ 21 | 22 | # Reaper dialogs and popups: float and center them 23 | # Match common Reaper dialog titles 24 | windowrulev2 = float, class:^(reaper)$, title:.*(Render|Export|Preferences|Settings|About|Dialog|Popup|Message|Warning|Error|Save|Open|Browse).* 25 | windowrulev2 = center, class:^(reaper)$, title:.*(Render|Export|Preferences|Settings|About|Dialog|Popup|Message|Warning|Error|Save|Open|Browse).* 26 | windowrulev2 = size 800 600, class:^(reaper)$, title:.*(Render|Export|Preferences|Settings|About|Dialog|Popup|Message|Warning|Error|Save|Open|Browse).* 27 | 28 | # Handle XWayland transient windows (dialogs) - these are typically child windows 29 | # This catches dialogs that might not have specific titles 30 | windowrulev2 = float, class:^(reaper)$, windowtype:^(dialog|popup_menu|utility)$ 31 | 32 | # Prevent Reaper from creating windows that stay on top unnecessarily 33 | windowrulev2 = noinitialfocus, class:^(reaper)$, title:.*(Render|Export|Preferences|Settings|About|Dialog|Popup|Message|Warning|Error|Save|Open|Browse).* 34 | 35 | # XWayland-specific: improve focus and window behavior for Reaper 36 | windowrulev2 = focusonopen, class:^(reaper)$ 37 | windowrulev2 = suppressevent fullscreen, class:^(reaper)$ -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-brightness.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | adjust() { 5 | local direction amount 6 | direction="$1" 7 | amount="$2" 8 | if ls /sys/class/backlight >/dev/null 2>&1 && [[ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]]; then 9 | if [[ "$direction" == "up" ]]; then 10 | brightnessctl set "+${amount}%" >/dev/null 2>&1 || true 11 | else 12 | brightnessctl set "${amount}%-" >/dev/null 2>&1 || true 13 | fi 14 | elif command -v ddcutil >/dev/null 2>&1; then 15 | # DDC/CI: iterate displays and setvcp 10 16 | # amount 5 or 10; we apply relative +/- 17 | local rel 18 | if [[ "$direction" == "up" ]]; then rel="+${amount}"; else rel="-${amount}"; fi 19 | while read -r busdev; do 20 | # Extract numeric bus id from device path like /dev/i2c-7 21 | busnum="${busdev##*-}" 22 | ddcutil --bus "$busnum" setvcp 10 "${rel}" >/dev/null 2>&1 || true 23 | done < <(ddcutil detect --terse 2>/dev/null | awk '/I2C bus:/ {print $3}') 24 | fi 25 | } 26 | 27 | if [[ "${1:-}" == "--up" && -n "${2:-}" ]]; then 28 | adjust up "$2" 29 | elif [[ "${1:-}" == "--down" && -n "${2:-}" ]]; then 30 | adjust down "$2" 31 | fi 32 | 33 | # Prefer kernel backlight via brightnessctl; fallback to DDC/CI via ddcutil 34 | percent="" 35 | if ls /sys/class/backlight >/dev/null 2>&1 && [[ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]]; then 36 | percent=$(brightnessctl -m | awk -F, '{gsub("%","", $4); print $4}' 2>/dev/null || true) 37 | fi 38 | if [[ -z "${percent}" ]]; then 39 | if command -v ddcutil >/dev/null 2>&1; then 40 | # Query first active display's current brightness using terse output: "VCP 10 C " 41 | percent=$(ddcutil getvcp 10 --terse 2>/dev/null | awk '{print $(NF-1)}' || true) 42 | fi 43 | fi 44 | if [[ -z "${percent}" ]]; then percent="?"; fi 45 | 46 | icon="🌞" 47 | if [[ "$percent" != "?" ]]; then 48 | if (( percent < 20 )); then icon="🌑"; elif (( percent < 50 )); then icon="🌓"; elif (( percent < 80 )); then icon="🌔"; else icon="🌕"; fi 49 | fi 50 | 51 | echo "{\"text\": \"$icon ${percent}%\", \"tooltip\": \"Brightness: ${percent}%\"}" 52 | 53 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-brightness.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | adjust() { 5 | local direction amount 6 | direction="$1" 7 | amount="$2" 8 | if ls /sys/class/backlight >/dev/null 2>&1 && [[ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]]; then 9 | if [[ "$direction" == "up" ]]; then 10 | brightnessctl set "+${amount}%" >/dev/null 2>&1 || true 11 | else 12 | brightnessctl set "${amount}%-" >/dev/null 2>&1 || true 13 | fi 14 | elif command -v ddcutil >/dev/null 2>&1; then 15 | # DDC/CI: iterate displays and setvcp 10 16 | # amount 5 or 10; we apply relative +/- 17 | local rel 18 | if [[ "$direction" == "up" ]]; then rel="+${amount}"; else rel="-${amount}"; fi 19 | while read -r busdev; do 20 | # Extract numeric bus id from device path like /dev/i2c-7 21 | busnum="${busdev##*-}" 22 | ddcutil --bus "$busnum" setvcp 10 "${rel}" >/dev/null 2>&1 || true 23 | done < <(ddcutil detect --terse 2>/dev/null | awk '/I2C bus:/ {print $3}') 24 | fi 25 | } 26 | 27 | if [[ "${1:-}" == "--up" && -n "${2:-}" ]]; then 28 | adjust up "$2" 29 | elif [[ "${1:-}" == "--down" && -n "${2:-}" ]]; then 30 | adjust down "$2" 31 | fi 32 | 33 | # Prefer kernel backlight via brightnessctl; fallback to DDC/CI via ddcutil 34 | percent="" 35 | if ls /sys/class/backlight >/dev/null 2>&1 && [[ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]]; then 36 | percent=$(brightnessctl -m | awk -F, '{gsub("%","", $4); print $4}' 2>/dev/null || true) 37 | fi 38 | if [[ -z "${percent}" ]]; then 39 | if command -v ddcutil >/dev/null 2>&1; then 40 | # Query first active display's current brightness using terse output: "VCP 10 C " 41 | percent=$(ddcutil getvcp 10 --terse 2>/dev/null | awk '{print $(NF-1)}' || true) 42 | fi 43 | fi 44 | if [[ -z "${percent}" ]]; then percent="?"; fi 45 | 46 | icon="🌞" 47 | if [[ "$percent" != "?" ]]; then 48 | if (( percent < 20 )); then icon="🌑"; elif (( percent < 50 )); then icon="🌓"; elif (( percent < 80 )); then icon="🌔"; else icon="🌕"; fi 49 | fi 50 | 51 | echo "{\"text\": \"$icon ${percent}%\", \"tooltip\": \"Brightness: ${percent}%\"}" 52 | 53 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-brightness.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | adjust() { 5 | local direction amount 6 | direction="$1" 7 | amount="$2" 8 | if ls /sys/class/backlight >/dev/null 2>&1 && [[ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]]; then 9 | if [[ "$direction" == "up" ]]; then 10 | brightnessctl set "+${amount}%" >/dev/null 2>&1 || true 11 | else 12 | brightnessctl set "${amount}%-" >/dev/null 2>&1 || true 13 | fi 14 | elif command -v ddcutil >/dev/null 2>&1; then 15 | # DDC/CI: iterate displays and setvcp 10 16 | # amount 5 or 10; we apply relative +/- 17 | local rel 18 | if [[ "$direction" == "up" ]]; then rel="+${amount}"; else rel="-${amount}"; fi 19 | while read -r busdev; do 20 | # Extract numeric bus id from device path like /dev/i2c-7 21 | busnum="${busdev##*-}" 22 | ddcutil --bus "$busnum" setvcp 10 "${rel}" >/dev/null 2>&1 || true 23 | done < <(ddcutil detect --terse 2>/dev/null | awk '/I2C bus:/ {print $3}') 24 | fi 25 | } 26 | 27 | if [[ "${1:-}" == "--up" && -n "${2:-}" ]]; then 28 | adjust up "$2" 29 | elif [[ "${1:-}" == "--down" && -n "${2:-}" ]]; then 30 | adjust down "$2" 31 | fi 32 | 33 | # Prefer kernel backlight via brightnessctl; fallback to DDC/CI via ddcutil 34 | percent="" 35 | if ls /sys/class/backlight >/dev/null 2>&1 && [[ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]]; then 36 | percent=$(brightnessctl -m | awk -F, '{gsub("%","", $4); print $4}' 2>/dev/null || true) 37 | fi 38 | if [[ -z "${percent}" ]]; then 39 | if command -v ddcutil >/dev/null 2>&1; then 40 | # Query first active display's current brightness using terse output: "VCP 10 C " 41 | percent=$(ddcutil getvcp 10 --terse 2>/dev/null | awk '{print $(NF-1)}' || true) 42 | fi 43 | fi 44 | if [[ -z "${percent}" ]]; then percent="?"; fi 45 | 46 | icon="🌞" 47 | if [[ "$percent" != "?" ]]; then 48 | if (( percent < 20 )); then icon="🌑"; elif (( percent < 50 )); then icon="🌓"; elif (( percent < 80 )); then icon="🌔"; else icon="🌕"; fi 49 | fi 50 | 51 | echo "{\"text\": \"$icon ${percent}%\", \"tooltip\": \"Brightness: ${percent}%\"}" 52 | 53 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; 4 | # musnix.url = "github:musnix/musnix"; 5 | # musnix.inputs.nixpkgs.follows = "nixpkgs"; 6 | # companion.url = "github:noblepayne/bitfocus-companion-flake"; 7 | # companion.inputs.nixpkgs.follows = "nixpkgs"; 8 | 9 | prettyswitch.url = "github:noblepayne/pretty-switch"; 10 | prettyswitch.inputs.nixpkgs.follows = "nixpkgs"; 11 | 12 | hyprland.url = "github:hyprwm/Hyprland"; 13 | hyprland.inputs.nixpkgs.follows = "nixpkgs"; 14 | }; 15 | 16 | outputs = { self, nixpkgs, prettyswitch, hyprland, ... }: { 17 | # Formatter (optional) 18 | formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.alejandra; 19 | 20 | nixosModules = { 21 | # New hyprvibe-prefixed exports 22 | hyprvibe = import ./modules/shared; 23 | hyprvibe-packages = import ./modules/shared/packages.nix; 24 | hyprvibe-desktop = import ./modules/shared/desktop.nix; 25 | hyprvibe-hyprland = import ./modules/shared/hyprland.nix; 26 | hyprvibe-waybar = import ./modules/shared/waybar.nix; 27 | hyprvibe-shell = import ./modules/shared/shell.nix; 28 | hyprvibe-services = import ./modules/shared/services.nix; 29 | }; 30 | 31 | nixosConfigurations = { 32 | rvbee = nixpkgs.lib.nixosSystem { 33 | system = "x86_64-linux"; 34 | modules = [ 35 | ./hosts/rvbee/system.nix 36 | prettyswitch.nixosModules.default 37 | ]; 38 | specialArgs = { 39 | inherit hyprland; 40 | }; 41 | }; 42 | nixstation = nixpkgs.lib.nixosSystem { 43 | system = "x86_64-linux"; 44 | modules = [ 45 | ./hosts/nixstation/system.nix 46 | prettyswitch.nixosModules.default 47 | ]; 48 | specialArgs = { 49 | inherit hyprland; 50 | }; 51 | }; 52 | nixbook = nixpkgs.lib.nixosSystem { 53 | system = "x86_64-linux"; 54 | modules = [ 55 | ./hosts/nixbook/system.nix 56 | prettyswitch.nixosModules.default 57 | ]; 58 | specialArgs = { 59 | inherit hyprland; 60 | }; 61 | }; 62 | }; 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-amd-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Requires amdgpu top info via sysfs; fallback to radeontop if available 5 | 6 | format_output() { 7 | local text tooltip 8 | text="$1" 9 | tooltip="$2" 10 | echo "{\"text\": \"${text}\", \"tooltip\": \"${tooltip}\"}" 11 | } 12 | 13 | # Locate AMD GPU card index and path dynamically (vendor 0x1002) 14 | card_index="" 15 | for dev in /sys/class/drm/card*/device; do 16 | [[ -e "$dev" ]] || continue 17 | if [[ -r "$dev/vendor" ]] && grep -qi "0x1002" "$dev/vendor"; then 18 | card_index=$(basename "$(dirname "$dev")" | sed 's/card//') 19 | gpu_path="$dev" 20 | break 21 | fi 22 | done 23 | 24 | temp_c="" 25 | power_w="" 26 | util="" 27 | 28 | # Try sysfs hwmon sensors for temp and power 29 | if [[ -n "${gpu_path:-}" && -r "${gpu_path}/hwmon" ]]; then 30 | hwmon_dir=$(readlink -f "${gpu_path}/hwmon"/* 2>/dev/null || true) 31 | if [[ -n "${hwmon_dir}" ]]; then 32 | if [[ -r "${hwmon_dir}/temp1_input" ]]; then 33 | t_raw=$(cat "${hwmon_dir}/temp1_input" 2>/dev/null || echo 0) 34 | temp_c=$(( t_raw / 1000 )) 35 | fi 36 | if [[ -r "${hwmon_dir}/power1_average" ]]; then 37 | p_raw=$(cat "${hwmon_dir}/power1_average" 2>/dev/null || echo 0) 38 | power_w=$(awk -v v="${p_raw}" 'BEGIN{ printf "%.1f", v/1000000 }') 39 | fi 40 | fi 41 | fi 42 | 43 | # Utilization via gpu_busy_percent if available; fallback to amdgpu_pm_info 44 | if [[ -n "${gpu_path:-}" && -r "${gpu_path}/gpu_busy_percent" ]]; then 45 | util=$(cat "${gpu_path}/gpu_busy_percent" 2>/dev/null | tr -dc '0-9') 46 | elif [[ -n "${card_index}" && -r "/sys/kernel/debug/dri/${card_index}/amdgpu_pm_info" ]]; then 47 | pm_info=$(cat "/sys/kernel/debug/dri/${card_index}/amdgpu_pm_info" 2>/dev/null || true) 48 | util=$(grep -iE 'GPU load' <<<"${pm_info}" | awk '{print $(NF-1)}' | tr -d '%') 49 | fi 50 | 51 | text="" 52 | tooltip="AMD GPU" 53 | 54 | parts=() 55 | [[ -n "${util}" ]] && parts+=("${util}%") 56 | [[ -n "${temp_c}" ]] && parts+=("${temp_c}°C") 57 | [[ -n "${power_w}" ]] && parts+=("${power_w}W") 58 | 59 | if [[ ${#parts[@]} -gt 0 ]]; then 60 | text="${parts[*]}" 61 | tooltip="AMD GPU: ${parts[*]}" 62 | fi 63 | 64 | format_output "${text}" "${tooltip}" 65 | 66 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/waybar-amd-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Requires amdgpu top info via sysfs; fallback to radeontop if available 5 | 6 | format_output() { 7 | local text tooltip 8 | text="$1" 9 | tooltip="$2" 10 | echo "{\"text\": \"${text}\", \"tooltip\": \"${tooltip}\"}" 11 | } 12 | 13 | # Locate AMD GPU card index and path dynamically (vendor 0x1002) 14 | card_index="" 15 | for dev in /sys/class/drm/card*/device; do 16 | [[ -e "$dev" ]] || continue 17 | if [[ -r "$dev/vendor" ]] && grep -qi "0x1002" "$dev/vendor"; then 18 | card_index=$(basename "$(dirname "$dev")" | sed 's/card//') 19 | gpu_path="$dev" 20 | break 21 | fi 22 | done 23 | 24 | temp_c="" 25 | power_w="" 26 | util="" 27 | 28 | # Try sysfs hwmon sensors for temp and power 29 | if [[ -n "${gpu_path:-}" && -r "${gpu_path}/hwmon" ]]; then 30 | hwmon_dir=$(readlink -f "${gpu_path}/hwmon"/* 2>/dev/null || true) 31 | if [[ -n "${hwmon_dir}" ]]; then 32 | if [[ -r "${hwmon_dir}/temp1_input" ]]; then 33 | t_raw=$(cat "${hwmon_dir}/temp1_input" 2>/dev/null || echo 0) 34 | temp_c=$(( t_raw / 1000 )) 35 | fi 36 | if [[ -r "${hwmon_dir}/power1_average" ]]; then 37 | p_raw=$(cat "${hwmon_dir}/power1_average" 2>/dev/null || echo 0) 38 | power_w=$(awk -v v="${p_raw}" 'BEGIN{ printf "%.1f", v/1000000 }') 39 | fi 40 | fi 41 | fi 42 | 43 | # Utilization via gpu_busy_percent if available; fallback to amdgpu_pm_info 44 | if [[ -n "${gpu_path:-}" && -r "${gpu_path}/gpu_busy_percent" ]]; then 45 | util=$(cat "${gpu_path}/gpu_busy_percent" 2>/dev/null | tr -dc '0-9') 46 | elif [[ -n "${card_index}" && -r "/sys/kernel/debug/dri/${card_index}/amdgpu_pm_info" ]]; then 47 | pm_info=$(cat "/sys/kernel/debug/dri/${card_index}/amdgpu_pm_info" 2>/dev/null || true) 48 | util=$(grep -iE 'GPU load' <<<"${pm_info}" | awk '{print $(NF-1)}' | tr -d '%') 49 | fi 50 | 51 | text="" 52 | tooltip="AMD GPU" 53 | 54 | parts=() 55 | [[ -n "${util}" ]] && parts+=("${util}%") 56 | [[ -n "${temp_c}" ]] && parts+=("${temp_c}°C") 57 | [[ -n "${power_w}" ]] && parts+=("${power_w}W") 58 | 59 | if [[ ${#parts[@]} -gt 0 ]]; then 60 | text="${parts[*]}" 61 | tooltip="AMD GPU: ${parts[*]}" 62 | fi 63 | 64 | format_output "${text}" "${tooltip}" 65 | 66 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/waybar-amd-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Requires amdgpu top info via sysfs; fallback to radeontop if available 5 | 6 | format_output() { 7 | local text tooltip 8 | text="$1" 9 | tooltip="$2" 10 | echo "{\"text\": \"${text}\", \"tooltip\": \"${tooltip}\"}" 11 | } 12 | 13 | # Locate AMD GPU card index and path dynamically (vendor 0x1002) 14 | card_index="" 15 | for dev in /sys/class/drm/card*/device; do 16 | [[ -e "$dev" ]] || continue 17 | if [[ -r "$dev/vendor" ]] && grep -qi "0x1002" "$dev/vendor"; then 18 | card_index=$(basename "$(dirname "$dev")" | sed 's/card//') 19 | gpu_path="$dev" 20 | break 21 | fi 22 | done 23 | 24 | temp_c="" 25 | power_w="" 26 | util="" 27 | 28 | # Try sysfs hwmon sensors for temp and power 29 | if [[ -n "${gpu_path:-}" && -r "${gpu_path}/hwmon" ]]; then 30 | hwmon_dir=$(readlink -f "${gpu_path}/hwmon"/* 2>/dev/null || true) 31 | if [[ -n "${hwmon_dir}" ]]; then 32 | if [[ -r "${hwmon_dir}/temp1_input" ]]; then 33 | t_raw=$(cat "${hwmon_dir}/temp1_input" 2>/dev/null || echo 0) 34 | temp_c=$(( t_raw / 1000 )) 35 | fi 36 | if [[ -r "${hwmon_dir}/power1_average" ]]; then 37 | p_raw=$(cat "${hwmon_dir}/power1_average" 2>/dev/null || echo 0) 38 | power_w=$(awk -v v="${p_raw}" 'BEGIN{ printf "%.1f", v/1000000 }') 39 | fi 40 | fi 41 | fi 42 | 43 | # Utilization via gpu_busy_percent if available; fallback to amdgpu_pm_info 44 | if [[ -n "${gpu_path:-}" && -r "${gpu_path}/gpu_busy_percent" ]]; then 45 | util=$(cat "${gpu_path}/gpu_busy_percent" 2>/dev/null | tr -dc '0-9') 46 | elif [[ -n "${card_index}" && -r "/sys/kernel/debug/dri/${card_index}/amdgpu_pm_info" ]]; then 47 | pm_info=$(cat "/sys/kernel/debug/dri/${card_index}/amdgpu_pm_info" 2>/dev/null || true) 48 | util=$(grep -iE 'GPU load' <<<"${pm_info}" | awk '{print $(NF-1)}' | tr -d '%') 49 | fi 50 | 51 | text="" 52 | tooltip="AMD GPU" 53 | 54 | parts=() 55 | [[ -n "${util}" ]] && parts+=("${util}%") 56 | [[ -n "${temp_c}" ]] && parts+=("${temp_c}°C") 57 | [[ -n "${power_w}" ]] && parts+=("${power_w}W") 58 | 59 | if [[ ${#parts[@]} -gt 0 ]]; then 60 | text="${parts[*]}" 61 | tooltip="AMD GPU: ${parts[*]}" 62 | fi 63 | 64 | format_output "${text}" "${tooltip}" 65 | 66 | -------------------------------------------------------------------------------- /hosts/nixbook/waybar.css: -------------------------------------------------------------------------------- 1 | /* Cyberpunk-inspired, high-contrast, readable */ 2 | * { 3 | font-family: "FiraCode Nerd Font", "Fira Code", monospace; 4 | font-size: 12pt; 5 | } 6 | 7 | window#waybar { 8 | background: rgba(10, 10, 16, 0.75); 9 | color: #e6e6e6; 10 | border-bottom: 2px solid #00ffd2; /* neon cyan */ 11 | } 12 | 13 | #workspaces { 14 | padding: 0 8px; 15 | } 16 | 17 | #workspaces button { 18 | padding: 4px 10px; 19 | color: #9ae6ff; /* soft cyan */ 20 | border: 1px solid transparent; 21 | margin: 2px; 22 | } 23 | 24 | #workspaces button.active { 25 | color: #0a0a10; 26 | background: linear-gradient(135deg, #00ffd2, #ff00aa); 27 | border-color: #00ffd2; 28 | } 29 | 30 | #workspaces button.urgent { 31 | background: #ff0055; 32 | color: #fff; 33 | } 34 | 35 | /* Large, readable workspace indicator */ 36 | #workspaces button label { 37 | font-weight: 700; 38 | font-size: 14pt; 39 | } 40 | 41 | #clock, #memory, #cpu, #tray, #network, #pulseaudio, #custom-public_ip, #custom-amd_gpu, #custom-dunst, #window { 42 | padding: 0 10px; 43 | } 44 | 45 | #clock { 46 | color: #ffe86b; /* warm */ 47 | } 48 | 49 | #network { 50 | color: #7af7a7; 51 | } 52 | 53 | #pulseaudio.muted { 54 | color: #888; 55 | } 56 | 57 | #custom-amd_gpu { 58 | color: #ff8bd1; /* neon pink */ 59 | } 60 | 61 | #custom-btc { 62 | color: #F7931A; /* BTC orange */ 63 | } 64 | 65 | #window { 66 | color: #e6e6e6; 67 | } 68 | 69 | /* Tooltips */ 70 | tooltip { 71 | background: #0f0f17; 72 | color: #f2f2f2; 73 | border: 1px solid #00ffd2; 74 | } 75 | 76 | /* Module “chips”: add subtle boxes with padding so width changes don't jitter neighbors */ 77 | .modules-left > widget, 78 | .modules-center > widget, 79 | .modules-right > widget { 80 | background-color: rgba(20, 20, 32, 0.55); 81 | border: none; 82 | border-radius: 8px; 83 | padding: 2px 10px; 84 | margin: 2px 4px; 85 | } 86 | 87 | /* Avoid double-styling workspaces block; buttons already styled above */ 88 | #workspaces { 89 | background: transparent; 90 | border: none; 91 | padding: 0 8px; 92 | margin: 0 4px; 93 | } 94 | 95 | /* Fix widths for metrics to reduce layout shift */ 96 | #cpu { min-width: 8em; } 97 | #memory { min-width: 8em; } 98 | #network { min-width: 14em; } 99 | #pulseaudio { min-width: 8em; } 100 | 101 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/rofi-power-profile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | # Rofi menu for power profile switching 5 | # Similar to rofi-brightness.sh but for power profiles 6 | 7 | get_current_profile() { 8 | if command -v powerprofilesctl >/dev/null 2>&1; then 9 | powerprofilesctl get 2>/dev/null || echo "unknown" 10 | else 11 | # Fallback: check CPU governor 12 | cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "unknown" 13 | fi 14 | } 15 | 16 | get_battery_status() { 17 | if command -v upower >/dev/null 2>&1; then 18 | BATTERY=$(upower -e | grep -i battery | head -1) 19 | if [ -n "$BATTERY" ]; then 20 | upower -i "$BATTERY" | grep -E 'state|percentage' | head -2 | \ 21 | awk -F: '{print $2}' | tr '\n' ' ' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' 22 | fi 23 | elif [ -f /sys/class/power_supply/BAT0/status ]; then 24 | STATUS=$(cat /sys/class/power_supply/BAT0/status 2>/dev/null || echo "unknown") 25 | CAPACITY=$(cat /sys/class/power_supply/BAT0/capacity 2>/dev/null || echo "?") 26 | echo "$STATUS $CAPACITY%" 27 | else 28 | echo "AC power" 29 | fi 30 | } 31 | 32 | current="$(get_current_profile)" 33 | battery_info="$(get_battery_status)" 34 | 35 | if ! command -v rofi >/dev/null 2>&1; then 36 | command -v notify-send >/dev/null 2>&1 && notify-send "Power Profile" "rofi not found" 37 | exit 1 38 | fi 39 | 40 | # Show menu with current status 41 | choice=$(printf "%s\n%s\n%s\n%s" \ 42 | "Performance" \ 43 | "Balanced" \ 44 | "Power Saver" \ 45 | "Status" | \ 46 | rofi -dmenu -p "Power Profile (Current: ${current})" -i -lines 4) 47 | 48 | if [ -z "${choice:-}" ]; then 49 | command -v notify-send >/dev/null 2>&1 && notify-send "Power Profile" "Cancelled" 50 | exit 0 51 | fi 52 | 53 | case "$choice" in 54 | "Performance") 55 | power-profile performance 56 | ;; 57 | "Balanced") 58 | power-profile balanced 59 | ;; 60 | "Power Saver") 61 | power-profile power-saver 62 | ;; 63 | "Status") 64 | # Show detailed status 65 | status_msg="Profile: $(power-profile status)" 66 | command -v notify-send >/dev/null 2>&1 && \ 67 | notify-send "Power Profile Status" "$status_msg\nBattery: $battery_info" -t 5000 68 | echo "$status_msg" 69 | ;; 70 | *) 71 | command -v notify-send >/dev/null 2>&1 && notify-send "Power Profile" "Unknown choice: $choice" 72 | exit 1 73 | ;; 74 | esac 75 | -------------------------------------------------------------------------------- /hosts/rvbee/waybar.css: -------------------------------------------------------------------------------- 1 | /* Cyberpunk-inspired, high-contrast, readable */ 2 | * { 3 | font-family: "FiraCode Nerd Font", "Fira Code", monospace; 4 | font-size: 12pt; 5 | } 6 | 7 | window#waybar { 8 | background: rgba(10, 10, 16, 0.75); 9 | color: #e6e6e6; 10 | border-bottom: 2px solid #00ffd2; /* neon cyan */ 11 | } 12 | 13 | #workspaces { 14 | padding: 0 8px; 15 | } 16 | 17 | #workspaces button { 18 | padding: 4px 10px; 19 | color: #9ae6ff; /* soft cyan */ 20 | border: 1px solid transparent; 21 | margin: 2px; 22 | } 23 | 24 | #workspaces button.active { 25 | color: #0a0a10; 26 | background: linear-gradient(135deg, #00ffd2, #ff00aa); 27 | border-color: #00ffd2; 28 | } 29 | 30 | #workspaces button.urgent { 31 | background: #ff0055; 32 | color: #fff; 33 | } 34 | 35 | /* Large, readable workspace indicator */ 36 | #workspaces button label { 37 | font-weight: 700; 38 | font-size: 14pt; 39 | } 40 | 41 | #clock, #memory, #cpu, #tray, #network, #pulseaudio, #custom-public_ip, #custom-amd_gpu, #custom-weather, #custom-dunst, #window { 42 | padding: 0 10px; 43 | } 44 | 45 | #clock { 46 | color: #ffe86b; /* warm */ 47 | } 48 | 49 | #network { 50 | color: #7af7a7; 51 | } 52 | 53 | #pulseaudio.muted { 54 | color: #888; 55 | } 56 | 57 | #custom-amd_gpu { 58 | color: #ff8bd1; /* neon pink */ 59 | } 60 | 61 | #custom-weather { 62 | color: #7ad1ff; /* sky */ 63 | } 64 | 65 | #custom-btc { 66 | color: #F7931A; /* BTC orange */ 67 | } 68 | 69 | #window { 70 | color: #e6e6e6; 71 | } 72 | 73 | /* Tooltips */ 74 | tooltip { 75 | background: #0f0f17; 76 | color: #f2f2f2; 77 | border: 1px solid #00ffd2; 78 | } 79 | 80 | /* Module “chips”: add subtle boxes with padding so width changes don't jitter neighbors */ 81 | .modules-left > widget, 82 | .modules-center > widget, 83 | .modules-right > widget { 84 | background-color: rgba(20, 20, 32, 0.55); 85 | border: none; 86 | border-radius: 8px; 87 | padding: 2px 10px; 88 | margin: 2px 4px; 89 | } 90 | 91 | /* Avoid double-styling workspaces block; buttons already styled above */ 92 | #workspaces { 93 | background: transparent; 94 | border: none; 95 | padding: 0 8px; 96 | margin: 0 4px; 97 | } 98 | 99 | /* Fix widths for metrics to reduce layout shift */ 100 | #cpu { min-width: 8em; } 101 | #memory { min-width: 8em; } 102 | #network { min-width: 14em; } 103 | #pulseaudio { min-width: 8em; } 104 | 105 | -------------------------------------------------------------------------------- /modules/shared/user.nix: -------------------------------------------------------------------------------- 1 | { lib, config, pkgs, ... }: 2 | let 3 | cfg = config.hyprvibe.user; 4 | userSubmodule = { ... }: { 5 | options = { 6 | name = lib.mkOption { 7 | type = lib.types.str; 8 | default = "chrisf"; 9 | description = "Primary user name for the host."; 10 | }; 11 | group = lib.mkOption { 12 | type = lib.types.str; 13 | default = "users"; 14 | description = "Primary user group for the host."; 15 | }; 16 | home = lib.mkOption { 17 | type = lib.types.str; 18 | default = "/home/chrisf"; 19 | description = "Home directory path for the primary user."; 20 | }; 21 | description = lib.mkOption { 22 | type = lib.types.str; 23 | default = "Hyprvibe User"; 24 | description = "GECOS/description for the primary user."; 25 | }; 26 | linger = lib.mkOption { 27 | type = lib.types.bool; 28 | default = true; 29 | description = "Keep user services running even when not logged in."; 30 | }; 31 | extraGroups = lib.mkOption { 32 | type = lib.types.listOf lib.types.str; 33 | default = []; 34 | description = "Additional groups to add on top of hyprvibe base groups."; 35 | }; 36 | }; 37 | }; 38 | in { 39 | options.hyprvibe.user = lib.mkOption { 40 | type = lib.types.either lib.types.str (lib.types.submodule userSubmodule); 41 | default = { name = "chrisf"; group = "users"; home = "/home/chrisf"; description = "Hyprvibe User"; linger = true; extraGroups = []; }; 42 | description = "Primary user (string short-form or attribute set)."; 43 | apply = value: 44 | if lib.isString value then 45 | { name = value; group = "users"; home = "/home/${value}"; } 46 | else 47 | { 48 | name = value.name; 49 | group = value.group or "users"; 50 | home = value.home or "/home/${value.name}"; 51 | description = value.description or "Hyprvibe User"; 52 | linger = value.linger or true; 53 | extraGroups = value.extraGroups or []; 54 | }; 55 | }; 56 | 57 | # Provide a sensible default user matching both hosts, while allowing per-host adds 58 | config = let 59 | baseGroups = [ 60 | "networkmanager" "wheel" "docker" "adbusers" "libvirtd" "video" "render" "audio" "i2c" 61 | ]; 62 | finalGroups = lib.unique (baseGroups ++ (cfg.extraGroups or [])); 63 | in { 64 | users.users."${cfg.name}" = { 65 | isNormalUser = true; 66 | shell = pkgs.fish; 67 | description = cfg.description or "Hyprvibe User"; 68 | linger = cfg.linger or true; 69 | extraGroups = finalGroups; 70 | group = cfg.group; 71 | home = cfg.home; 72 | }; 73 | }; 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /docs/monitor-keybindings.md: -------------------------------------------------------------------------------- 1 | # Monitor-Specific Application Launch Keybindings 2 | 3 | This document describes the custom keybindings for launching applications on specific monitors on the **nixstation** host. 4 | 5 | ## Monitor Layout 6 | 7 | ``` 8 | [DP-1] Top Monitor (2560x1440) 9 | [DP-3] Center/Main Monitor (2560x1440) 10 | [DP-2] Left Vertical [HDMI-A-1] Right Vertical 11 | ``` 12 | 13 | ## Application Launch Keybindings 14 | 15 | ### Communication Apps (Right Vertical Monitor - HDMI-A-1) 16 | - **SUPER + S**: Launch Slack, then Telegram after 2-second delay 17 | - Opens both communication apps on the right vertical monitor 18 | - Slack launches first, then Telegram 19 | 20 | ### Development Tools (Left Vertical Monitor - DP-2) 21 | - **SUPER + D**: Launch Cursor editor and terminal 22 | - Opens development environment on the left vertical monitor 23 | 24 | ### Browser (Top Monitor - DP-1) 25 | - **SUPER + G**: Launch Junction on top monitor 26 | - Opens browser on the top monitor (DP-1) 27 | 28 | ### Media Player (Main Monitor - DP-3) 29 | - **SUPER + K**: Launch media player on main monitor 30 | - Opens media player on the center/main monitor 31 | 32 | ## Monitor Navigation Keybindings 33 | 34 | ### Focus Monitors 35 | - **SUPER + F1**: Focus top monitor (DP-1) 36 | - **SUPER + F2**: Focus left vertical monitor (DP-2) 37 | - **SUPER + F3**: Focus main monitor (DP-3) 38 | - **SUPER + F4**: Focus right vertical monitor (HDMI-A-1) 39 | 40 | ### Move Windows Between Monitors 41 | - **SUPER + SHIFT + F1**: Move window to top monitor (DP-1) 42 | - **SUPER + SHIFT + F2**: Move window to left vertical monitor (DP-2) 43 | - **SUPER + SHIFT + F3**: Move window to main monitor (DP-3) 44 | - **SUPER + SHIFT + F4**: Move window to right vertical monitor (HDMI-A-1) 45 | 46 | ### Arrow Key Navigation 47 | - **SUPER + CTRL + Arrow Keys**: Move focus between monitors 48 | - **SUPER + SHIFT + CTRL + Arrow Keys**: Move windows between monitors 49 | 50 | ## Creating Custom Keybindings 51 | 52 | To add new monitor-specific keybindings: 53 | 54 | 1. **Edit the monitor config**: `hyprvibe/configs/hyprland-monitors-nixstation.conf` 55 | 2. **Add your keybinding**: Follow the pattern: 56 | ```bash 57 | # SUPER + [KEY]: Description 58 | bind = SUPER, [KEY], exec, your-command-here 59 | ``` 60 | 3. **Copy to system**: `cp configs/hyprland-monitors-nixstation.conf ~/.config/hypr/` 61 | 4. **Reload Hyprland**: `hyprctl reload` 62 | 63 | ## Important Notes 64 | 65 | - **Avoid conflicts**: Check that your new keybinding doesn't conflict with existing bindings in `hyprland-base.conf` 66 | - **Monitor names**: Use the exact monitor names (DP-1, DP-2, DP-3, HDMI-A-1) 67 | - **Positioning**: Use `hyprctl dispatch movewindow exact X Y` for precise positioning 68 | - **Focus management**: Use `hyprctl dispatch focusmonitor` to ensure apps open on the correct monitor 69 | -------------------------------------------------------------------------------- /configs/hyprland-monitors-nixstation.conf: -------------------------------------------------------------------------------- 1 | # Nixstation Monitor Configuration (4 monitors) 2 | # This file contains monitor-specific settings for nixstation 3 | 4 | # Monitor configuration for 4-monitor setup 5 | # Layout: Screen 1 (above center), Screen 2 (left vertical), Screen 3 (center/main), Screen 4 (right vertical) 6 | 7 | # Screen 1: Above center (DP-1 - GIGA-BYTE M27Q) 8 | monitor=DP-1,2560x1440@144,2560x-1440,1 9 | 10 | # Screen 2: Left vertical (DP-2 - ASUS PB278) - rotated 90 degrees clockwise 11 | monitor=DP-2,2560x1440@60,0x0,1,transform,1 12 | 13 | # Screen 3: Center/main (DP-3 - ASUS PB278) 14 | monitor=DP-3,2560x1440@144,1440x0,1 15 | 16 | # Screen 4: Right vertical (HDMI-A-1 - ASUS PB277) - rotated 90 degrees clockwise 17 | monitor=HDMI-A-1,2560x1440@60,4000x0,1,transform,1 18 | # HDMI-specific settings for better DPMS support 19 | monitor=HDMI-A-1,addreserved,0,0,0,0 20 | 21 | # Launch waybar with per-monitor configurations 22 | exec-once = ~/.config/waybar/scripts/waybar-per-monitor.sh 23 | 24 | # Multi-monitor keybindings for moving between monitors 25 | # SUPER + CTRL + arrow keys to move focus between monitors 26 | bind = SUPER CTRL, left, focusmonitor, l 27 | bind = SUPER CTRL, right, focusmonitor, r 28 | bind = SUPER CTRL, up, focusmonitor, u 29 | bind = SUPER CTRL, down, focusmonitor, d 30 | 31 | # SUPER + SHIFT + CTRL + arrow keys to move windows between monitors 32 | bind = SUPER SHIFT CTRL, left, movewindow, mon:l 33 | bind = SUPER SHIFT CTRL, right, movewindow, mon:r 34 | bind = SUPER SHIFT CTRL, up, movewindow, mon:u 35 | bind = SUPER SHIFT CTRL, down, movewindow, mon:d 36 | 37 | # Quick monitor focus keys (SUPER + number) 38 | bind = SUPER, F1, focusmonitor, DP-1 39 | bind = SUPER, F2, focusmonitor, DP-2 40 | bind = SUPER, F3, focusmonitor, DP-3 41 | bind = SUPER, F4, focusmonitor, HDMI-A-1 42 | 43 | # Move active window to specific monitor 44 | bind = SUPER SHIFT, F1, movewindow, mon:DP-1 45 | bind = SUPER SHIFT, F2, movewindow, mon:DP-2 46 | bind = SUPER SHIFT, F3, movewindow, mon:DP-3 47 | bind = SUPER SHIFT, F4, movewindow, mon:HDMI-A-1 48 | 49 | # Launch applications to specific monitors and positions 50 | # SUPER + S: Launch Slack and Telegram on right vertical monitor (HDMI-A-1) 51 | # Slack on top half, Telegram on bottom half 52 | bind = SUPER, S, exec, ~/.config/hypr/scripts/launch-communication.sh 53 | 54 | # SUPER + D: Launch development tools on left vertical monitor (DP-2) 55 | # Cursor editor on top half, terminal on bottom half 56 | bind = SUPER, D, exec, ~/.config/hypr/scripts/launch-development.sh 57 | 58 | # SUPER + G: Launch Junction on top monitor (DP-1) 59 | bind = SUPER, G, exec, hyprctl dispatch focusmonitor DP-1 && junction & sleep 1 && hyprctl dispatch movewindow exact 2560 -1440 && hyprctl dispatch resizeactive exact 2560 1440 && hyprctl dispatch focusmonitor DP-3 60 | 61 | # SUPER + K: Launch media player on main monitor (DP-3) in center 62 | bind = SUPER, K, exec, hyprctl dispatch focusmonitor DP-3 && mpv & sleep 1 && hyprctl dispatch movewindow exact 1440 0 && hyprctl dispatch resizeactive exact 2560 1440 63 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar.css: -------------------------------------------------------------------------------- 1 | /* Cyberpunk-inspired, high-contrast, readable */ 2 | * { 3 | font-family: "FiraCode Nerd Font", "Fira Code", monospace; 4 | font-size: 12pt; 5 | } 6 | 7 | window#waybar { 8 | background: rgba(10, 10, 16, 0.75); 9 | color: #e6e6e6; 10 | border-bottom: 2px solid #00ffd2; /* neon cyan */ 11 | } 12 | 13 | #workspaces { 14 | padding: 0 8px; 15 | } 16 | 17 | #workspaces button { 18 | padding: 0 5px; 19 | background-color: transparent; 20 | color: #ffffff; 21 | border-bottom: 3px solid transparent; 22 | } 23 | 24 | #workspaces button:hover { 25 | background: rgba(0, 0, 0, 0.2); 26 | box-shadow: inset 0 -3px #ffffff; 27 | } 28 | 29 | #workspaces button.active { 30 | background-color: #64727D; 31 | border-bottom: 3px solid #ffffff; 32 | } 33 | 34 | #workspaces button.urgent { 35 | background-color: #eb4d4b; 36 | } 37 | 38 | /* Large, readable workspace indicator */ 39 | #workspaces button label { 40 | font-weight: 700; 41 | font-size: 14pt; 42 | } 43 | 44 | #clock { 45 | background-color: transparent; 46 | color: #ffe86b; /* warm */ 47 | padding: 0 10px; 48 | } 49 | 50 | #memory { 51 | background-color: transparent; 52 | color: #ffffff; 53 | padding: 0 10px; 54 | } 55 | 56 | #cpu { 57 | background-color: transparent; 58 | color: #ffffff; 59 | padding: 0 10px; 60 | } 61 | 62 | #tray { 63 | background-color: transparent; 64 | padding: 0 10px; 65 | } 66 | 67 | #network { 68 | background-color: transparent; 69 | color: #7af7a7; 70 | padding: 0 10px; 71 | } 72 | 73 | #pulseaudio { 74 | background-color: transparent; 75 | color: #ffffff; 76 | padding: 0 10px; 77 | } 78 | 79 | #pulseaudio.muted { 80 | color: #888; 81 | } 82 | 83 | #custom-public_ip { 84 | color: #ff8bd1; /* neon pink */ 85 | } 86 | 87 | #custom-amd_gpu { 88 | color: #ff8bd1; /* neon pink */ 89 | } 90 | 91 | #custom-weather { 92 | color: #7ad1ff; /* sky */ 93 | } 94 | 95 | #custom-btc { 96 | color: #F7931A; /* BTC orange */ 97 | } 98 | 99 | #window { 100 | background-color: transparent; 101 | color: #ffffff; 102 | padding: 0 10px; 103 | } 104 | 105 | /* Tooltips */ 106 | tooltip { 107 | background: #0f0f17; 108 | color: #f2f2f2; 109 | border: 1px solid #00ffd2; 110 | } 111 | 112 | /* Module "chips": add subtle boxes with padding so width changes don't jitter neighbors */ 113 | .modules-left > widget, 114 | .modules-center > widget, 115 | .modules-right > widget { 116 | background-color: rgba(20, 20, 32, 0.55); 117 | border: none; 118 | border-radius: 8px; 119 | padding: 2px 10px; 120 | margin: 2px 4px; 121 | } 122 | 123 | /* Avoid double-styling workspaces block; buttons already styled above */ 124 | #workspaces { 125 | background: transparent; 126 | border: none; 127 | padding: 0 8px; 128 | margin: 0 4px; 129 | } 130 | 131 | /* Fix widths for metrics to reduce layout shift */ 132 | #cpu { min-width: 8em; } 133 | #memory { min-width: 8em; } 134 | #network { min-width: 14em; } 135 | #pulseaudio { min-width: 8em; } 136 | 137 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/rofi-brightness.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | get_percent() { 5 | if ls /sys/class/backlight >/dev/null 2>&1 && [ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]; then 6 | brightnessctl -m | awk -F, '{gsub("%","", $4); print $4}' 2>/dev/null || true 7 | elif command -v ddcutil >/dev/null 2>&1; then 8 | ddcutil getvcp 0x10 --terse 2>/dev/null | awk '{print $(NF-1)}' || true 9 | fi 10 | } 11 | 12 | has_kernel_backlight() { 13 | ls /sys/class/backlight >/dev/null 2>&1 && [ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ] 14 | } 15 | 16 | adjust_kernel() { 17 | local arg="$1" 18 | brightnessctl set "$arg" >/dev/null 2>&1 || false 19 | } 20 | 21 | adjust_ddc() { 22 | local req="$1" # "+5" "-5" or absolute 0-100 23 | local ok=0 24 | # Determine absolute target per display and set 25 | while read -r busdev; do 26 | [ -n "$busdev" ] || continue 27 | busnum="${busdev##*-}" 28 | # Read current and max 29 | read -r cur max < <(ddcutil --bus "$busnum" getvcp 0x10 --terse 2>/dev/null | awk '{print $(NF-1), $NF}') 30 | # Fallback if parsing fails 31 | cur=${cur:-0}; max=${max:-100} 32 | # Compute new absolute value 33 | local target 34 | if [[ "$req" =~ ^[+-] ]]; then 35 | local delta=${req} 36 | # Strip sign for arithmetic, then reapply 37 | target=$(( cur + delta )) 38 | else 39 | target=$req 40 | fi 41 | # Clamp 0..max 42 | if [ "$target" -lt 0 ]; then target=0; fi 43 | if [ "$target" -gt "$max" ]; then target=$max; fi 44 | if ddcutil --bus "$busnum" setvcp 0x10 "$target" >/dev/null 2>&1; then 45 | ok=1 46 | fi 47 | done < <(ddcutil detect --terse 2>/dev/null | awk '/I2C bus:/ {print $3}') 48 | [ $ok -eq 1 ] 49 | } 50 | 51 | act() { 52 | case "$1" in 53 | "+5%") if has_kernel_backlight; then adjust_kernel "+5%"; else adjust_ddc "+5"; fi ;; 54 | "-5%") if has_kernel_backlight; then adjust_kernel "5%-"; else adjust_ddc "-5"; fi ;; 55 | "25%") if has_kernel_backlight; then adjust_kernel "25%"; else adjust_ddc "25"; fi ;; 56 | "50%") if has_kernel_backlight; then adjust_kernel "50%"; else adjust_ddc "50"; fi ;; 57 | "75%") if has_kernel_backlight; then adjust_kernel "75%"; else adjust_ddc "75"; fi ;; 58 | "100%") if has_kernel_backlight; then adjust_kernel "100%"; else adjust_ddc "100"; fi ;; 59 | esac 60 | } 61 | 62 | current="$(get_percent || echo "?")" 63 | if ! command -v rofi >/dev/null 2>&1; then 64 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "rofi not found" 65 | exit 1 66 | fi 67 | 68 | choice=$(printf "%s\n" "+5%" "-5%" "25%" "50%" "75%" "100%" | rofi -dmenu -p "Brightness (${current}% )" -i) 69 | if [ -n "${choice:-}" ]; then 70 | if act "$choice"; then 71 | newp=$(get_percent || echo "?") 72 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Set to: $choice (now ${newp}%)" 73 | else 74 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Adjustment failed" 75 | exit 1 76 | fi 77 | else 78 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Cancelled" 79 | fi 80 | 81 | 82 | -------------------------------------------------------------------------------- /hosts/rvbee/scripts/rofi-brightness.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | get_percent() { 5 | if ls /sys/class/backlight >/dev/null 2>&1 && [ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]; then 6 | brightnessctl -m | awk -F, '{gsub("%","", $4); print $4}' 2>/dev/null || true 7 | elif command -v ddcutil >/dev/null 2>&1; then 8 | ddcutil getvcp 0x10 --terse 2>/dev/null | awk '{print $(NF-1)}' || true 9 | fi 10 | } 11 | 12 | has_kernel_backlight() { 13 | ls /sys/class/backlight >/dev/null 2>&1 && [ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ] 14 | } 15 | 16 | adjust_kernel() { 17 | local arg="$1" 18 | brightnessctl set "$arg" >/dev/null 2>&1 || false 19 | } 20 | 21 | adjust_ddc() { 22 | local req="$1" # "+5" "-5" or absolute 0-100 23 | local ok=0 24 | # Determine absolute target per display and set 25 | while read -r busdev; do 26 | [ -n "$busdev" ] || continue 27 | busnum="${busdev##*-}" 28 | # Read current and max 29 | read -r cur max < <(ddcutil --bus "$busnum" getvcp 0x10 --terse 2>/dev/null | awk '{print $(NF-1), $NF}') 30 | # Fallback if parsing fails 31 | cur=${cur:-0}; max=${max:-100} 32 | # Compute new absolute value 33 | local target 34 | if [[ "$req" =~ ^[+-] ]]; then 35 | local delta=${req} 36 | # Strip sign for arithmetic, then reapply 37 | target=$(( cur + delta )) 38 | else 39 | target=$req 40 | fi 41 | # Clamp 0..max 42 | if [ "$target" -lt 0 ]; then target=0; fi 43 | if [ "$target" -gt "$max" ]; then target=$max; fi 44 | if ddcutil --bus "$busnum" setvcp 0x10 "$target" >/dev/null 2>&1; then 45 | ok=1 46 | fi 47 | done < <(ddcutil detect --terse 2>/dev/null | awk '/I2C bus:/ {print $3}') 48 | [ $ok -eq 1 ] 49 | } 50 | 51 | act() { 52 | case "$1" in 53 | "+5%") if has_kernel_backlight; then adjust_kernel "+5%"; else adjust_ddc "+5"; fi ;; 54 | "-5%") if has_kernel_backlight; then adjust_kernel "5%-"; else adjust_ddc "-5"; fi ;; 55 | "25%") if has_kernel_backlight; then adjust_kernel "25%"; else adjust_ddc "25"; fi ;; 56 | "50%") if has_kernel_backlight; then adjust_kernel "50%"; else adjust_ddc "50"; fi ;; 57 | "75%") if has_kernel_backlight; then adjust_kernel "75%"; else adjust_ddc "75"; fi ;; 58 | "100%") if has_kernel_backlight; then adjust_kernel "100%"; else adjust_ddc "100"; fi ;; 59 | esac 60 | } 61 | 62 | current="$(get_percent || echo "?")" 63 | if ! command -v rofi >/dev/null 2>&1; then 64 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "rofi not found" 65 | exit 1 66 | fi 67 | 68 | choice=$(printf "%s\n" "+5%" "-5%" "25%" "50%" "75%" "100%" | rofi -dmenu -p "Brightness (${current}% )" -i) 69 | if [ -n "${choice:-}" ]; then 70 | if act "$choice"; then 71 | newp=$(get_percent || echo "?") 72 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Set to: $choice (now ${newp}%)" 73 | else 74 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Adjustment failed" 75 | exit 1 76 | fi 77 | else 78 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Cancelled" 79 | fi 80 | 81 | 82 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/rofi-brightness.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | get_percent() { 5 | if ls /sys/class/backlight >/dev/null 2>&1 && [ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ]; then 6 | brightnessctl -m | awk -F, '{gsub("%","", $4); print $4}' 2>/dev/null || true 7 | elif command -v ddcutil >/dev/null 2>&1; then 8 | ddcutil getvcp 0x10 --terse 2>/dev/null | awk '{print $(NF-1)}' || true 9 | fi 10 | } 11 | 12 | has_kernel_backlight() { 13 | ls /sys/class/backlight >/dev/null 2>&1 && [ -n "$(ls -A /sys/class/backlight 2>/dev/null)" ] 14 | } 15 | 16 | adjust_kernel() { 17 | local arg="$1" 18 | brightnessctl set "$arg" >/dev/null 2>&1 || false 19 | } 20 | 21 | adjust_ddc() { 22 | local req="$1" # "+5" "-5" or absolute 0-100 23 | local ok=0 24 | # Determine absolute target per display and set 25 | while read -r busdev; do 26 | [ -n "$busdev" ] || continue 27 | busnum="${busdev##*-}" 28 | # Read current and max 29 | read -r cur max < <(ddcutil --bus "$busnum" getvcp 0x10 --terse 2>/dev/null | awk '{print $(NF-1), $NF}') 30 | # Fallback if parsing fails 31 | cur=${cur:-0}; max=${max:-100} 32 | # Compute new absolute value 33 | local target 34 | if [[ "$req" =~ ^[+-] ]]; then 35 | local delta=${req} 36 | # Strip sign for arithmetic, then reapply 37 | target=$(( cur + delta )) 38 | else 39 | target=$req 40 | fi 41 | # Clamp 0..max 42 | if [ "$target" -lt 0 ]; then target=0; fi 43 | if [ "$target" -gt "$max" ]; then target=$max; fi 44 | if ddcutil --bus "$busnum" setvcp 0x10 "$target" >/dev/null 2>&1; then 45 | ok=1 46 | fi 47 | done < <(ddcutil detect --terse 2>/dev/null | awk '/I2C bus:/ {print $3}') 48 | [ $ok -eq 1 ] 49 | } 50 | 51 | act() { 52 | case "$1" in 53 | "+5%") if has_kernel_backlight; then adjust_kernel "+5%"; else adjust_ddc "+5"; fi ;; 54 | "-5%") if has_kernel_backlight; then adjust_kernel "5%-"; else adjust_ddc "-5"; fi ;; 55 | "25%") if has_kernel_backlight; then adjust_kernel "25%"; else adjust_ddc "25"; fi ;; 56 | "50%") if has_kernel_backlight; then adjust_kernel "50%"; else adjust_ddc "50"; fi ;; 57 | "75%") if has_kernel_backlight; then adjust_kernel "75%"; else adjust_ddc "75"; fi ;; 58 | "100%") if has_kernel_backlight; then adjust_kernel "100%"; else adjust_ddc "100"; fi ;; 59 | esac 60 | } 61 | 62 | current="$(get_percent || echo "?")" 63 | if ! command -v rofi >/dev/null 2>&1; then 64 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "rofi not found" 65 | exit 1 66 | fi 67 | 68 | choice=$(printf "%s\n" "+5%" "-5%" "25%" "50%" "75%" "100%" | rofi -dmenu -p "Brightness (${current}% )" -i) 69 | if [ -n "${choice:-}" ]; then 70 | if act "$choice"; then 71 | newp=$(get_percent || echo "?") 72 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Set to: $choice (now ${newp}%)" 73 | else 74 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Adjustment failed" 75 | exit 1 76 | fi 77 | else 78 | command -v notify-send >/dev/null 2>&1 && notify-send "Brightness" "Cancelled" 79 | fi 80 | 81 | 82 | -------------------------------------------------------------------------------- /switch-oh-my-posh-theme.sh: -------------------------------------------------------------------------------- 1 | #!/run/current-system/sw/bin/bash 2 | 3 | # Oh My Posh Theme Switcher 4 | # Easily switch between different Oh My Posh themes 5 | 6 | THEME_DIR="$HOME/.config/oh-my-posh" 7 | CURRENT_CONFIG="$THEME_DIR/config.json" 8 | 9 | # Available themes 10 | THEMES=( 11 | "default" # Your current Tokyo Night theme 12 | "enhanced" # Feature-rich Agnoster-inspired theme 13 | "minimal" # Clean Robby Russell-inspired theme 14 | "professional" # Modern Atomic-inspired diamond theme 15 | ) 16 | 17 | show_usage() { 18 | echo "Oh My Posh Theme Switcher" 19 | echo "=========================" 20 | echo 21 | echo "Usage: $0 [theme_name]" 22 | echo 23 | echo "Available themes:" 24 | for theme in "${THEMES[@]}"; do 25 | echo " - $theme" 26 | done 27 | echo 28 | echo "Examples:" 29 | echo " $0 enhanced # Switch to enhanced development theme" 30 | echo " $0 minimal # Switch to minimalist theme" 31 | echo " $0 professional # Switch to professional diamond theme" 32 | echo " $0 default # Switch back to default theme" 33 | echo 34 | echo "Current theme: $(basename $(readlink -f "$CURRENT_CONFIG" 2>/dev/null || echo "config.json"))" 35 | } 36 | 37 | switch_theme() { 38 | local theme_name="$1" 39 | local theme_file="$THEME_DIR/config-${theme_name}.json" 40 | 41 | if [[ "$theme_name" == "default" ]]; then 42 | theme_file="$THEME_DIR/config.json" 43 | fi 44 | 45 | if [[ ! -f "$theme_file" ]]; then 46 | echo "Error: Theme '$theme_name' not found at $theme_file" 47 | echo "Available themes:" 48 | for theme in "${THEMES[@]}"; do 49 | if [[ -f "$THEME_DIR/config-${theme}.json" ]] || [[ "$theme" == "default" && -f "$CURRENT_CONFIG" ]]; then 50 | echo " - $theme" 51 | fi 52 | done 53 | exit 1 54 | fi 55 | 56 | # Create backup of current config 57 | if [[ -f "$CURRENT_CONFIG" ]]; then 58 | cp "$CURRENT_CONFIG" "$THEME_DIR/config-backup-$(date +%Y%m%d-%H%M%S).json" 59 | fi 60 | 61 | # Switch to new theme 62 | if [[ "$theme_name" == "default" ]]; then 63 | # Restore original config 64 | if [[ -f "$THEME_DIR/config-original.json" ]]; then 65 | cp "$THEME_DIR/config-original.json" "$CURRENT_CONFIG" 66 | fi 67 | else 68 | # Copy theme to main config 69 | cp "$theme_file" "$CURRENT_CONFIG" 70 | fi 71 | 72 | echo "✅ Switched to '$theme_name' theme" 73 | echo "🔄 Restart your terminal or run 'exec fish' to see changes" 74 | echo 75 | echo "Theme descriptions:" 76 | echo " default - Tokyo Night inspired, balanced features" 77 | echo " enhanced - Feature-rich with comprehensive dev tools" 78 | echo " minimal - Clean, distraction-free for productivity" 79 | echo " professional - Modern diamond style for presentations" 80 | } 81 | 82 | # Main script logic 83 | if [[ $# -eq 0 ]]; then 84 | show_usage 85 | exit 0 86 | fi 87 | 88 | if [[ "$1" == "-h" || "$1" == "--help" ]]; then 89 | show_usage 90 | exit 0 91 | fi 92 | 93 | switch_theme "$1" 94 | -------------------------------------------------------------------------------- /modules/shared/waybar.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, config, ... }: 2 | let 3 | cfg = config.hyprvibe.waybar; 4 | user = config.hyprvibe.user; 5 | userHome = user.home; 6 | userName = user.name; 7 | userGroup = user.group; 8 | in { 9 | options.hyprvibe.waybar = { 10 | enable = lib.mkEnableOption "Waybar setup and config install"; 11 | configPath = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; }; 12 | stylePath = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; }; 13 | scriptsDir = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; }; 14 | extraConfigs = lib.mkOption { 15 | type = with lib.types; listOf (submodule ({ ... }: { 16 | options = { 17 | source = lib.mkOption { type = lib.types.path; description = "Path to additional Waybar config variant"; }; 18 | destName = lib.mkOption { type = lib.types.str; description = "Destination filename under ~/.config/waybar"; }; 19 | }; 20 | })); 21 | default = []; 22 | description = "Additional Waybar configs to install alongside main config"; 23 | }; 24 | }; 25 | 26 | config = lib.mkIf cfg.enable { 27 | environment.systemPackages = [ pkgs.waybar ]; 28 | system.activationScripts.waybar = lib.mkAfter '' 29 | set -euo pipefail 30 | trap 'echo "[hyprvibe][waybar] ERROR at line $LINENO"' ERR 31 | echo "[hyprvibe][waybar] starting activation" 32 | mkdir -p ${userHome}/.config/waybar/scripts 33 | # Remove existing files/symlinks before creating new ones 34 | rm -f ${userHome}/.config/waybar/config 35 | rm -f ${userHome}/.config/waybar/style.css 36 | ${if cfg.configPath != null then ''ln -sf ${cfg.configPath} ${userHome}/.config/waybar/config'' else ''ln -sf ${../../configs/waybar-rvbee.json} ${userHome}/.config/waybar/config''} 37 | ${if cfg.stylePath != null then ''ln -sf ${cfg.stylePath} ${userHome}/.config/waybar/style.css'' else ''ln -sf ${../../configs/waybar-rvbee.css} ${userHome}/.config/waybar/style.css''} 38 | ${lib.optionalString (cfg.scriptsDir != null) '' 39 | # Copy all scripts from scriptsDir and set executable permissions 40 | if [ -d ${cfg.scriptsDir} ]; then 41 | find ${cfg.scriptsDir} -type f -exec cp -f {} ${userHome}/.config/waybar/scripts/ \; 42 | chmod +x ${userHome}/.config/waybar/scripts/*.sh 2>/dev/null || true 43 | chmod +x ${userHome}/.config/waybar/scripts/*.py 2>/dev/null || true 44 | fi 45 | ''} 46 | ${lib.optionalString (cfg.scriptsDir == null) '' 47 | # Install RVBEE-inspired default scripts and brightness helper 48 | cp -f ${../../configs/waybar-scripts}/* ${userHome}/.config/waybar/scripts/ 2>/dev/null || true 49 | install -Dm0755 ${../../configs/waybar-scripts/rofi-brightness.sh} ${userHome}/.local/bin/rofi-brightness 50 | ''} 51 | # Install extra config variants 52 | ${lib.concatStringsSep "\n" (map (c: '' 53 | ln -sf ${c.source} ${userHome}/.config/waybar/${c.destName} 54 | '') cfg.extraConfigs)} 55 | chown -R ${userName}:${userGroup} ${userHome}/.config/waybar 56 | echo "[hyprvibe][waybar] activation complete" 57 | ''; 58 | }; 59 | } 60 | 61 | 62 | -------------------------------------------------------------------------------- /hosts/nixbook/TAILSCALE_SETUP.md: -------------------------------------------------------------------------------- 1 | # Tailscale Setup for Nixbook 2 | 3 | ## Current Configuration Status 4 | 5 | Tailscale is **already configured** in the nixbook system, but there's a configuration inconsistency that should be fixed. 6 | 7 | ## Current State 8 | 9 | 1. ✅ Tailscale service is enabled: `services.tailscale.enable = true;` (line 624) 10 | 2. ⚠️ Configuration inconsistency: Using direct `services.tailscale.enable` instead of shared module option 11 | 3. ✅ Firewall is disabled: `networking.firewall.enable = false;` (line 569) - Tailscale will work fine 12 | 4. ⚠️ Routing features may not be configured properly 13 | 14 | ## What Needs to Be Done 15 | 16 | ### Option 1: Use Shared Module (Recommended) 17 | 18 | Update `hosts/nixbook/system.nix` to use the shared module's Tailscale option: 19 | 20 | **Remove:** 21 | ```nix 22 | services = { 23 | # ... 24 | tailscale.enable = true; 25 | # ... 26 | }; 27 | ``` 28 | 29 | **Add to hyprvibe.services section (if it exists) or add:** 30 | ```nix 31 | hyprvibe.services = { 32 | enable = true; 33 | tailscale.enable = true; # This will configure with useRoutingFeatures = "both" 34 | }; 35 | ``` 36 | 37 | ### Option 2: Keep Direct Configuration (Current) 38 | 39 | If you want to keep the direct configuration, ensure routing features are set: 40 | 41 | **Change:** 42 | ```nix 43 | services.tailscale.enable = true; 44 | ``` 45 | 46 | **To:** 47 | ```nix 48 | services.tailscale = { 49 | enable = true; 50 | useRoutingFeatures = "both"; # or "client" or "server" depending on your needs 51 | }; 52 | ``` 53 | 54 | ## After Configuration 55 | 56 | 1. **Rebuild the system:** 57 | ```bash 58 | sudo nixos-rebuild switch --flake .#nixbook 59 | ``` 60 | 61 | 2. **Start Tailscale:** 62 | ```bash 63 | sudo systemctl start tailscaled 64 | sudo systemctl enable tailscaled 65 | ``` 66 | 67 | 3. **Authenticate the machine:** 68 | ```bash 69 | sudo tailscale up 70 | ``` 71 | This will give you a URL to authenticate via your Tailscale account. 72 | 73 | 4. **Verify status:** 74 | ```bash 75 | tailscale status 76 | ``` 77 | 78 | ## Routing Features Explained 79 | 80 | - **"both"**: Can act as both a client (use routes) and server (advertise routes) 81 | - **"client"**: Can use routes advertised by other devices, but won't advertise routes 82 | - **"server"**: Can advertise routes but won't use routes from other devices 83 | - **"none"**: No routing features (default) 84 | 85 | For a laptop like nixbook, **"client"** is usually sufficient unless you want to advertise routes. 86 | 87 | ## Firewall Considerations 88 | 89 | The firewall is currently disabled (`networking.firewall.enable = false`), which means Tailscale will work without any firewall rules. If you enable the firewall later, Tailscale will automatically configure the necessary rules via `networking.firewall.checkReversePath`. 90 | 91 | ## Troubleshooting 92 | 93 | ### Check if Tailscale is running: 94 | ```bash 95 | sudo systemctl status tailscaled 96 | ``` 97 | 98 | ### Check Tailscale logs: 99 | ```bash 100 | sudo journalctl -u tailscaled -f 101 | ``` 102 | 103 | ### Verify network connectivity: 104 | ```bash 105 | tailscale ping 106 | ``` 107 | 108 | ### Check if authenticated: 109 | ```bash 110 | tailscale status 111 | ``` 112 | 113 | If you see "Logged out", run `sudo tailscale up` to authenticate. 114 | -------------------------------------------------------------------------------- /hosts/nixstation/scripts/logitech-bluetooth.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Logitech Bluetooth Mouse Management Script 4 | # This script helps manage Logitech mouse Bluetooth connections 5 | 6 | set -e 7 | 8 | # Colors for output 9 | RED='\033[0;31m' 10 | GREEN='\033[0;32m' 11 | YELLOW='\033[1;33m' 12 | BLUE='\033[0;34m' 13 | NC='\033[0m' # No Color 14 | 15 | # Logitech MX Vertical MAC address (update this with your mouse's MAC) 16 | MOUSE_MAC="C5:7D:FD:5F:EB:DC" 17 | 18 | log() { 19 | echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" 20 | } 21 | 22 | error() { 23 | echo -e "${RED}[ERROR]${NC} $1" 24 | } 25 | 26 | success() { 27 | echo -e "${GREEN}[SUCCESS]${NC} $1" 28 | } 29 | 30 | warning() { 31 | echo -e "${YELLOW}[WARNING]${NC} $1" 32 | } 33 | 34 | # Check if Bluetooth is enabled 35 | check_bluetooth() { 36 | if ! systemctl is-active --quiet bluetooth; then 37 | error "Bluetooth service is not running" 38 | return 1 39 | fi 40 | success "Bluetooth service is running" 41 | } 42 | 43 | # Check mouse connection status 44 | check_mouse_status() { 45 | log "Checking mouse connection status..." 46 | 47 | # Check if mouse is connected via Bluetooth 48 | if bluetoothctl info "$MOUSE_MAC" | grep -q "Connected: yes"; then 49 | success "Mouse is connected via Bluetooth" 50 | return 0 51 | else 52 | warning "Mouse is not connected via Bluetooth" 53 | return 1 54 | fi 55 | } 56 | 57 | # Connect mouse via Bluetooth 58 | connect_mouse() { 59 | log "Attempting to connect mouse via Bluetooth..." 60 | 61 | # Check if mouse is trusted 62 | if ! bluetoothctl info "$MOUSE_MAC" | grep -q "Trusted: yes"; then 63 | warning "Mouse is not trusted. Please pair it first." 64 | return 1 65 | fi 66 | 67 | # Try to connect 68 | if bluetoothctl connect "$MOUSE_MAC"; then 69 | success "Mouse connected successfully" 70 | return 0 71 | else 72 | error "Failed to connect mouse" 73 | return 1 74 | fi 75 | } 76 | 77 | # Disconnect mouse from Bluetooth 78 | disconnect_mouse() { 79 | log "Disconnecting mouse from Bluetooth..." 80 | 81 | if bluetoothctl disconnect "$MOUSE_MAC"; then 82 | success "Mouse disconnected successfully" 83 | return 0 84 | else 85 | error "Failed to disconnect mouse" 86 | return 1 87 | fi 88 | } 89 | 90 | # Show mouse battery level (if supported) 91 | show_battery() { 92 | log "Checking mouse battery level..." 93 | 94 | # Try to get battery level via bluetoothctl 95 | if bluetoothctl info "$MOUSE_MAC" | grep -q "Battery"; then 96 | bluetoothctl info "$MOUSE_MAC" | grep "Battery" 97 | else 98 | warning "Battery information not available" 99 | fi 100 | } 101 | 102 | # Show available Logitech devices 103 | list_devices() { 104 | log "Available Logitech devices:" 105 | bluetoothctl devices | grep -i logitech || warning "No Logitech devices found" 106 | } 107 | 108 | # Main function 109 | main() { 110 | case "${1:-help}" in 111 | "status") 112 | check_bluetooth 113 | check_mouse_status 114 | ;; 115 | "connect") 116 | check_bluetooth 117 | connect_mouse 118 | ;; 119 | "disconnect") 120 | check_bluetooth 121 | disconnect_mouse 122 | ;; 123 | "battery") 124 | check_bluetooth 125 | show_battery 126 | ;; 127 | "list") 128 | list_devices 129 | ;; 130 | "help"|*) 131 | echo "Usage: $0 {status|connect|disconnect|battery|list|help}" 132 | echo "" 133 | echo "Commands:" 134 | echo " status - Check Bluetooth and mouse connection status" 135 | echo " connect - Connect mouse via Bluetooth" 136 | echo " disconnect - Disconnect mouse from Bluetooth" 137 | echo " battery - Show mouse battery level" 138 | echo " list - List available Logitech devices" 139 | echo " help - Show this help message" 140 | echo "" 141 | echo "Note: Update MOUSE_MAC variable in this script with your mouse's MAC address" 142 | ;; 143 | esac 144 | } 145 | 146 | main "$@" 147 | -------------------------------------------------------------------------------- /hosts/nixbook/waybar.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 30, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | "modules-left": ["hyprland/workspaces", "hyprland/window", "custom/mpris"], 11 | "modules-center": [], 12 | "modules-right": [ 13 | "custom/btc_price", 14 | "pulseaudio", 15 | 16 | "network", 17 | "custom/public_ip", 18 | "cpu", 19 | "memory", 20 | "gamemode", 21 | "tray", 22 | "bluetooth", 23 | "custom/dunst", 24 | "idle_inhibitor", 25 | "custom/brightness_menu", 26 | "clock", 27 | "custom/reboot" 28 | ], 29 | "hyprland/workspaces": { 30 | "disable-scroll": true, 31 | "all-outputs": true, 32 | "format": "{name}", 33 | "format-icons": { 34 | "1": "1", 35 | "2": "2", 36 | "3": "3", 37 | "4": "4", 38 | "5": "5", 39 | "6": "6", 40 | "7": "7", 41 | "8": "8", 42 | "9": "9", 43 | "10": "10", 44 | "urgent": "urgent", 45 | "focused": "focused", 46 | "default": "default" 47 | } 48 | }, 49 | "custom/btc_price": { 50 | "return-type": "json", 51 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-btc-coingecko.sh", 52 | "interval": 60, 53 | "format": "{}", 54 | "tooltip": true 55 | }, 56 | "hyprland/window": { 57 | "format": "{}", 58 | "max-length": 50 59 | }, 60 | "pulseaudio": { 61 | "format": "🔊 {volume}%", 62 | "format-bluetooth": "🔊 {volume}%", 63 | "format-bluetooth-muted": "🔊", 64 | "format-muted": "🔊", 65 | "on-click": "pavucontrol" 66 | }, 67 | "custom/mpris": { 68 | "return-type": "json", 69 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-mpris.sh", 70 | "interval": 1, 71 | "tooltip": true, 72 | "format": "{}", 73 | "on-click": "playerctl -p playerctld play-pause", 74 | "on-scroll-up": "playerctl -p playerctld next", 75 | "on-scroll-down": "playerctl -p playerctld previous" 76 | }, 77 | "custom/dunst": { 78 | "return-type": "json", 79 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-dunst.sh", 80 | "interval": 5, 81 | "on-click": "dunstctl set-paused toggle", 82 | "tooltip": true, 83 | "format": "{}" 84 | }, 85 | "network": { 86 | "format-wifi": "📶 {essid} ({signalStrength}%) ", 87 | "format-ethernet": "🖧 {ipaddr}/{cidr} ", 88 | "format-linked": "{ifname} (No IP) ", 89 | "format-disconnected": "Disconnected ⚠", 90 | "format-alt": "🖧 {ifname}: {ipaddr}/{cidr}", 91 | "on-click": "/home/chrisf/.config/waybar/scripts/waybar-wifi.sh", 92 | "on-click-right": "nm-connection-editor", 93 | "tooltip-format": "{ifname}\n{ipaddr}/{cidr}\n{essid} ({signalStrength}%)" 94 | }, 95 | "custom/public_ip": { 96 | "return-type": "json", 97 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-public-ip.sh", 98 | "interval": 300, 99 | "tooltip": true, 100 | "format": "🌍 {}" 101 | }, 102 | "cpu": { 103 | "format": "🖥️ {usage}% ", 104 | "tooltip": false 105 | }, 106 | "memory": { 107 | "format": "🤖 {percentage}% ", 108 | "tooltip": false 109 | }, 110 | "idle_inhibitor": { 111 | "format": "{icon}", 112 | "format-icons": { 113 | "activated": "☀️", 114 | "deactivated": "🌙" 115 | } 116 | }, 117 | "gamemode": { 118 | "format": "GM {count}" 119 | }, 120 | "clock": { 121 | "format": "🕒 {:%I:%M %p}", 122 | "tooltip-format": "{:%Y %B}\n{calendar}", 123 | "format-alt": "{:%Y-%m-%d}" 124 | }, 125 | "tray": { 126 | "spacing": 10 127 | } 128 | , 129 | "bluetooth": { 130 | "format": "🔵 {status}", 131 | "format-connected": "🔵 {num_connections}", 132 | "format-connected-battery": "🔵 {device_battery_percentage}%", 133 | "format-off": "⚪ off", 134 | "tooltip": true, 135 | "on-click": "blueman-manager" 136 | }, 137 | 138 | "custom/brightness_menu": { 139 | "format": "🖥️", 140 | "tooltip": true, 141 | "tooltip-format": "Brightness menu", 142 | "on-click": "~/.local/bin/rofi-brightness", 143 | "return-type": "json", 144 | "exec": "echo '{\"text\": \"🖥️\"}'", 145 | "interval": 0 146 | }, 147 | 148 | "custom/reboot": { 149 | "format": "⏻", 150 | "tooltip": true, 151 | "tooltip-format": "Reboot", 152 | "on-click": "/home/chrisf/.config/waybar/scripts/waybar-reboot.sh", 153 | "return-type": "json", 154 | "exec": "echo '{\"text\": \"⏻\"}'", 155 | "interval": 0 156 | } 157 | } -------------------------------------------------------------------------------- /configs/waybar-rvbee.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 30, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | "modules-left": ["hyprland/workspaces", "hyprland/window", "custom/mpris"], 11 | "modules-center": [], 12 | "modules-right": [ 13 | "custom/btc_price", 14 | "pulseaudio", 15 | "network", 16 | "custom/public_ip", 17 | "cpu", 18 | "memory", 19 | "custom/amd_gpu", 20 | "gamemode", 21 | "custom/weather", 22 | "tray", 23 | "bluetooth", 24 | "custom/dunst", 25 | "idle_inhibitor", 26 | "custom/brightness_menu", 27 | "clock", 28 | "custom/reboot" 29 | ], 30 | "hyprland/workspaces": { 31 | "disable-scroll": true, 32 | "all-outputs": true, 33 | "format": "{name}", 34 | "format-icons": { 35 | "1": "1", 36 | "2": "2", 37 | "3": "3", 38 | "4": "4", 39 | "5": "5", 40 | "6": "6", 41 | "7": "7", 42 | "8": "8", 43 | "9": "9", 44 | "10": "10", 45 | "urgent": "urgent", 46 | "focused": "focused", 47 | "default": "default" 48 | } 49 | }, 50 | "custom/btc_price": { 51 | "return-type": "json", 52 | "exec": "~/.config/waybar/scripts/waybar-btc-coingecko.sh", 53 | "interval": 60, 54 | "format": "{}", 55 | "tooltip": true 56 | }, 57 | "hyprland/window": { 58 | "format": "{}", 59 | "max-length": 50 60 | }, 61 | "pulseaudio": { 62 | "format": "🔊 {volume}%", 63 | "format-bluetooth": "🔊 {volume}%", 64 | "format-bluetooth-muted": "🔊", 65 | "format-muted": "🔊", 66 | "on-click": "pavucontrol" 67 | }, 68 | "custom/mpris": { 69 | "return-type": "json", 70 | "exec": "~/.config/waybar/scripts/waybar-mpris.sh", 71 | "interval": 1, 72 | "tooltip": true, 73 | "format": "{}", 74 | "on-click": "playerctl -p playerctld play-pause", 75 | "on-scroll-up": "playerctl -p playerctld next", 76 | "on-scroll-down": "playerctl -p playerctld previous" 77 | }, 78 | "custom/dunst": { 79 | "return-type": "json", 80 | "exec": "~/.config/waybar/scripts/waybar-dunst.sh", 81 | "interval": 5, 82 | "on-click": "dunstctl set-paused toggle", 83 | "tooltip": true, 84 | "format": "{}" 85 | }, 86 | "network": { 87 | "format-wifi": "{essid} ({signalStrength}%) ", 88 | "format-ethernet": "🖧 {ipaddr}/{cidr} ", 89 | "format-linked": "{ifname} (No IP) ", 90 | "format-disconnected": "Disconnected ⚠", 91 | "format-alt": "🖧 {ifname}: {ipaddr}/{cidr}", 92 | "on-click": "nm-connection-editor" 93 | }, 94 | "custom/public_ip": { 95 | "return-type": "json", 96 | "exec": "~/.config/waybar/scripts/waybar-public-ip.sh", 97 | "interval": 300, 98 | "tooltip": true, 99 | "format": "🌍 {}" 100 | }, 101 | "cpu": { 102 | "format": "🖥️ {usage}% ", 103 | "tooltip": false 104 | }, 105 | "memory": { 106 | "format": "🤖 {percentage}% ", 107 | "tooltip": false 108 | }, 109 | "custom/amd_gpu": { 110 | "return-type": "json", 111 | "exec": "~/.config/waybar/scripts/waybar-amd-gpu.sh", 112 | "interval": 5, 113 | "tooltip": true, 114 | "format": "🎮 {}" 115 | }, 116 | "idle_inhibitor": { 117 | "format": "{icon}", 118 | "format-icons": { 119 | "activated": "☀️", 120 | "deactivated": "🌙" 121 | } 122 | }, 123 | "custom/weather": { 124 | "return-type": "json", 125 | "exec": "~/.config/waybar/scripts/waybar-weather.sh", 126 | "interval": 600, 127 | "tooltip": true, 128 | "format": "{}" 129 | }, 130 | "gamemode": { "format": "GM {count}" }, 131 | "clock": { 132 | "format": "🕒 {:%I:%M %p}", 133 | "tooltip-format": "{:%Y %B}\n{calendar}", 134 | "format-alt": "{:%Y-%m-%d}" 135 | }, 136 | "tray": { "spacing": 10 }, 137 | "bluetooth": { 138 | "format": "🔵 {status}", 139 | "format-connected": "🔵 {num_connections}", 140 | "format-connected-battery": "🔵 {device_battery_percentage}%", 141 | "format-off": "⚪ off", 142 | "tooltip": true, 143 | "on-click": "blueman-manager" 144 | }, 145 | "custom/brightness_menu": { 146 | "format": "🖥️", 147 | "tooltip": true, 148 | "tooltip-format": "Brightness menu", 149 | "on-click": "~/.local/bin/rofi-brightness", 150 | "return-type": "json", 151 | "exec": "echo '{\"text\": \"🖥️\"}'", 152 | "interval": 0 153 | }, 154 | "custom/reboot": { 155 | "format": "⏻", 156 | "tooltip": true, 157 | "tooltip-format": "Reboot", 158 | "on-click": "~/.config/waybar/scripts/waybar-reboot.sh", 159 | "return-type": "json", 160 | "exec": "echo '{\"text\": \"⏻\"}'", 161 | "interval": 0 162 | } 163 | } 164 | 165 | 166 | -------------------------------------------------------------------------------- /hosts/nixstation/waybar-multi.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 38, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | 11 | "output": [ 12 | "DP-3" 13 | ], 14 | 15 | "modules-left": ["hyprland/workspaces", "hyprland/window", "custom/mpris"], 16 | "modules-center": [], 17 | "modules-right": [ 18 | "custom/btc_price", 19 | "pulseaudio", 20 | "network", 21 | "custom/public_ip", 22 | "cpu", 23 | "memory", 24 | "custom/amd_gpu", 25 | "gamemode", 26 | "custom/weather", 27 | "tray", 28 | "bluetooth", 29 | "custom/dunst", 30 | "idle_inhibitor", 31 | "custom/brightness_menu", 32 | "clock", 33 | "custom/reboot" 34 | ], 35 | 36 | "hyprland/workspaces": { 37 | "disable-scroll": true, 38 | "all-outputs": true, 39 | "format": "{name}", 40 | "format-icons": { 41 | "1": "1", 42 | "2": "2", 43 | "3": "3", 44 | "4": "4", 45 | "5": "5", 46 | "6": "6", 47 | "7": "7", 48 | "8": "8", 49 | "9": "9", 50 | "10": "10", 51 | "urgent": "urgent", 52 | "focused": "focused", 53 | "default": "default" 54 | } 55 | }, 56 | "custom/btc_price": { 57 | "return-type": "json", 58 | "exec": "~/.config/waybar/scripts/waybar-btc-coingecko.sh", 59 | "interval": 60, 60 | "format": "{}", 61 | "tooltip": true 62 | }, 63 | "hyprland/window": { 64 | "format": "{}", 65 | "max-length": 50 66 | }, 67 | "pulseaudio": { 68 | "format": "🔊 {volume}%", 69 | "format-bluetooth": "🔊 {volume}%", 70 | "format-bluetooth-muted": "🔊", 71 | "format-muted": "🔊", 72 | "on-click": "pavucontrol" 73 | }, 74 | "custom/mpris": { 75 | "return-type": "json", 76 | "exec": "~/.config/waybar/scripts/waybar-mpris.sh", 77 | "interval": 1, 78 | "tooltip": true, 79 | "format": "{}", 80 | "on-click": "playerctl -p playerctld play-pause", 81 | "on-scroll-up": "playerctl -p playerctld next", 82 | "on-scroll-down": "playerctl -p playerctld previous" 83 | }, 84 | "custom/dunst": { 85 | "return-type": "json", 86 | "exec": "~/.config/waybar/scripts/waybar-dunst.sh", 87 | "interval": 5, 88 | "on-click": "dunstctl set-paused toggle", 89 | "tooltip": true, 90 | "format": "{}" 91 | }, 92 | "network": { 93 | "format-wifi": "{essid} ({signalStrength}%) ", 94 | "format-ethernet": "🖧 {ipaddr}/{cidr} ", 95 | "format-linked": "{ifname} (No IP) ", 96 | "format-disconnected": "Disconnected ⚠", 97 | "format-alt": "🖧 {ifname}: {ipaddr}/{cidr}", 98 | "on-click": "nm-connection-editor" 99 | }, 100 | "custom/public_ip": { 101 | "return-type": "json", 102 | "exec": "~/.config/waybar/scripts/waybar-public-ip.sh", 103 | "interval": 300, 104 | "tooltip": true, 105 | "format": "🌍 {}" 106 | }, 107 | "cpu": { 108 | "format": "🖥️ {usage}% ", 109 | "tooltip": false 110 | }, 111 | "memory": { 112 | "format": "🤖 {percentage}% ", 113 | "tooltip": false 114 | }, 115 | "custom/amd_gpu": { 116 | "return-type": "json", 117 | "exec": "~/.config/waybar/scripts/waybar-amd-gpu.sh", 118 | "interval": 5, 119 | "tooltip": true, 120 | "format": "🎮 {}" 121 | }, 122 | "idle_inhibitor": { 123 | "format": "{icon}", 124 | "format-icons": { 125 | "activated": "☀️", 126 | "deactivated": "🌙" 127 | } 128 | }, 129 | "custom/weather": { 130 | "return-type": "json", 131 | "exec": "~/.config/waybar/scripts/waybar-weather.sh", 132 | "interval": 600, 133 | "tooltip": true, 134 | "format": "{}" 135 | }, 136 | "gamemode": { 137 | "format": "GM {count}" 138 | }, 139 | "clock": { 140 | "format": "🕒 {:%I:%M %p}", 141 | "tooltip-format": "{:%Y %B}\n{calendar}", 142 | "format-alt": "{:%Y-%m-%d}" 143 | }, 144 | "tray": { 145 | "spacing": 10 146 | }, 147 | "bluetooth": { 148 | "format": "🔵 {status}", 149 | "format-connected": "🔵 {num_connections}", 150 | "format-connected-battery": "🔵 {device_battery_percentage}%", 151 | "format-off": "⚪ off", 152 | "tooltip": true, 153 | "on-click": "blueman-manager" 154 | }, 155 | "custom/brightness_menu": { 156 | "format": "🖥️", 157 | "tooltip": true, 158 | "tooltip-format": "Brightness menu", 159 | "on-click": "~/.local/bin/rofi-brightness", 160 | "return-type": "json", 161 | "exec": "echo '{\"text\": \"🖥️\"}'", 162 | "interval": 0 163 | }, 164 | "custom/reboot": { 165 | "format": "⏻", 166 | "tooltip": true, 167 | "tooltip-format": "Reboot", 168 | "on-click": "~/.config/waybar/scripts/waybar-reboot.sh", 169 | "return-type": "json", 170 | "exec": "echo '{\"text\": \"⏻\"}'", 171 | "interval": 0 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /hosts/rvbee/waybar.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 30, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | "modules-left": ["hyprland/workspaces", "hyprland/window", "custom/mpris"], 11 | "modules-center": [], 12 | "modules-right": [ 13 | "custom/btc_price", 14 | "pulseaudio", 15 | 16 | "network", 17 | "custom/public_ip", 18 | "cpu", 19 | "memory", 20 | "custom/amd_gpu", 21 | "gamemode", 22 | "custom/weather", 23 | "tray", 24 | "bluetooth", 25 | "custom/dunst", 26 | "idle_inhibitor", 27 | "custom/brightness_menu", 28 | "clock", 29 | "custom/reboot" 30 | ], 31 | "hyprland/workspaces": { 32 | "disable-scroll": true, 33 | "all-outputs": true, 34 | "format": "{name}", 35 | "format-icons": { 36 | "1": "1", 37 | "2": "2", 38 | "3": "3", 39 | "4": "4", 40 | "5": "5", 41 | "6": "6", 42 | "7": "7", 43 | "8": "8", 44 | "9": "9", 45 | "10": "10", 46 | "urgent": "urgent", 47 | "focused": "focused", 48 | "default": "default" 49 | } 50 | }, 51 | "custom/btc_price": { 52 | "return-type": "json", 53 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-btc-coingecko.sh", 54 | "interval": 60, 55 | "format": "{}", 56 | "tooltip": true 57 | }, 58 | "hyprland/window": { 59 | "format": "{}", 60 | "max-length": 50 61 | }, 62 | "pulseaudio": { 63 | "format": "🔊 {volume}%", 64 | "format-bluetooth": "🔊 {volume}%", 65 | "format-bluetooth-muted": "🔊", 66 | "format-muted": "🔊", 67 | "on-click": "pavucontrol" 68 | }, 69 | "custom/mpris": { 70 | "return-type": "json", 71 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-mpris.sh", 72 | "interval": 1, 73 | "tooltip": true, 74 | "format": "{}", 75 | "on-click": "playerctl -p playerctld play-pause", 76 | "on-scroll-up": "playerctl -p playerctld next", 77 | "on-scroll-down": "playerctl -p playerctld previous" 78 | }, 79 | "custom/dunst": { 80 | "return-type": "json", 81 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-dunst.sh", 82 | "interval": 5, 83 | "on-click": "dunstctl set-paused toggle", 84 | "tooltip": true, 85 | "format": "{}" 86 | }, 87 | "network": { 88 | "format-wifi": "{essid} ({signalStrength}%) ", 89 | "format-ethernet": "🖧 {ipaddr}/{cidr} ", 90 | "format-linked": "{ifname} (No IP) ", 91 | "format-disconnected": "Disconnected ⚠", 92 | "format-alt": "🖧 {ifname}: {ipaddr}/{cidr}", 93 | "on-click": "nm-connection-editor" 94 | }, 95 | "custom/public_ip": { 96 | "return-type": "json", 97 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-public-ip.sh", 98 | "interval": 300, 99 | "tooltip": true, 100 | "format": "🌍 {}" 101 | }, 102 | "cpu": { 103 | "format": "🖥️ {usage}% ", 104 | "tooltip": false 105 | }, 106 | "memory": { 107 | "format": "🤖 {percentage}% ", 108 | "tooltip": false 109 | }, 110 | "custom/amd_gpu": { 111 | "return-type": "json", 112 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-amd-gpu.sh", 113 | "interval": 5, 114 | "tooltip": true, 115 | "format": "🎮 {}" 116 | }, 117 | 118 | "idle_inhibitor": { 119 | "format": "{icon}", 120 | "format-icons": { 121 | "activated": "☀️", 122 | "deactivated": "🌙" 123 | } 124 | }, 125 | "custom/weather": { 126 | "return-type": "json", 127 | "exec": "/home/chrisf/.config/waybar/scripts/waybar-weather.sh", 128 | "interval": 600, 129 | "tooltip": true, 130 | "format": "{}" 131 | }, 132 | "gamemode": { 133 | "format": "GM {count}" 134 | }, 135 | "clock": { 136 | "format": "🕒 {:%I:%M %p}", 137 | "tooltip-format": "{:%Y %B}\n{calendar}", 138 | "format-alt": "{:%Y-%m-%d}" 139 | }, 140 | "tray": { 141 | "spacing": 10 142 | } 143 | , 144 | "bluetooth": { 145 | "format": "🔵 {status}", 146 | "format-connected": "🔵 {num_connections}", 147 | "format-connected-battery": "🔵 {device_battery_percentage}%", 148 | "format-off": "⚪ off", 149 | "tooltip": true, 150 | "on-click": "blueman-manager" 151 | }, 152 | 153 | "custom/brightness_menu": { 154 | "format": "🖥️", 155 | "tooltip": true, 156 | "tooltip-format": "Brightness menu", 157 | "on-click": "~/.local/bin/rofi-brightness", 158 | "return-type": "json", 159 | "exec": "echo '{\"text\": \"🖥️\"}'", 160 | "interval": 0 161 | }, 162 | 163 | "custom/reboot": { 164 | "format": "⏻", 165 | "tooltip": true, 166 | "tooltip-format": "Reboot", 167 | "on-click": "/home/chrisf/.config/waybar/scripts/waybar-reboot.sh", 168 | "return-type": "json", 169 | "exec": "echo '{\"text\": \"⏻\"}'", 170 | "interval": 0 171 | } 172 | } -------------------------------------------------------------------------------- /hosts/nixstation/waybar.json: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "position": "top", 4 | "height": 38, 5 | "spacing": 4, 6 | "margin-top": 0, 7 | "margin-bottom": 0, 8 | "margin-left": 0, 9 | "margin-right": 0, 10 | "output": ["DP-3"], 11 | "modules-left": ["hyprland/workspaces", "hyprland/window", "custom/mpris"], 12 | "modules-center": [], 13 | "modules-right": [ 14 | "custom/btc_price", 15 | "pulseaudio", 16 | "network", 17 | "custom/public_ip", 18 | "cpu", 19 | "memory", 20 | "custom/amd_gpu", 21 | "gamemode", 22 | "custom/weather", 23 | "tray", 24 | "bluetooth", 25 | "custom/dunst", 26 | "idle_inhibitor", 27 | "custom/brightness_menu", 28 | "clock", 29 | "custom/timezones", 30 | "custom/reboot" 31 | ], 32 | "hyprland/workspaces": { 33 | "disable-scroll": true, 34 | "all-outputs": true, 35 | "format": "{name}", 36 | "format-icons": { 37 | "1": "1", 38 | "2": "2", 39 | "3": "3", 40 | "4": "4", 41 | "5": "5", 42 | "6": "6", 43 | "7": "7", 44 | "8": "8", 45 | "9": "9", 46 | "10": "10", 47 | "urgent": "urgent", 48 | "focused": "focused", 49 | "default": "default" 50 | } 51 | }, 52 | "custom/btc_price": { 53 | "return-type": "json", 54 | "exec": "~/.config/waybar/scripts/waybar-btc-coingecko.sh", 55 | "interval": 60, 56 | "format": "{}", 57 | "tooltip": true 58 | }, 59 | "hyprland/window": { 60 | "format": "{}", 61 | "max-length": 50 62 | }, 63 | "pulseaudio": { 64 | "format": "󰕾 {volume}%", 65 | "format-bluetooth": "󰕾 {volume}%", 66 | "format-bluetooth-muted": "󰖁", 67 | "format-muted": "󰖁", 68 | "on-click": "pavucontrol" 69 | }, 70 | "custom/mpris": { 71 | "return-type": "json", 72 | "exec": "~/.config/waybar/scripts/waybar-mpris.sh", 73 | "interval": 1, 74 | "tooltip": true, 75 | "format": "{}", 76 | "on-click": "playerctl -p playerctld play-pause", 77 | "on-scroll-up": "playerctl -p playerctld next", 78 | "on-scroll-down": "playerctl -p playerctld previous" 79 | }, 80 | "custom/dunst": { 81 | "return-type": "json", 82 | "exec": "~/.config/waybar/scripts/waybar-dunst.sh", 83 | "interval": 5, 84 | "on-click": "dunstctl set-paused toggle", 85 | "tooltip": true, 86 | "format": "{}" 87 | }, 88 | "network": { 89 | "format-wifi": "󰖩 {essid} ({signalStrength}%) ", 90 | "format-ethernet": "󰈀 {ipaddr}/{cidr} ", 91 | "format-linked": "󰈁 {ifname} (No IP) ", 92 | "format-disconnected": "󰈂 Disconnected", 93 | "format-alt": "󰈀 {ifname}: {ipaddr}/{cidr}", 94 | "on-click": "nm-connection-editor" 95 | }, 96 | "custom/public_ip": { 97 | "return-type": "json", 98 | "exec": "~/.config/waybar/scripts/waybar-public-ip.sh", 99 | "interval": 300, 100 | "tooltip": true, 101 | "format": "󰍉 {}" 102 | }, 103 | "cpu": { 104 | "format": "󰘚 {usage}% ", 105 | "tooltip": false 106 | }, 107 | "memory": { 108 | "format": "󰍛 {percentage}% ", 109 | "tooltip": false 110 | }, 111 | "custom/amd_gpu": { 112 | "return-type": "json", 113 | "exec": "~/.config/waybar/scripts/waybar-amd-gpu.sh", 114 | "interval": 5, 115 | "tooltip": true, 116 | "format": "󰓃 {}" 117 | }, 118 | "idle_inhibitor": { 119 | "format": "{icon}", 120 | "format-icons": { 121 | "activated": "󰌵", 122 | "deactivated": "󰌶" 123 | } 124 | }, 125 | "custom/weather": { 126 | "return-type": "json", 127 | "exec": "~/.config/waybar/scripts/waybar-weather.sh", 128 | "interval": 600, 129 | "tooltip": true, 130 | "format": "{}" 131 | }, 132 | "gamemode": { 133 | "format": "󰊄 {count}" 134 | }, 135 | "clock": { 136 | "format": "{:%I:%M %p}", 137 | "tooltip-format": "{:%Y %B}\n{calendar}", 138 | "format-alt": "{:%Y-%m-%d}" 139 | }, 140 | "custom/timezones": { 141 | "return-type": "json", 142 | "exec": "~/.config/waybar/scripts/waybar-timezones.sh", 143 | "interval": 1, 144 | "tooltip": true, 145 | "format": "{}" 146 | }, 147 | "tray": { 148 | "spacing": 10 149 | }, 150 | "bluetooth": { 151 | "format": "󰂯 {status}", 152 | "format-connected": "󰂯 {num_connections}", 153 | "format-connected-battery": "󰂯 {device_battery_percentage}%", 154 | "format-off": "󰂲 off", 155 | "tooltip": true, 156 | "on-click": "blueman-manager" 157 | }, 158 | "custom/brightness_menu": { 159 | "format": "󰃠", 160 | "tooltip": true, 161 | "tooltip-format": "Brightness menu", 162 | "on-click": "~/.local/bin/rofi-brightness", 163 | "return-type": "json", 164 | "exec": "echo '{\"text\": \"󰃠\"}'", 165 | "interval": 0 166 | }, 167 | "custom/reboot": { 168 | "format": "󰐥", 169 | "tooltip": true, 170 | "tooltip-format": "Reboot", 171 | "on-click": "~/.config/waybar/scripts/waybar-reboot.sh", 172 | "return-type": "json", 173 | "exec": "echo '{\"text\": \"󰐥\"}'", 174 | "interval": 0 175 | } 176 | } -------------------------------------------------------------------------------- /scripts/setup-monitors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Monitor Setup Helper Script 4 | # This script helps you configure monitors for different hosts 5 | 6 | set -e 7 | 8 | HOSTNAME=$(hostname) 9 | CONFIG_DIR="/home/chrisf/.config/hypr" 10 | 11 | echo "=== Monitor Setup Helper for $HOSTNAME ===" 12 | 13 | # Function to detect monitors 14 | detect_monitors() { 15 | echo "Detecting monitors..." 16 | hyprctl monitors 17 | echo "" 18 | echo "Monitor names and their current configuration:" 19 | hyprctl monitors | grep -E "(Monitor|resolution|refreshRate)" | sed 's/^/ /' 20 | } 21 | 22 | # Function to generate monitor configuration 23 | generate_monitor_config() { 24 | local host=$1 25 | local config_file="$CONFIG_DIR/hyprland-monitors-$host.conf" 26 | 27 | echo "Generating monitor configuration for $host..." 28 | echo "# Auto-generated monitor configuration for $host" > "$config_file" 29 | echo "# Generated on $(date)" >> "$config_file" 30 | echo "" >> "$config_file" 31 | 32 | # Get monitor information 33 | hyprctl monitors | while IFS= read -r line; do 34 | if [[ $line =~ ^Monitor\ ([^:]+): ]]; then 35 | monitor_name="${BASH_REMATCH[1]}" 36 | echo "Found monitor: $monitor_name" 37 | echo "# monitor=$monitor_name,resolution@refresh,x,y,scale" >> "$config_file" 38 | fi 39 | done 40 | 41 | echo "" >> "$config_file" 42 | echo "# Example configuration (uncomment and modify as needed):" >> "$config_file" 43 | echo "# monitor=DP-1,2560x1440@144,0x0,1" >> "$config_file" 44 | echo "# monitor=DP-2,2560x1440@144,2560x0,1" >> "$config_file" 45 | echo "# monitor=HDMI-A-1,1920x1080@60,5120x0,1" >> "$config_file" 46 | echo "# monitor=HDMI-A-2,1920x1080@60,5120x1080,1" >> "$config_file" 47 | 48 | echo "Configuration written to $config_file" 49 | echo "Please edit this file with your actual monitor settings." 50 | } 51 | 52 | # Function to apply monitor configuration 53 | apply_monitor_config() { 54 | local host=$1 55 | local config_file="$CONFIG_DIR/hyprland-monitors-$host.conf" 56 | 57 | if [[ ! -f "$config_file" ]]; then 58 | echo "Error: Monitor configuration file not found: $config_file" 59 | exit 1 60 | fi 61 | 62 | echo "Applying monitor configuration from $config_file..." 63 | 64 | # Extract monitor lines and apply them 65 | grep "^monitor=" "$config_file" | while read -r line; do 66 | if [[ $line =~ ^monitor=([^,]+),([^,]+),([^,]+),([^,]+)$ ]]; then 67 | monitor="${BASH_REMATCH[1]}" 68 | resolution="${BASH_REMATCH[2]}" 69 | position="${BASH_REMATCH[3]}" 70 | scale="${BASH_REMATCH[4]}" 71 | 72 | echo "Applying: $monitor -> $resolution at $position with scale $scale" 73 | hyprctl keyword monitor "$monitor,$resolution,$position,$scale" 74 | fi 75 | done 76 | 77 | echo "Monitor configuration applied!" 78 | } 79 | 80 | # Function to show current monitor status 81 | show_status() { 82 | echo "Current monitor configuration:" 83 | hyprctl monitors 84 | echo "" 85 | echo "Current monitor keywords:" 86 | hyprctl getoption monitor | grep -v "Option" | sed 's/^/ /' 87 | } 88 | 89 | # Main script logic 90 | case "${1:-help}" in 91 | "detect") 92 | detect_monitors 93 | ;; 94 | "generate") 95 | if [[ -z "$2" ]]; then 96 | echo "Usage: $0 generate " 97 | echo "Example: $0 generate nixstation" 98 | exit 1 99 | fi 100 | generate_monitor_config "$2" 101 | ;; 102 | "apply") 103 | if [[ -z "$2" ]]; then 104 | echo "Usage: $0 apply " 105 | echo "Example: $0 apply nixstation" 106 | exit 1 107 | fi 108 | apply_monitor_config "$2" 109 | ;; 110 | "status") 111 | show_status 112 | ;; 113 | "setup") 114 | if [[ -z "$2" ]]; then 115 | echo "Usage: $0 setup " 116 | echo "Example: $0 setup nixstation" 117 | exit 1 118 | fi 119 | detect_monitors 120 | generate_monitor_config "$2" 121 | echo "" 122 | echo "Next steps:" 123 | echo "1. Edit $CONFIG_DIR/hyprland-monitors-$2.conf with your monitor settings" 124 | echo "2. Run: $0 apply $2" 125 | ;; 126 | "help"|*) 127 | echo "Usage: $0 [hostname]" 128 | echo "" 129 | echo "Commands:" 130 | echo " detect - Detect and display current monitors" 131 | echo " generate - Generate monitor config template for host" 132 | echo " apply - Apply monitor config for host" 133 | echo " status - Show current monitor status" 134 | echo " setup - Full setup process for host" 135 | echo " help - Show this help message" 136 | echo "" 137 | echo "Examples:" 138 | echo " $0 setup nixstation # Full setup for nixstation" 139 | echo " $0 setup rvbee # Full setup for rvbee" 140 | echo " $0 detect # Just detect monitors" 141 | echo " $0 apply nixstation # Apply existing config" 142 | ;; 143 | esac 144 | -------------------------------------------------------------------------------- /hosts/nixbook/POWER_MANAGEMENT.md: -------------------------------------------------------------------------------- 1 | # Dynamic Power Management for Nixbook 2 | 3 | This configuration provides modern, NixOS-first dynamic power management with a performance bias, manual low-power mode switching, and automatic battery sleep. 4 | 5 | ## Features 6 | 7 | - **Performance-biased defaults**: CPU, disk, WiFi, and GPU optimized for performance by default 8 | - **Dynamic power profiles**: Switch between Performance, Balanced, and Power Saver modes 9 | - **Automatic battery sleep**: System automatically sleeps after 30 minutes of inactivity when on battery 10 | - **Hyprland integration**: Power profile switching via keybindings and launcher 11 | - **Comprehensive control**: Manages CPU governor, WiFi power saving, disk power management, and GPU power states 12 | 13 | ## Usage 14 | 15 | ### Power Profile Switching 16 | 17 | #### Via Hyprland Keybinding 18 | - Press `SUPER+SHIFT+P` to open the power profile menu 19 | 20 | #### Via Command Line 21 | ```bash 22 | # Switch to performance mode (maximum performance) 23 | power-profile performance 24 | 25 | # Switch to balanced mode (balanced performance/power) 26 | power-profile balanced 27 | 28 | # Switch to power saver mode (maximum battery life) 29 | power-profile power-saver 30 | 31 | # Check current profile and battery status 32 | power-profile status 33 | ``` 34 | 35 | #### Via Rofi Menu 36 | ```bash 37 | rofi-power-profile 38 | ``` 39 | 40 | ### Power Profiles 41 | 42 | #### Performance Mode 43 | - **CPU Governor**: `performance` (maximum frequency) 44 | - **WiFi Power Saving**: Disabled 45 | - **Disk Power Saving**: Disabled (drives stay active) 46 | - **GPU Power Saving**: Disabled (Intel RC6 disabled, AMD high performance) 47 | - **Use Case**: Gaming, video editing, compilation, maximum responsiveness 48 | 49 | #### Balanced Mode 50 | - **CPU Governor**: `schedutil` (adaptive) 51 | - **WiFi Power Saving**: Enabled 52 | - **Disk Power Saving**: Auto (allows some power saving) 53 | - **GPU Power Saving**: Auto (balanced) 54 | - **Use Case**: General desktop use, mixed workloads 55 | 56 | #### Power Saver Mode 57 | - **CPU Governor**: `powersave` (minimum frequency) 58 | - **WiFi Power Saving**: Enabled 59 | - **Disk Power Saving**: Enabled (aggressive power saving) 60 | - **GPU Power Saving**: Enabled (maximum power saving) 61 | - **Use Case**: Battery conservation, light workloads 62 | 63 | ## Automatic Battery Sleep 64 | 65 | The system automatically monitors battery status and will: 66 | - Lock the session 67 | - Suspend the system 68 | 69 | After **30 minutes** of inactivity when running on battery power. 70 | 71 | This is handled by the `battery-auto-sleep` systemd user service. 72 | 73 | ### Disabling Auto-Sleep 74 | 75 | To disable automatic battery sleep, set `autoSleepOnBatteryMinutes = 0` in your `system.nix`: 76 | 77 | ```nix 78 | hyprvibe.power = { 79 | enable = true; 80 | autoSleepOnBatteryMinutes = 0; # Disable auto-sleep 81 | # ... other settings 82 | }; 83 | ``` 84 | 85 | ## Configuration 86 | 87 | Power management is configured in `hosts/nixbook/system.nix`: 88 | 89 | ```nix 90 | hyprvibe.power = { 91 | enable = true; 92 | autoSleepOnBatteryMinutes = 30; 93 | performanceMode = { 94 | cpuGovernor = "performance"; 95 | wifiPowerSave = false; 96 | diskPowerSave = false; 97 | }; 98 | powerSaverMode = { 99 | cpuGovernor = "powersave"; 100 | wifiPowerSave = true; 101 | diskPowerSave = true; 102 | }; 103 | }; 104 | ``` 105 | 106 | ## Technical Details 107 | 108 | ### Components 109 | 110 | 1. **power-profiles-daemon**: Provides D-Bus interface for power profile switching 111 | 2. **power-profile script**: Installed to `~/.local/bin/power-profile` - handles profile switching 112 | 3. **rofi-power-profile script**: Rofi menu interface for power profiles 113 | 4. **battery-auto-sleep service**: Systemd user service for automatic sleep on battery 114 | 115 | ### Hardware Support 116 | 117 | - **CPU**: Intel and AMD CPUs with frequency scaling support 118 | - **WiFi**: Modern (iw) and legacy (iwconfig) WiFi drivers 119 | - **Disk**: NVMe and SATA SSDs/HDDs 120 | - **GPU**: Intel i915 and AMD amdgpu drivers 121 | 122 | ### System Integration 123 | 124 | - Power profiles integrate with `power-profiles-daemon` when available 125 | - Falls back to manual sysfs manipulation if daemon unavailable 126 | - All changes require sudo privileges (handled automatically) 127 | - User notifications via `notify-send` when switching profiles 128 | 129 | ## Troubleshooting 130 | 131 | ### Power profile not switching 132 | - Ensure `power-profiles-daemon` is running: `systemctl --user status power-profiles-daemon` 133 | - Check if CPU frequency scaling is available: `ls /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor` 134 | - Verify sudo access: `sudo -v` 135 | 136 | ### Auto-sleep not working 137 | - Check battery detection: `upower -i $(upower -e | grep battery | head -1)` 138 | - Verify service is running: `systemctl --user status battery-auto-sleep` 139 | - Check logs: `journalctl --user -u battery-auto-sleep` 140 | 141 | ### WiFi power saving not applying 142 | - Verify WiFi interface name: `ip link show | grep -E 'wl|wifi|wlan'` 143 | - Check if `iw` or `iwconfig` is available: `which iw iwconfig` 144 | - Test manually: `sudo iw dev wlan0 set power_save off` 145 | 146 | ## Performance Impact 147 | 148 | - **Performance Mode**: Maximum performance, higher power consumption 149 | - **Balanced Mode**: Good balance, moderate power consumption 150 | - **Power Saver Mode**: Maximum battery life, reduced performance 151 | 152 | The system defaults to **Performance Mode** to prioritize CPU, disk, WiFi, and GPU performance as requested. 153 | -------------------------------------------------------------------------------- /docs/KITTY_DEFAULT_TERMINAL_SETUP.md: -------------------------------------------------------------------------------- 1 | # Kitty Default Terminal Setup Summary 2 | 3 | ## Overview 4 | 5 | Successfully configured Kitty as the default terminal emulator across both NIXSTATION and RVBEE systems, replacing Alacritty. This ensures a consistent terminal experience with the enhanced Oh My Posh configuration we previously set up. 6 | 7 | ## Changes Made 8 | 9 | ### 1. **Hyprland Configuration Updates** 10 | 11 | #### **Base Configuration (`hyprvibe/configs/hyprland-base.conf`)** 12 | - ✅ Changed `$terminal = alacritty` to `$terminal = kitty` 13 | - ✅ This affects the Super+Return keybinding that opens the terminal 14 | 15 | ### 2. **System Package Management** 16 | 17 | #### **NIXSTATION (`hyprvibe/hosts/nixstation/system.nix`)** 18 | - ✅ Removed `alacritty` from `devTools` package list 19 | - ✅ Removed `alacritty` from `applications` package list 20 | - ✅ Removed `alacritty` from `systemTools` package list 21 | - ✅ Kitty was already installed in `devTools` package list 22 | 23 | #### **RVBEE (`hyprvibe/hosts/rvbee/system.nix`)** 24 | - ✅ Removed `alacritty` from `applications` package list 25 | - ✅ Kitty was already installed in `devTools` package list 26 | 27 | ### 3. **Environment Variables** 28 | 29 | #### **Both Systems** 30 | - ✅ Added `TERMINAL = "kitty"` to session variables 31 | - ✅ Added `KITTY_CONFIG_DIRECTORY = "~/.config/kitty"` for configuration path 32 | - ✅ Added `KITTY_SHELL_INTEGRATION = "enabled"` for enhanced integration 33 | 34 | ### 4. **Desktop Entry Configuration** 35 | 36 | #### **Both Systems** 37 | - ✅ Created custom desktop entry for Kitty at `~/.local/share/applications/kitty.desktop` 38 | - ✅ Added desktop database update to register Kitty properly 39 | - ✅ Ensures Kitty appears in application launchers and file managers 40 | 41 | ## Configuration Details 42 | 43 | ### **Hyprland Keybinding** 44 | ```bash 45 | # Super+Return now opens Kitty instead of Alacritty 46 | bind = SUPER, RETURN, exec, $terminal # $terminal = kitty 47 | ``` 48 | 49 | ### **Environment Variables** 50 | ```bash 51 | TERMINAL = "kitty" 52 | KITTY_CONFIG_DIRECTORY = "~/.config/kitty" 53 | KITTY_SHELL_INTEGRATION = "enabled" 54 | ``` 55 | 56 | ### **Desktop Entry** 57 | ```ini 58 | [Desktop Entry] 59 | Version=1.0 60 | Type=Application 61 | Name=Kitty 62 | GenericName=Terminal 63 | Comment=Fast, feature-rich, GPU based terminal emulator 64 | Exec=kitty 65 | Icon=kitty 66 | Terminal=false 67 | Categories=System;TerminalEmulator; 68 | ``` 69 | 70 | ## Features Now Available 71 | 72 | ### **Kitty Terminal Features** 73 | - ✅ **URL Detection**: Clickable hyperlinks in terminal 74 | - ✅ **Copy on Select**: Automatic clipboard copying 75 | - ✅ **Shell Integration**: Enhanced Fish shell integration 76 | - ✅ **GPU Acceleration**: Hardware-accelerated rendering 77 | - ✅ **Font Ligatures**: Fira Code with programming ligatures 78 | - ✅ **Performance**: Optimized for smooth operation 79 | 80 | ### **Oh My Posh Integration** 81 | - ✅ **Beautiful Prompts**: 4 different themes available 82 | - ✅ **Development Tools**: Git, Node.js, Python, Go, Rust, Docker detection 83 | - ✅ **Theme Switching**: Easy theme switching with `switch-oh-my-posh-theme` 84 | - ✅ **Fish Integration**: Seamless integration with Fish shell and Atuin 85 | 86 | ### **System Integration** 87 | - ✅ **Default Terminal**: Kitty opens with Super+Return 88 | - ✅ **Application Launchers**: Kitty appears in Rofi and other launchers 89 | - ✅ **File Managers**: Right-click "Open in Terminal" uses Kitty 90 | - ✅ **Desktop Environment**: Properly registered in desktop environment 91 | 92 | ## Usage Instructions 93 | 94 | ### **Opening Terminal** 95 | - **Keyboard**: Press `Super+Return` to open Kitty 96 | - **Application Launcher**: Search for "Kitty" in Rofi or other launchers 97 | - **Command Line**: Type `kitty` in any terminal 98 | 99 | ### **Theme Switching** 100 | ```bash 101 | switch-oh-my-posh-theme enhanced # Feature-rich development 102 | switch-oh-my-posh-theme minimal # Clean, distraction-free 103 | switch-oh-my-posh-theme professional # Modern diamond style 104 | switch-oh-my-posh-theme default # Tokyo Night theme 105 | ``` 106 | 107 | ### **Testing Features** 108 | - **URLs**: Type a URL and it will be clickable 109 | - **Copy on Select**: Select text and it's automatically copied 110 | - **Oh My Posh**: Beautiful prompt with development context 111 | - **Atuin History**: Ctrl+R for command history search 112 | 113 | ## Compatibility 114 | 115 | ### **✅ Verified Working** 116 | - Kitty + Hyprland 117 | - Kitty + Fish shell 118 | - Kitty + Oh My Posh 119 | - Kitty + Atuin history 120 | - Kitty + Shell integration 121 | - All existing functionality preserved 122 | 123 | ### **Removed Components** 124 | - Alacritty terminal emulator (no longer installed) 125 | - Alacritty configuration files (replaced by Kitty config) 126 | 127 | ## Next Steps 128 | 129 | 1. **Rebuild Systems**: Run `sudo nixos-rebuild switch` on both systems 130 | 2. **Test Terminal**: Press Super+Return to verify Kitty opens 131 | 3. **Test Features**: Verify URL detection, copy on select, and Oh My Posh 132 | 4. **Enjoy**: Experience the enhanced terminal setup 133 | 134 | ## Benefits 135 | 136 | ### **Performance** 137 | - GPU-accelerated rendering for smooth operation 138 | - Optimized for modern hardware 139 | - Fast startup and operation 140 | 141 | ### **Features** 142 | - URL detection and clickable links 143 | - Automatic copy on text selection 144 | - Beautiful Oh My Posh prompts 145 | - Comprehensive development tool detection 146 | 147 | ### **Integration** 148 | - Seamless Hyprland integration 149 | - Proper desktop environment registration 150 | - Consistent experience across both systems 151 | 152 | Kitty is now the default terminal emulator across both NIXSTATION and RVBEE, providing a modern, feature-rich terminal experience with excellent integration with Oh My Posh and the overall system configuration. 153 | -------------------------------------------------------------------------------- /docs/KITTY_OH_MY_POSH_SETUP.md: -------------------------------------------------------------------------------- 1 | # Kitty Terminal + Oh My Posh + Fish + Atuin Setup 2 | 3 | ## Overview 4 | 5 | This configuration sets up a complete terminal environment with: 6 | - **Kitty Terminal**: Modern, fast terminal emulator with GPU acceleration 7 | - **Oh My Posh**: Beautiful, customizable prompt engine 8 | - **Fish Shell**: User-friendly shell with excellent features 9 | - **Atuin**: Advanced command history management 10 | 11 | ## Compatibility Verification ✅ 12 | 13 | All components work perfectly together: 14 | - ✅ **Oh My Posh + Fish**: Native Fish shell support with excellent integration 15 | - ✅ **Oh My Posh + Atuin**: No conflicts - Atuin manages history, Oh My Posh manages prompt 16 | - ✅ **Kitty + Oh My Posh**: Excellent shell integration and prompt rendering 17 | - ✅ **Kitty + Fish**: Native Fish shell support with shell integration 18 | 19 | ## Features Configured 20 | 21 | ### Kitty Terminal Features 22 | - **URL Detection**: Automatically detects and underlines URLs 23 | - **Hyperlink Support**: Clickable URLs with target preview 24 | - **Copy on Select**: Automatic clipboard copying when text is selected 25 | - **Shell Integration**: Enhanced integration with Fish shell 26 | - **Tokyo Night Theme**: Beautiful dark theme with blue accents 27 | - **Fira Code Font**: Programming font with ligatures 28 | - **Performance Optimized**: GPU acceleration and efficient rendering 29 | 30 | ### Oh My Posh Features 31 | - **Custom Theme**: Tokyo Night inspired colors 32 | - **Development Tools**: Shows Git, Node.js, Python, Go, Rust, Docker context 33 | - **Execution Time**: Shows command execution time for slow commands 34 | - **Exit Status**: Visual feedback for command success/failure 35 | - **Time Display**: Current time in the right prompt 36 | - **Path Display**: Smart path truncation and styling 37 | 38 | ### Fish Shell Features 39 | - **Atuin Integration**: Advanced command history with search 40 | - **Oh My Posh Integration**: Beautiful, informative prompts 41 | - **Kitty Integration**: Enhanced terminal features 42 | - **Git Integration**: Built-in Git status and completion 43 | 44 | ### Atuin Features 45 | - **Command History**: Persistent, searchable command history 46 | - **Cross-Session**: History shared across all terminal sessions 47 | - **Search**: Fuzzy search with Ctrl+R 48 | - **Sync**: Optional cloud sync for history 49 | 50 | ## Configuration Files 51 | 52 | ### Kitty Configuration 53 | - **Location**: `~/.config/kitty/kitty.conf` 54 | - **Features**: 55 | - URL detection and hyperlinks 56 | - Copy on select enabled 57 | - Shell integration enabled 58 | - Tokyo Night color scheme 59 | - Fira Code font 60 | - Performance optimizations 61 | 62 | ### Oh My Posh Configuration 63 | - **Location**: `~/.config/oh-my-posh/config.json` 64 | - **Features**: 65 | - Custom Tokyo Night theme 66 | - Development tool detection 67 | - Execution time tracking 68 | - Exit status display 69 | - Time display 70 | 71 | ### Fish Shell Configuration 72 | - **Location**: `~/.config/fish/conf.d/` 73 | - **Files**: 74 | - `oh-my-posh.fish`: Oh My Posh integration 75 | - `kitty-integration.fish`: Kitty terminal integration 76 | - `atuin.fish`: Atuin history integration 77 | 78 | ## Usage Instructions 79 | 80 | ### Starting Kitty Terminal 81 | ```bash 82 | kitty 83 | ``` 84 | 85 | ### Testing Features 86 | Run the test script to verify all features: 87 | ```bash 88 | ./test-kitty-features.sh 89 | ``` 90 | 91 | ### Oh My Posh Commands 92 | - **Change Theme**: Edit `~/.config/oh-my-posh/config.json` 93 | - **Reload Prompt**: `omp_repaint_prompt` in Fish 94 | - **Enable Tooltips**: `enable_poshtooltips` in Fish 95 | 96 | ### Atuin Commands 97 | - **Search History**: `Ctrl+R` in Fish 98 | - **Sync History**: `atuin sync` 99 | - **Import History**: `atuin import` 100 | - **Stats**: `atuin stats` 101 | 102 | ### Kitty Commands 103 | - **New Window**: `Ctrl+Shift+Enter` 104 | - **New Tab**: `Ctrl+Shift+T` 105 | - **Close Tab**: `Ctrl+Shift+W` 106 | - **Font Size**: `Ctrl+Shift+Plus/Minus` 107 | - **Reset Font**: `Ctrl+Shift+0` 108 | 109 | ## Troubleshooting 110 | 111 | ### Oh My Posh Not Loading 112 | 1. Check if package is installed: `which oh-my-posh` 113 | 2. Verify Fish configuration: `cat ~/.config/fish/conf.d/oh-my-posh.fish` 114 | 3. Restart Fish shell: `exec fish` 115 | 116 | ### Kitty Features Not Working 117 | 1. Check configuration: `kitty --config ~/.config/kitty/kitty.conf` 118 | 2. Verify shell integration: `echo $KITTY_SHELL_INTEGRATION` 119 | 3. Restart Kitty terminal 120 | 121 | ### Atuin Not Working 122 | 1. Check service status: `systemctl --user status atuin` 123 | 2. Verify Fish integration: `cat ~/.config/fish/conf.d/atuin.fish` 124 | 3. Test history search: `Ctrl+R` in Fish 125 | 126 | ## System Integration 127 | 128 | ### NixOS Configuration 129 | The setup is integrated into the NixOS system configuration: 130 | - Oh My Posh package added to system packages 131 | - Configuration files created via activation scripts 132 | - Fish shell configured with all integrations 133 | - Atuin service enabled 134 | 135 | ### Automatic Setup 136 | On system rebuild, the following is automatically configured: 137 | - Kitty terminal configuration 138 | - Oh My Posh theme and integration 139 | - Fish shell with all plugins 140 | - Atuin history service 141 | 142 | ## Performance Notes 143 | 144 | - **Kitty**: GPU-accelerated rendering for smooth performance 145 | - **Oh My Posh**: Efficient prompt rendering with caching 146 | - **Fish**: Fast startup and command execution 147 | - **Atuin**: Minimal overhead for history management 148 | 149 | ## Security Considerations 150 | 151 | - **Atuin**: History can be optionally encrypted and synced 152 | - **Kitty**: Secure clipboard handling 153 | - **Oh My Posh**: No sensitive data in prompts 154 | - **Fish**: Secure by default with no additional risks 155 | 156 | ## Future Enhancements 157 | 158 | Potential improvements: 159 | - Custom Oh My Posh themes 160 | - Additional Kitty keybindings 161 | - Fish shell plugins 162 | - Atuin cloud sync configuration 163 | - Performance monitoring integration 164 | -------------------------------------------------------------------------------- /docs/CONFIGURATION_GUIDE.md: -------------------------------------------------------------------------------- 1 | # Hyprland Configuration Guide 2 | 3 | This guide explains the modular configuration structure for managing Hyprland settings across multiple hosts. 4 | 5 | ## Overview 6 | 7 | The configuration is split into modular components to allow for: 8 | - **Shared base configuration** across all hosts 9 | - **Host-specific monitor configurations** for different setups 10 | - **Easy maintenance** and updates 11 | - **Scalability** for future hosts 12 | 13 | ## File Structure 14 | 15 | ``` 16 | hyprvibe/ 17 | ├── configs/ 18 | │ ├── hyprland-base.conf # Shared base configuration 19 | │ ├── hyprland-monitors-nixstation.conf # Nixstation monitor config 20 | │ └── hyprland-monitors-rvbee.conf # Rvbee monitor config 21 | ├── hosts/ 22 | │ ├── nixstation/ 23 | │ │ └── hyprland.conf # Nixstation main config (sources others) 24 | │ └── rvbee/ 25 | │ └── hyprland.conf # Rvbee main config (sources others) 26 | └── scripts/ 27 | └── setup-monitors.sh # Monitor setup helper script 28 | ``` 29 | 30 | ## Configuration Components 31 | 32 | ### 1. Base Configuration (`configs/hyprland-base.conf`) 33 | 34 | Contains all shared settings: 35 | - Keybindings 36 | - General appearance settings 37 | - Input configuration 38 | - Animations 39 | - Window rules 40 | - Application launchers 41 | 42 | ### 2. Monitor Configurations 43 | 44 | #### Nixstation (`configs/hyprland-monitors-nixstation.conf`) 45 | - 4-monitor setup 46 | - Workspace assignments per monitor 47 | - Multi-monitor specific settings 48 | 49 | #### Rvbee (`configs/hyprland-monitors-rvbee.conf`) 50 | - Single monitor setup 51 | - Simplified configuration 52 | 53 | ### 3. Host-Specific Configurations 54 | 55 | Each host has a main configuration file that sources the appropriate components: 56 | 57 | ```bash 58 | # Source shared base configuration 59 | source = ~/.config/hypr/hyprland-base.conf 60 | 61 | # Source host-specific monitor configuration 62 | source = ~/.config/hypr/hyprland-monitors-{hostname}.conf 63 | 64 | # Host-specific overrides and additions 65 | ``` 66 | 67 | ## Setting Up Monitors 68 | 69 | ### Using the Helper Script 70 | 71 | The `setup-monitors` script makes it easy to configure monitors: 72 | 73 | ```bash 74 | # Full setup process for nixstation 75 | setup-monitors setup nixstation 76 | 77 | # Just detect current monitors 78 | setup-monitors detect 79 | 80 | # Apply existing configuration 81 | setup-monitors apply nixstation 82 | 83 | # Show current status 84 | setup-monitors status 85 | ``` 86 | 87 | ### Manual Monitor Configuration 88 | 89 | 1. **Detect your monitors:** 90 | ```bash 91 | hyprctl monitors 92 | ``` 93 | 94 | 2. **Edit the monitor configuration file:** 95 | ```bash 96 | nano ~/.config/hypr/hyprland-monitors-nixstation.conf 97 | ``` 98 | 99 | 3. **Example configuration for 4 monitors:** 100 | ```bash 101 | monitor=DP-1,2560x1440@144,0x0,1 102 | monitor=DP-2,2560x1440@144,2560x0,1 103 | monitor=HDMI-A-1,1920x1080@60,5120x0,1 104 | monitor=HDMI-A-2,1920x1080@60,5120x1080,1 105 | ``` 106 | 107 | 4. **Apply the configuration:** 108 | ```bash 109 | setup-monitors apply nixstation 110 | ``` 111 | 112 | ## Adding a New Host 113 | 114 | 1. **Create monitor configuration:** 115 | ```bash 116 | cp configs/hyprland-monitors-rvbee.conf configs/hyprland-monitors-newhost.conf 117 | ``` 118 | 119 | 2. **Create host configuration:** 120 | ```bash 121 | cp hosts/rvbee/hyprland.conf hosts/newhost/hyprland.conf 122 | ``` 123 | 124 | 3. **Update the host configuration:** 125 | ```bash 126 | # Edit hosts/newhost/hyprland.conf 127 | source = ~/.config/hypr/hyprland-monitors-newhost.conf 128 | ``` 129 | 130 | 4. **Update system.nix:** 131 | - Add the new host to the flake.nix 132 | - Copy configuration files in the activation script 133 | 134 | ## Making Changes 135 | 136 | ### Global Changes (affects all hosts) 137 | Edit `configs/hyprland-base.conf` and rebuild all hosts. 138 | 139 | ### Host-Specific Changes 140 | Edit the appropriate host configuration file: 141 | - `hosts/nixstation/hyprland.conf` for nixstation 142 | - `hosts/rvbee/hyprland.conf` for rvbee 143 | 144 | ### Monitor-Specific Changes 145 | Edit the appropriate monitor configuration: 146 | - `configs/hyprland-monitors-nixstation.conf` for nixstation 147 | - `configs/hyprland-monitors-rvbee.conf` for rvbee 148 | 149 | ## Rebuilding Configuration 150 | 151 | After making changes, rebuild the system: 152 | 153 | ```bash 154 | # For nixstation 155 | sudo nixos-rebuild switch --flake /home/chrisf/build/config/hyprvibe#nixstation 156 | 157 | # For rvbee 158 | sudo nixos-rebuild switch --flake /home/chrisf/build/config/hyprvibe#rvbee 159 | ``` 160 | 161 | ## Troubleshooting 162 | 163 | ### Configuration Not Loading 164 | 1. Check that all source files exist: 165 | ```bash 166 | ls -la ~/.config/hypr/ 167 | ``` 168 | 169 | 2. Check Hyprland logs: 170 | ```bash 171 | journalctl --user -u hyprland --since "5 minutes ago" 172 | ``` 173 | 174 | ### Monitor Issues 175 | 1. Verify monitor detection: 176 | ```bash 177 | setup-monitors detect 178 | ``` 179 | 180 | 2. Check current configuration: 181 | ```bash 182 | setup-monitors status 183 | ``` 184 | 185 | 3. Test monitor configuration: 186 | ```bash 187 | hyprctl keyword monitor "DP-1,2560x1440@144,0x0,1" 188 | ``` 189 | 190 | ## Best Practices 191 | 192 | 1. **Always test changes** on one host before applying to others 193 | 2. **Use the helper script** for monitor configuration 194 | 3. **Keep monitor configurations simple** and well-documented 195 | 4. **Document host-specific requirements** in the configuration files 196 | 5. **Use version control** to track changes across hosts 197 | 198 | ## Future Enhancements 199 | 200 | Potential improvements to consider: 201 | - **Dynamic monitor detection** and configuration 202 | - **Per-monitor workspace assignments** based on monitor count 203 | - **Performance optimizations** for multi-monitor setups 204 | - **Backup and restore** functionality for monitor configurations 205 | -------------------------------------------------------------------------------- /hosts/nixbook/scripts/waybar-wifi.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # WiFi management script for waybar using rofi and nmcli 3 | 4 | # Check if NetworkManager is available 5 | if ! command -v nmcli &> /dev/null; then 6 | notify-send "WiFi Manager" "NetworkManager (nmcli) is not available" 7 | exit 1 8 | fi 9 | 10 | # Get WiFi device name 11 | WIFI_DEVICE=$(nmcli -t -f DEVICE,TYPE device | grep -E ':wifi$' | cut -d: -f1 | head -n1) 12 | 13 | if [ -z "$WIFI_DEVICE" ]; then 14 | notify-send "WiFi Manager" "No WiFi device found" 15 | exit 1 16 | fi 17 | 18 | # Check if WiFi is enabled 19 | WIFI_ENABLED=$(nmcli radio wifi) 20 | if [ "$WIFI_ENABLED" != "enabled" ]; then 21 | # Ask to enable WiFi 22 | if rofi -dmenu -p "WiFi is disabled. Enable?" -lines 2 -width 300 <<< "Yes\nNo" | grep -q "Yes"; then 23 | nmcli radio wifi on 24 | sleep 2 25 | else 26 | exit 0 27 | fi 28 | fi 29 | 30 | # Function to scan and show networks 31 | show_wifi_networks() { 32 | # Scan for networks 33 | nmcli device wifi rescan 2>/dev/null 34 | sleep 2 35 | 36 | # Get list of networks - store raw colon-separated data for accurate SSID extraction 37 | RAW_NETWORKS=$(nmcli -t -f SSID,SIGNAL,SECURITY device wifi list | sort -t: -k2 -rn) 38 | 39 | # Format for display (colon-separated input, space-formatted output) 40 | NETWORKS=$(echo "$RAW_NETWORKS" | \ 41 | awk -F: '{printf "%-30s %3s%% %s\n", $1, $2, $3}') 42 | 43 | if [ -z "$NETWORKS" ]; then 44 | notify-send "WiFi Manager" "No networks found. Try scanning again." 45 | exit 1 46 | fi 47 | 48 | # Show in rofi 49 | SELECTED=$(echo "$NETWORKS" | rofi -dmenu -p "Select WiFi Network" -lines 10 -width 500 -i) 50 | 51 | if [ -z "$SELECTED" ]; then 52 | exit 0 53 | fi 54 | 55 | # Extract signal strength from selected line (more reliable than SSID for matching) 56 | SELECTED_SIGNAL=$(echo "$SELECTED" | awk '{print $2}' | sed 's/%//') 57 | 58 | # Find matching network in raw data using signal strength (handles SSIDs with spaces) 59 | SSID=$(echo "$RAW_NETWORKS" | awk -F: -v sig="$SELECTED_SIGNAL" '$2 == sig {print $1; exit}') 60 | 61 | # Fallback: extract SSID directly if signal match fails (works for most SSIDs) 62 | if [ -z "$SSID" ] || [ "$SSID" = "" ]; then 63 | SSID=$(echo "$SELECTED" | awk '{for(i=1;i&1; then 83 | notify-send "WiFi Manager" "Connected to $SSID" 84 | else 85 | # Saved connection failed, try with password prompt 86 | PASSWORD=$(rofi -dmenu -password -p "Password for $SSID:" -width 400) 87 | if [ -z "$PASSWORD" ]; then 88 | exit 0 89 | fi 90 | nmcli device wifi connect "$SSID" password "$PASSWORD" 2>&1 | \ 91 | notify-send "WiFi Manager" "$(cat)" 92 | fi 93 | else 94 | # New network, ask for password 95 | PASSWORD=$(rofi -dmenu -password -p "Password for $SSID:" -width 400) 96 | if [ -z "$PASSWORD" ]; then 97 | exit 0 98 | fi 99 | # Connect with password 100 | CONNECT_OUTPUT=$(nmcli device wifi connect "$SSID" password "$PASSWORD" 2>&1) 101 | if [ $? -eq 0 ]; then 102 | notify-send "WiFi Manager" "Connected to $SSID" -t 3000 103 | else 104 | notify-send "WiFi Manager" "Failed to connect: $CONNECT_OUTPUT" -t 5000 105 | fi 106 | fi 107 | else 108 | # Open network, connect without password 109 | CONNECT_OUTPUT=$(nmcli device wifi connect "$SSID" 2>&1) 110 | if [ $? -eq 0 ]; then 111 | notify-send "WiFi Manager" "Connected to $SSID" -t 3000 112 | else 113 | notify-send "WiFi Manager" "Failed to connect: $CONNECT_OUTPUT" -t 5000 114 | fi 115 | fi 116 | } 117 | 118 | # Function to show current connection and options 119 | show_wifi_menu() { 120 | CURRENT=$(nmcli -t -f active,ssid dev wifi | grep '^yes:' | cut -d: -f2) 121 | if [ -z "$CURRENT" ]; then 122 | CURRENT="Not connected" 123 | fi 124 | 125 | MENU_OPTIONS="Connect to Network\nDisconnect\nToggle WiFi" 126 | if [ "$CURRENT" != "Not connected" ]; then 127 | MENU_OPTIONS="Current: $CURRENT\n$MENU_OPTIONS" 128 | fi 129 | 130 | SELECTED=$(echo -e "$MENU_OPTIONS" | rofi -dmenu -p "WiFi Manager" -lines 5 -width 300) 131 | 132 | case "$SELECTED" in 133 | "Connect to Network") 134 | show_wifi_networks 135 | ;; 136 | "Disconnect") 137 | nmcli device disconnect "$WIFI_DEVICE" 2>&1 | \ 138 | notify-send "WiFi Manager" "$(cat)" 139 | ;; 140 | "Toggle WiFi") 141 | if [ "$WIFI_ENABLED" = "enabled" ]; then 142 | nmcli radio wifi off 143 | notify-send "WiFi Manager" "WiFi disabled" 144 | else 145 | nmcli radio wifi on 146 | notify-send "WiFi Manager" "WiFi enabled" 147 | fi 148 | ;; 149 | esac 150 | } 151 | 152 | # Main execution 153 | show_wifi_menu 154 | -------------------------------------------------------------------------------- /docs/RVBEE_UPDATE_SUMMARY.md: -------------------------------------------------------------------------------- 1 | ## Recent Fixes and Changes (2025-08-22) 2 | 3 | - Enabled `systemd-resolved` and pointed `NetworkManager` DNS to it to eliminate DBus resolve1 activation errors at boot. 4 | - Fixed `kwalletd` on Wayland: user service now starts on `graphical-session.target` with `QT_QPA_PLATFORM=wayland`. 5 | - Netdata tuning: 6 | - Disabled Postgres collector (go.d) and silenced several noisy plugins (`logs-management`, `ioping`, `perf`, `freeipmi`, `charts.d`). 7 | - Kept Netdata installed but not auto-started; also prevented auto-restart on rebuilds. Start manually via `sudo systemctl start netdata`. 8 | - Reduced Bluetooth HFP log spam by limiting BlueZ `General.Enable` to `Source,Sink,Media,Socket`. 9 | - Activation script fix: call `${pkgs.desktop-file-utils}/bin/update-desktop-database` directly to avoid PATH-related errors. 10 | 11 | # RVBEE Update Summary: Oh My Posh & Kitty Configuration 12 | 13 | ## Overview 14 | 15 | Successfully updated RVBEE to have the same Oh My Posh and Kitty terminal configuration as NIXSTATION. All changes have been applied to ensure consistency across both systems. 16 | 17 | ## Changes Applied to RVBEE 18 | 19 | ### 1. **Package Installation** 20 | - ✅ Added `oh-my-posh` to `devTools` package list 21 | - ✅ Added `oh-my-posh` to `utilities` package list 22 | - ✅ Added `oh-my-posh` to `environment.systemPackages` 23 | 24 | ### 2. **Kitty Terminal Configuration** 25 | - ✅ Created `~/.config/kitty/kitty.conf` with: 26 | - Tokyo Night color scheme 27 | - Fira Code font 28 | - URL detection and hyperlinks (`detect_urls yes`, `show_hyperlink_targets yes`, `underline_hyperlinks always`) 29 | - Copy on select enabled (`copy_on_select yes`) 30 | - Shell integration enabled (`shell_integration enabled`) 31 | - Fish shell integration 32 | - Performance optimizations 33 | - Key bindings for font size adjustment 34 | 35 | ### 3. **Oh My Posh Configuration** 36 | - ✅ Created main configuration: `~/.config/oh-my-posh/config.json` (Tokyo Night theme) 37 | - ✅ Created enhanced theme: `~/.config/oh-my-posh/config-enhanced.json` (Agnoster-inspired) 38 | - ✅ Created minimal theme: `~/.config/oh-my-posh/config-minimal.json` (Robby Russell-inspired) 39 | - ✅ Created professional theme: `~/.config/oh-my-posh/config-professional.json` (Atomic-inspired) 40 | 41 | ### 4. **Fish Shell Integration** 42 | - ✅ Enhanced Atuin integration (already existed) 43 | - ✅ Added Oh My Posh integration: `~/.config/fish/conf.d/oh-my-posh.fish` 44 | - ✅ Added Kitty integration: `~/.config/fish/conf.d/kitty-integration.fish` 45 | - ✅ Disabled Fish default prompt when Oh My Posh is active 46 | 47 | ### 5. **Theme Switching Script** 48 | - ✅ Created `~/.local/bin/switch-oh-my-posh-theme` script 49 | - ✅ Script allows easy switching between all 4 themes 50 | - ✅ Includes backup functionality and help system 51 | 52 | ## Features Available on RVBEE 53 | 54 | ### **Kitty Terminal Features** 55 | - URL detection and clickable hyperlinks 56 | - Automatic copy on text selection 57 | - Shell integration with Fish 58 | - Tokyo Night color scheme 59 | - Fira Code font with ligatures 60 | - Performance optimizations 61 | - Font size adjustment shortcuts (Ctrl+Shift+Plus/Minus) 62 | 63 | ### **Oh My Posh Features** 64 | - **Default Theme**: Tokyo Night inspired, balanced features 65 | - **Enhanced Theme**: Feature-rich with comprehensive dev tools 66 | - **Minimal Theme**: Clean, distraction-free for productivity 67 | - **Professional Theme**: Modern diamond style for presentations 68 | 69 | ### **Development Tool Detection** 70 | - Git branch and status with dynamic backgrounds 71 | - Node.js version detection 72 | - Python version and virtual environment detection 73 | - Go version detection 74 | - Rust version detection 75 | - Docker context detection 76 | - Execution time for slow commands (>5 seconds) 77 | - Exit status with error codes 78 | 79 | ### **Shell Integration** 80 | - Atuin command history (Ctrl+R) 81 | - Oh My Posh beautiful prompts 82 | - Kitty terminal integration 83 | - All existing Fish functionality preserved 84 | 85 | ## Usage Instructions 86 | 87 | ### **Switch Themes** 88 | ```bash 89 | switch-oh-my-posh-theme enhanced # Feature-rich development 90 | switch-oh-my-posh-theme minimal # Clean, distraction-free 91 | switch-oh-my-posh-theme professional # Modern diamond style 92 | switch-oh-my-posh-theme default # Back to Tokyo Night 93 | ``` 94 | 95 | ### **Start Kitty Terminal** 96 | ```bash 97 | kitty 98 | ``` 99 | 100 | ### **Test Features** 101 | - URLs are automatically detected and underlined 102 | - Text selection automatically copies to clipboard 103 | - Oh My Posh prompt shows development tool information 104 | - Atuin history search works with Ctrl+R 105 | 106 | ## Compatibility Verification 107 | 108 | ✅ **All components work together**: 109 | - Oh My Posh + Fish shell 110 | - Oh My Posh + Atuin history 111 | - Kitty + Oh My Posh 112 | - Kitty + Fish shell 113 | - All existing RVBEE functionality preserved 114 | 115 | ## System Integration 116 | 117 | - All configurations are automatically applied on system rebuild 118 | - Theme switching script is available system-wide 119 | - All Fish shell integrations are automatically loaded 120 | - Kitty terminal is configured with optimal settings 121 | 122 | ## Next Steps 123 | 124 | 1. **Rebuild RVBEE**: Run `sudo nixos-rebuild switch` to apply changes 125 | 2. **Test Configuration**: Start a new terminal session to verify everything works 126 | 3. **Switch Themes**: Use the theme switcher to try different themes 127 | 4. **Enjoy**: Experience the same beautiful terminal setup as NIXSTATION 128 | 129 | ## Files Created/Modified 130 | 131 | ### **New Configuration Files** 132 | - `~/.config/kitty/kitty.conf` 133 | - `~/.config/oh-my-posh/config.json` 134 | - `~/.config/oh-my-posh/config-enhanced.json` 135 | - `~/.config/oh-my-posh/config-minimal.json` 136 | - `~/.config/oh-my-posh/config-professional.json` 137 | - `~/.config/fish/conf.d/oh-my-posh.fish` 138 | - `~/.config/fish/conf.d/kitty-integration.fish` 139 | - `~/.local/bin/switch-oh-my-posh-theme` 140 | 141 | ### **Modified System Files** 142 | - `hyprvibe/hosts/rvbee/system.nix` - Added packages and activation scripts 143 | 144 | RVBEE now has the exact same Oh My Posh and Kitty terminal setup as NIXSTATION, providing a consistent and beautiful development experience across both systems! 145 | -------------------------------------------------------------------------------- /docs/MIGRATION_PLAN.md: -------------------------------------------------------------------------------- 1 | # NixStation Migration Plan: Local NixOS → Hyprland Configuration 2 | 3 | ## Overview 4 | This document outlines the migration plan for moving your `nixstation` system from the current local NixOS configuration to the GitHub Hyprland-based configuration while preserving your existing file system layout and bootloader configuration. 5 | 6 | ## ✅ Completed Setup 7 | 8 | ### 1. Repository Structure 9 | - ✅ Created `hosts/nixstation/` directory 10 | - ✅ Created `hosts/nixstation/system.nix` - Main system configuration 11 | - ✅ Created `hosts/nixstation/hardware-configuration.nix` - Hardware-specific config 12 | - ✅ Copied Hyprland configuration files from `rvbee` host 13 | - ✅ Copied Waybar configuration and scripts 14 | - ✅ Updated `flake.nix` to include `nixstation` configuration 15 | 16 | ### 2. Preserved Configuration Elements 17 | - ✅ **File System Layout**: Preserved your existing BTRFS `/nix` and `/home` mounts 18 | - ✅ **Boot Loader**: Kept GRUB configuration with EFI support 19 | - ✅ **Hardware Support**: Preserved Intel CPU and AMD GPU configurations 20 | - ✅ **User Configuration**: Preserved user `chrisf` with all existing groups 21 | - ✅ **Package Set**: Preserved all your existing packages and applications 22 | - ✅ **Services**: Preserved Tor, SSH, Sunshine, and other custom services 23 | 24 | ### 3. Migration Changes 25 | - ✅ **Kernel**: Switched from `linuxPackages_latest` to `linuxPackages_zen` 26 | - ✅ **Desktop**: Migrated from Plasma 6 to Hyprland 27 | - ✅ **Display Manager**: Switched from SDDM to GDM (Wayland) 28 | - ✅ **Performance**: Added BPF tuning and additional performance optimizations 29 | 30 | ## 🔄 Migration Steps Required 31 | 32 | ### Step 1: Test Configuration (Recommended) 33 | ```bash 34 | # Test the configuration without applying 35 | sudo nixos-rebuild build --flake .#nixstation 36 | 37 | # If successful, you can proceed with the actual switch 38 | sudo nixos-rebuild switch --flake .#nixstation 39 | ``` 40 | 41 | ### Step 2: Backup Current Configuration 42 | ```bash 43 | # Backup your current configuration 44 | sudo cp -r /etc/nixos /etc/nixos.backup.$(date +%Y%m%d) 45 | ``` 46 | 47 | ### Step 3: Update Boot Configuration 48 | Since you're switching from Plasma 6 to Hyprland, you'll need to: 49 | 1. Log out of your current session 50 | 2. At the GDM login screen, select "Hyprland" from the session menu 51 | 3. Log in with your existing credentials 52 | 53 | ### Step 4: Post-Migration Tasks 54 | 1. **Wallpaper**: Replace the placeholder wallpaper with your preferred image 55 | 2. **Hyprland Configuration**: Customize `hosts/nixstation/hyprland.conf` as needed 56 | 3. **Waybar**: Customize `hosts/nixstation/waybar.json` and `waybar.css` if desired 57 | 4. **User Scripts**: Any custom scripts in your home directory will need to be adapted for Hyprland 58 | 59 | ## 📋 Configuration Details 60 | 61 | ### File System Layout (Preserved) 62 | ``` 63 | / - ext4 (root) 64 | /nix - btrfs (Nix store) 65 | /home - btrfs (user home) 66 | /scary - xfs (additional storage) 67 | ``` 68 | 69 | ### Boot Configuration (Preserved) 70 | - **Boot Loader**: GRUB with EFI 71 | - **Kernel**: linuxPackages_zen (changed from latest) 72 | - **Kernel Modules**: amdgpu, kvm-intel, kvm-amd 73 | - **Kernel Parameters**: elevator=none 74 | 75 | ### Desktop Environment (Changed) 76 | - **From**: Plasma 6 with SDDM 77 | - **To**: Hyprland with GDM (Wayland) 78 | - **Display Protocol**: Wayland (with XWayland support) 79 | 80 | ### Package Groups (Preserved + Enhanced) 81 | - **Development Tools**: All your existing dev tools + additional ones 82 | - **Multimedia**: All your existing multimedia tools + additional ones 83 | - **Utilities**: All your existing utilities + Hyprland-specific tools 84 | - **Applications**: All your existing applications + Hyprland apps 85 | - **Gaming**: All your existing gaming tools + Steam integration 86 | - **System Tools**: All your existing system tools 87 | 88 | ### Services (Preserved + Enhanced) 89 | - **Audio**: PipeWire with ALSA/Pulse/JACK support 90 | - **Networking**: NetworkManager, Tailscale, OpenSSH 91 | - **Virtualization**: Docker, libvirtd 92 | - **Security**: Tor, Polkit, sudo configuration 93 | - **Performance**: BPF tuning, ZRAM, OOM management 94 | 95 | ## ⚠️ Important Notes 96 | 97 | ### 1. Desktop Environment Change 98 | - You'll need to learn Hyprland keybindings and workflow 99 | - Some Plasma-specific applications may need alternatives 100 | - Wayland compatibility for all applications 101 | 102 | ### 2. Performance Optimizations 103 | - Zen kernel should provide better performance 104 | - BPF tuning will optimize system performance automatically 105 | - ZRAM configuration preserved for memory optimization 106 | 107 | ### 3. Backup Strategy 108 | - Always backup before major configuration changes 109 | - Test in a VM if possible before applying to physical system 110 | - Keep your old configuration as a fallback 111 | 112 | ## 🚀 Next Steps 113 | 114 | 1. **Review Configuration**: Check `hosts/nixstation/system.nix` for any customizations needed 115 | 2. **Test Build**: Run `sudo nixos-rebuild build --flake .#nixstation` to test 116 | 3. **Apply Configuration**: Run `sudo nixos-rebuild switch --flake .#nixstation` 117 | 4. **Login**: Use GDM to log into Hyprland session 118 | 5. **Customize**: Adapt to Hyprland workflow and customize as needed 119 | 120 | ## 🔧 Troubleshooting 121 | 122 | ### If Build Fails 123 | - Check for missing packages or configuration errors 124 | - Review the error messages and adjust configuration 125 | - Ensure all file paths and UUIDs are correct 126 | 127 | ### If Boot Fails 128 | - Boot into recovery mode or use a live USB 129 | - Restore from backup: `sudo nixos-rebuild switch --flake /path/to/backup#nixstation` 130 | 131 | ### If Hyprland Doesn't Start 132 | - Check GDM session selection 133 | - Review Hyprland logs: `journalctl --user -u hyprland` 134 | - Check Waybar and other components 135 | 136 | ## 📞 Support 137 | 138 | If you encounter issues during migration: 139 | 1. Check the Hyprland documentation 140 | 2. Review the GitHub repository README 141 | 3. Check NixOS and Hyprland community resources 142 | 4. Keep your backup configuration for rollback if needed 143 | 144 | --- 145 | 146 | **Migration Status**: Configuration files created and ready for testing 147 | **Next Action**: Test build and apply configuration 148 | **Risk Level**: Medium (major desktop environment change) -------------------------------------------------------------------------------- /hosts/nixstation/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by 'nixos-generate-config' 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "nvme" "usbhid" "uas" "sd_mod" ]; 12 | boot.initrd.kernelModules = [ "amdgpu" ]; 13 | # boot.kernelModules removed - defined in system.nix with complete list 14 | boot.extraModulePackages = [ ]; 15 | boot.kernelParams = [ 16 | "elevator=none" 17 | # AMD GPU parameters for better HDMI DPMS support 18 | "amdgpu.dc=1" 19 | "amdgpu.dmcu=1" 20 | "amdgpu.ppfeaturemask=0xffffffff" 21 | # Intel e1000e network driver stability fixes 22 | "e1000e.InterruptThrottleRate=1" 23 | "e1000e.eee=0" 24 | "e1000e.FlowControl=0" 25 | # Batch 2: CPU optimizations for Haswell-E (i7-5820K) 26 | "intel_idle.max_cstate=1" # Reduce C-state latency (faster wake from idle) 27 | "processor.max_cstate=1" # Limit processor C-states for lower latency 28 | "intel_pstate=disable" # Use acpi-cpufreq for better control 29 | # Batch 2: RCU tuning for 6-core CPU 30 | "rcu_nocbs=0-5" # Offload RCU callbacks from all 6 cores 31 | "nohz_full=0-5" # Enable full dynticks on all cores (reduces timer interrupts) 32 | # Batch 2: Transparent hugepages for better memory performance 33 | "transparent_hugepage=always" # Always use hugepages when possible 34 | # Batch 2: GPU power management 35 | "amdgpu.powerplay=1" # Enable AMD GPU power management 36 | ]; 37 | 38 | boot.kernel.sysctl = { 39 | # Memory management - Batch 1 optimizations 40 | "vm.min_free_kbytes" = 65536; # Ensure there's always some free memory 41 | "vm.swappiness" = 10; # Reduce swapping aggressiveness 42 | "vm.vfs_cache_pressure" = 50; # Balance between inode and dentry caches 43 | "vm.dirty_background_ratio" = 5; # Flush dirty pages more aggressively 44 | "vm.dirty_ratio" = 10; # Hard limit for dirty pages 45 | "vm.dirty_expire_centisecs" = 3000; # How long dirty pages can stay (30s) 46 | "vm.dirty_writeback_centisecs" = 500; # How often writeback happens (5s) 47 | "vm.overcommit_memory" = 1; # Allow overcommit (better for desktop) 48 | "vm.overcommit_ratio" = 50; # Allow 50% overcommit 49 | "vm.page-cluster" = 0; # Disable page clustering for faster swap (if needed) 50 | "vm.oom_kill_allocating_task" = 0; # Don't kill the allocating task 51 | "vm.stat_interval" = 10; # Update VM stats every 10s (reduced from 60s) 52 | 53 | # Kernel memory management 54 | "kernel.panic_on_oom" = 0; # Don't panic on OOM 55 | "vm.oom_dump_tasks" = 1; # Dump tasks on OOM for debugging 56 | 57 | # File system cache 58 | "vm.drop_caches" = 0; # Don't drop caches automatically 59 | 60 | # Batch 2: Transparent hugepages tuning 61 | "vm.nr_hugepages" = 0; # Let system manage hugepages automatically 62 | "vm.nr_overcommit_hugepages" = 0; # No overcommit of hugepages 63 | 64 | # Batch 2: Memory compaction and fragmentation 65 | "vm.compact_memory" = 0; # Don't force compaction 66 | "vm.extfrag_threshold" = 500; # Threshold for external fragmentation (lower = more aggressive) 67 | 68 | # Batch 2: Page reclaim and swap tuning 69 | "vm.zone_reclaim_mode" = 0; # Disable zone reclaim (better for NUMA, but also helps UMA) 70 | 71 | # Batch 1: Network TCP tuning for better throughput 72 | "net.core.rmem_max" = 67108864; # 64MB max receive buffer 73 | "net.core.wmem_max" = 67108864; # 64MB max send buffer 74 | "net.core.rmem_default" = 87380; # Default receive buffer 75 | "net.core.wmem_default" = 65536; # Default send buffer 76 | "net.ipv4.tcp_rmem" = "4096 87380 67108864"; # TCP receive buffer (min default max) 77 | "net.ipv4.tcp_wmem" = "4096 65536 67108864"; # TCP send buffer (min default max) 78 | "net.ipv4.tcp_window_scaling" = 1; # Enable TCP window scaling 79 | "net.ipv4.tcp_timestamps" = 1; # Enable TCP timestamps 80 | "net.ipv4.tcp_sack" = 1; # Enable TCP SACK 81 | "net.ipv4.tcp_fastopen" = 3; # Enable TCP Fast Open (client and server) 82 | "net.core.netdev_max_backlog" = 5000; # Increase network device backlog 83 | "net.ipv4.tcp_fin_timeout" = 10; # Reduce FIN timeout for faster connection cleanup 84 | "net.ipv4.tcp_keepalive_time" = 600; # TCP keepalive time 85 | "net.ipv4.tcp_keepalive_probes" = 3; # TCP keepalive probes 86 | "net.ipv4.tcp_keepalive_intvl" = 15; # TCP keepalive interval 87 | }; 88 | 89 | fileSystems."/" = 90 | { device = "/dev/disk/by-uuid/6cfe0859-9022-445b-8439-5a761d695e71"; 91 | fsType = "ext4"; 92 | }; 93 | 94 | fileSystems."/nix" = { 95 | device = "/dev/disk/by-uuid/a10f0323-3b33-4dec-b460-606c8a8cd795"; 96 | fsType = "btrfs"; 97 | neededForBoot = true; 98 | # Batch 1: Add commit interval to reduce fsync overhead 99 | options = [ "noatime" "compress=zstd" "commit=60" ]; 100 | }; 101 | 102 | fileSystems."/home" = { 103 | device = "/dev/disk/by-uuid/5de63f28-ca1a-4866-86e1-f592905c9ba3"; 104 | fsType = "btrfs"; 105 | neededForBoot = true; 106 | # Batch 1: Add commit interval to reduce fsync overhead 107 | options = [ "noatime" "compress=zstd" "commit=60" ]; 108 | }; 109 | 110 | fileSystems."/scary" = 111 | { device = "/dev/disk/by-uuid/3808bc5f-0619-4920-8045-e36264f0cb2c"; 112 | fsType = "xfs"; 113 | # Batch 1: Optimize XFS for performance 114 | options = [ "noatime" "largeio" "inode64" ]; 115 | }; 116 | 117 | swapDevices = [ ]; 118 | 119 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 120 | # (the default) this is the recommended approach. When using systemd-networkd it's 121 | # still possible to use this option, but it's recommended to use it in conjunction 122 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 123 | networking.useDHCP = lib.mkDefault true; 124 | # networking.interfaces.eno1.useDHCP = lib.mkDefault true; 125 | 126 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 127 | # Batch 1: Ensure Intel microcode is enabled for Haswell-E (i7-5820K) 128 | hardware.cpu.intel.updateMicrocode = true; 129 | hardware.enableRedistributableFirmware = true; 130 | } --------------------------------------------------------------------------------