Compare commits

48 Commits

Author SHA1 Message Date
9c73a335b9 feat(hypr): make animations smoother 2026-08-27 22:28:09 +01:00
fa4f7a322d feat(style): update css to claude-style theme 2026-08-27 22:22:29 +01:00
561e478849 feat(zshrc): add pacman -Syu alias 2026-08-27 21:51:32 +01:00
ad539234f1 feat(styling): update hyprland gtw icons & themes 2026-08-13 23:07:04 +01:00
b62db3a09d fix(binds): window not wrapping text 2026-07-23 20:15:51 +01:00
0513ab1abb feat(binds): add view keybinds script 2026-07-23 20:13:31 +01:00
84f51e8365 feat(packages): add yad package 2026-07-23 20:07:58 +01:00
4b08df386f feat(binds): add descriptions & change swap window bind 2026-07-23 20:00:58 +01:00
491f2b2765 feat(packages): add missing zsh package 2026-07-20 11:10:31 +01:00
5c29ef00f1 feat(zsh): add pacman install alias 2026-07-19 23:31:50 +01:00
5b40c331b6 feat(wofi): improve wofi program selection 2026-07-16 19:19:39 +01:00
901cfeca0d feat(wallpaper): add better wallpaper script 2026-07-16 19:12:02 +01:00
a1001e521e fix(wlogout): incorrect hyprland exit command 2026-07-16 18:42:19 +01:00
aae8be4001 style(hypr): cleanup lua configs 2026-07-16 10:20:11 +01:00
5dce5eb3b7 refactor(zsh): cleanup zshrc file 2026-07-14 19:46:20 +01:00
06b5aaa2d8 fix(hypr): incorrect mouse sens 2026-07-14 19:32:39 +01:00
84c0bb23b8 refactor!(hypr): switch to Lua config 2026-07-14 19:31:21 +01:00
3ec778781d fix(binds): update playerctl keybinds
Interfered with CS2 voting systems. Must find another way for it not to
override with other programs.
2026-04-06 20:47:36 +01:00
30425fa1e4 fix(hyprland): increase hyprland window animation speed
Was too slow, got really annoying
2026-04-06 20:44:33 +01:00
b55b45f25e fix(gitconfig): auto-lf 2026-04-06 20:43:50 +01:00
6bb29b7539 feat(vscode): update font size 2026-04-06 20:42:34 +01:00
3481125919 fix(hypr): fix minimum force speed 2026-03-16 22:51:08 +00:00
798ecf40a2 fix(hypr): adjust gesture settings for smoother workspace swaps
It turns out there are options for adjust the cancelling ratio and force
speed for workspace animations. This makes it much closer to real MacOS
animations.

This was tested against Jas's Macbook Air - M1 and they seem quite
closer.
2026-03-16 22:26:54 +00:00
eabcc3de6b feat(hyprland): add hypridle and lid close binds 2026-03-16 22:26:14 +00:00
bf9d570ff3 Merge branch 'main' of ssh://gitea/dylan/birch-dots 2026-03-14 13:21:03 +00:00
2c3c58e92d feat(packages): add yt-dlp 2026-03-14 00:34:20 +00:00
bc2c508969 fix(wlogout): broken logout button 2026-03-12 22:51:22 +00:00
8b12bc3a3b fix(mouse): incorrect sens 2026-03-12 22:46:17 +00:00
e628456780 Merge branch 'main' of ssh://gitea/dylan/birch-dots 2026-03-12 22:45:02 +00:00
3c463300b5 feat(gitconfig): add LFS config 2026-03-12 22:44:31 +00:00
984027efcb fix(hyprcursor): breeze mouse pointer uses lowercase "b"
Not really sure why it worked before, but after logging in this morning
the cursor was the default hyprland cursor. Fixed by reinstalling Breeze
and changing this.
2026-03-12 09:27:17 +00:00
1c12506728 chore(gitconfig): add LFS config 2026-03-12 08:56:16 +00:00
568a81a94d fix(hypr): increase scroll factor
Scrolling on certain apps is too slow with 0.2
2026-03-12 08:55:49 +00:00
9ee3da3100 feat(waybar): add bluetooth module 2026-03-12 08:55:28 +00:00
fab1c53cb3 fix(bootstrap): entire file skip upon one package fail
If one package in a file failed, the whole file was skipped.
2026-03-09 15:45:19 +00:00
f29cf5e920 fix(packages): update incorrect docker compose package 2026-03-09 15:40:21 +00:00
3ef8420a21 feat(packages): add rsync 2026-03-09 15:36:40 +00:00
7805b3c98d docs: add common issues markdown
These mostly pertain to the QEMU VM setup, so they might not be fully
relevant outside of VMs.
2026-03-09 15:24:19 +00:00
ccb5b1ab96 fix(bootstrap): missing NetworkManager install before enabling 2026-03-09 15:23:16 +00:00
c65c286606 fix(bootstrap): remove bluetooth service enabling
Bluetooth does not for now work reliably on my machines.
2026-03-09 15:10:58 +00:00
34ce514c75 fix(packages): remove zoom
Zoom is not a base package that I use on a base system. It can be
installed after the fact.
2026-03-09 14:53:20 +00:00
6e6376eee9 fix(bootstrap): missing system setups in bootstrap 2026-03-09 14:49:45 +00:00
d3617c3866 feat(bootstrap): update bootstrap script to install packages 2026-03-09 14:30:02 +00:00
378cc51cc3 feat(packages): add git-lfs 2026-03-08 15:45:18 +00:00
1bd5bebcda fix(hyprland): anime wallpaper accidentally added in default config
Cringe.
2026-03-08 00:22:25 +00:00
d96970bc8d fix(packages): remove redundant xdg-desktop-portal-wlr module
`xdg-desktop-portal-hyprland` is a fork of wlr that includes
Hyprland-specific features.
2026-03-08 00:00:16 +00:00
4bf3764855 fix(packages): remove qdirstat
ncdu (pacman/dev.txt) does everything that it does but as a CLI.
2026-03-07 23:56:35 +00:00
af00cb8735 feat(packages): remove libdwarf dev package
Not used by anything, not sure when or why it was installed.
2026-03-07 23:55:53 +00:00
35 changed files with 855 additions and 524 deletions

View File

@@ -1,13 +0,0 @@
github.copilot-chat
ms-azuretools.vscode-containers
ms-python.debugpy
ms-python.python
ms-python.vscode-pylance
ms-python.vscode-python-envs
ms-vscode-remote.remote-containers
ms-vscode.cmake-tools
ms-vscode.cpp-devtools
ms-vscode.cpptools
ms-vscode.cpptools-extension-pack
ms-vscode.cpptools-themes
tomoki1207.pdf

View File

@@ -1,7 +0,0 @@
{
"explorer.confirmDragAndDrop": false,
"python.defaultInterpreterPath": "/sbin/python3.14",
"git.autofetch": true,
"explorer.confirmDelete": false,
"git.confirmSync": false
}

View File

@@ -1,16 +0,0 @@
{
"offloadAdmControls": true,
"BACKGROUND_COLOR": "#000000",
"enableHardwareAcceleration": true,
"chromiumSwitches": {},
"asyncVideoInputDeviceInit": false,
"IS_MAXIMIZED": false,
"IS_MINIMIZED": false,
"WINDOW_BOUNDS": {
"x": 1927,
"y": 57,
"width": 1906,
"height": 1016
},
"SKIP_HOST_UPDATE": true
}

