diff --git a/hypr/rules.conf b/hypr/rules.conf
index 09acb16..233afe9 100644
--- a/hypr/rules.conf
+++ b/hypr/rules.conf
@@ -5,6 +5,8 @@
# 文件对话框
windowrule = float, class:^(thunar|google-chrome|chromium)$, title:^(.*文件.*|.*保存.*|.*打开.*)
+windowrule = float, class:^(Alacritty)$, title:^(alacritty -e \./system-update\.sh.*)
+
# Ignore maximize requests from apps. You'll probably like this.
windowrule = suppressevent maximize, class:.*
diff --git a/waybar/LICENSE b/waybar/LICENSE
new file mode 100644
index 0000000..355f2ba
--- /dev/null
+++ b/waybar/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Jesse Mirabel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/waybar/config.jsonc b/waybar/config.jsonc
new file mode 100644
index 0000000..97a2845
--- /dev/null
+++ b/waybar/config.jsonc
@@ -0,0 +1,119 @@
+{
+ /*
+ "include": [
+ "~/.config/waybar/modules/*.jsonc",
+ "~/.config/waybar/modules/custom/*.jsonc",
+ "~/.config/waybar/modules/hyprland/*.jsonc"
+
+ // modules that are not included by default:
+ // "~/.config/waybar/modules/extras/*.jsonc"
+ ],
+ */
+
+ "include": [
+ // modules-left
+ "~/.config/waybar/modules/custom/user.jsonc",
+ "~/.config/waybar/modules/hyprland/workspaces.jsonc",
+ "~/.config/waybar/modules/hyprland/window.jsonc",
+
+ // modules-center
+ "~/.config/waybar/modules/hyprland/windowcount.jsonc",
+ "~/.config/waybar/modules/temperature.jsonc",
+ "~/.config/waybar/modules/memory.jsonc",
+ "~/.config/waybar/modules/cpu.jsonc",
+ "~/.config/waybar/modules/custom/distro.jsonc",
+ "~/.config/waybar/modules/idle_inhibitor.jsonc",
+ "~/.config/waybar/modules/clock.jsonc",
+ "~/.config/waybar/modules/custom/system_update.jsonc",
+
+ // modules-right
+ "~/.config/waybar/modules/mpris.jsonc",
+ "~/.config/waybar/modules/pulseaudio.jsonc",
+ "~/.config/waybar/modules/backlight.jsonc",
+ "~/.config/waybar/modules/battery.jsonc",
+ "~/.config/waybar/modules/custom/power_menu.jsonc",
+
+ "~/.config/waybar/modules/custom/dividers.jsonc"
+
+ // modules that are not included by default:
+ // "~/.config/waybar/modules/extras/taskbar.jsonc",
+ // "~/.config/waybar/modules/extras/tray.jsonc",
+ // "~/.config/waybar/modules/extras/wireplumber.jsonc"
+ ],
+
+ /*------------
+ layout
+ ------------*/
+
+ "modules-left": [
+ "group/user",
+ "custom/left_div#1",
+ "hyprland/workspaces",
+ "custom/right_div#1",
+ "hyprland/window"
+ ],
+ "modules-center": [
+ "hyprland/windowcount",
+ "custom/left_div#2",
+ "temperature",
+ "custom/left_div#3",
+ "memory",
+ "custom/left_div#4",
+ "cpu",
+ "custom/left_inv#1",
+ "custom/left_div#5",
+ "custom/distro",
+ "custom/right_div#2",
+ "custom/right_inv#1",
+ "idle_inhibitor",
+ "clock#time",
+ "custom/right_div#3",
+ "clock#date",
+ "custom/right_div#4",
+ "custom/system_update",
+ "custom/right_div#5"
+ ],
+ "modules-right": [
+ "mpris",
+ "custom/left_div#6",
+ "group/pulseaudio",
+ "custom/left_div#7",
+ "backlight",
+ "custom/left_div#8",
+ "battery",
+ "custom/left_inv#2",
+ "custom/power_menu"
+ ],
+
+ /*-------------
+ options
+ -------------*/
+
+ // "expand-center":
+ // "expand-left":
+ // "expand-right":
+ "layer": "top",
+ // "output":
+ // "position":
+ "height": 0,
+ "width": 0,
+ "margin": 0,
+ // "margin-top":
+ // "margin-left":
+ // "margin-bottom":
+ // "margin-right":
+ // "no-center":
+ "spacing": 0,
+ // "name":
+ "mode": "dock",
+ // "start_hidden":
+ // "modifier-reset":
+ // "exclusive":
+ // "fixed-center":
+ // "passthrough":
+ // "ipc":
+ // "id":
+ "reload_style_on_change": true
+ // "on-sigusr1":
+ // "on-sigusr2":
+}
diff --git a/waybar/current-theme.css b/waybar/current-theme.css
new file mode 100644
index 0000000..ea025b2
--- /dev/null
+++ b/waybar/current-theme.css
@@ -0,0 +1,63 @@
+/* catppuccin mocha */
+
+@define-color rosewater #f5e0dc;
+@define-color flamingo #f2cdcd;
+@define-color pink #f5c2e7;
+@define-color mauve #cba6f7;
+@define-color red #f38ba8;
+@define-color maroon #eba0ac;
+@define-color peach #fab387;
+@define-color yellow #f9e2af;
+@define-color green #a6e3a1;
+@define-color teal #94e2d5;
+@define-color sky #89dceb;
+@define-color sapphire #74c7ec;
+@define-color blue #89b4fa;
+@define-color lavender #b4befe;
+@define-color text #cdd6f4;
+@define-color subtext1 #bac2de;
+@define-color subtext0 #a6adc8;
+@define-color overlay2 #9399b2;
+@define-color overlay1 #7f849c;
+@define-color overlay0 #6c7086;
+@define-color surface2 #585b70;
+@define-color surface1 #45475a;
+@define-color surface0 #313244;
+@define-color base #1e1e2e;
+@define-color mantle #181825;
+@define-color crust #11111b;
+
+/*
+ br - border
+ bg - background
+ fg - foreground
+*/
+
+/* main colors */
+
+@define-color accent @lavender;
+@define-color main-br @subtext0;
+@define-color main-bg @crust;
+@define-color main-fg @text;
+@define-color hover-bg @base;
+@define-color hover-fg alpha(@main-fg, 0.75);
+@define-color outline shade(@main-bg, 0.5);
+
+/* module colors */
+
+@define-color workspaces @mantle;
+@define-color temperature @mantle;
+@define-color memory @base;
+@define-color cpu @surface0;
+@define-color time @surface0;
+@define-color date @base;
+@define-color tray @mantle;
+@define-color volume @mantle;
+@define-color backlight @base;
+@define-color battery @surface0;
+
+/* state colors */
+
+@define-color warning @yellow;
+@define-color critical @red;
+@define-color charging @green;
diff --git a/waybar/install.sh b/waybar/install.sh
new file mode 100755
index 0000000..1f98a40
--- /dev/null
+++ b/waybar/install.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+RED='\033[1;31m'
+GRN='\033[1;32m'
+BLU='\033[1;34m'
+RST='\033[0m'
+
+DEPS=(
+ bluez
+ bluez-utils # bluetoothctl
+ brightnessctl
+ fzf
+ networkmanager # nmcli
+ pacman-contrib # checkupdates
+ pipewire-pulse
+ otf-commit-mono-nerd
+)
+
+main() {
+ printf '%bInstalling dependencies...%b\n' "$BLU" "$RST"
+
+ local package
+ local error=0
+ for package in "${DEPS[@]}"; do
+ if pacman -Qi "$package" > /dev/null; then
+ printf '[%b/%b] %s\n' "$GRN" "$RST" "$package"
+ else
+ printf '[ ] %s...\n' "$package"
+ if sudo pacman -S --noconfirm "$package"; then
+ printf '[%b+%b] %s\n' "$GRN" "$RST" "$package"
+ else
+ printf '[%bx%b] %s\n' "$RED" "$RST" "$package"
+ ((error++))
+ fi
+ fi
+ done
+
+ printf '\n%bMaking scripts executable...%b\n' "$BLU" "$RST"
+ chmod +x ~/.config/waybar/scripts/*.sh --verbose
+
+ pkill waybar
+ waybar &> /dev/null &
+ disown
+
+ if ((error > 0)); then
+ printf '\nInstallation completed with %b%d errors%b\n' \
+ "$RED" "$error" "$RST"
+ else
+ printf '\n%bInstallation complete!%b\n' "$GRN" "$RST"
+ fi
+}
+
+main
diff --git a/waybar/modules/backlight.jsonc b/waybar/modules/backlight.jsonc
new file mode 100644
index 0000000..d5b53fc
--- /dev/null
+++ b/waybar/modules/backlight.jsonc
@@ -0,0 +1,32 @@
+{
+ "backlight": {
+ // "interval":
+ "format": "{icon} {percent}%",
+ "format-icons": [
+ "", "", "", "", "", "", "", "", ""
+ ],
+ "min-length": 7,
+ "max-length": 7,
+ // "align":
+ // "justify":
+ // "rotate":
+ // "states":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ "on-scroll-up": "~/.config/waybar/scripts/backlight.sh up",
+ "on-scroll-down": "~/.config/waybar/scripts/backlight.sh down",
+ // "smooth-scrolling-threshold":
+ // "reverse-scrolling":
+ // "reverse-mouse-scrolling":
+ // "scroll-step":
+ // "min-brightness":
+ "tooltip": false
+ // "tooltip-format":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/battery.jsonc b/waybar/modules/battery.jsonc
new file mode 100644
index 0000000..f1aacca
--- /dev/null
+++ b/waybar/modules/battery.jsonc
@@ -0,0 +1,45 @@
+{
+ "battery": {
+ // "bat":
+ // "adapter":
+ // "design-capacity":
+ // "full-at":
+ // "interval":
+ "states": {
+ "warning": 20,
+ "critical": 10
+ },
+ "format": "{icon} {capacity}%",
+ "format-time": "{H}h {M}min",
+ "format-icons": [
+ "", "", "", "", "", "", "", "", "", ""
+ ],
+ "format-charging": " {capacity}%",
+ "min-length": 7,
+ "max-length": 7,
+ // "align":
+ // "justify":
+ // "rotate":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Discharging: {time}",
+ "tooltip-format-charging": "Charging: {time}",
+ // "weighted-average":
+ // "bat-compatibility":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ "events": {
+ "on-discharging-warning": "notify-send 'Battery Low (20%)' -u critical -i 'battery-020' -r 1525",
+ "on-discharging-critical": "notify-send 'Battery Critical (10%)' -u critical -i 'battery-010' -r 1525",
+ "on-charging-100": "notify-send 'Battery Full (100%)' -i 'battery-100-charged'"
+ }
+ }
+}
diff --git a/waybar/modules/bluetooth.jsonc b/waybar/modules/bluetooth.jsonc
new file mode 100644
index 0000000..3113870
--- /dev/null
+++ b/waybar/modules/bluetooth.jsonc
@@ -0,0 +1,38 @@
+{
+ "bluetooth": {
+ // "controller":
+ // "format-device-preference":
+ "format": "",
+ "format-disabled": "",
+ "format-off": "",
+ "format-on": "",
+ "format-connected": "",
+ // "format-connected-battery":
+ // "format-no-controller":
+ // "format-icons":
+ // "rotate":
+ "min-length": 2,
+ "max-length": 2,
+ // "align":
+ // "justify":
+ "on-click": "kitty -e ~/.config/waybar/scripts/bluetooth.sh",
+ // "on-click-middle":
+ "on-click-right": "bluetoothctl power off && notify-send 'Bluetooth Off' -i 'network-bluetooth-inactive' -r 1925",
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Device Addr: {device_address}",
+ "tooltip-format-disabled": "Bluetooth Disabled",
+ "tooltip-format-off": "Bluetooth Off",
+ "tooltip-format-on": "Bluetooth Disconnected",
+ "tooltip-format-connected": "Device: {device_alias}",
+ "tooltip-format-enumerate-connected": "Device: {device_alias}",
+ "tooltip-format-connected-battery": "Device: {device_alias}\nBattery: {device_battery_percentage}%",
+ "tooltip-format-enumerate-connected-battery": "Device: {device_alias}\nBattery: {device_battery_percentage}%"
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/clock.jsonc b/waybar/modules/clock.jsonc
new file mode 100644
index 0000000..9bcbfb8
--- /dev/null
+++ b/waybar/modules/clock.jsonc
@@ -0,0 +1,71 @@
+{
+ "clock#time": {
+ // "interval":
+ "format": "{:%H:%M}",
+ // "timezone":
+ // "timezones":
+ // "locale":
+ "min-length": 5,
+ "max-length": 5,
+ // "rotate": 0,
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Standard Time: {:%I:%M %p}"
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ },
+
+ /*--------------
+ calendar
+ --------------*/
+
+ "clock#date": {
+ // "interval":
+ "format": " {:%d-%m}",
+ // "timezone":
+ // "timezones":
+ // "locale":
+ "min-length": 8,
+ "max-length": 8,
+ // "rotate":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "{calendar}",
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ "calendar": {
+ "mode": "month",
+ "mode-mon-col": 6,
+ // "week-pos":
+ // "on-scroll":
+ "format": {
+ "months": "{}",
+ "days": "{}",
+ // "weeks":
+ "weekdays": "{}",
+ "today": "{}"
+ }
+ },
+ "actions": {
+ "on-click": "mode"
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ }
+ }
+}
diff --git a/waybar/modules/cpu.jsonc b/waybar/modules/cpu.jsonc
new file mode 100644
index 0000000..67ac8a5
--- /dev/null
+++ b/waybar/modules/cpu.jsonc
@@ -0,0 +1,27 @@
+{
+ "cpu": {
+ "interval": 10,
+ "format": " {usage}%",
+ "format-warning": " {usage}%",
+ "format-critical": " {usage}%",
+ // "format-icons":
+ "min-length": 7,
+ "max-length": 7,
+ // "align":
+ // "justify":
+ // "rotate":
+ "states": {
+ "warning": 75,
+ "critical": 90
+ },
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ "tooltip": false
+ // "expand":
+ }
+}
diff --git a/waybar/modules/custom/distro.jsonc b/waybar/modules/custom/distro.jsonc
new file mode 100644
index 0000000..62c86ea
--- /dev/null
+++ b/waybar/modules/custom/distro.jsonc
@@ -0,0 +1,33 @@
+{
+ "custom/distro": {
+ // "exec":
+ // "exec-if":
+ // "exec-on-event":
+ // "hide-empty-text":
+ // "return-type":
+ // "interval":
+ // "restart-interval":
+ // "signal":
+ "format": "",
+ // "format-icons":
+ // "rotate":
+ // "min-length":
+ // "max-length":
+ // "align":
+ // "justify":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ "tooltip": false
+ // "tooltip-format":
+ // "escape":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/custom/dividers.jsonc b/waybar/modules/custom/dividers.jsonc
new file mode 100644
index 0000000..b1944a0
--- /dev/null
+++ b/waybar/modules/custom/dividers.jsonc
@@ -0,0 +1,79 @@
+{
+ /*-------------------
+ left dividers
+ -------------------*/
+
+ "custom/left_div#1": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#2": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#3": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#4": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#5": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#6": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#7": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#8": {
+ "format": "",
+ "tooltip": false
+ },
+
+ // inverse
+ "custom/left_inv#1": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_inv#2": {
+ "format": "",
+ "tooltip": false
+ },
+
+ /*--------------------
+ right dividers
+ --------------------*/
+
+ "custom/right_div#1": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#2": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#3": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#4": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#5": {
+ "format": "",
+ "tooltip": false
+ },
+
+ // inverse
+ "custom/right_inv#1": {
+ "format": "",
+ "tooltip": false
+ }
+}
diff --git a/waybar/modules/custom/power_menu.jsonc b/waybar/modules/custom/power_menu.jsonc
new file mode 100644
index 0000000..c438735
--- /dev/null
+++ b/waybar/modules/custom/power_menu.jsonc
@@ -0,0 +1,33 @@
+{
+ "custom/power_menu": {
+ // "exec":
+ // "exec-if":
+ // "exec-on-event":
+ // "hide-empty-text":
+ // "return-type":
+ // "interval":
+ // "restart-interval":
+ // "signal":
+ "format": "",
+ // "format-icons":
+ // "rotate":
+ // "min-length":
+ // "max-length":
+ // "align":
+ // "justify":
+ "on-click": "kitty -e ~/.config/waybar/scripts/power-menu.sh",
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Power Menu"
+ // "escape":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/custom/system_update.jsonc b/waybar/modules/custom/system_update.jsonc
new file mode 100644
index 0000000..d8bd085
--- /dev/null
+++ b/waybar/modules/custom/system_update.jsonc
@@ -0,0 +1,33 @@
+{
+ "custom/system_update": {
+ "exec": "~/.config/waybar/scripts/system-update.sh module",
+ // "exec-if":
+ // "exec-on-event":
+ // "hide-empty-text":
+ "return-type": "json",
+ "interval": 3600,
+ // "restart-interval":
+ "signal": 1,
+ "format": "{}",
+ // "format-icons":
+ // "rotate":
+ // "align":
+ // "justify":
+ "min-length": 2,
+ "max-length": 2,
+ "on-click": "alacritty -e ~/.config/waybar/scripts/system-update.sh",
+ // "on-click-middle":
+ "on-click-right": "pkill -RTMIN+1 waybar"
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ // "tooltip-format":
+ // "escape":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/custom/user.jsonc b/waybar/modules/custom/user.jsonc
new file mode 100644
index 0000000..9046dfe
--- /dev/null
+++ b/waybar/modules/custom/user.jsonc
@@ -0,0 +1,83 @@
+{
+ "group/user": {
+ "orientation": "horizontal",
+ "modules": [
+ "custom/trigger",
+ "custom/user"
+ ],
+ "drawer": {
+ // "transition-duration":
+ // "transition-left-to-right":
+ // "children-class":
+ // "click-to-reveal":
+ }
+ },
+
+ "custom/trigger": {
+ // "exec":
+ // "exec-if":
+ // "exec-on-event":
+ // "hide-empty-text":
+ // "return-type":
+ // "interval":
+ // "restart-interval":
+ // "signal":
+ "format": "",
+ // "format-icons":
+ // "rotate":
+ "min-length": 4,
+ "max-length": 4,
+ // "align":
+ // "justify":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ "tooltip": false
+ // "tooltip-format":
+ // "escape":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ },
+
+ /*--------------
+ username
+ --------------*/
+
+ "custom/user": {
+ "exec": "id -un",
+ // "exec-if":
+ // "exec-on-event":
+ // "hide-empty-text":
+ // "return-type":
+ // "interval":
+ // "restart-interval":
+ // "signal":
+ "format": "{}",
+ // "format-icons":
+ // "rotate":
+ // "min-length":
+ // "max-length":
+ // "align":
+ // "justify":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ "tooltip": false
+ // "tooltip-format":
+ // "escape":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/extras/taskbar.jsonc b/waybar/modules/extras/taskbar.jsonc
new file mode 100644
index 0000000..245ca32
--- /dev/null
+++ b/waybar/modules/extras/taskbar.jsonc
@@ -0,0 +1,21 @@
+{
+ "wlr/taskbar": {
+ // "all-outputs":
+ // "format":
+ // "icon-theme":
+ // "icon-size":
+ // "markup":
+ // "tooltip":
+ // "tooltip-format":
+ // "active-first":
+ // "sort-by-app-id":
+ "on-click": "activate",
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ "ignore-list": [ "kitty" ],
+ // "app_ids-mapping":
+ // "rewrite":
+ "cursor": true
+ }
+}
diff --git a/waybar/modules/extras/tray.jsonc b/waybar/modules/extras/tray.jsonc
new file mode 100644
index 0000000..c576fdb
--- /dev/null
+++ b/waybar/modules/extras/tray.jsonc
@@ -0,0 +1,13 @@
+{
+ "tray": {
+ "icon-size": 16,
+ // "show-passive-items":
+ // "smooth-scrolling-threshold":
+ "spacing": 12,
+ // "reverse-direction":
+ // "on-update":
+ // "expand":
+ // "icons":
+ "cursor": true
+ }
+}
diff --git a/waybar/modules/extras/wireplumber.jsonc b/waybar/modules/extras/wireplumber.jsonc
new file mode 100644
index 0000000..7bfc14e
--- /dev/null
+++ b/waybar/modules/extras/wireplumber.jsonc
@@ -0,0 +1,82 @@
+{
+ "group/wireplumber": {
+ "orientation": "horizontal",
+ "modules": [
+ "wireplumber#output",
+ "wireplumber#input"
+ ],
+ "drawer": {
+ // "transition-duration":
+ "transition-left-to-right": false
+ // "children-class":
+ // "click-to-reveal":
+ }
+ },
+
+ /*-------------------
+ output device
+ -------------------*/
+
+ "wireplumber#output": {
+ "format": "{icon} {volume}%",
+ "format-muted": " {volume}%",
+ // "format-source":
+ // "format-source-muted":
+ "format-icons": [
+ "", "", ""
+ ],
+ // "rotate":
+ // "states":
+ "min-length": 7,
+ "max-length": 7,
+ // "align":
+ // "justify":
+ // "scroll-step":
+ "on-click": "~/.config/waybar/scripts/volume.sh output mute",
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ "on-scroll-up": "~/.config/waybar/scripts/volume.sh output raise",
+ "on-scroll-down": "~/.config/waybar/scripts/volume.sh output lower",
+ // "tooltip":
+ "tooltip-format": "Device: {node_name}",
+ // "max-volume":
+ // "reverse-scrolling":
+ "node-type": "Audio/Sink"
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ },
+
+ /*----------------
+ microphone
+ ----------------*/
+
+ "wireplumber#input": {
+ "format": " {volume}%",
+ "format-muted": " {volume}%",
+ // "format-source":
+ // "format-source-muted":
+ // "rotate":
+ // "states":
+ "min-length": 7,
+ "max-length": 7,
+ // "align":
+ // "justify":
+ // "scroll-step":
+ "on-click": "~/.config/waybar/scripts/volume.sh input mute",
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ "on-scroll-up": "~/.config/waybar/scripts/volume.sh input raise",
+ "on-scroll-down": "~/.config/waybar/scripts/volume.sh input lower",
+ // "tooltip":
+ "tooltip-format": "Device: {node_name}",
+ // "max-volume":
+ // "reverse-scrolling":
+ "node-type": "Audio/Source"
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ }
+}
diff --git a/waybar/modules/hyprland/window.jsonc b/waybar/modules/hyprland/window.jsonc
new file mode 100644
index 0000000..caca1cd
--- /dev/null
+++ b/waybar/modules/hyprland/window.jsonc
@@ -0,0 +1,19 @@
+{
+ "hyprland/window": {
+ "format": "{}",
+ "rewrite": {
+ "": "Desktop",
+ "kitty": "Terminal",
+ "zsh": "Terminal",
+ "~": "Terminal"
+ },
+ // "separate-outputs":
+ // "icon":
+ // "icon-size":
+ // "min-length":
+ // "max-length":
+ // "tooltip":
+ "swap-icon-label": false
+ // "expand":
+ }
+}
diff --git a/waybar/modules/hyprland/windowcount.jsonc b/waybar/modules/hyprland/windowcount.jsonc
new file mode 100644
index 0000000..65e959d
--- /dev/null
+++ b/waybar/modules/hyprland/windowcount.jsonc
@@ -0,0 +1,12 @@
+{
+ "hyprland/windowcount": {
+ "format": "[{}]",
+ // "format-empty":
+ // "format-windowed":
+ // "format-fullscreen":
+ // "separate-outputs":
+ // "min-length":
+ // "max-length":
+ "swap-icon-label": false
+ }
+}
diff --git a/waybar/modules/hyprland/workspaces.jsonc b/waybar/modules/hyprland/workspaces.jsonc
new file mode 100644
index 0000000..864fcac
--- /dev/null
+++ b/waybar/modules/hyprland/workspaces.jsonc
@@ -0,0 +1,38 @@
+{
+ "hyprland/workspaces": {
+ // "active-only":
+ // "hide-active":
+ // "all-outputs":
+ "format": "{icon}",
+ "format-icons": {
+ "active": "",
+ "default": ""
+ },
+ "persistent-workspaces": {
+ "*": 5
+ },
+ // "persistent-only":
+ // "show-special":
+ // "special-visible-only":
+ // "sort-by":
+ // "window-rewrite":
+ // "window-rewrite-default":
+ // "format-window-separator":
+ "workspace-taskbar": {
+ // "enable":
+ // "update-active-window":
+ // "format":
+ // "icon-size":
+ // "icon-theme":
+ // "orientation":
+ // "ignore-list":
+ // "on-click-window":
+ },
+ // "move-to-monitor":
+ // "ignore-workspaces":
+ "on-scroll-up": "hyprctl dispatch workspace +1",
+ "on-scroll-down": "hyprctl dispatch workspace -1",
+ // "expand":
+ "cursor": true
+ }
+}
diff --git a/waybar/modules/idle_inhibitor.jsonc b/waybar/modules/idle_inhibitor.jsonc
new file mode 100644
index 0000000..c05e5a2
--- /dev/null
+++ b/waybar/modules/idle_inhibitor.jsonc
@@ -0,0 +1,30 @@
+{
+ "idle_inhibitor": {
+ "format": "{icon}",
+ "format-icons": {
+ "activated": "",
+ "deactivated": ""
+ },
+ // "rotate":
+ "min-length": 3,
+ "max-length": 3,
+ // "align":
+ // "justify":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format-activated": "Idle Inhibitor: Activated",
+ "tooltip-format-deactivated": "Idle Inhibitor: Deactivated",
+ "start-activated": false
+ // "timeout":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/memory.jsonc b/waybar/modules/memory.jsonc
new file mode 100644
index 0000000..dba44bc
--- /dev/null
+++ b/waybar/modules/memory.jsonc
@@ -0,0 +1,31 @@
+{
+ "memory": {
+ "interval": 10,
+ "format": " {percentage}%",
+ "format-warning": " {percentage}%",
+ "format-critical": " {percentage}%",
+ // "format-icons":
+ // "rotate":
+ "states": {
+ "warning": 75,
+ "critical": 90
+ },
+ "min-length": 7,
+ "max-length": 7,
+ // "align":
+ // "justify":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Memory Used: {used:0.0f}/{total:0.0f} GB"
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/mpris.jsonc b/waybar/modules/mpris.jsonc
new file mode 100644
index 0000000..51218b4
--- /dev/null
+++ b/waybar/modules/mpris.jsonc
@@ -0,0 +1,36 @@
+{
+ "mpris": {
+ // "player":
+ // "ignored-players":
+ // "interval":
+ "format": "{player_icon} {title} - {artist}",
+ "format-paused": "{status_icon} {title} - {artist}",
+ "tooltip-format": "Playing: {title} - {artist}",
+ "tooltip-format-paused": "Paused: {title} - {artist}",
+ // "enable-tooltip-len-limits":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ "player-icons": {
+ "default": ""
+ },
+ "status-icons": {
+ "paused": ""
+ },
+ // "artist-len":
+ // "album-len":
+ // "title-len":
+ // "dynamic-len":
+ // "dynamic-order":
+ // "dynamic-separator":
+ // "dynamic-importance-order":
+ // "truncate-hours":
+ // "ellipsis":
+ // "rotate":
+ // "min-length":
+ "max-length": 1000
+ // "align":
+ // "justify":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/network.jsonc b/waybar/modules/network.jsonc
new file mode 100644
index 0000000..e4c6df0
--- /dev/null
+++ b/waybar/modules/network.jsonc
@@ -0,0 +1,40 @@
+{
+ "network": {
+ // "interface":
+ // "rfkill":
+ "interval": 10,
+ // "family":
+ "format": "",
+ "format-ethernet": "",
+ "format-wifi": "{icon}",
+ // "format-linked":
+ "format-disconnected": "",
+ "format-disabled": "",
+ // "format-alt":
+ "format-icons": [
+ "", "", "", ""
+ ],
+ // "rotate":
+ "min-length": 2,
+ "max-length": 2,
+ // "align":
+ // "justify":
+ "on-click": "kitty -e ~/.config/waybar/scripts/network.sh",
+ // "on-click-middle":
+ "on-click-right": "nmcli radio wifi off && notify-send 'Wi-Fi Disabled' -i 'network-wireless-off' -r 1125",
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Gateway: {gwaddr}",
+ "tooltip-format-ethernet": "Interface: {ifname}",
+ "tooltip-format-wifi": "Network: {essid}\nIP Addr: {ipaddr}/{cidr}\nStrength: {signalStrength}%\nFrequency: {frequency} GHz",
+ "tooltip-format-disconnected": "Wi-Fi Disconnected",
+ "tooltip-format-disabled": "Wi-Fi Disabled"
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/pulseaudio.jsonc b/waybar/modules/pulseaudio.jsonc
new file mode 100644
index 0000000..97ac12a
--- /dev/null
+++ b/waybar/modules/pulseaudio.jsonc
@@ -0,0 +1,96 @@
+{
+ "group/pulseaudio": {
+ "orientation": "horizontal",
+ "modules": [
+ "pulseaudio#output",
+ "pulseaudio#input"
+ ],
+ "drawer": {
+ // "transition-duration":
+ "transition-left-to-right": false
+ // "children-class":
+ // "click-to-reveal":
+ }
+ },
+
+ /*-------------------
+ output device
+ -------------------*/
+
+ "pulseaudio#output": {
+ "format": "{icon} {volume}%",
+ // "format-bluetooth":
+ "format-muted": "{icon} {volume}%",
+ // "format-source":
+ // "format-source-muted":
+ "format-icons": {
+ "default": [ "", "", "" ],
+ "default-muted": "",
+ "headphone": "",
+ "headphone-muted": "",
+ "headset": "",
+ "headset-muted": ""
+ },
+ // "rotate":
+ // "states":
+ "min-length": 7,
+ "max-length": 7,
+ // "align":
+ // "justify":
+ // "scroll-step":
+ "on-click": "~/.config/waybar/scripts/volume.sh output mute",
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ "on-scroll-up": "~/.config/waybar/scripts/volume.sh output raise",
+ "on-scroll-down": "~/.config/waybar/scripts/volume.sh output lower",
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Output Device: {desc}"
+ // "max-volume":
+ // "ignored-sinks":
+ // "reverse-scrolling":
+ // "reverse-mouse-scrolling":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ },
+
+ /*----------------
+ microphone
+ ----------------*/
+
+ "pulseaudio#input": {
+ "format": "{format_source}",
+ // "format-bluetooth":
+ // "format-muted":
+ "format-source": " {volume}%",
+ "format-source-muted": " {volume}%",
+ // "format-icons":
+ // "rotate":
+ // "states":
+ "min-length": 7,
+ "max-length": 7,
+ // "align":
+ // "justify":
+ // "scroll-step":
+ "on-click": "~/.config/waybar/scripts/volume.sh input mute",
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ "on-scroll-up": "~/.config/waybar/scripts/volume.sh input raise",
+ "on-scroll-down": "~/.config/waybar/scripts/volume.sh input lower",
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Input Device: {desc}"
+ // "max-volume":
+ // "ignored-sinks":
+ // "reverse-scrolling":
+ // "reverse-mouse-scrolling":
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/modules/temperature.jsonc b/waybar/modules/temperature.jsonc
new file mode 100644
index 0000000..6c2dc25
--- /dev/null
+++ b/waybar/modules/temperature.jsonc
@@ -0,0 +1,35 @@
+{
+ "temperature": {
+ "thermal-zone": 1,
+ // "hwmon-path":
+ // "hwmon-path-abs":
+ // "input-filename":
+ // "warning-threshold":
+ "critical-threshold": 90,
+ "interval": 10,
+ // "format-warning":
+ "format-critical": " {temperatureC}°C",
+ "format": "{icon} {temperatureC}°C",
+ "format-icons": [
+ "", "", ""
+ ],
+ // "rotate":
+ "min-length": 8,
+ "max-length": 8,
+ // "align":
+ // "justify":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-update":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "tooltip-format": "Fahrenheit: {temperatureF}°F"
+ // "menu":
+ // "menu-file":
+ // "menu-actions":
+ // "expand":
+ }
+}
diff --git a/waybar/scripts/_fzf_colorizer.sh b/waybar/scripts/_fzf_colorizer.sh
new file mode 100755
index 0000000..2efa0bf
--- /dev/null
+++ b/waybar/scripts/_fzf_colorizer.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+#
+# A helper script that syncs fzf colors with the current Waybar theme
+#
+
+main() {
+ local wcss="$HOME/.config/waybar/current-theme.css"
+
+ local wtheme fcolors
+ wtheme=$(sed 1q "$wcss" | awk '{print $2}')
+ fcolors="$HOME/.config/waybar/themes/fzf/$wtheme.txt"
+
+ # Extract theme colors starting from line 3 up to (but not including) the
+ # first blank line
+ local wcolors
+ wcolors=$(sed -n '3,${/^ *$/Q;p}' "$wcss")
+
+ local element color hex
+ fcconf=()
+ while read -r element color; do
+ read -r _ _ hex < <(grep " $color " <<< "$wcolors")
+ hex=${hex%;}
+ fcconf+=("--color=$element:$hex")
+ done < "$fcolors"
+}
+
+main
diff --git a/waybar/scripts/backlight.sh b/waybar/scripts/backlight.sh
new file mode 100755
index 0000000..ed44dad
--- /dev/null
+++ b/waybar/scripts/backlight.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+#
+# Adjust screen brightness and send a notification with the current level
+#
+# Requirements:
+# - brightnessctl
+# - notify-send (libnotify)
+#
+# Author: Jesse Mirabel
+# Created: August 28, 2025
+# License: MIT
+
+VALUE=1
+
+print-usage() {
+ local script=${0##*/}
+ cat <<- EOF
+ USAGE: $script [OPTIONS]
+
+ Adjust screen brightness and send a notification with the current level
+
+ OPTIONS:
+ up Increase brightness by
+ down Decrease brightness by
+ Default value: $VALUE
+
+ EXAMPLES:
+ Increase brightness:
+ $ $script up
+
+ Decrease brightness by 5:
+ $ $script down 5
+ EOF
+ exit 1
+}
+
+set-brightness() {
+ local op
+ case $action in
+ 'up') op='+' ;;
+ 'down') op='-' ;;
+ esac
+
+ brightnessctl -n set "${value}%${op}" > /dev/null
+
+ local level
+ level=$(brightnessctl -m | awk -F ',' '{print $4}')
+
+ notify-send "Brightness: $level" -h int:value:"$level" -i 'contrast' -r 2825
+}
+
+main() {
+ action=$1
+ value=${2:-$VALUE}
+
+ ! ((value > 0)) && print-usage
+
+ case $action in
+ 'up' | 'down') set-brightness ;;
+ *) print-usage ;;
+ esac
+}
+
+main "$@"
diff --git a/waybar/scripts/bluetooth.sh b/waybar/scripts/bluetooth.sh
new file mode 100755
index 0000000..d05b9fc
--- /dev/null
+++ b/waybar/scripts/bluetooth.sh
@@ -0,0 +1,141 @@
+#!/usr/bin/env bash
+#
+# Scan, select, pair, and connect to Bluetooth devices
+#
+# Requirements:
+# - bluetoothctl (bluez-utils)
+# - fzf
+# - notify-send (libnotify)
+#
+# Author: Jesse Mirabel
+# Created: August 19, 2025
+# License: MIT
+
+fcconf=()
+# Get fzf color config
+# shellcheck disable=SC1090,SC2154
+. ~/.config/waybar/scripts/_fzf_colorizer.sh 2> /dev/null || true
+# If the file is missing, fzf will fall back to its default colors
+
+RED='\033[1;31m'
+RST='\033[0m'
+
+TIMEOUT=10
+
+ensure-on() {
+ local status
+ status=$(bluetoothctl show | awk '/PowerState/ {print $2}')
+
+ case $status in
+ 'off') bluetoothctl power on > /dev/null ;;
+ 'off-blocked')
+ rfkill unblock bluetooth
+
+ local i new_status
+ for ((i = 1; i <= TIMEOUT; i++)); do
+ printf '\rUnblocking Bluetooth... (%d/%d)' $i $TIMEOUT
+
+ new_status=$(bluetoothctl show | awk '/PowerState/ {print $2}')
+ if [[ $new_status == 'on' ]]; then
+ break
+ fi
+ sleep 1
+ done
+
+ # Bluetooth could be hard blocked
+ if [[ $new_status != 'on' ]]; then
+ notify-send 'Bluetooth' 'Failed to unblock' -i 'package-purge'
+ return 1
+ fi
+ ;;
+ *) return 0 ;;
+ esac
+
+ notify-send 'Bluetooth On' -i 'network-bluetooth-activated' -r 1925
+}
+
+get-device-list() {
+ bluetoothctl --timeout $TIMEOUT scan on > /dev/null &
+
+ local i num
+ for ((i = 1; i <= TIMEOUT; i++)); do
+ printf '\rScanning for devices... (%d/%d)' $i $TIMEOUT
+ printf '\n%bPress [q] to stop%b\n\n' "$RED" "$RST"
+
+ num=$(bluetoothctl devices | grep -c 'Device')
+ printf '\rDevices: %s' "$num"
+ printf '\033[3A'
+
+ read -rs -n 1 -t 1
+ if [[ $REPLY == [Qq] ]]; then
+ break
+ fi
+ done
+ printf '\n%bScanning stopped.%b\n\n' "$RED" "$RST"
+
+ list=$(bluetoothctl devices | sed 's/^Device //')
+ if [[ -z $list ]]; then
+ notify-send 'Bluetooth' 'No devices found' -i 'package-broken'
+ return 1
+ fi
+}
+
+select-device() {
+ local header
+ header=$(printf '%-17s %s' 'Address' 'Name')
+ local opts=(
+ '--border=sharp'
+ '--border-label= Bluetooth Devices '
+ '--ghost=Search'
+ "--header=$header"
+ '--height=~100%'
+ '--highlight-line'
+ '--info=inline-right'
+ '--pointer='
+ '--reverse'
+ "${fcconf[@]}"
+ )
+
+ address=$(fzf "${opts[@]}" <<< "$list" | awk '{print $1}')
+ if [[ -z $address ]]; then
+ return 1
+ fi
+
+ local connected
+ connected=$(bluetoothctl info "$address" | awk '/Connected/ {print $2}')
+ if [[ $connected == 'yes' ]]; then
+ notify-send 'Bluetooth' 'Already connected to this device' \
+ -i 'package-install'
+ return 1
+ fi
+}
+
+pair-and-connect() {
+ local paired
+ paired=$(bluetoothctl info "$address" | awk '/Paired/ {print $2}')
+ if [[ $paired == 'no' ]]; then
+ printf 'Pairing...'
+ if ! timeout $TIMEOUT bluetoothctl pair "$address" > /dev/null; then
+ notify-send 'Bluetooth' 'Failed to pair' -i 'package-purge'
+ return 1
+ fi
+ fi
+
+ printf '\nConnecting...'
+ if ! timeout $TIMEOUT bluetoothctl connect "$address" > /dev/null; then
+ notify-send 'Bluetooth' 'Failed to connect' -i 'package-purge'
+ return 1
+ fi
+ notify-send 'Bluetooth' 'Successfully connected' -i 'package-install'
+}
+
+main() {
+ tput civis
+ ensure-on || exit 1
+ get-device-list || exit 1
+ tput cnorm
+ select-device || exit 1
+ pair-and-connect || exit 1
+}
+
+main
diff --git a/waybar/scripts/network.sh b/waybar/scripts/network.sh
new file mode 100755
index 0000000..6c61a5a
--- /dev/null
+++ b/waybar/scripts/network.sh
@@ -0,0 +1,114 @@
+#!/usr/bin/env bash
+#
+# Scan, select, and connect to Wi-Fi networks
+#
+# Requirements:
+# - nmcli (networkmanager)
+# - fzf
+# - notify-send (libnotify)
+#
+# Author: Jesse Mirabel
+# Created: August 11, 2025
+# License: MIT
+
+fcconf=()
+# Get fzf color config
+# shellcheck disable=SC1090,SC2154
+. ~/.config/waybar/scripts/_fzf_colorizer.sh 2> /dev/null || true
+# If the file is missing, fzf will fall back to its default colors
+
+RED='\033[1;31m'
+RST='\033[0m'
+
+TIMEOUT=5
+
+ensure-enabled() {
+ local radio
+ radio=$(nmcli radio wifi)
+ if [[ $radio == 'enabled' ]]; then
+ return 0
+ fi
+ nmcli radio wifi on
+
+ local i state
+ for ((i = 1; i <= TIMEOUT; i++)); do
+ printf '\rEnabling Wi-Fi... (%d/%d)' $i $TIMEOUT
+
+ state=$(nmcli -t -f STATE general)
+ # If STATE returns anything other than this, we assume that Wi-Fi is
+ # fully enabled
+ if [[ $state != 'connected (local only)' ]]; then
+ break
+ fi
+ sleep 1
+ done
+ notify-send 'Wi-Fi Enabled' -i 'network-wireless-on' -r 1125
+}
+
+get-network-list() {
+ nmcli device wifi rescan
+
+ local i
+ for ((i = 1; i <= TIMEOUT; i++)); do
+ printf '\rScanning for networks... (%d/%d)' $i $TIMEOUT
+
+ list=$(timeout 1 nmcli device wifi list)
+ networks=$(tail -n +2 <<< "$list" | awk '$2 != "--"')
+ if [[ -n $networks ]]; then
+ break
+ fi
+ done
+ printf '\n%bScanning stopped.%b\n\n' "$RED" "$RST"
+
+ if [[ -z $networks ]]; then
+ notify-send 'Wi-Fi' 'No networks found' -i 'package-broken'
+ return 1
+ fi
+}
+
+select-network() {
+ local header
+ header=$(head -n 1 <<< "$list")
+ local opts=(
+ '--border=sharp'
+ '--border-label= Wi-Fi Networks '
+ '--ghost=Search'
+ "--header=$header"
+ '--height=~100%'
+ '--highlight-line'
+ '--info=inline-right'
+ '--pointer='
+ '--reverse'
+ "${fcconf[@]}"
+ )
+
+ bssid=$(fzf "${opts[@]}" <<< "$networks" | awk '{print $1}')
+ if [[ -z $bssid ]]; then
+ return 1
+ fi
+ if [[ $bssid == '*' ]]; then
+ notify-send 'Wi-Fi' 'Already connected to this network' \
+ -i 'package-install'
+ return 1
+ fi
+}
+
+connect-to-network() {
+ printf 'Connecting...\n'
+ if ! nmcli --ask device wifi connect "$bssid"; then
+ notify-send 'Wi-Fi' 'Failed to connect' -i 'package-purge'
+ return 1
+ fi
+ notify-send 'Wi-Fi' 'Successfully connected' -i 'package-install'
+}
+
+main() {
+ tput civis
+ ensure-enabled || exit 1
+ get-network-list || exit 1
+ tput cnorm
+ select-network || exit 1
+ connect-to-network || exit 1
+}
+
+main
diff --git a/waybar/scripts/power-menu.sh b/waybar/scripts/power-menu.sh
new file mode 100755
index 0000000..2d4323f
--- /dev/null
+++ b/waybar/scripts/power-menu.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+#
+# Launch a power menu
+#
+# Requirements:
+# - fzf
+#
+# Author: Jesse Mirabel
+# Created: August 19, 2025
+# License: MIT
+
+fcconf=()
+# Get fzf color config
+# shellcheck disable=SC1090,SC2154
+. ~/.config/waybar/scripts/_fzf_colorizer.sh 2> /dev/null || true
+# If the file is missing, fzf will fall back to its default colors
+
+main() {
+ local list=(
+ 'Lock'
+ 'Shutdown'
+ 'Reboot'
+ 'Logout'
+ 'Hibernate'
+ 'Suspend'
+ )
+ local opts=(
+ '--border=sharp'
+ '--border-label= Power Menu '
+ '--height=~100%'
+ '--highlight-line'
+ '--no-input'
+ '--pointer='
+ '--reverse'
+ "${fcconf[@]}"
+ )
+
+ local selected
+ selected=$(printf '%s\n' "${list[@]}" | fzf "${opts[@]}")
+ case $selected in
+ 'Lock') loginctl lock-session ;;
+ 'Shutdown') systemctl poweroff ;;
+ 'Reboot') systemctl reboot ;;
+ 'Logout') loginctl terminate-session "$XDG_SESSION_ID" ;;
+ 'Hibernate') systemctl hibernate ;;
+ 'Suspend') systemctl suspend ;;
+ *) exit 1 ;;
+ esac
+}
+
+main
diff --git a/waybar/scripts/system-update.sh b/waybar/scripts/system-update.sh
new file mode 100755
index 0000000..43cbbe8
--- /dev/null
+++ b/waybar/scripts/system-update.sh
@@ -0,0 +1,115 @@
+#!/usr/bin/env bash
+#
+# Check for official and AUR package updates and upgrade them. When run with the
+# 'module' argument, output the status icon and update counts in JSON format for
+# Waybar
+#
+# Requirements:
+# - checkupdates (pacman-contrib)
+# - notify-send (libnotify)
+# - optional: an AUR helper
+#
+# Author: Jesse Mirabel
+# Created: August 16, 2025
+# License: MIT
+
+GRN='\033[1;32m'
+BLU='\033[1;34m'
+RST='\033[0m'
+
+TIMEOUT=10
+HELPERS=('aura' 'paru' 'pikaur' 'trizen' 'yay')
+
+detect-helper() {
+ local h
+ for h in "${HELPERS[@]}"; do
+ if command -v "$h" > /dev/null; then
+ helper=$h
+ break
+ fi
+ done
+}
+
+check-updates() {
+ is_online=true
+ repo=0
+ aur=0
+
+ local rout rstat
+ rout=$(timeout $TIMEOUT checkupdates)
+ rstat=$?
+ # 2 means no updates are available
+ if ((rstat != 0 && rstat != 2)); then
+ is_online=false
+ return 1
+ fi
+ repo=$(grep -cve '^\s*$' <<< "$rout")
+
+ if [[ -z $helper ]]; then
+ return 0
+ fi
+
+ local aout astat
+ aout=$(timeout $TIMEOUT "$helper" -Quaq)
+ astat=$?
+ # Return only if the exit status is non-zero and there is an error
+ # message
+ if ((${#aout} > 0 && astat != 0)); then
+ is_online=false
+ return 1
+ fi
+ aur=$(grep -cve '^\s*$' <<< "$aout")
+}
+
+update-packages() {
+ printf '\n%bUpdating pacman packages...%b\n' "$BLU" "$RST"
+ sudo pacman -Syu
+
+ if [[ -n $helper ]]; then
+ printf '\n%bUpdating AUR packages...%b\n' "$BLU" "$RST"
+ "$helper" -Syu
+ fi
+
+ notify-send 'Update Complete' -i 'package-install'
+ printf '\n%bUpdate Complete!%b\n' "$GRN" "$RST"
+ read -rs -n 1 -p 'Press any key to exit...'
+}
+
+display-module() {
+ if [[ $is_online == false ]]; then
+ echo "{ \"text\": \"\", \"tooltip\": \"Cannot fetch updates. Right-click to retry.\" }"
+ return 0
+ fi
+
+ local tooltip="Official: $repo"
+ if [[ -n $helper ]]; then
+ tooltip+="\nAUR($helper): $aur"
+ fi
+
+ local total=$((repo + aur))
+ if ((total == 0)); then
+ echo "{ \"text\": \"\", \"tooltip\": \"No updates available\" }"
+ else
+ echo "{ \"text\": \"\", \"tooltip\": \"$tooltip\" }"
+ fi
+}
+
+main() {
+ detect-helper
+
+ case $1 in
+ 'module')
+ check-updates
+ display-module
+ ;;
+ *)
+ printf '%bChecking for updates...%b' "$BLU" "$RST"
+ check-updates
+ update-packages
+ # use signal to update the module
+ pkill -RTMIN+1 waybar
+ ;;
+ esac
+}
+
+main "$@"
diff --git a/waybar/scripts/volume.sh b/waybar/scripts/volume.sh
new file mode 100755
index 0000000..e6d571f
--- /dev/null
+++ b/waybar/scripts/volume.sh
@@ -0,0 +1,143 @@
+#!/usr/bin/env bash
+#
+# Adjust default device volume and send a notification with the current level
+#
+# Requirements:
+# - pactl (libpulse)
+# - notify-send (libnotify)
+#
+# Author: Jesse Mirabel
+# Created: September 07, 2025
+# License: MIT
+
+VALUE=1
+MIN=0
+MAX=100
+
+print-usage() {
+ local script=${0##*/}
+ cat <<- EOF
+ USAGE: $script [OPTIONS]
+
+ Adjust default device volume and send a notification with the current level
+
+ OPTIONS:
+ input Set device as '@DEFAULT_SOURCE@'
+ output Set device as '@DEFAULT_SINK@'
+
+ mute Toggle device mute
+
+ raise Raise volume by
+ lower Lower volume by
+ Default value: $VALUE
+
+ EXAMPLES:
+ Toggle microphone mute:
+ $ $script input mute
+
+ Raise speaker volume:
+ $ $script output raise
+
+ Lower speaker volume by 5:
+ $ $script output lower 5
+ EOF
+ exit 1
+}
+
+check-muted() {
+ local muted
+ muted=$(pactl "get-$dev_mute" "$dev" | awk '{print $2}')
+ local state
+ case $muted in
+ 'yes') state='Muted' ;;
+ 'no') state='Unmuted' ;;
+ esac
+
+ echo "$state"
+}
+
+get-volume() {
+ pactl "get-$dev_vol" "$dev" | awk '{print $5}' | tr -d '%'
+}
+
+get-icon() {
+ local icon
+ local new_vol=${1:-$(get-volume)}
+
+ if [[ $(check-muted) == 'Muted' ]]; then
+ icon="$dev_icon-muted"
+ else
+ if ((new_vol < ((MAX * 33) / 100))); then
+ icon="$dev_icon-low"
+ elif ((new_vol < ((MAX * 66) / 100))); then
+ icon="$dev_icon-medium"
+ else
+ icon="$dev_icon-high"
+ fi
+ fi
+
+ echo "$icon"
+}
+
+toggle-mute() {
+ pactl "set-$dev_mute" "$dev" toggle
+ notify-send "$title: $(check-muted)" -i "$(get-icon)" -r 2425
+}
+
+set-volume() {
+ local vol
+ vol=$(get-volume)
+ local new_vol
+
+ case $action in
+ 'raise')
+ new_vol=$((vol + value))
+ ((new_vol > MAX)) && new_vol=$MAX
+ ;;
+ 'lower')
+ new_vol=$((vol - value))
+ ((new_vol < MIN)) && new_vol=$MIN
+ ;;
+ esac
+
+ pactl "set-$dev_vol" "$dev" "${new_vol}%"
+
+ local icon
+ icon=$(get-icon "$new_vol")
+
+ notify-send "$title: ${new_vol}%" -h int:value:$new_vol -i "$icon" -r 2425
+}
+
+main() {
+ device=$1
+ action=$2
+ value=${3:-$VALUE}
+
+ ! ((value > 0)) && print-usage
+
+ case $device in
+ 'input')
+ dev='@DEFAULT_SOURCE@'
+ dev_mute='source-mute'
+ dev_vol='source-volume'
+ dev_icon='mic-volume'
+ title='Microphone'
+ ;;
+ 'output')
+ dev='@DEFAULT_SINK@'
+ dev_mute='sink-mute'
+ dev_vol='sink-volume'
+ dev_icon='audio-volume'
+ title='Volume'
+ ;;
+ *) print-usage ;;
+ esac
+
+ case $action in
+ 'mute') toggle-mute ;;
+ 'raise' | 'lower') set-volume ;;
+ *) print-usage ;;
+ esac
+}
+
+main "$@"
diff --git a/waybar/style.css b/waybar/style.css
new file mode 100644
index 0000000..6bee011
--- /dev/null
+++ b/waybar/style.css
@@ -0,0 +1,12 @@
+/* ignore GTK theme */
+* {
+ all: initial;
+}
+
+@import "current-theme.css";
+@import "styles/fonts.css";
+@import "styles/global.css";
+@import "styles/modules-center.css";
+@import "styles/modules-left.css";
+@import "styles/modules-right.css";
+@import "styles/states.css";
diff --git a/waybar/styles/fonts.css b/waybar/styles/fonts.css
new file mode 100644
index 0000000..8a7b96a
--- /dev/null
+++ b/waybar/styles/fonts.css
@@ -0,0 +1,29 @@
+* {
+ font-family: "Commit Mono Nerd Font";
+ font-weight: bold;
+ font-size: 16px;
+}
+
+#custom-user,
+#window label,
+#mpris,
+tooltip label {
+ font-weight: normal;
+}
+
+#workspaces button.active label,
+#workspaces button.focused label,
+#custom-distro {
+ font-size: 20px;
+}
+
+#custom-power_menu {
+ font-size: 18px;
+}
+
+#custom-left_div,
+#custom-left_inv,
+#custom-right_div,
+#custom-right_inv {
+ font-size: 22px;
+}
diff --git a/waybar/styles/global.css b/waybar/styles/global.css
new file mode 100644
index 0000000..9db99a0
--- /dev/null
+++ b/waybar/styles/global.css
@@ -0,0 +1,34 @@
+* {
+ color: @main-fg;
+}
+
+.module {
+ margin-bottom: -1px;
+}
+
+#waybar {
+ background-color: @outline;
+}
+#waybar > box {
+ margin: 4px;
+ background-color: @main-bg;
+}
+
+button {
+ border-radius: 16px;
+ min-width: 16px;
+ padding: 0 10px;
+}
+button:hover {
+ background-color: @hover-bg;
+ color: @hover-fg;
+}
+
+tooltip {
+ border: 2px solid @main-br;
+ border-radius: 10px;
+ background-color: @main-bg;
+}
+tooltip > box {
+ padding: 0 6px;
+}
diff --git a/waybar/styles/modules-center.css b/waybar/styles/modules-center.css
new file mode 100644
index 0000000..8647310
--- /dev/null
+++ b/waybar/styles/modules-center.css
@@ -0,0 +1,119 @@
+/*------------------
+ window count
+------------------*/
+
+#windowcount {
+ margin-right: 12px;
+}
+#windowcount label {
+ color: @hover-fg;
+}
+
+/*-----------------
+ temperature
+-----------------*/
+
+#custom-left_div.2 {
+ color: @temperature;
+}
+#temperature {
+ background-color: @temperature;
+}
+
+/*------------
+ memory
+------------*/
+
+#custom-left_div.3 {
+ background-color: @temperature;
+ color: @memory;
+}
+#memory {
+ background-color: @memory;
+}
+
+/*---------
+ cpu
+---------*/
+
+#custom-left_div.4 {
+ background-color: @memory;
+ color: @cpu;
+}
+#cpu {
+ background-color: @cpu;
+}
+#custom-left_inv.1 {
+ color: @cpu;
+}
+
+/*-----------------
+ distro icon
+-----------------*/
+
+#custom-left_div.5,
+#custom-right_div.2 {
+ color: @accent;
+}
+#custom-distro {
+ padding: 0 10px 0 5px;
+ background-color: @accent;
+ color: @main-bg;
+}
+
+/*--------------------
+ idle inhibitor
+--------------------*/
+
+#custom-right_inv.1 {
+ color: @time;
+}
+#idle_inhibitor {
+ background-color: @time;
+}
+
+/*----------
+ time
+----------*/
+
+#clock.time {
+ padding-right: 6px;
+ background-color: @time;
+}
+#custom-right_div.3 {
+ background-color: @date;
+ color: @time;
+}
+
+/*----------
+ date
+----------*/
+
+#clock.date {
+ padding-left: 6px;
+ background-color: @date;
+}
+#custom-right_div.4 {
+ background-color: @tray;
+ color: @date;
+}
+
+/*-----------------
+ system tray
+-----------------*/
+
+#network {
+ background-color: @tray;
+ padding: 0 6px 0 4px;
+}
+#bluetooth {
+ background-color: @tray;
+ padding: 0 5px;
+}
+#custom-system_update {
+ background-color: @tray;
+ padding: 0 8px 0 2px;
+}
+#custom-right_div.5 {
+ color: @tray;
+}
diff --git a/waybar/styles/modules-left.css b/waybar/styles/modules-left.css
new file mode 100644
index 0000000..6756e8d
--- /dev/null
+++ b/waybar/styles/modules-left.css
@@ -0,0 +1,32 @@
+/*--------------
+ username
+--------------*/
+
+#custom-user {
+ padding-right: 12px;
+}
+
+/*----------------
+ workspaces
+----------------*/
+
+#custom-left_div.1,
+#custom-right_div.1 {
+ color: @workspaces;
+}
+#workspaces {
+ padding: 0 1px;
+ background-color: @workspaces;
+}
+#workspaces button.active label,
+#workspaces button.focused label {
+ color: @accent;
+}
+
+/*------------------
+ window title
+------------------*/
+
+#window {
+ margin-left: 12px;
+}
diff --git a/waybar/styles/modules-right.css b/waybar/styles/modules-right.css
new file mode 100644
index 0000000..50f2598
--- /dev/null
+++ b/waybar/styles/modules-right.css
@@ -0,0 +1,59 @@
+/*----------------
+ media info
+----------------*/
+
+#mpris {
+ padding: 0 12px;
+}
+
+/*------------
+ volume
+------------*/
+
+#custom-left_div.6 {
+ color: @volume;
+}
+#pulseaudio,
+#wireplumber {
+ background-color: @volume;
+}
+
+/*----------------
+ brightness
+----------------*/
+
+#custom-left_div.7 {
+ background-color: @volume;
+ color: @backlight;
+}
+#backlight {
+ background-color: @backlight;
+}
+
+/*-------------
+ battery
+-------------*/
+
+#custom-left_div.8 {
+ background-color: @backlight;
+ color: @battery;
+}
+#battery {
+ background-color: @battery;
+}
+#custom-left_inv.2 {
+ color: @battery;
+}
+
+/*----------------
+ power menu
+----------------*/
+
+#custom-power_menu {
+ border-radius: 16px;
+ padding: 0 19px 0 16px;
+ color: @accent;
+}
+#custom-power_menu:hover {
+ background-color: @hover-bg;
+}
diff --git a/waybar/styles/states.css b/waybar/styles/states.css
new file mode 100644
index 0000000..a1c52f8
--- /dev/null
+++ b/waybar/styles/states.css
@@ -0,0 +1,37 @@
+#custom-trigger:hover,
+#idle_inhibitor:hover,
+#clock.date:hover,
+#network:hover,
+#bluetooth:hover,
+#custom-system_update:hover,
+#mpris:hover,
+#pulseaudio:hover,
+#wireplumber:hover {
+ color: @hover-fg;
+}
+
+/* inactive state */
+#idle_inhibitor.deactivated,
+#mpris.paused,
+#pulseaudio.output.muted,
+#pulseaudio.input.source-muted,
+#wireplumber.muted {
+ color: @hover-fg;
+}
+
+#memory.warning,
+#cpu.warning,
+#battery.warning {
+ color: @warning;
+}
+
+#temperature.critical,
+#memory.critical,
+#cpu.critical,
+#battery.critical {
+ color: @critical;
+}
+
+#battery.charging {
+ color: @charging;
+}
diff --git a/waybar/themes/catppuccin-frappe.css b/waybar/themes/catppuccin-frappe.css
new file mode 100644
index 0000000..be98dd1
--- /dev/null
+++ b/waybar/themes/catppuccin-frappe.css
@@ -0,0 +1,63 @@
+/* catppuccin frappe */
+
+@define-color rosewater #f2d5cf;
+@define-color flamingo #eebebe;
+@define-color pink #f4b8e4;
+@define-color mauve #ca9ee6;
+@define-color red #e78284;
+@define-color maroon #ea999c;
+@define-color peach #ef9f76;
+@define-color yellow #e5c890;
+@define-color green #a6d189;
+@define-color teal #81c8be;
+@define-color sky #99d1db;
+@define-color sapphire #85c1dc;
+@define-color blue #8caaee;
+@define-color lavender #babbf1;
+@define-color text #c6d0f5;
+@define-color subtext1 #b5bfe2;
+@define-color subtext0 #a5adce;
+@define-color overlay2 #949cbb;
+@define-color overlay1 #838ba7;
+@define-color overlay0 #737994;
+@define-color surface2 #626880;
+@define-color surface1 #51576d;
+@define-color surface0 #414559;
+@define-color base #303446;
+@define-color mantle #292c3c;
+@define-color crust #232634;
+
+/*
+ br - border
+ bg - background
+ fg - foreground
+*/
+
+/* main colors */
+
+@define-color accent @lavender;
+@define-color main-br @subtext0;
+@define-color main-bg @crust;
+@define-color main-fg @text;
+@define-color hover-bg @base;
+@define-color hover-fg alpha(@main-fg, 0.75);
+@define-color outline shade(@main-bg, 0.5);
+
+/* module colors */
+
+@define-color workspaces @mantle;
+@define-color temperature @mantle;
+@define-color memory @base;
+@define-color cpu @surface0;
+@define-color time @surface0;
+@define-color date @base;
+@define-color tray @mantle;
+@define-color volume @mantle;
+@define-color backlight @base;
+@define-color battery @surface0;
+
+/* state colors */
+
+@define-color warning @yellow;
+@define-color critical @red;
+@define-color charging @green;
diff --git a/waybar/themes/catppuccin-latte.css b/waybar/themes/catppuccin-latte.css
new file mode 100644
index 0000000..26d9499
--- /dev/null
+++ b/waybar/themes/catppuccin-latte.css
@@ -0,0 +1,63 @@
+/* catppuccin latte */
+
+@define-color rosewater #dc8a78;
+@define-color flamingo #dd7878;
+@define-color pink #ea76cb;
+@define-color mauve #8839ef;
+@define-color red #d20f39;
+@define-color maroon #e64553;
+@define-color peach #fe640b;
+@define-color yellow #df8e1d;
+@define-color green #40a02b;
+@define-color teal #179299;
+@define-color sky #04a5e5;
+@define-color sapphire #209fb5;
+@define-color blue #1e66f5;
+@define-color lavender #7287fd;
+@define-color text #4c4f69;
+@define-color subtext1 #5c5f77;
+@define-color subtext0 #6c6f85;
+@define-color overlay2 #7c7f93;
+@define-color overlay1 #8c8fa1;
+@define-color overlay0 #9ca0b0;
+@define-color surface2 #acb0be;
+@define-color surface1 #bcc0cc;
+@define-color surface0 #ccd0da;
+@define-color base #eff1f5;
+@define-color mantle #e6e9ef;
+@define-color crust #dce0e8;
+
+/*
+ br - border
+ bg - background
+ fg - foreground
+*/
+
+/* main colors */
+
+@define-color accent @lavender;
+@define-color main-br @subtext0;
+@define-color main-bg @crust;
+@define-color main-fg @text;
+@define-color hover-bg @base;
+@define-color hover-fg alpha(@main-fg, 0.75);
+@define-color outline shade(@main-bg, 0.5);
+
+/* module colors */
+
+@define-color workspaces @mantle;
+@define-color temperature @mantle;
+@define-color memory @base;
+@define-color cpu @surface0;
+@define-color time @surface0;
+@define-color date @base;
+@define-color tray @mantle;
+@define-color volume @mantle;
+@define-color backlight @base;
+@define-color battery @surface0;
+
+/* state colors */
+
+@define-color warning @yellow;
+@define-color critical @red;
+@define-color charging @green;
diff --git a/waybar/themes/catppuccin-macchiato.css b/waybar/themes/catppuccin-macchiato.css
new file mode 100644
index 0000000..d98b1cc
--- /dev/null
+++ b/waybar/themes/catppuccin-macchiato.css
@@ -0,0 +1,63 @@
+/* catppuccin macchiato */
+
+@define-color rosewater #f4dbd6;
+@define-color flamingo #f0c6c6;
+@define-color pink #f5bde6;
+@define-color mauve #c6a0f6;
+@define-color red #ed8796;
+@define-color maroon #ee99a0;
+@define-color peach #f5a97f;
+@define-color yellow #eed49f;
+@define-color green #a6da95;
+@define-color teal #8bd5ca;
+@define-color sky #91d7e3;
+@define-color sapphire #7dc4e4;
+@define-color blue #8aadf4;
+@define-color lavender #b7bdf8;
+@define-color text #cad3f5;
+@define-color subtext1 #b8c0e0;
+@define-color subtext0 #a5adcb;
+@define-color overlay2 #939ab7;
+@define-color overlay1 #8087a2;
+@define-color overlay0 #6e738d;
+@define-color surface2 #5b6078;
+@define-color surface1 #494d64;
+@define-color surface0 #363a4f;
+@define-color base #24273a;
+@define-color mantle #1e2030;
+@define-color crust #181926;
+
+/*
+ br - border
+ bg - background
+ fg - foreground
+*/
+
+/* main colors */
+
+@define-color accent @lavender;
+@define-color main-br @subtext0;
+@define-color main-bg @crust;
+@define-color main-fg @text;
+@define-color hover-bg @base;
+@define-color hover-fg alpha(@main-fg, 0.75);
+@define-color outline shade(@main-bg, 0.5);
+
+/* module colors */
+
+@define-color workspaces @mantle;
+@define-color temperature @mantle;
+@define-color memory @base;
+@define-color cpu @surface0;
+@define-color time @surface0;
+@define-color date @base;
+@define-color tray @mantle;
+@define-color volume @mantle;
+@define-color backlight @base;
+@define-color battery @surface0;
+
+/* state colors */
+
+@define-color warning @yellow;
+@define-color critical @red;
+@define-color charging @green;
diff --git a/waybar/themes/catppuccin-mocha.css b/waybar/themes/catppuccin-mocha.css
new file mode 100644
index 0000000..ea025b2
--- /dev/null
+++ b/waybar/themes/catppuccin-mocha.css
@@ -0,0 +1,63 @@
+/* catppuccin mocha */
+
+@define-color rosewater #f5e0dc;
+@define-color flamingo #f2cdcd;
+@define-color pink #f5c2e7;
+@define-color mauve #cba6f7;
+@define-color red #f38ba8;
+@define-color maroon #eba0ac;
+@define-color peach #fab387;
+@define-color yellow #f9e2af;
+@define-color green #a6e3a1;
+@define-color teal #94e2d5;
+@define-color sky #89dceb;
+@define-color sapphire #74c7ec;
+@define-color blue #89b4fa;
+@define-color lavender #b4befe;
+@define-color text #cdd6f4;
+@define-color subtext1 #bac2de;
+@define-color subtext0 #a6adc8;
+@define-color overlay2 #9399b2;
+@define-color overlay1 #7f849c;
+@define-color overlay0 #6c7086;
+@define-color surface2 #585b70;
+@define-color surface1 #45475a;
+@define-color surface0 #313244;
+@define-color base #1e1e2e;
+@define-color mantle #181825;
+@define-color crust #11111b;
+
+/*
+ br - border
+ bg - background
+ fg - foreground
+*/
+
+/* main colors */
+
+@define-color accent @lavender;
+@define-color main-br @subtext0;
+@define-color main-bg @crust;
+@define-color main-fg @text;
+@define-color hover-bg @base;
+@define-color hover-fg alpha(@main-fg, 0.75);
+@define-color outline shade(@main-bg, 0.5);
+
+/* module colors */
+
+@define-color workspaces @mantle;
+@define-color temperature @mantle;
+@define-color memory @base;
+@define-color cpu @surface0;
+@define-color time @surface0;
+@define-color date @base;
+@define-color tray @mantle;
+@define-color volume @mantle;
+@define-color backlight @base;
+@define-color battery @surface0;
+
+/* state colors */
+
+@define-color warning @yellow;
+@define-color critical @red;
+@define-color charging @green;
diff --git a/waybar/themes/fzf/catppuccin.txt b/waybar/themes/fzf/catppuccin.txt
new file mode 100644
index 0000000..77d1a72
--- /dev/null
+++ b/waybar/themes/fzf/catppuccin.txt
@@ -0,0 +1,15 @@
+current-bg surface0
+bg base
+spinner rosewater
+hl red
+fg text
+header red
+info mauve
+pointer rosewater
+marker lavender
+current-fg text
+prompt mauve
+current-hl red
+selected-bg surface1
+border overlay0
+label text