chore: initial commit of all dotfiles, configs, and setup scripts

Includes modular setup, device profile support, and documentation.

🤖 Generated with [opencode](https://opencode.ai)

Co-Authored-By: opencode <noreply@opencode.ai>
This commit is contained in:
Martin Büchler 2025-08-07 23:05:28 +02:00
parent 39687d0769
commit 7d13e6ff1c
43 changed files with 1292 additions and 0 deletions

View File

@ -0,0 +1,6 @@
[font]
normal = { family = "JetBrainsMono", style = "Regular" }
size = 12.0
[window]
opacity = 0.95

3
.config/hypr/README.md Normal file
View File

@ -0,0 +1,3 @@
# Modular Hyprland Config
This directory contains a modular Hyprland configuration. Edit files in `includes/` to customize your setup.

View File

@ -0,0 +1,14 @@
general {
lock_cmd = pidof hyprlock || hyprlock
before_sleep_cmd = loginctl lock-session
after_sleep_cmd = hyprctl dispatch dpms on
}
listener {
timeout = 300
on-timeout = pidof hyprlock || hyprlock
}
listener {
timeout = 600
on-timeout = systemctl suspend
}

View File

@ -0,0 +1,12 @@
# Main Hyprland config (modular)
# Source modular configs
source = ~/.config/hypr/includes/programs.conf
source = ~/.config/hypr/includes/monitors.conf
source = ~/.config/hypr/includes/input.conf
source = ~/.config/hypr/includes/env.conf
source = ~/.config/hypr/includes/autostart.conf
source = ~/.config/hypr/includes/binds.conf
source = ~/.config/hypr/includes/appearance.conf
# You can add more includes as needed

View File

@ -0,0 +1,68 @@
general {
disable_loading_bar = true
grace = 300
hide_cursor = true
no_fade_in = false
}
background {
monitor =
path = screenshot
blur_passes = 3
blur_size = 8
}
input-field {
monitor =
size = 200, 50
position = 0, -80
dots_center = true
fade_on_empty = false
font_color = rgb(202, 211, 245)
inner_color = rgb(91, 96, 120)
outer_color = rgb(24, 25, 38)
outline_thickness = 5
placeholder_text = <i>Input Password...</i>
shadow_passes = 2
}
label {
monitor =
text = cmd[update:1000] echo "$TIME"
color = rgb(200, 200, 200)
font_size = 55
font_family = Noto Sans
position = -40, 40
halign = right
valign = bottom
shadow_passes = 5
shadow_size = 10
}
label {
monitor =
text = $USER
color = rgb(200, 200, 200)
font_size = 20
font_family = Noto Sans
position = -100, 160
halign = right
valign = bottom
shadow_passes = 5
shadow_size = 10
}
image {
monitor =
path = ~/.face
size = 280
rounding = -1
border_size = 4
border_color = rgb(221, 221, 221)
rotate = 0
reload_time = -1
reload_cmd =
position = 0, 200
halign = center
valign = center
}

View File

@ -0,0 +1,118 @@
#####################
### LOOK AND FEEL ###
#####################
# Refer to https://wiki.hyprland.org/Configuring/Variables/
# https://wiki.hyprland.org/Configuring/Variables/#general
env = XCURSOR_SIZE,36
env = HYPRCURSOR_SIZE,36
env = HYPRCURSOR_THEME,rose-pine-hyprcursor
env = QT_QPA_PLATFORMTHEME,qt6ct # for Qt apps
exec = gsettings set org.gnome.desktop.interface gtk-theme "Breeze-Dark" # for GTK3 apps
exec = gsettings set org.gnome.desktop.interface color-scheme "prefer-dark" # for GTK4 apps
general {
gaps_in = 2
gaps_out = 5
border_size = 2
# https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.inactive_border = rgba(595959aa)
# Set to true enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
allow_tearing = false
layout = dwindle
}
# https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration {
rounding = 5
rounding_power = 2
# Change transparency of focused and unfocused windows
active_opacity = 1.0
inactive_opacity = 1.0
shadow {
enabled = true
range = 4
render_power = 3
color = rgba(1a1a1aee)
}
# https://wiki.hyprland.org/Configuring/Variables/#blur
blur {
enabled = true
size = 3
passes = 1
vibrancy = 0.1696
}
}
# https://wiki.hyprland.org/Configuring/Variables/#animations
animations {
enabled = yes, please :)
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
bezier = easeOutQuint,0.23,1,0.32,1
bezier = easeInOutCubic,0.65,0.05,0.36,1
bezier = linear,0,0,1,1
bezier = almostLinear,0.5,0.5,0.75,1.0
bezier = quick,0.15,0,0.1,1
animation = global, 1, 10, default
animation = border, 1, 5.39, easeOutQuint
animation = windows, 1, 4.79, easeOutQuint
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
animation = windowsOut, 1, 1.49, linear, popin 87%
animation = fadeIn, 1, 1.73, almostLinear
animation = fadeOut, 1, 1.46, almostLinear
animation = fade, 1, 3.03, quick
animation = layers, 1, 3.81, easeOutQuint
animation = layersIn, 1, 4, easeOutQuint, fade
animation = layersOut, 1, 1.5, linear, fade
animation = fadeLayersIn, 1, 1.79, almostLinear
animation = fadeLayersOut, 1, 1.39, almostLinear
animation = workspaces, 1, 1.94, almostLinear, fade
animation = workspacesIn, 1, 1.21, almostLinear, fade
animation = workspacesOut, 1, 1.94, almostLinear, fade
}
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
# "Smart gaps" / "No gaps when only"
# uncomment all if you wish to use that.
workspace = w[tv1], gapsout:0, gapsin:0
workspace = f[1], gapsout:0, gapsin:0
windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
dwindle {
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = true # You probably want this
}
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
master {
new_status = master
}
# https://wiki.hyprland.org/Configuring/Variables/#misc
misc {
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
}