View File

@@ -1,6 +0,0 @@
# Floating
windowrule = float 1, match:title Play Timer
# Opacity
windowrule = opacity 0.9 0.75, match:class $terminal

View File

@@ -0,0 +1,31 @@
-- Opacity
hl.window_rule({
name = "opacity_0_75_0_6",
match = {
class = ".*" .. terminal .. ".*"
},
opacity = "0.75 0.6",
})
-- Workspaces
hl.window_rule({
workspace = "1",
match = {
class = ".*[Mm]inecraft.*"
}
})
hl.window_rule({
workspace = "1",
match = {
class = ".*[Ss]team*."
}
})
hl.window_rule({
name = "shrink-file-picker",
match = { class = "^(xdg-desktop-portal-gtk)$" },
float = true,
size = {900, 900},
move = {"(monitor_w - window_w) / 2", "(monitor_h - window_h) / 2"},
})

View File

@@ -1,67 +0,0 @@
general {
# Gaps & borders – light and uncluttered
gaps_in = 4
gaps_out = 6
gaps_workspaces = 32
border_size = 1
col.active_border = rgba(0DB7D4FF)
col.inactive_border = rgba(31313633)
no_focus_fallback = true
allow_tearing = true
snap {
enabled = true
window_gap = 4
monitor_gap = 6
respect_gaps = true
}
}
dwindle {
preserve_split = true
smart_split = false
smart_resizing = false
}
decoration {
rounding = 10
shadow {
enabled = yes
range = 16
render_power = 2
color = rgba(00000040)
}
blur {
enabled = yes
size = 5
passes = 2
vibrancy = 0.14
}
}
animations {
enabled = yes
bezier = overshoot, 0.22, 0.61, 0.36, 1.15
bezier = breeze, 0.22, 0.61, 0.36, 1.0
# Windows: quick, soft, intentional
animation = windows, 1, 5, breeze, slidefade
animation = windowsOut, 1, 4, breeze, slidefade
# Workspaces: airy glide, finishes fast
animation = workspaces, 1, 5, overshoot, slidefade
# Subtle polish
animation = fade, 1, 4, breeze
animation = windowsMove, 1, 3, breeze
animation = border, 1, 3, breeze
}

View File

@@ -0,0 +1,56 @@
hl.config({
general = {
-- Gaps & borders – light and uncluttered
gaps_in = 4,
gaps_out = 6,
gaps_workspaces = 32,
border_size = 1,
no_focus_fallback = true,
allow_tearing = true,
snap = {
enabled = true,
window_gap = 4,
monitor_gap = 6,
respect_gaps = true,
},
col = {
active_border = "rgba(E29A6EFF)",
inactive_border = "rgba(2C252033)",
},
},
})
hl.config({
dwindle = {
preserve_split = true,
smart_split = false,
smart_resizing = false,
},
})
hl.config({
decoration = {
rounding = 10,
shadow = {
enabled = true,
range = 16,
render_power = 2,
color = "rgba(1A161340)",
},
blur = {
enabled = true,
size = 5,
passes = 2,
vibrancy = 0.14,
},
},
})
hl.config({
animations = {
enabled = true,
},
})
hl.curve("myBezier", { type = "bezier", points = { {0.16, 1}, {0.3, 1} } })
hl.animation({ leaf = "windows", enabled = true, speed = 1.8, bezier = "myBezier" })
hl.animation({ leaf = "windowsOut", enabled = true, speed = 1.6, bezier = "myBezier", style = "popin 90%" })
hl.animation({ leaf = "border", enabled = true, speed = 2.5, bezier = "myBezier" })
hl.animation({ leaf = "fade", enabled = true, speed = 1.8, bezier = "myBezier" })
hl.animation({ leaf = "workspaces", enabled = true, speed = 1.8, bezier = "myBezier" })

View File

@@ -1,37 +0,0 @@
source = ~/.config/hypr/monitors.conf
# Set programs that you use
$terminal = kitty
$fileManager = thunar
$menu = wofi --show drun
$browser = brave
exec-once = /usr/lib/xdg-desktop-portal-hyprland &
exec-once = /usr/lib/xdg-desktop-portal &
exec-once = hyprpaper
exec = gsettings set org.gnome.desktop.interface color-scheme "prefer-dark" # for GTK4 apps
exec = gsettings set org.gnome.desktop.interface gtk-theme "adw-gtk3-dark" # for GTK3 apps
misc:initial_workspace_tracking=1
#############################
### ENVIRONMENT VARIABLES ###
#############################
env = XCURSOR_SIZE,24
env = HYPRCURSOR_SIZE,24
env = LIBVA_DRIVER_NAME,nvidia
env = __GLX_VENDOR_LIBRARY_NAME,nvidia
env = NVD_BACKEND,direct
env = QT_QPA_PLATFORMTHEME,qt6ct # for Qt apps# Theme
exec-once = waybar
exec-once = nextcloud
exec-once = hyprctl setcursor Breeze 24
source = ~/.config/hypr/input.conf
source = ~/.config/hypr/keybinds.conf
source = ~/.config/hypr/applications.conf
source = ~/.config/hypr/decoration.conf
source = ~/.config/hypr/workspaces.conf
source = ~/.config/hypr/hyprpaper.conf

48
.config/hypr/hyprland.lua Normal file
View File

@@ -0,0 +1,48 @@
local monitors = require("monitors")
-- Set programs that you use
terminal = "kitty"
fileManager = "thunar"
menu = "wofi --show drun"
browser = "brave"
hl.config({
misc = {
force_default_wallpaper = 0,
disable_hyprland_logo = true,
initial_workspace_tracking = 1,
},
})
-- Envs
hl.env("XCURSOR_SIZE", 24)
hl.env("XCUROSR_THEME", "breeze-dark")
hl.env("HYPRCURSOR_SIZE", 24)
hl.env("HYPRCURSOR_THEME", "breeze-dark")
hl.env("LIBVA_DRIVER_NAME", "nvidia")
hl.env("__GLX_VENDOR_LIBRARY_NAME", "nvidia")
hl.env("NVD_BACKEND", "direct")
hl.env("QT_QPA_PLATFORMTHEME", "qt6ct")
local keybinds = require("keybinds")
local input = require("input")
local applications = require("applications")
local decorations = require("decoration")
local workspaces = require("workspaces")
-- Autostart
hl.on("hyprland.start", function()
hl.exec_cmd("/usr/lib/xdg-desktop-portal-hyprland &")
hl.exec_cmd("/usr/lib/xdg-desktop-portal &")
hl.exec_cmd("hyprpaper")
hl.exec_cmd("nextcloud")
hl.exec_cmd("waybar")
hl.exec_cmd("hyprctl setcursor breeze 24")
hl.exec_cmd("xsettingsd")
end)
-- Exec (run every reload)
hl.on("config.reloaded", function()
hl.exec_cmd("gsettings set org.gnome.desktop.interface color-scheme prefer-dark")
hl.exec_cmd("gsettings set org.gnome.desktop.interface gtk-theme adw-gtk3-dark")
end)

View File

@@ -1 +1,4 @@
ipc = on
preload = /home/dylan/.wallpapers/monochrome.png
wallpaper = ,/home/dylan/.wallpapers/monochrome.png
splash = false

View File

@@ -1,26 +0,0 @@
input {
kb_layout = ie
kb_variant =
kb_model =
kb_options =
kb_rules =
follow_mouse = 1
accel_profile = flat
force_no_accel=2
sensitivity = 1
touchpad {
natural_scroll = true
scroll_factor = 0.2
}
}
device {
name = logitech-usb-receiver
sensitivity = 0
}
gesture = 3, horizontal, workspace
gesture = 3, down, fullscreen

20
.config/hypr/input.lua Normal file
View File

@@ -0,0 +1,20 @@
hl.config({
input = {
kb_layout = "ie",
follow_mouse = 1,
accel_profile = "flat",
sensitivity = 0,
touchpad = {
natural_scroll = true,
scroll_factor = 0.45,
},
},
})
hl.config({
gestures = {
workspace_swipe_cancel_ratio = 0,
workspace_swipe_min_speed_to_force = 10,
},
})

View File

@@ -1,71 +0,0 @@
$mainMod = SUPER # Sets "Windows" key as main modifier
bind = $mainMod, RETURN, exec, $terminal
# Move focus with mainMod + arrow keys
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
# Switch workspaces with mainMod + [0-9]
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
# Move active window to a workspace with mainMod + SHIFT + [0-9]
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
# Change wallpaper
bind = $mainMod, W, exec, ~/.config/wofi/scripts/wallpaper.sh
bindel = $mainMod, L, exec, brightnessctl -e4 -n2 set 5%+
bindel = $mainMod, K, exec, brightnessctl -e4 -n2 set 5%-
# Volume
bindl = , F4, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindl = , F5, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
bindl = , F6, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindl = , F7, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
# Playback (requires playerctl)
bindl = , F2, exec, playerctl previous
bindl = , F1, exec, playerctl play-pause
bindl = , F3, exec, playerctl next
bind = SUPER CTRL, left, swapwindow, l
bind = SUPER CTRL, right, swapwindow, r
bind = SUPER SHIFT, F, fullscreen
bind = SUPER CTRL, F, fullscreen, 1
bind = SUPER, Q, killactive
bind = ALT, TAB, cyclenext
bind = SUPER, F, exec, $fileManager
bind = SUPER, D, exec, $menu
bind = SUPER, B, exec, $browser
bind = SUPER SHIFT, S, exec, grim -g "$(slurp)" - | wl-copy

74
.config/hypr/keybinds.lua Normal file
View File