View File

@ -0,0 +1,12 @@
# Autostart applications
exec-once = waybar &
exec-once = mako &
exec-once = wl-clipboard-history -t &
exec-once = wlogout &
exec-once = rofi-wayland &
# exec-once = hyprpaper &
exec-once = hypridle &
# Start Brave browser on Hyprland startup
exec-once = brave &

View File

@ -0,0 +1,84 @@
###################
### KEYBINDINGS ###
###################
# See https://wiki.hyprland.org/Configuring/Keywords/
$mainMod = SUPER # Sets "Windows" key as main modifier
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
bind = $mainMod, Q, exec, $terminal
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, $fileManager
bind = $mainMod CTRL, B, exec, google-chrome-stable
bind = $mainMod, B, exec, firefox
bind = $mainMod SHIFT, B, exec, brave
bind = $mainMod, V, togglefloating,
bind = $mainMod, R, exec, $menu
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle
bind = $mainMod SHIFT, P, exec, ~/.config/hypr/reway.sh
bind = $mainMod, L, exec, hyprlock
# 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
bind = $mainMod SHIFT, left, swapwindow, l
bind = $mainMod SHIFT, right, swapwindow, r
bind = $mainMod SHIFT, up, swapwindow, u
bind = $mainMod SHIFT, down, swapwindow, 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
# Example special workspace (scratchpad)
bind = $mainMod, S, togglespecialworkspace, magic
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
# 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
# Laptop multimedia keys for volume and LCD brightness
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+
bindel = ,XF86AudioRaiseVolume, exec, ~/.local/bin/wp-vol
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%-
bindel = ,XF86AudioLowerVolume, exec, ~/.local/bin/wp-vol
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
# Requires playerctl
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previous

View File

@ -0,0 +1,3 @@
# Environment variables
env = XCURSOR_SIZE,24
env = QT_QPA_PLATFORM,wayland

View File

View File

@ -0,0 +1,21 @@
# Input configuration (desktop)
input {
kb_layout = de
kb_variant = nodeadkeys
kb_model =
kb_options = caps:escape
kb_rules =
numlock_by_default = true
follow_mouse = 1
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
}
# Gestures configuration
gestures {
workspace_swipe = true
workspace_swipe_fingers = 4
workspace_swipe_distance = 300
workspace_swipe_invert = false
}

View File

@ -0,0 +1,28 @@
# Input configuration (laptop)
input {
kb_layout = de
kb_variant = nodeadkeys
kb_model =
kb_options = caps:escape
kb_rules =
numlock_by_default = true
follow_mouse = 1
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
touchpad {
natural_scroll = yes
tap-to-click = yes
disable_while_typing = yes
clickfinger_behavior = yes
}
}
# Gestures configuration
gestures {
workspace_swipe = true
workspace_swipe_fingers = 4
workspace_swipe_distance = 300
workspace_swipe_invert = false
}

View File

@ -0,0 +1,28 @@
# Input configuration
input {
kb_layout = de
kb_variant = nodeadkeys
kb_model =
kb_options = caps:escape
kb_rules =
numlock_by_default = true
follow_mouse = 1
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
touchpad {
natural_scroll = yes
tap-to-click = yes
disable_while_typing = yes
clickfinger_behavior = yes
}
}
# Gestures configuration
gestures {
workspace_swipe = true
workspace_swipe_fingers = 4
workspace_swipe_distance = 300
workspace_swipe_invert = false
}

View File

@ -0,0 +1,13 @@
# Monitor configuration (desktop)
monitor=DP-1,preferred,auto,1
# Workspace assignments
workspace=1,monitor:DP-1
workspace=2,monitor:DP-1
workspace=3,monitor:DP-1
workspace=4,monitor:DP-1
workspace=5,monitor:DP-1
workspace=6,monitor:DP-1
workspace=7,monitor:DP-1
workspace=8,monitor:DP-1
workspace=9,monitor:DP-1

View File