@@ -0,0 +1,74 @@
---@module 'hl'
local mainMod = "SUPER"
-- Sets "Windows" key as main modifier
hl.bind(mainMod .. " + " .. "RETURN", hl.dsp.exec_cmd(terminal), { description = "Terminal" })
-- Move focus with mainMod + arrow keys
hl.bind(mainMod .. " + " .. "up", hl.dsp.focus({ direction = "up" }), { description = "Focus up" })
hl.bind(mainMod .. " + " .. "down", hl.dsp.focus({ direction = "down" }), { description = "Focus down" })
-- Switch workspaces with mainMod + [0-9]
hl.bind(mainMod .. " + " .. 1, hl.dsp.focus({ workspace = 1 }), { description = "Workspace 1" })
hl.bind(mainMod .. " + " .. 2, hl.dsp.focus({ workspace = 2 }), { description = "Workspace 2" })
hl.bind(mainMod .. " + " .. 3, hl.dsp.focus({ workspace = 3 }), { description = "Workspace 3" })
hl.bind(mainMod .. " + " .. 4, hl.dsp.focus({ workspace = 4 }), { description = "Workspace 4" })
hl.bind(mainMod .. " + " .. 5, hl.dsp.focus({ workspace = 5 }), { description = "Workspace 5" })
hl.bind(mainMod .. " + " .. 6, hl.dsp.focus({ workspace = 6 }), { description = "Workspace 6" })
hl.bind(mainMod .. " + " .. 7, hl.dsp.focus({ workspace = 7 }), { description = "Workspace 7" })
hl.bind(mainMod .. " + " .. 8, hl.dsp.focus({ workspace = 8 }), { description = "Workspace 8" })
hl.bind(mainMod .. " + " .. 9, hl.dsp.focus({ workspace = 9 }), { description = "Workspace 9" })
hl.bind(mainMod .. " + " .. 0, hl.dsp.focus({ workspace = 10 }), { description = "Workspace 10" })
-- Move active window to a workspace with mainMod + SHIFT + [0-9]
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 1, hl.dsp.window.move({ workspace = 1 }), { description = "Move window to workspace 1" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 2, hl.dsp.window.move({ workspace = 2 }), { description = "Move window to workspace 2" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 3, hl.dsp.window.move({ workspace = 3 }), { description = "Move window to workspace 3" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 4, hl.dsp.window.move({ workspace = 4 }), { description = "Move window to workspace 4" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 5, hl.dsp.window.move({ workspace = 5 }), { description = "Move window to workspace 5" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 6, hl.dsp.window.move({ workspace = 6 }), { description = "Move window to workspace 6" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 7, hl.dsp.window.move({ workspace = 7 }), { description = "Move window to workspace 7" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 8, hl.dsp.window.move({ workspace = 8 }), { description = "Move window to workspace 8" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 9, hl.dsp.window.move({ workspace = 9 }), { description = "Move window to workspace 9" })
hl.bind(mainMod .. " + " .. "SHIFT" .. " + " .. 0, hl.dsp.window.move({ workspace = 10 }), { description = "Move window to workspace 10" })
-- Scroll through existing workspaces with mainMod + scroll
hl.bind(mainMod .. " + " .. "right", hl.dsp.focus({ workspace = "+1" }), { description = "Next workspace" })
hl.bind(mainMod .. " + " .. "left", hl.dsp.focus({ workspace = "-1" }), { description = "Previous workspace" })
-- Move/resize windows with mainMod + LMB/RMB and dragging
hl.bind(mainMod .. " + " .. "mouse:272", hl.dsp.window.drag(), { mouse = true, description = "Move window" })
hl.bind(mainMod .. " + " .. "mouse:273", hl.dsp.window.resize(), { mouse = true, description = "Resize window" })
-- Change wallpaper
hl.bind(mainMod .. " + " .. "W", hl.dsp.exec_cmd("~/.config/wofi/scripts/wallpaper.sh"), { description = "Change wallpaper" })
hl.bind(mainMod .. " + " .. "L", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%+"), { locked = true, description = "Brightness up" })
hl.bind(mainMod .. " + " .. "K", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%-"), { locked = true, description = "Brightness down" })
-- Volume
hl.bind("F7", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"), { locked = true, description = "Volume down" })
hl.bind("F8", hl.dsp.exec_cmd("wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"), { locked = true, description = "Volume up" })
hl.bind("F9", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"), { locked = true, description = "Mute output" })
hl.bind("F10", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"), { locked = true, description = "Mute microphone" })
-- Playback (requires playerctl)
hl.bind("F4", hl.dsp.exec_cmd("playerctl previous"), { locked = true, description = "Previous track" })
hl.bind("F5", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true, description = "Play/pause" })
hl.bind("F6", hl.dsp.exec_cmd("playerctl next"), { locked = true, description = "Next track" })
hl.bind("switch:on:Lid Switch", hl.dsp.exec_cmd("hyprctl dispatch dpms off"), { locked = true, description = "Displays off on lid close" })
hl.bind("switch:off:Lid Switch", hl.dsp.exec_cmd("hyprctl dispatch dpms on"), { locked = true, description = "Displays on on lid open" })
-- My binds
hl.bind("SUPER + CTRL" .. " + " .. "left", hl.dsp.window.swap({ direction = "left" }), { description = "Swap window left" })
hl.bind("SUPER + CTRL" .. " + " .. "right", hl.dsp.window.swap({ direction = "right" }), { description = "Swap window right" })
hl.bind("SUPER + SHIFT" .. " + " .. "F", hl.dsp.window.fullscreen(), { description = "Fullscreen" })
hl.bind("SUPER + CTRL" .. " + " .. "F", hl.dsp.window.fullscreen({mode = "maximized"}), { description = "Maximize" })
hl.bind("SUPER" .. " + " .. "Q", hl.dsp.window.close(), { description = "Close window" })
hl.bind("ALT" .. " + " .. "TAB", hl.dsp.window.cycle_next(), { description = "Cycle windows" })
hl.bind("SUPER" .. " + " .. "F", hl.dsp.exec_cmd(fileManager), { description = "File manager" })
hl.bind("SUPER" .. " + " .. "D", hl.dsp.exec_cmd(menu), { description = "App launcher" })
hl.bind("SUPER" .. " + " .. "B", hl.dsp.exec_cmd(browser), { description = "Browser" })
hl.bind("SUPER + SHIFT + S", hl.dsp.exec_cmd('grim -g "$(slurp -d)" - | wl-copy'), { description = "Screenshot region to clipboard" })
hl.bind(mainMod .. " + slash", hl.dsp.exec_cmd(os.getenv("HOME") .. "/.config/hypr/scripts/show-binds.sh"), { description = "Show keybind cheat sheet" })

13
.config/hypr/monitors.lua Normal file
View File

@@ -0,0 +1,13 @@
hl.monitor({
output = "DP-3",
mode = "1920x1080@270",
position = "0x0",
scale = 1,
})
hl.monitor({
output = "DP-1",
mode = "1920x1080@144",
position = "-1920x0",
scale = 1,
})

View File

@@ -0,0 +1,26 @@
#!/usr/bin/env bash
DATA=$(hyprctl -j binds | jq -r '
def mods(m):
[ if m >= 64 then "SUPER" else empty end,
if (m % 16) >= 8 then "ALT" else empty end,
if (m % 8) >= 4 then "CTRL" else empty end,
if (m % 2) >= 1 then "SHIFT" else empty end ] | join("+");
[ .[] | select(.has_description)
| { k: "\(if .modmask > 0 then mods(.modmask) + "+" else "" end)\(.key)",
d: .description } ]
| sort_by(.k)
| (map(.k | length) | max) as $w
| .[] | "\(.k + (" " * ($w - (.k | length)))) \(.d)"
')
COLS=$(awk '{ if (length > m) m = length } END { print m }' <<< "$DATA")
ROWS=$(wc -l <<< "$DATA")
PRW=$(( COLS * 2 + 4 ))
PX=$(( PRW * 7 + 60 ))
PY=$(( (ROWS / 2 + 2) * 18 + 60 ))
pr -2 -t -w "$PRW" <<< "$DATA" \
| yad --text-info --title="Hyprland Keybinds" \
--width="$PX" --height="$PY" --center \
--fontname="monospace 10" --no-buttons --wrap=false

View File

@@ -1,14 +0,0 @@
# Workspaces 1–5 on DP-3
workspace = 1, monitor:DP-3, default:true
workspace = 2, monitor:DP-3
workspace = 3, monitor:DP-3
workspace = 4, monitor:DP-3
workspace = 5, monitor:DP-3
# Workspaces 6–10 on DP-1
workspace = 6, monitor:DP-1, default:true
workspace = 7, monitor:DP-1
workspace = 8, monitor:DP-1
workspace = 9, monitor:DP-1
workspace = 10, monitor:DP-1

View File

@@ -0,0 +1,51 @@
-- Workspaces 1–5 on DP-3
hl.workspace_rule({
workspace = 1,
monitor = "DP-3",
})
hl.workspace_rule({
workspace = 2,
monitor = "DP-3",
})
hl.workspace_rule({
workspace = 3,
monitor = "DP-3",
})
hl.workspace_rule({
workspace = 4,
monitor = "DP-3",
})
hl.workspace_rule({
workspace = 5,
monitor = "DP-3",
})
-- Workspaces 6–10 on DP-1
hl.workspace_rule({
workspace = 6,
monitor = "DP-1",
})
hl.workspace_rule({
workspace = 7,
monitor = "DP-1",
})
hl.workspace_rule({
workspace = 8,
monitor = "DP-1",
})
hl.workspace_rule({
workspace = 9,
monitor = "DP-1",
})
hl.workspace_rule({
workspace = 10,
monitor = "DP-1",
})

View File

@@ -16,6 +16,7 @@
"modules-right": [
"tray",
"pulseaudio",
"bluetooth",
"custom/micmute",
"battery",
"custom/power"
@@ -62,6 +63,16 @@
"on-click-right": "pavucontrol"
},
"bluetooth": {
"format": "󰂯 {num_connections}",
"format-connected": "󰂱 {num_connections}",
"format-disabled": "󰂲",
"tooltip-format-connected": "{device_enumerate}",
"tooltip-format-enumerate-connected": "󰂱 {device_alias} ({device_battery_percentage}%)",
"on-click": "blueman-manager",
"on-click-right": "bluectl power toggle"
},
"battery": {
"interval":2,
"states": {

View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
#
# waybar custom module: shows currently playing media, mac-menu-bar style.
# Outputs a single JSON line: {"text":..., "tooltip":..., "class":..., "alt":...}
# waybar re-runs this on an interval (set in config.jsonc) and re-renders.
# --status-format lets us build one compact string per call instead of
# separate playerctl invocations for title/artist/status (fewer subprocess
# spawns = faster polling, matters since waybar calls this every ~1s).
STATUS=$(playerctl -a metadata --format '{{status}}|{{artist}}|{{title}}|{{playerName}}' 2>/dev/null | head -n1)
if [ -z "$STATUS" ]; then
# No MPRIS players running at all -> render nothing (empty text hides
# the module if `"class": "hidden"` is styled to display:none, but
# simplest is just an empty text with no tooltip).
echo '{"text": "", "tooltip": "No media playing", "class": "hidden"}'
exit 0
fi
# IFS='|' read splits our pipe-delimited format string into vars.
IFS='|' read -r PSTATUS ARTIST TITLE PLAYER <<< "$STATUS"
# Playing vs Paused get different CSS classes so you can dim the paused state.
case "$PSTATUS" in
Playing) ICON="" ;; # nerd-font play glyph
Paused) ICON="" ;; # nerd-font pause glyph
*) ICON="" ;;
esac
# Truncate long titles so the bar doesn't blow out — cut at 30 chars,
# append an ellipsis. This is bash parameter expansion, not a subprocess.
LABEL="${ARTIST} - ${TITLE}"
if [ "${#LABEL}" -gt 32 ]; then
LABEL="${LABEL:0:29}..."
fi
# Escape double quotes so we don't break the JSON if a title contains one.
LABEL_ESC=$(printf '%s' "$LABEL" | sed 's/"/\\"/g')
TOOLTIP_ESC=$(printf '%s — %s\n(%s)' "$ARTIST" "$TITLE" "$PLAYER" | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
CLASS="media-${PSTATUS,,}" # bash ${var,,} lowercases -> "media-playing" / "media-paused"
echo "{\"text\": \"${ICON} ${LABEL_ESC}\", \"tooltip\": \"${TOOLTIP_ESC}\", \"class\": \"${CLASS}\", \"alt\": \"${PSTATUS}\"}"

View File

@@ -1,32 +1,33 @@
/* ============================================================
WAYBAR STYLE — Dark Industrial / Refined Utility
Palette: deep charcoal base, amber accents, cool greys
WAYBAR STYLE — Cream Claude / Warm Minimal
Palette: warm cream base, clay/terracotta accent, soft browns
============================================================ */
/* ── Root Variables ───────────────────────────────────────── */
* {
font-family: "JetBrainsMono Nerd Font Propo";
font-family: "Inter", "SF Pro Display", "Segoe UI", sans-serif;
font-size: 13px;
font-weight: 400;
border: none;
border-radius: 0;
}
/* ── Bar ──────────────────────────────────────────────────── */
window#waybar {
background: rgba(10, 10, 14, 0);
color: #dcdce8;
background: rgba(26, 22, 19, 0.55);
color: #e8ddd0;
}
/* ── Tooltip ──────────────────────────────────────────────── */
tooltip {
background: #0e0e12;
border: 1px solid rgba(255, 180, 60, 0.35);
color: #dcdce8;
background: rgba(30, 25, 21, 0.92);
border: 1px solid rgba(196, 108, 74, 0.4);
color: #e8ddd0;
padding: 6px 10px;
}
tooltip label {
color: #dcdce8;
color: #e8ddd0;
}
/* ── Shared Module Base ───────────────────────────────────── */
@@ -41,53 +42,42 @@ tooltip label {
#custom-power {
padding: 6px 12px;
margin: 5px 0;
color: #dcdce8;
background: rgba(10, 10, 14, 0.3);
color: #e8ddd0;
background: rgba(44, 37, 32, 0.5);
transition: color 0.2s ease, background 0.2s ease;
}
/* ── Separator dots between modules ──────────────────────── */
#cpu,
#memory,
#pulseaudio,
#bluetooth,
#custom-micmute,
#battery {
border-left: 1px solid rgba(255, 255, 255, 0);
}
/* ═══════════════════════════════════════════════════════════
LEFT — System Info: Clock · CPU · Memory
═══════════════════════════════════════════════════════════ */
#clock {
font-family: "JetBrainsMono Nerd Font Propo";
font-weight: 400;
font-weight: 500;
font-size: 12.5px;
color: #f0de9c;
letter-spacing: 0.04em;
color: #e29a6e;
letter-spacing: 0.03em;
padding-left: 0.4em;
border-left: 3px solid rgba(255, 180, 60, 0.3);
border-left: 3px solid rgba(226, 154, 110, 0.5);
margin-left: 8px;
}
#cpu {
color: #b8d8ee;
color: #c9baa8;
}
#cpu:hover {
color: #d8f0ff;
background: rgba(160, 196, 216, 0.14);
color: #f0e6d8;
background: rgba(226, 154, 110, 0.16);
}
#memory {
color: #b0d4be;
color: #c9baa8;
}
#memory:hover {
color: #ceeede;
background: rgba(157, 191, 173, 0.14);
color: #f0e6d8;
background: rgba(180, 156, 120, 0.2);
}
@@ -102,12 +92,11 @@ tooltip label {
}
#workspaces button {
font-family: 'JetBrains Nerd Font Propo';
font-size: 12px;
padding: 2px 10px;
margin: 4px 2px;
color: #6e6e88;
background: rgba(255, 255, 255, 0.05);
color: #8a7a68;
background: rgba(232, 221, 208, 0.08);
border: 1px solid transparent;
border-radius: 3px;
transition: all 0.15s ease;
@@ -115,22 +104,22 @@ tooltip label {
}
#workspaces button:hover {
color: #c0c0d8;
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.15);
color: #e8ddd0;
background: rgba(232, 221, 208, 0.14);
border-color: rgba(232, 221, 208, 0.2);
}
#workspaces button.active {
color: #f0c060;
background: rgba(255, 180, 60, 0.14);
border-color: rgba(255, 180, 60, 0.5);
color: #e29a6e;
background: rgba(226, 154, 110, 0.18);
border-color: rgba(226, 154, 110, 0.55);
font-weight: 600;
}
#workspaces button.urgent {
color: #f08080;
background: rgba(240, 80, 80, 0.15);
border-color: rgba(240, 80, 80, 0.45);
color: #d9695a;
background: rgba(217, 105, 90, 0.18);
border-color: rgba(217, 105, 90, 0.5);
}
@@ -149,61 +138,61 @@ tooltip label {
#tray > .needs-attention {
-gtk-icon-effect: highlight;
background-color: rgba(240, 120, 60, 0.25);
background-color: rgba(196, 108, 74, 0.25);
}
/* ── Audio ────────────────────────────────────────────────── */
#pulseaudio {
color: #c4bce8;
color: #c9a68c;
}
#pulseaudio:hover {
color: #e0d8ff;
background: rgba(176, 168, 216, 0.14);
color: #f0e6d8;
background: rgba(201, 166, 140, 0.16);
}
/* ── Bluetooth ────────────────────────────────────────────── */
#bluetooth {
color: #90c8f0;
color: #9ab4c4;
}
#bluetooth.connected {
color: #70d8ff;
color: #a8c8dc;
}
#bluetooth:hover {
background: rgba(128, 184, 224, 0.14);
background: rgba(154, 180, 196, 0.16);
}
/* ── Microphone Mute ──────────────────────────────────────── */
#custom-micmute {
color: #b0d4be;
color: #c9baa8;
}
#custom-micmute.muted {
color: #585870;
color: #6e6055;
}
#custom-micmute:hover {
background: rgba(157, 191, 173, 0.14);
background: rgba(201, 186, 168, 0.16);
}
/* ── Battery ──────────────────────────────────────────────── */
#battery {
color: #b8dc98;
color: #a8bc90;
}
#battery.charging,
#battery.plugged {
color: #d4f098;
color: #c0d4a0;
}
#battery.warning:not(.charging) {
color: #eecb68;
color: #dcb06a;
}
#battery.critical:not(.charging) {
color: #f07060;
color: #e0796a;
animation: battery-pulse 1.5s ease-in-out infinite;
}
@@ -220,19 +209,19 @@ tooltip label {
}
#battery:hover {
background: rgba(168, 204, 136, 0.14);
background: rgba(168, 188, 144, 0.16);
}
/* ── Power Button ─────────────────────────────────────────── */
#custom-power {
color: #d07070;
color: #e29a6e;
font-size: 14px;
padding: 2px 14px 2px 12px;
margin-right: 8px;
border-right: 3px solid rgba(255, 0, 0, 0.3);
border-right: 3px solid rgba(196, 108, 74, 0.4);
}
#custom-power:hover {
color: #f09090;
background: rgba(200, 60, 60, 0.2);
color: #c0392b;
background: rgba(196, 108, 74, 0.2);
}

View File

@@ -12,7 +12,7 @@
}
{
"label" : "logout",
"action" : "loginctl terminate-user $USER",
"action" : "hyprctl dispatch 'hl.dsp.exit()'",
"text" : "Logout",
"keybind" : "e"
}

View File

@@ -1,8 +1,11 @@
mode=drun
allow_images=true
image_size=32
term=kitty
insensitive=true
show=drun
width=600
height=420
location=center
no_actions=true
prompt=Search
allow_images=true
image_size=28
insensitive=true
hide_scroll=true
no_actions=true
gtk_dark=true

View File

@@ -1,91 +1,44 @@
#!/usr/bin/env bash
# Configuration
WALLPAPER_DIR="$HOME/.wallpapers" # Change this to your wallpaper directory
CACHE_DIR="$HOME/.cache/wallpaper-selector"
THUMBNAIL_WIDTH="250" # Size of thumbnails in pixels (16:9)
THUMBNAIL_HEIGHT="141"
# Create cache directory if it doesn't exist
mkdir -p "$CACHE_DIR"
# wallpaper.sh — pick a wallpaper from ~/.wallpapers via wofi, apply with hyprpaper
set -euo pipefail
DIR="${HOME}/.wallpapers"
CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/wallpaper-thumbs"
[[ -d "$DIR" ]] || { notify-send "wallpaper.sh" "No $DIR"; exit 1; }
mkdir -p "$CACHE"
# Function to generate thumbnail
generate_thumbnail() {
local input="$1"
local output="$2"
magick "$input" -thumbnail "${THUMBNAIL_WIDTH}x${THUMBNAIL_HEIGHT}^" -gravity center -extent "${THUMBNAIL_WIDTH}x${THUMBNAIL_HEIGHT}" "$output"
}
mapfile -t files < <(find -L "$DIR" -maxdepth 1 -type f \
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.webp' \) \
-printf '%f\n' | LC_ALL=C sort)
[[ ${#files[@]} -gt 0 ]] || { notify-send "wallpaper.sh" "No images found"; exit 1; }
# Create shuffle icon thumbnail on the fly
SHUFFLE_ICON="$CACHE_DIR/shuffle_thumbnail.png"
# Create a properly sized shuffle icon thumbnail
# magick -size "${THUMBNAIL_WIDTH}x${THUMBNAIL_HEIGHT}" xc:#1e1e2e \
# "$HOME/Repos/wallpaper-selector/assets/shuffle.png" -resize "120x120" -gravity center -composite \
# "$SHUFFLE_ICON"
magick -size "${THUMBNAIL_WIDTH}x${THUMBNAIL_HEIGHT}" xc:#1e1e2e \
\( "$HOME/Repos/wallpaper-selector/assets/shuffle.png" -resize "80x80" \) \
-gravity center -composite "$SHUFFLE_ICON"
# Generate thumbnails and create menu items
generate_menu() {
# Add random/shuffle option with a name that sorts first (using ! prefix)
echo -en "img:$SHUFFLE_ICON\x00info:!Random Wallpaper\x1fRANDOM\n"
# Then add all wallpapers
for img in "$WALLPAPER_DIR"/*.{jpg,jpeg,png}; do
# Skip if no matches found
[[ -f "$img" ]] || continue
# Generate thumbnail filename
thumbnail="$CACHE_DIR/$(basename "${img%.*}").png"
# Generate thumbnail if it doesn't exist or is older than source
if [[ ! -f "$thumbnail" ]] || [[ "$img" -nt "$thumbnail" ]]; then
generate_thumbnail "$img" "$thumbnail"
fi
# Output menu item (filename and path)
echo -en "img:$thumbnail\x00info:$(basename "$img")\x1f$img\n"
# Build any missing/stale thumbnails, in parallel.
for f in "${files[@]}"; do
src="${DIR}/${f}"
thumb="${CACHE}/${f%.*}.png"
[[ -f "$thumb" && "$thumb" -nt "$src" ]] && continue
magick "$src" -thumbnail 360x360^ -strip "$thumb" &
done
}
wait
# Use wofi to display grid of wallpapers - IMPORTANT: added --sort-order=default
selected=$(generate_menu | wofi --show dmenu \
--cache-file /dev/null \
--define "image-size=${THUMBNAIL_WIDTH}x${THUMBNAIL_HEIGHT}" \
--columns 3 \
--allow-images \
--insensitive \
--sort-order=default \
--prompt "Select Wallpaper" \
--conf ~/.config/wofi/wallpaper.conf \
)
RANDOM_LABEL="🎲 Random"
menu="img::text:${RANDOM_LABEL}\n"
for f in "${files[@]}"; do
menu+="img:${CACHE}/${f%.*}.png:text:${f}\n"
done
# Set wallpaper if one was selected
if [ -n "$selected" ]; then
# Remove the img: prefix to get the cached thumbnail path
thumbnail_path="${selected#img:}"
line=$(echo -en "$menu" | wofi \
--dmenu --show dmenu --allow-images --insensitive \
--define image_size=180 --columns 4 --prompt "Wallpaper" \
--define sort_order=default --cache-file /dev/null \
--style "${HOME}/.config/wofi/wallpaper.css" \
--width 900 --height 620 --define halign=fill --define content_halign=fill)
[[ -n "$line" ]] || exit 0
# Check if random wallpaper was selected
if [[ "$thumbnail_path" == "$SHUFFLE_ICON" ]]; then
# Select a random wallpaper from the directory
original_path=$(find "$WALLPAPER_DIR" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) | shuf -n 1)
if [[ "$line" == *"$RANDOM_LABEL"* ]]; then
WALL="${DIR}/${files[RANDOM % ${#files[@]}]}"
else
# Get the original filename from the thumbnail path
original_filename=$(basename "${thumbnail_path%.*}")
# Find the corresponding original file in the wallpaper directory
original_path=$(find "$WALLPAPER_DIR" -type f -name "${original_filename}.*" | head -n1)
choice="${line##*:text:}"
WALL="${DIR}/${choice}"
fi
# Ensure a valid wallpaper was found before proceeding
if [ -n "$original_path" ]; then
hyprctl hyprpaper wallpaper ",$original_path"
# Save the selection for persistence
echo "$original_path" > "$HOME/.cache/current_wallpaper"
# Optional: Notify user
notify-send "Wallpaper" "Wallpaper has been updated" -i "$original_path"
else
notify-send "Wallpaper Error" "Could not find the original wallpaper file."
fi
fi
hyprctl hyprpaper wallpaper ",${WALL}"

View File

@@ -1,66 +1,70 @@
/* ========================
Wofi Lovely Theme
======================== */
/* ~/.config/wofi/style.css */
@define-color base rgba(26, 22, 19, 0.75);
@define-color mantle rgba(20, 17, 14, 0.7);
@define-color surface rgba(232, 221, 208, 0.1);
@define-color overlay #8a7a68;
@define-color text #e8ddd0;
@define-color subtext #c9baa8;
@define-color accent #e29a6e;
@define-color accent2 #c46c4a;
/* Window styling */
window {
background-color: #1e1e2e; /* Dark blue-ish background */
border-radius: 12px;
padding: 10px;
border: 1px solid #44475a;
background-color: transparent;
font-family: "Inter", "SF Pro Display", "Segoe UI", sans-serif;
font-size: 14px;
}
/* Entry box styling */
entry {
font-family: "JetBrains Mono", monospace;
font-size: 16px;
color: #f8f8f2; /* light text */
#outer-box {
background-color: @base;
border: 1px solid rgba(226, 154, 110, 0.35);
border-radius: 14px;
padding: 12px;
}
#input {
background-color: @mantle;
color: @text;
border: 1px solid rgba(232, 221, 208, 0.12);
border-radius: 10px;
padding: 10px 14px;
margin-bottom: 10px;
caret-color: @accent;
}
#input:focus {
border-color: @accent;
}
#scroll {
margin: 0;
border: none;
}
#inner-box {
background-color: transparent;
}
#entry {
padding: 8px 10px;
border-radius: 8px;
background-color: #2e2e3e; /* darker input box */
border: 1px solid #6272a4;
}
/* Selected suggestion */
row:selected {
background-color: #6272a4;
color: #f8f8f2;
}
/* Suggestions list */
row {
padding: 6px 10px;
border-radius: 6px;
margin: 2px 0;
transition: background 0.2s ease;
color: @subtext;
transition: background-color 120ms ease, color 120ms ease;
}
/* Icon styling */
image {
width: 32px; /* smaller icons */
height: 32px;
margin-right: 10px;
#entry:selected,
#entry:hover {
background-color: @surface;
color: @text;
outline: none;
}
/* Scrollbar styling */
scrollbar {
background-color: #1e1e2e;
width: 6px;
border-radius: 3px;
#entry:selected {
box-shadow: inset 3px 0 0 0 @accent;
}
scrollbar slider {
background-color: #6272a4;
border-radius: 3px;
/* node type `image`, not `img` — this is the one that actually moves the icon */
#entry image {
margin-right: 18px;
-gtk-icon-transform: scale(0.9);
}
/* Hint text */
entry placeholder {
color: #bfbfbf;
#entry #text {
color: inherit;
}
/* For accessibility: highlight keyboard navigation */
row:focus {
outline: 2px solid #ff79c6;
#entry:selected #text {
font-weight: 600;
}
#unselected {
color: @subtext;
}