@ -0,0 +1,15 @@
# Monitor configuration (laptop)
monitor=eDP-1,preferred,auto,1
monitor=DP-1,preferred,auto,1
# Workspace assignments
workspace=10,monitor:eDP-1
workspace=1,monitor:DP-1
workspace=2,monitor:DP-1
workspace=3,monitor:DP-1
workspace=4,monitor:DP-1
workspace=5,monitor:DP-1
workspace=6,monitor:DP-1
workspace=7,monitor:DP-1
workspace=8,monitor:DP-1
workspace=9,monitor:DP-1

View File

@ -0,0 +1,16 @@
# Monitor configuration
# Assign workspace 1 to laptop (eDP-1), others to external (DP-1)
monitor=eDP-1,preferred,auto,1
monitor=DP-1,preferred,auto,1
# Workspace assignments
workspace=10,monitor:eDP-1
workspace=1,monitor:DP-1
workspace=2,monitor:DP-1
workspace=3,monitor:DP-1
workspace=4,monitor:DP-1
workspace=5,monitor:DP-1
workspace=6,monitor:DP-1
workspace=7,monitor:DP-1
workspace=8,monitor:DP-1
workspace=9,monitor:DP-1

View File

@ -0,0 +1,7 @@
# Set programs that you use
$terminal = alacritty
$fileManager = dolphin
$menu = rofi -show combi
# Always move Brave browser to workspace 10
windowrulev2 = workspace 10, class:^(Brave-browser)$

19
.config/mako/config Normal file
View File

@ -0,0 +1,19 @@
font=JetBrainsMono 12
background-color=#1e1e2e
text-color=#cdd6f4
border-color=#89b4fa
border-size=2
# Default: notifications at the top right
anchor=top-right
margin=20,20,0,0
# Default notification timeout (ms)
default-timeout=3000
# Shorter timeout and bottom center for volume notifications
[app-name=Volume]
anchor=bottom-center
margin=0,0,40,0
default-timeout=1200

7
.config/rofi/config.rasi Normal file
View File

@ -0,0 +1,7 @@
configuration {
font: "JetBrainsMono 12";
location: 0;
width: 30;
lines: 10;
columns: 1;
}

61
.config/tmux/tmux.conf Normal file
View File

@ -0,0 +1,61 @@
# Set prefix to Ctrl-a
set -g prefix C-a
unbind C-b
bind C-a send-prefix
# Enable mouse support
set -g mouse on
# Set 256 color mode
set -g default-terminal "tmux-256color"
set-option -ga terminal-overrides ",*:Tc"
# Vi mode for copy mode
setw -g mode-keys vi
# Split panes
bind | split-window -h
bind - split-window -v
# Reload config
bind r source-file ~/.config/tmux/tmux.conf \; display-message "Config reloaded!"
# --- Modern and simple status bar ---
set -g status-bg colour236
set -g status-fg colour250
set -g status-style "bg=colour236,fg=colour250"
set -g status-left-length 40
set -g status-right-length 100
set -g status-left '#[fg=colour33,bg=colour236,bold] #S #[fg=colour250,bg=colour236,nobold]|'
set -g status-right '#[fg=colour250,bg=colour236,nobold]| #[fg=colour33,bg=colour236]#(date +"%a %d %b %Y") %H:%M #[fg=colour250,bg=colour236,nobold]| #[fg=colour33]#(whoami)@#H'
# Clean window titles
setw -g window-status-format ' #[fg=colour250,bg=colour236]#I:#W#{?window_flags,#[fg=colour208]#{window_flags},} '
setw -g window-status-current-format ' #[fg=colour234,bg=colour33]#I:#W#{?window_flags,#[fg=colour208]#{window_flags},} '
setw -g window-status-separator ''
setw -g window-status-style "bg=colour236,fg=colour250"
setw -g window-status-current-style "bg=colour33,fg=colour234"
# Pane border
set -g pane-border-style fg=colour238
set -g pane-active-border-style fg=colour39
# Message styling
set -g message-style bg=colour234,fg=colour39
set -g message-command-style bg=colour234,fg=colour208
# Command prompt styling
# Bell
set -g visual-bell on
set -g bell-action any
# Allow faster command sequences
set -s escape-time 0
# Clipboard integration (requires xclip or wl-clipboard)
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -in"
# Start window numbering at 1
set -g base-index 1
setw -g pane-base-index 1

82
.config/waybar/config Normal file
View File