View File

@@ -1,47 +1,50 @@
/* wallpaper.sh picker — dark glass, terracotta accent */
window {
background-color: #1e1e2e;
border-radius: 8px;
border: 2px solid #313244;
background-color: rgba(26, 22, 19, 0.85);
border: 1px solid rgba(226, 154, 110, 0.35);
border-radius: 16px;
font-family: "Inter", "SF Pro Display", "Segoe UI", sans-serif;
}
#input {
margin: 2px;
padding: 4px;
border-radius: 4px;
border: none;
background-color: #313244;
color: #cdd6f4;
margin: 12px;
padding: 10px 14px;
border: 1px solid rgba(226, 154, 110, 0.25);
border-radius: 10px;
background-color: rgba(20, 17, 14, 0.85);
color: #e8ddd0;
font-size: 15px;
}
#input:focus {
border-color: rgba(226, 154, 110, 0.8);
}
#inner-box {
margin: 0px;
margin: 6px 12px 12px 12px;
background-color: transparent;
}
#outer-box {
margin: 0px;
background-color: transparent;
}
#scroll {
margin: 0px;
}
#text {
margin: 2px;
color: #cdd6f4;
}
#entry {
padding: 2px;
margin: 0px;
border-radius: 4px;
margin: 6px;
padding: 6px;
border: 2px solid transparent;
border-radius: 12px;
background-color: rgba(44, 37, 32, 0.5);
}
#entry:selected {
background-color: #313244;
border-color: #e29a6e;
background-color: rgba(226, 154, 110, 0.15);
}
#img {
margin: 2px;
padding-left: 4px;
border-radius: 4px;
#entry image {
border-radius: 8px;
}
#text {
color: #c9baa8;
margin: 0px 4px;
}
#entry:selected #text {
color: #ffffff;
}

View File

@@ -1,3 +1,10 @@
[user]
email = dylanseandefaoite@gmail.com
name = Dylan De Faoite
[filter "lfs"]
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
required = true
[core]
autocrlf = input

38
.zshrc
View File

@@ -1,24 +1,28 @@
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
# INSTANT PROMPT
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
# Environment for apps
export QT_QPA_PLATFORMTHEME=qt5ct # for Qt5
export QT_QPA_PLATFORMTHEME=qt6ct # for Qt6
# PATH
export PATH="$HOME/.local/bin:$HOME/.opencode/bin:$PATH"
alias dotfiles="git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME"
source ~/powerlevel10k/powerlevel10k.zsh-theme
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
# Path updates
export PATH="$HOME/.local/bin:$PATH"
export PATH="$HOME/.opencode/bin:$PATH"
# Env Variables
# ENVIRONMENT
export EDITOR=nvim
export VISUAL=nvim
export QT_QPA_PLATFORMTHEME=qt6ct # Qt6 apps
# ALIASES
alias dotfiles="git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME"
alias pac="sudo pacman -S"
alias update="sudo pacman -Syu"
# COMPLETION (before plugins that hook into it)
autoload -Uz compinit && compinit
# PLUGINS
source ~/powerlevel10k/powerlevel10k.zsh-theme
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh # keep LAST
# THEME CONFIG (after theme is loaded)
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

235
bootstrap.sh Executable file → Normal file
View File