@ -0,0 +1,82 @@
{
"layer": "top",
"position": "top",
"modules-left": ["hyprland/workspaces"],
"modules-center": ["clock"],
"modules-right": ["idle_inhibitor", "backlight", "cpu", "memory", "disk", "temperature", "pulseaudio", "network", "battery", "tray"],
"hyprland/workspaces": {
"format": "{icon}",
"on-click": "activate",
"on-scroll-up": "hyprctl dispatch workspace e-1",
"on-scroll-down": "hyprctl dispatch workspace e+1",
"all-outputs": true,
"persistent-workspaces": {
"*": [1,2,3,4,5,6,7,8,9]
}
},
"clock": {
"format": "{:%a %d.%m %H:%M}",
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
"format-alt": "{:%Y-%m-%d}"
},
"cpu": {
"format": " {usage}%"
},
"memory": {
"format": " {used}G/{total}G"
},
"temperature": {
"critical-threshold": 80,
"format": " {temperatureC}°C"
},
"backlight": {
"device": "intel_backlight",
"format": " {percent}%"
},
"disk": {
"format": " {free} free",
"path": "/"
},
"idle_inhibitor": {
"format": " {status}",
"format-alt": " {status}"
},
"network": {
"format-wifi": "󰖩 {essid} ({signalStrength}%)",
"format-ethernet": "󰈀 {ipaddr}/{cidr}",
"format-linked": "󰈂 {ifname} (No IP)",
"format-disconnected": "󰖪 Disconnected",
"format-alt": "{ifname}: {ipaddr}/{cidr}",
"tooltip-format": "{ifname} via {gwaddr}",
"tooltip-format-wifi": "󰖩 {essid} ({signalStrength}%)\n{ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
"tooltip-format-ethernet": "󰈀 {ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
"on-click": "nm-connection-editor"
},
"pulseaudio": {
"format": "{icon} {volume}%",
"format-muted": "󰝟 Muted",
"format-icons": {
"headphone": "󰋋",
"hands-free": "󱡒",
"headset": "󰋎",
"phone": "󰏲",
"portable": "󰦧",
"car": "󰄋",
"default": ["󰕿", "󰖀", "󰕾"]
},
"on-click": "pavucontrol"
},
"battery": {
"states": {
"warning": 30,
"critical": 15
},
"format": "{icon} {capacity}%",
"format-charging": "󰂄 {capacity}% ({time})",
"format-plugged": "󰂄 {capacity}%",
"format-alt": "{icon} {capacity}% • {power:.1f}W • {time}",
"format-time": "{H}h {M}m",
"tooltip-format": "{capacity}% • {power:.1f}W\n{timeTo}",
"format-icons": ["󰂎", "󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹"]
}
}

View File

@ -0,0 +1,63 @@
{
"layer": "top",
"position": "top",
"modules-left": ["hyprland/workspaces"],
"modules-center": ["clock"],
"modules-right": ["idle_inhibitor", "cpu", "memory", "disk", "temperature", "pulseaudio", "network", "tray"],
"hyprland/workspaces": {
"format": "{icon}",
"on-click": "activate",
"on-scroll-up": "hyprctl dispatch workspace e-1",
"on-scroll-down": "hyprctl dispatch workspace e+1",
"all-outputs": true,
"persistent-workspaces": {
"*": [1,2,3,4,5,6,7,8,9]
}
},
"clock": {
"format": "{:%a %d.%m %H:%M}",
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
"format-alt": "{:%Y-%m-%d}"
},
"cpu": {
"format": " {usage}%"
},
"memory": {
"format": " {used}G/{total}G"
},
"temperature": {
"critical-threshold": 80,
"format": " {temperatureC}°C"
},
"disk": {
"format": " {free} free",
"path": "/"
},
"idle_inhibitor": {
"format": " {status}",
"format-alt": " {status}"
},
"network": {
"format-ethernet": "󰈀 {ipaddr}/{cidr}",
"format-linked": "󰈂 {ifname} (No IP)",
"format-disconnected": "󰖪 Disconnected",
"format-alt": "{ifname}: {ipaddr}/{cidr}",
"tooltip-format": "{ifname} via {gwaddr}",
"tooltip-format-ethernet": "󰈀 {ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
"on-click": "nm-connection-editor"
},
"pulseaudio": {
"format": "{icon} {volume}%",
"format-muted": "󰝟 Muted",
"format-icons": {
"headphone": "󰋋",
"hands-free": "󱡒",
"headset": "󰋎",
"phone": "󰏲",
"portable": "󰦧",
"car": "󰄋",
"default": ["󰕿", "󰖀", "󰕾"]
},
"on-click": "pavucontrol"
}
}

View File

@ -0,0 +1,82 @@
{
"layer": "top",
"position": "top",
"modules-left": ["hyprland/workspaces"],
"modules-center": ["clock"],
"modules-right": ["idle_inhibitor", "backlight", "cpu", "memory", "disk", "temperature", "pulseaudio", "network", "battery", "tray"],
"hyprland/workspaces": {
"format": "{icon}",
"on-click": "activate",
"on-scroll-up": "hyprctl dispatch workspace e-1",
"on-scroll-down": "hyprctl dispatch workspace e+1",
"all-outputs": true,
"persistent-workspaces": {
"*": [1,2,3,4,5,6,7,8,9]
}
},
"clock": {
"format": "{:%a %d.%m %H:%M}",
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
"format-alt": "{:%Y-%m-%d}"
},
"cpu": {
"format": " {usage}%"
},
"memory": {
"format": " {used}G/{total}G"
},
"temperature": {
"critical-threshold": 80,
"format": " {temperatureC}°C"
},
"backlight": {
"device": "intel_backlight",
"format": " {percent}%"
},
"disk": {
"format": " {free} free",
"path": "/"
},
"idle_inhibitor": {
"format": " {status}",
"format-alt": " {status}"
},
"network": {
"format-wifi": "󰖩 {essid} ({signalStrength}%)",
"format-ethernet": "󰈀 {ipaddr}/{cidr}",
"format-linked": "󰈂 {ifname} (No IP)",
"format-disconnected": "󰖪 Disconnected",
"format-alt": "{ifname}: {ipaddr}/{cidr}",
"tooltip-format": "{ifname} via {gwaddr}",
"tooltip-format-wifi": "󰖩 {essid} ({signalStrength}%)\n{ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
"tooltip-format-ethernet": "󰈀 {ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
"on-click": "nm-connection-editor"
},
"pulseaudio": {
"format": "{icon} {volume}%",
"format-muted": "󰝟 Muted",
"format-icons": {
"headphone": "󰋋",
"hands-free": "󱡒",
"headset": "󰋎",
"phone": "󰏲",
"portable": "󰦧",
"car": "󰄋",
"default": ["󰕿", "󰖀", "󰕾"]
},
"on-click": "pavucontrol"
},
"battery": {
"states": {
"warning": 30,
"critical": 15
},
"format": "{icon} {capacity}%",
"format-charging": "󰂄 {capacity}% ({time})",
"format-plugged": "󰂄 {capacity}%",
"format-alt": "{icon} {capacity}% • {power:.1f}W • {time}",
"format-time": "{H}h {M}m",
"tooltip-format": "{capacity}% • {power:.1f}W\n{timeTo}",
"format-icons": ["󰂎", "󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹"]
}
}

48
.config/waybar/style.css Normal file
View File

@ -0,0 +1,48 @@
* {
font-family: JetBrainsMono, monospace;
font-size: 13px;
border: none;
box-shadow: none;
min-height: 0;
}
window#waybar {
background: rgba(30, 30, 46, 0.95);
border-radius: 10px;
color: #cdd6f4;
border: 1px solid #181825;
margin: 6px 6px 0 6px;
}
#workspaces button {
background: transparent;
color: #a6adc8;
border-radius: 6px;
margin: 0 2px;
padding: 0 8px;
transition: background 0.2s, color 0.2s;
}
#workspaces button.active {
background: #89b4fa;
color: #1e1e2e;
}
#workspaces button.urgent {
background: #f38ba8;
color: #1e1e2e;
}
#clock, #cpu, #memory, #temperature, #pulseaudio, #network, #battery, #tray, #backlight, #disk, #idle_inhibitor {
padding: 0 10px;
margin: 0 2px;
border-radius: 6px;
background: rgba(49, 50, 68, 0.7);
}
#battery.charging {
color: #a6e3a1;
}
#battery.critical {
color: #f38ba8;
}
#pulseaudio.muted {
color: #f9e2af;
}

4
.config/wlogout/layout Normal file
View File

@ -0,0 +1,4 @@
{
"label": "Logout",
"command": "loginctl terminate-user $USER"
}

46
.github/copilot-instructions.md vendored Normal file
View File

@ -0,0 +1,46 @@
# Copilot Instructions for This Dotfiles Project
## Project Overview
- This is a modular dotfiles and desktop setup for Arch Linux, focused on Wayland/Hyprland workflows.
- All package management is done with `paru` (AUR helper). Do not use `pacman` or other helpers.
- Dotfiles and app configs are version-controlled in the repo root and `.config/` directory, then symlinked to `$HOME` and `$HOME/.config`.
- The setup is fully modular: each major component (packages, symlinks, shell, Neovim, Hyprland, sound, etc.) is handled by its own script in `modules/`.
## Architecture & Workflow
- The main entrypoint is `setup.sh`, which finds and runs all numbered scripts in `modules/` in sorted order.
- Each module script is responsible for a single concern (e.g., `01-packages.sh` for package install, `05-hyprland.sh` for Hyprland/Wayland packages, etc.).
- The symlinking logic (`02-symlinks.sh`) links all dotfiles (including `.config/`) from the repo to the home directory, so configs are always up to date and versioned.
- App configs (Hyprland, Waybar, etc.) are stored in `.config/` and should be modular and extensible (e.g., Hyprland uses `includes/` for config fragments).
## Key Conventions
- Always add new packages to the appropriate module script (e.g., Hyprland-related to `05-hyprland.sh`, sound to `06-sound.sh`).
- To add new dotfiles, place them in the repo root (for files like `.zshrc`) or in `.config/` for app configs.
- To add new setup logic, create a new numbered module in `modules/` (e.g., `07-myfeature.sh`).
- All scripts must be idempotent and safe to re-run.
- Use only `paru` for package installation.
## Examples
- To add a new app config (e.g., for `kitty`):
1. Place config files in `.config/kitty/` in the repo.
2. The symlink module will link them to `$HOME/.config/kitty` on setup.
- To add a new package:
1. Edit the appropriate `modules/XX-*.sh` script and add the package to the array.
2. Re-run `setup.sh`.
- To add a new setup step:
1. Create `modules/07-myfeature.sh` and make it executable.
2. It will be picked up automatically by `setup.sh`.
## Integration Points
- Hyprland, Waybar, Rofi, Mako, Alacritty, wlogout, and sound are all integrated and configured via `.config/`.
- Neovim is set up with AstroNvim by default.
- Sound is managed with PipeWire, WirePlumber, and related tools.
## Notable Patterns
- All configuration is declarative and modular. Avoid hardcoding paths; use `$HOME` and relative repo paths.
- Avoid duplicating logic between modules; each should have a single responsibility.
## See Also
- `README.md` for user-facing setup and customization instructions.
- `modules/` for all setup logic.
- `.config/` for all app configs.