@@ -1,8 +1,235 @@
#!/usr/bin/env bash
# =============================================================================
# birch-dots bootstrap.sh
# Goes from a bare Arch install to a fully configured Hyprland desktop.
# Run as your normal user (with sudo access), NOT as root.
# =============================================================================
## SDDM Confs
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PKG_DIR="$REPO_ROOT/packages"
# Colours
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
log() { echo -e "${GREEN}==>${NC} $*"; }
warn() { echo -e "${YELLOW}[!]${NC} $*"; }
die() { echo -e "${RED}[✗]${NC} $*"; exit 1; }
# Guard: must not run as root
[[ "$EUID" -ne 0 ]] || die "Run as your normal user, not root."
# =============================================================================
# 1. SYSTEM SETUP
# =============================================================================
log "Setting locale (en_IE.UTF-8)"
sudo sed -i 's/^#en_IE.UTF-8 UTF-8/en_IE.UTF-8 UTF-8/' /etc/locale.gen
sudo locale-gen
echo "LANG=en_IE.UTF-8" | sudo tee /etc/locale.conf > /dev/null
log "Setting keymap (uk)"
echo "KEYMAP=uk" | sudo tee /etc/vconsole.conf > /dev/null
log "Setting timezone (Europe/Dublin)"
sudo ln -sf /usr/share/zoneinfo/Europe/Dublin /etc/localtime
sudo hwclock --systohc
log "Setting hostname"
read -rp " Enter hostname [dylanvm]: " HOSTNAME
HOSTNAME="${HOSTNAME:-dylanvm}"
echo "$HOSTNAME" | sudo tee /etc/hostname > /dev/null
sudo tee /etc/hosts > /dev/null <<EOF
127.0.0.1 localhost
::1 localhost
127.0.1.1 $HOSTNAME.localdomain $HOSTNAME
EOF
# =============================================================================
# 2. NETWORKING
# =============================================================================
log "Enabling NetworkManager"
sudo systemctl enable --now NetworkManager
# =============================================================================
# 3. PACMAN SETUP
# =============================================================================
log "Configuring pacman (colour + parallel downloads)"
sudo sed -i 's/^#Color/Color/' /etc/pacman.conf
sudo sed -i 's/^#ParallelDownloads.*/ParallelDownloads = 5/' /etc/pacman.conf
log "Enabling multilib repo"
sudo sed -i '/\[multilib\]/,/Include/s/^#//' /etc/pacman.conf
log "Updating mirrors and syncing package database"
sudo pacman -Sy --noconfirm reflector 2>/dev/null || true
sudo reflector --country Ireland,Germany --age 12 --protocol https \
--sort rate --save /etc/pacman.d/mirrorlist 2>/dev/null \
|| warn "reflector failed, using existing mirrorlist"
sudo pacman -Syyu --noconfirm
# =============================================================================
# 4. PACMAN PACKAGES
# =============================================================================
log "Installing pacman packages"
for file in "$PKG_DIR"/pacman/*.txt; do
log " → $(basename "$file")"
while IFS= read -r pkg; do
[[ -z "$pkg" || "$pkg" == \#* ]] && continue
sudo pacman -S --needed --noconfirm "$pkg" \
|| warn " Skipping pacman package not found: $pkg"
done < "$file"
done
# =============================================================================
# 5. ZSH AS DEFAULT SHELL
# =============================================================================
log "Setting zsh as default shell"
chsh -s /bin/zsh
# =============================================================================
# 6. YAY (AUR HELPER)
# =============================================================================
log "Installing yay"
if ! command -v yay &>/dev/null; then
tmpdir=$(mktemp -d)
git clone https://aur.archlinux.org/yay.git "$tmpdir/yay"
pushd "$tmpdir/yay" > /dev/null
makepkg -si --noconfirm
popd > /dev/null
rm -rf "$tmpdir"
else
log " yay already installed, skipping"
fi
# =============================================================================
# 7. AUR PACKAGES
# =============================================================================
log "Installing AUR packages"
for file in "$PKG_DIR"/aur/*.txt; do
log " → $(basename "$file")"
while IFS= read -r pkg; do
[[ -z "$pkg" || "$pkg" == \#* ]] && continue
yay -S --needed --noconfirm "$pkg" \
|| warn " Skipping AUR package not found: $pkg"
done < "$file"
done
# =============================================================================
# 8. POWERLEVEL10K
# =============================================================================
log "Installing Powerlevel10k"
if [[ ! -d "$HOME/powerlevel10k" ]]; then
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
"$HOME/powerlevel10k"
else
log " powerlevel10k already present, skipping"
fi
# =============================================================================
# 9. DOTFILES
# =============================================================================
log "Deploying dotfiles from repo into HOME"
# Copy everything except git internals, system/, packages/, bootstrap.sh
rsync -av --exclude='.git' \
--exclude='system/' \
--exclude='packages/' \
--exclude='bootstrap.sh' \
--exclude='README.md' \
--exclude='dotfiles_log.txt' \
"$REPO_ROOT/" "$HOME/"
# Make scripts executable
find "$HOME/.config" -name "*.sh" -exec chmod +x {} \;
# =============================================================================
# 10. SYSTEM CONFIG FILES (SDDM etc.)
# =============================================================================
log "Applying SDDM configuration"
sudo mkdir -p /etc/sddm.conf.d
sudo cp -a system/sddm.conf.d /etc/
sudo cp -a system/sddm /etc/
sudo cp -a "$REPO_ROOT/system/sddm.conf.d/." /etc/sddm.conf.d/
sudo cp -a "$REPO_ROOT/system/sddm/." /etc/sddm/
sudo chown -R root:root /etc/sddm.conf.d /etc/sddm
sudo chmod -R 644 /etc/sddm.conf.d /etc/sddm
sudo chmod 644 /etc/sddm.conf.d/*.conf
sudo chmod +x /etc/sddm/scripts/Xsetup 2>/dev/null || true
log "Enabling SDDM"
sudo systemctl enable sddm
# =============================================================================
# 11. SERVICES
# =============================================================================
log "Enabling system services"
sudo systemctl enable bluetooth
sudo systemctl enable docker
sudo usermod -aG docker "$USER"
sudo systemctl enable earlyoom 2>/dev/null || true
# =============================================================================
# 12. MONITOR CONFIG (machine-specific)
# =============================================================================
MONITORS_CONF="$HOME/.config/hypr/monitors.conf"
if [[ ! -f "$MONITORS_CONF" ]]; then
warn "No monitors.conf found — creating a safe default (single monitor)"
cat > "$MONITORS_CONF" <<'EOF'
# Auto-generated default — replace with your actual monitor config.
# See: https://wiki.hyprland.org/Configuring/Monitors/
monitor = , preferred, auto, 1
EOF
warn "Edit ~/.config/hypr/monitors.conf before starting Hyprland."
else
log "monitors.conf already exists, skipping"
fi
# =============================================================================
# 13. VSCODE EXTENSIONS
# =============================================================================
EXTENSIONS_FILE="$HOME/.config/Code/User/extensions.txt"
if command -v code &>/dev/null && [[ -f "$EXTENSIONS_FILE" ]]; then
log "Installing VS Code extensions"
while IFS= read -r ext; do
code --install-extension "$ext" --force 2>/dev/null || true
done < "$EXTENSIONS_FILE"
else
warn "VS Code not found or extensions.txt missing — skipping"
fi
# =============================================================================
# 14. WALLPAPER DIRECTORY
# =============================================================================
log "Creating wallpaper directory"
mkdir -p "$HOME/.wallpapers"
warn "Add wallpapers to ~/.wallpapers/ for hyprpaper + wofi selector to work."
# =============================================================================
# DONE
# =============================================================================
echo ""
echo -e "${GREEN}============================================${NC}"
echo -e "${GREEN} Bootstrap complete!${NC}"
echo -e "${GREEN}============================================${NC}"
echo ""
echo " Next steps:"
echo " 1. Edit ~/.config/hypr/monitors.conf for your display layout"
echo " 2. Add wallpapers to ~/.wallpapers/"
echo " 3. Run p10k configure after first zsh launch"
echo " 4. Reboot"
echo ""

21
common-issues.md Normal file
View File

@@ -0,0 +1,21 @@
# Creating a new user
1) Login to root account
2) Type `useradd -m -G wheel -s /bin/bash <NAME>`
3) Install `sudo` and `nvim`
4) Type `EDITOR=nvim visudo`
5) Uncomment the line `# %wheel ALL=(ALL:ALL) ALL`
- Towards the end of the file
# Broken Internet Access on VM
- This works for a VM with `enp1s0` link.
```
ip addr add 192.168.122.100/24 dev enp1s0
ip route add default via 192.168.122.1
echo "nameserver 8.8.8.8" > /etc/resolv.conf
ping 8.8.8.8
```
- Then install dhcpcd
```
pacman -S dhcpcd
systemctl enable --now dhcpcd@enp1s0
```

View File

@@ -1,5 +1,3 @@
brave-bin
play-timer
spotify
zoom
qdirstat

View File

@@ -20,3 +20,4 @@ unzip
zip
zsh
zsh-syntax-highlighting
zsh-autosuggestions

View File

@@ -18,7 +18,6 @@ pipewire-jack
pipewire-pulse
wireplumber
xdg-desktop-portal-hyprland
xdg-desktop-portal-wlr
qt5ct
qt6ct
qt6-wayland
@@ -42,3 +41,4 @@ imagemagick
webkit2gtk
xorg-xrandr
earlyoom
yad

View File

@@ -1,4 +1,5 @@
git
git-lfs
neovim
tmux
fzf
@@ -18,12 +19,12 @@ jdk21-openjdk
maven
openmpi
docker
docker-compose-plugin
docker-compose
postgresql
postgresql-libs
libdwarf
nmap
ncdu
ufw
sshfs
nvidia-container-toolkit
rsync

View File

@@ -5,3 +5,4 @@ obs-studio
gpu-screen-recorder
gpu-screen-recorder-ui
wf-recorder
yt-dlp