11
.local/bin/wp-vol Normal file
View File

@ -0,0 +1,11 @@
#!/bin/bash
# Show current volume in a Mako notification using wpctl
# Get current volume as a percentage
VOLUME=$(wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{printf "%d", $2 * 100}')
# Get mute status
MUTED=$(wpctl get-volume @DEFAULT_AUDIO_SINK@ | grep -q MUTED && echo " (muted)" || echo "")
# Show notification
notify-send -a Volume -h string:x-canonical-private-synchronous:volume -u low "Volume: $VOLUME%$MUTED"

12
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Run dotfiles setup script",
"type": "shell",
"command": "chmod +x ./setup.sh && ./setup.sh",
"problemMatcher": [],
"group": "build"
}
]
}

88
.zshrc Normal file
View File

@ -0,0 +1,88 @@
# =====================
# Environment settings
# =====================
# Do Not Track for CLI tools
export DO_NOT_TRACK=1
# Preferred editor
export EDITOR='nvim'
# =====================
# Prompt and UI
# =====================
# Starship prompt (modern, fast, customizable)
eval "$(starship init zsh)"
# =====================
# fzf integration
# =====================
# fzf key bindings and completion
if [ -f /usr/share/fzf/key-bindings.zsh ]; then
source /usr/share/fzf/key-bindings.zsh
fi
if [ -f /usr/share/fzf/completion.zsh ]; then
source /usr/share/fzf/completion.zsh
fi
# =====================
# Aliases
# =====================
# Modern replacements for coreutils
alias cat="bat"
alias ls="exa --icons"
alias ll="exa -l --icons"
alias la="exa -la --icons"
# Developer tools
alias lg="lazygit"
# =====================
# Zsh history settings
# =====================
HISTFILE=~/.zsh_history
HISTSIZE=10000
SAVEHIST=10000
setopt append_history
setopt inc_append_history
setopt share_history
setopt hist_ignore_dups
setopt hist_reduce_blanks
# =====================
# Zsh plugin integrations
# =====================
# Autosuggestions
if [ -f /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh ]; then
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
fi
# Syntax highlighting
if [ -f /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
fi
# Additional completions
fpath+=/usr/share/zsh/site-functions
autoload -Uz compinit && compinit
# =====================
# Command-not-found handler (Arch/pkgfile)
# =====================
if [ -f /usr/share/doc/pkgfile/command-not-found.zsh ]; then
source /usr/share/doc/pkgfile/command-not-found.zsh
fi
# =====================
# End of .zshrc
# =====================

65
README.md Normal file
View File

@ -0,0 +1,65 @@
# Arch Linux Dotfiles & Hyprland Setup
This repository manages your personal dotfiles and a modular, Wayland-ready desktop environment for Arch Linux using `paru`.
## Features
- Modular setup: each aspect (packages, symlinks, shell, Neovim, Hyprland, sound, browsers, devtools, etc.) is handled by its own script in `modules/`.
- All dotfiles and app configs are version-controlled and symlinked to your home directory.
- Out-of-the-box integration for Hyprland, Waybar, Rofi, Mako, Alacritty, wlogout, and more.
- Modern sound stack (PipeWire, WirePlumber, pavucontrol, etc.).
- Volume notifications: see current volume as a Mako popup at the bottom center when changed.
- Multi-monitor workspace rules: workspace 1 always on laptop, others on external (DP-1) if connected; all on laptop if standalone.
- Brave browser always launches on workspace 10 and autostarts with Hyprland.
- TTY/console uses German nodeadkeys layout (`de-latin1-nodeadkeys`).
- Devtools module installs git, Python, Node.js, Docker, VS Code, opencode-bin, and more.
- Easily extensible: add new modules or configs as needed.
## Setup
1. Clone this repository:
```sh
git clone https://github.com/yourusername/dotfiles.git ~/git/dotfiles
cd ~/git/dotfiles
```
2. Run the setup script:
```sh
./setup.sh
```
When you run `setup.sh`, you will be prompted to select your device profile (`laptop` or `desktop`).
This ensures that device-specific configs (e.g., battery, backlight, touchpad, monitor layout) are applied correctly for your hardware.
You can also set the environment variable `DOTFILES_DEVICE` to skip the prompt:
```sh
DOTFILES_DEVICE=desktop ./setup.sh
```
The script will install all required packages and symlink dotfiles and configs (including everything in `.config/`) to your home directory, using the correct device-specific fragments for Hyprland and Waybar.
## Customization
- Add new dotfiles to the repo root (e.g., `.zshrc`, `.tmux.conf`).
- Place app configs in `.config/` (e.g., `.config/hypr/hyprland.conf`).
- Add or edit modules in the `modules/` directory to automate more setup steps.
- To add custom scripts, place them in `.local/bin/` in the repo; they will be symlinked to `~/.local/bin/`.
- To add browsers, edit `modules/06-browsers.sh` (Chrome, Firefox, Brave supported out of the box).
- To add devtools, edit `modules/50-devtools.sh` (includes VS Code, opencode-bin, lazygit, etc.).
## Requirements
- Arch Linux
- [paru](https://github.com/Morganamilo/paru) (will be installed automatically if missing)
- For TTY keymap: `kbd` package (should be present on most systems)
## Notable Integrations & Tips
- **Browsers:** Chrome, Firefox, and Brave are installed via the browser module. Brave autostarts and is always on workspace 10.
- **Devtools:** Includes VS Code (`visual-studio-code-bin`), opencode-bin, lazygit, and more.
- **Volume OSD:** Volume changes show a notification at the bottom center of the screen (Mako).
- **Multi-monitor:** Workspace 1 is always on the laptop display, others on DP-1 if connected.
- **TTY Keymap:** Console uses German nodeadkeys layout for all users (system-wide via `localectl`).
- **No official Teams/Outlook client:** Use the web app or AUR wrappers for best compatibility.
- **TortoiseGit alternative:** Use GitKraken, Sublime Merge, SmartGit, or lazygit for graphical Git workflows.
## License
MIT

28
modules/01-packages.sh Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
# Install paru if not present
if ! command -v paru &>/dev/null; then
echo "paru not found. Installing paru..."
git clone https://aur.archlinux.org/paru.git /tmp/paru
(cd /tmp/paru && makepkg -si --noconfirm)
fi
# List of packages to install (edit as needed)
PACKAGES=(
git
zsh
neovim
tmux
starship
fzf
ripgrep
bat
exa
zsh-autosuggestions
zsh-syntax-highlighting
zsh-completions
btop
pkgfile
# Add more packages here
)
paru -S --needed --noconfirm "${PACKAGES[@]}"

69
modules/02-symlinks.sh Executable file
View File

@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Ensure required directories exist
mkdir -p "$HOME/.config"
echo "Symlinking dotfiles..."
# Get the dotfiles directory (parent of modules directory)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOTFILES_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
# Symlink regular dotfiles (excluding .config directory)
for file in $(find "$DOTFILES_DIR" -maxdepth 1 -name ".*"); do
[ "$file" = "$DOTFILES_DIR/.git" ] && continue
[ "$file" = "$DOTFILES_DIR/.github" ] && continue
[ "$file" = "$DOTFILES_DIR/.vscode" ] && continue
[ "$file" = "$DOTFILES_DIR/.config" ] && continue # Handle .config separately
basefile="$(basename "$file")"
if [ -f "$file" ] || [ -d "$file" ]; then
ln -sf "$file" "$HOME/$basefile"
echo "Linked $basefile"
fi
done
# Symlink .config directory contents
CONFIG_DIR="$DOTFILES_DIR/.config"
if [ -d "$CONFIG_DIR" ]; then
echo "Symlinking .config contents..."
for item in "$CONFIG_DIR"/*; do
[ -e "$item" ] || continue
baseitem="$(basename "$item")"
target_dir="$HOME/.config/$baseitem"
# Remove existing symlink or directory to avoid conflicts
[ -L "$target_dir" ] && rm "$target_dir"
[ -d "$target_dir" ] && [ ! -L "$target_dir" ] && rm -rf "$target_dir"
ln -sf "$item" "$target_dir"
echo "Linked .config/$baseitem"
done
# Device-specific symlinks for Hyprland and Waybar
if [ -n "$DOTFILES_DEVICE" ]; then
# Hyprland monitors
ln -sf "$CONFIG_DIR/hypr/includes/monitors-$DOTFILES_DEVICE.conf" "$CONFIG_DIR/hypr/includes/monitors.conf"
echo "Linked monitors-$DOTFILES_DEVICE.conf as monitors.conf"
# Hyprland input
ln -sf "$CONFIG_DIR/hypr/includes/input-$DOTFILES_DEVICE.conf" "$CONFIG_DIR/hypr/includes/input.conf"
echo "Linked input-$DOTFILES_DEVICE.conf as input.conf"
# Waybar config
ln -sf "$CONFIG_DIR/waybar/config-$DOTFILES_DEVICE" "$CONFIG_DIR/waybar/config"
echo "Linked config-$DOTFILES_DEVICE as waybar config"
fi
fi
echo "Dotfiles setup complete!"
# Symlink .local/bin scripts
LOCAL_BIN_REPO="$DOTFILES_DIR/.local/bin"
LOCAL_BIN_HOME="$HOME/.local/bin"
if [ -d "$LOCAL_BIN_REPO" ]; then
mkdir -p "$LOCAL_BIN_HOME"
echo "Symlinking .local/bin scripts..."
for script in "$LOCAL_BIN_REPO"/*; do
[ -e "$script" ] || continue
base_script="$(basename "$script")"
ln -sf "$script" "$LOCAL_BIN_HOME/$base_script"
echo "Linked .local/bin/$base_script"
done
fi

13
modules/03-shell.sh Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Set zsh as the default shell
if [ "$SHELL" != "$(command -v zsh)" ]; then
echo "Setting zsh as the default shell..."
chsh -s "$(command -v zsh)"
fi
# Set German nodeadkeys layout for TTY/console
if command -v localectl >/dev/null 2>&1; then
echo "Setting TTY keyboard layout to de-latin1-nodeadkeys..."
sudo localectl set-keymap de-latin1-nodeadkeys
fi

13
modules/04-nvim.sh Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Install AstroNvim if not already installed
ASTRONVIM_DIR="$HOME/.config/nvim"
mkdir -p "$HOME/.config"
if [ ! -d "$ASTRONVIM_DIR" ] || [ -z "$(ls -A "$ASTRONVIM_DIR")" ]; then
echo "Installing AstroNvim..."
rm -rf "$ASTRONVIM_DIR"
git clone --depth 1 https://github.com/AstroNvim/template "$ASTRONVIM_DIR"
rm -rf "$ASTRONVIM_DIR/.git"
echo "AstroNvim installed in $ASTRONVIM_DIR"
else
echo "AstroNvim already installed. Skipping."
fi

0
modules/05-hyprland.sh Normal file
View File

22
modules/05-sound.sh Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Install sound-related packages for Hyprland
SOUND_PACKAGES=(
pipewire
pipewire-alsa
pipewire-pulse
pipewire-jack
wireplumber
pavucontrol
pamixer
playerctl
alsa-utils
sof-firmware
)
paru -S --needed --noconfirm "${SOUND_PACKAGES[@]}"
# Enable and start PipeWire services
systemctl --user enable --now pipewire pipewire-pulse wireplumber
echo "Sound packages installed and services enabled."

0
modules/06-browsers.sh Normal file
View File

23
modules/06-hyprland.sh Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Install Hyprland and related software
HYPR_PACKAGES=(
hyprland
hyprlock
hypridle
xdg-desktop-portal-hyprland
waybar
rofi-wayland
mako
wl-clipboard
wlogout
brightnessctl
alacritty
ttf-jetbrains-mono
ttf-nerd-fonts-symbols
noto-fonts
)
paru -S --needed --noconfirm "${HYPR_PACKAGES[@]}"
echo "Hyprland and related tools installed and configured."

0
modules/06-sound.sh Normal file
View File

13
modules/07-browsers.sh Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# 06-browsers.sh - Install web browsers (Chrome, Firefox, Brave)
set -e
# List of browser packages to install
BROWSERS=(google-chrome firefox brave-bin)
# Install browsers with paru (AUR helper)
echo "Installing browsers: ${BROWSERS[*]}"
paru -S --needed --noconfirm "${BROWSERS[@]}"
echo "Browsers installed."

22
modules/50-devtools.sh Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Install development tools and utilities
DEVTOOLS_PACKAGES=(
git
python
nodejs
npm
docker
jq
ripgrep
fd
btop
htop
lazygit
visual-studio-code-bin
opencode-bin
)
paru -S --needed --noconfirm "${DEVTOOLS_PACKAGES[@]}"
echo "Development tools installed."

21
modules/99-postinstall.sh Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Post-install steps for dotfiles setup
# Update pkgfile database for command-not-found suggestions
if command -v pkgfile &>/dev/null; then
echo "Updating pkgfile database..."
sudo pkgfile --update
fi
# Rehash zsh command hash table so new executables are found
if command -v zsh &>/dev/null; then
echo "Running zsh rehash..."
zsh -c 'rehash'
fi
# Add other post-install steps here as needed
# Example: update icon cache, font cache, etc.
# sudo fc-cache -fv
# sudo gtk-update-icon-cache -f /usr/share/icons/hicolor
echo "Post-install steps complete."

32
setup.sh Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Dotfiles setup script for Arch Linux using paru
set -e
#!/usr/bin/env bash
# Dotfiles setup script for Arch Linux using paru
set -e
# Device profile detection
if [ -z "$DOTFILES_DEVICE" ]; then
echo "Select device profile:"
select profile in "laptop" "desktop"; do
DOTFILES_DEVICE="$profile"
export DOTFILES_DEVICE
echo "Using device profile: $DOTFILES_DEVICE"
break
done
else
echo "Using device profile from environment: $DOTFILES_DEVICE"
fi
# Find, sort, and run all modules in the modules directory
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
MODULES=( $(find "$SCRIPT_DIR/modules" -maxdepth 1 -type f -name "*.sh" | sort) )
COUNT=${#MODULES[@]}
for i in "${!MODULES[@]}"; do
MODULE="${MODULES[$i]}"
STEP=$((i+1))
BASENAME=$(basename "$MODULE")
echo "[$STEP/$COUNT] Running $BASENAME..."
source "$MODULE"
done