Compare commits

..
3 Commits
Author SHA1 Message Date
bgrollemanandClaude Sonnet 5.5 227ea2371b Cleanup dotfiles: niri float rules, tmux agent status, noctalia, claude settings
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 11:10:33 +02:00
bgrollemanandClaude Sonnet 5.5 cb80e100f4 Switch to Noctalia v5 and fix niri startup
Fix Mod+T bind (one action per bind), launch noctalia v5 from autostart,
port keybinds to `noctalia msg`, add config.toml, changelog and docs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 11:08:24 +02:00
bgrolleman 626bf30386 Add ~/.local/bin to fish PATH 2026-07-29 23:12:28 +02:00
11 changed files with 254 additions and 96 deletions

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
# Changelog
## 2026-10-10 (cleanup)
- Niri: floating windows open bottom-left by default; Picture-in-picture floats at a fixed offset.
- Noctalia v4 `settings.json`: move workspaces and system monitor to the right, add taskbar, enable idle.
- tmux: add per-window agent status indicator, 2s status refresh and a Prefix+Tab window switcher popup.
- Claude settings: pin model to sonnet, add herdr SessionStart hook, humanizer and ui-ux-pro-max plugins.
- CLAUDE.md: document claude/fish/kanshi linking, `workspaces.kdl` and the tmux helper script living outside the repo.
## 2026-10-10
- Fix niri login: Mod+T bind had three actions, niri rejected the config and fell back to defaults (no bar, no kanshi).
- Autostart now launches `noctalia` (v5, native) instead of `qs -c noctalia-shell` (v4, Quickshell/QML).
- Reason for the switch: Qt 6.12 broke noctalia-shell 4.x colours (`resolveColorKey is not a function`) and noctalia-qs was built on 6.11.
- Port all niri keybinds from `qs ... ipc call` to `noctalia msg` (launcher, lock, session, volume, media, brightness).
- Add `noctalia/config.toml`: theme, wallpaper, weather, idle, dock and bar layout ported from the old `settings.json`.
- Bar on the 5120px ultrawide (DP-1) is limited to ~70% width via a per-monitor `margin_ends` override.
- Restore previous wallpaper (`stellar-blade-2024-ultrawide.jpg`) on all outputs.
- Document the noctalia v4 to v5 migration (files, keybinds, bar, rollback) in `docs/noctalia-v5.md` and CLAUDE.md.
+7 -3
View File
@@ -8,7 +8,7 @@ Personal dotfiles for a Linux desktop, currently running **Niri** (Wayland compo
## Deployment
Configs are deployed by symlinking into `~/.config/` and `~/.profile`:
Configs are deployed by symlinking into `~/.config/`, `~/.profile` and `~/.claude/settings.json` (fish is linked per file):
```bash
bash ~/.dotfiles/setup.sh
@@ -35,12 +35,14 @@ This installs ansible if missing, then runs the playbook. Tasks are split by cat
- `display.kdl` — monitor layout and scaling
- `autostart.kdl` — apps launched on compositor start
- `rules.kdl` — window-specific rules
- `workspaces.kdl` — named workspaces
- `animation.kdl`, `misc.kdl` — tweaks
Edit the relevant split file, not `config.kdl` itself.
### Noctalia (desktop shell / bar)
All settings live in `noctalia/settings.json` (JSON, edited by the Noctalia GUI or directly). Colorschemes are in `noctalia/colorschemes/` and plugins in `noctalia/plugins/`.
Runs **Noctalia v5** (`noctalia`, native). Config is `noctalia/config.toml` (TOML, hot-reloaded); validate with `noctalia config validate`.
`noctalia/settings.json` is the legacy v4 config (kept for rollback, still tweaked occasionally). See `docs/noctalia-v5.md` for details and `CHANGELOG.md` for history.
### Neovim
Uses **LazyVIM** framework. Entry point is `nvim/init.lua` which bootstraps lazy.nvim via `nvim/lua/config/lazy.lua`.
@@ -52,13 +54,15 @@ Uses **LazyVIM** framework. Entry point is `nvim/init.lua` which bootstraps lazy
LazyVIM handles most plugin management; only deviations from LazyVIM defaults need entries in `lua/plugins/`.
### tmux
`tmux/tmux.conf` + catppuccin theme as a git submodule at `tmux/plugins/catppuccin/tmux`. After cloning, initialize the submodule:
`tmux/tmux.conf` + catppuccin theme as a git submodule at `tmux/plugins/catppuccin/tmux`. The agent-status indicators call `~/.local/bin/tmux-window-agent-status`, which is **not** in this repo. After cloning, initialize the submodule:
```bash
git submodule update --init
```
### Shell / profile
`fish/` holds the fish config (`config.fish`, `conf.d/ssh-keychain.fish`); machine-specific vars go in untracked `~/.config/fish/local.fish`.
`profile` is symlinked to `~/.profile`. It sets up SSH keys via `keychain` and defines the `notes` alias (attaches/creates a tmux session with nvim opening `~/Notes/Personal`).
`zoxide.bash` provides shell integration for zoxide (directory jumping) — sourced separately, not via `profile`.
+42 -15
View File
@@ -2,17 +2,8 @@
"permissions": {
"defaultMode": "auto"
},
"model": "sonnet",
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude' 'Task complete' --icon=dialog-information 2>/dev/null || true"
}
]
}
],
"Notification": [
{
"hooks": [
@@ -22,6 +13,28 @@
}
]
}
],
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "bash '/home/bgrolleman/.claude/hooks/herdr-agent-state.sh' session",
"timeout": 10
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude' 'Task complete' --icon=dialog-information 2>/dev/null || true"
}
]
}
]
},
"statusLine": {
@@ -30,20 +43,34 @@
},
"enabledPlugins": {
"frontend-design@claude-plugins-official": true,
"humanizer@humanizer": true,
"lua-lsp@claude-plugins-official": true,
"ponytail@ponytail": true
"ponytail@ponytail": true,
"ui-ux-pro-max@ui-ux-pro-max-skill": true
},
"extraKnownMarketplaces": {
"caveman": {
"source": {
"source": "github",
"repo": "juliusbrussee/caveman"
}
},
"humanizer": {
"source": {
"source": "github",
"repo": "blader/humanizer"
}
},
"ponytail": {
"source": {
"source": "github",
"repo": "DietrichGebert/ponytail"
}
},
"caveman": {
"ui-ux-pro-max-skill": {
"source": {
"source": "github",
"repo": "juliusbrussee/caveman"
"repo": "nextlevelbuilder/ui-ux-pro-max-skill"
}
}
},
@@ -59,10 +86,10 @@
"voiceEnabled": true,
"mcpServers": {
"comfyui-image-gen": {
"command": "/home/bgrolleman/Project/ComfyUI/.venv/bin/python",
"args": [
"/home/bgrolleman/Project/ComfyUI/mcp_server.py"
]
],
"command": "/home/bgrolleman/Project/ComfyUI/.venv/bin/python"
}
}
}
+36
View File
@@ -0,0 +1,36 @@
# Noctalia v5
Noctalia v5 (`noctalia` package) is a native Wayland shell with no Qt dependency. It replaces v4
(`noctalia-shell` + `noctalia-qs`, Quickshell/QML), which broke on Qt 6.12.
## Files
- `noctalia/config.toml` - hand-edited config, hot-reloaded. Linked to `~/.config/noctalia/config.toml`.
- `~/.local/state/noctalia/settings.toml` - GUI-managed overrides and runtime state (not in this repo).
- `noctalia/settings.json` - old v4 config, kept for reference or fallback.
Validate after editing: `noctalia config validate`. Open the settings GUI: `noctalia msg settings-open`.
## Startup and keybinds
- Started from `niri/cfg/autostart.kdl` with `spawn-at-startup "noctalia"`.
- Keybinds in `niri/cfg/keybinds.kdl` call `noctalia msg <command>`; list them with `noctalia msg --help`.
- Panel ids for `panel-toggle`: clipboard, control-center, launcher, polkit, session, tray-drawer, wallpaper.
- Wallpaper is set with `noctalia msg wallpaper-set [output] <path>` and persists.
## Bar
- Layout is the `start`, `center` and `end` lists in `[bar.main]`.
- `[bar.main.monitor.ultrawide]` matches DP-1 and sets `margin_ends = 768`, which gives about 70% width on 5120px.
Formula: `(monitor_width - wanted_width) / 2`.
## Not ported from v4
- System monitor widget (widget id unknown in v5), per-widget options such as hover-only labels.
- v4 plugins (`polkit-agent`): v5 has a built-in `polkit` panel instead.
- The v4 bar only ran on DP-1; v5 runs on every output.
## Rolling back
Set autostart to `qs -c noctalia-shell` again and restore the `qs ... ipc call` binds from git history.
This needs a `noctalia-shell` that works with the installed Qt version.
+3
View File
@@ -1,4 +1,7 @@
fish_add_path ~/.local/bin
# Machine-specific config (secrets, local overrides) — not tracked in dotfiles
if test -f ~/.config/fish/local.fish
source ~/.config/fish/local.fish
end
alias davinci-resolve-studio 'env QT_QPA_PLATFORM=xcb /usr/bin/davinci-resolve-studio'
+1 -1
View File
@@ -1,5 +1,5 @@
// ────────────── Startup Applications ──────────────
// https://github.com/YaLTeR/niri/wiki/Configuration:-Miscellaneous#spawn-sh-at-startup
spawn-sh-at-startup "qs -c noctalia-shell"
spawn-at-startup "noctalia"
spawn-at-startup "kanshi"
+15 -15
View File
@@ -16,29 +16,29 @@ binds {
Mod+G hotkey-overlay-title="Focus: Gmail" { spawn-sh "$HOME/.config/niri/focus-or-launch.sh chrome-fmgjjmmmlfnkbppncabfkddbjimcfncm-Default /opt/helium-browser-bin/helium-wrapper --profile-directory=Default --app-id=fmgjjmmmlfnkbppncabfkddbjimcfncm"; }
Mod+W hotkey-overlay-title="Focus: WhatsApp" { spawn-sh "$HOME/.config/niri/focus-or-launch.sh chrome-hnpfjngllnobngcgfapefoaidbinmjnm-Default /opt/helium-browser-bin/helium-wrapper --profile-directory=Default --app-id=hnpfjngllnobngcgfapefoaidbinmjnm"; }
Mod+D hotkey-overlay-title="Focus: Todoist" { spawn-sh "$HOME/.config/niri/focus-or-launch.sh chrome-dlgohinmglaoopaiplliaecdpmnepmga-Default /opt/helium-browser-bin/helium-wrapper --profile-directory=Default --app-id=dlgohinmglaoopaiplliaecdpmnepmga"; }
//Mod+CTRL+Return hotkey-overlay-title="Open App Launcher: noctalia launcher" { spawn-sh "qs -c noctalia-shell ipc call launcher toggle"; }
Alt+Space hotkey-overlay-title="Open App Launcher: noctalia launcher" { spawn-sh "qs -c noctalia-shell ipc call launcher toggle"; }
Alt+Shift+Space hotkey-overlay-title="Open Window Search: noctalia launcher" { spawn-sh "qs -c noctalia-shell ipc call launcher windows"; }
//Mod+CTRL+Return hotkey-overlay-title="Open App Launcher: noctalia launcher" { spawn-sh "noctalia msg panel-toggle launcher"; }
Alt+Space hotkey-overlay-title="Open App Launcher: noctalia launcher" { spawn-sh "noctalia msg panel-toggle launcher"; }
Alt+Shift+Space hotkey-overlay-title="Open Window Search: noctalia launcher" { spawn-sh "noctalia msg window-switcher"; }
Mod+B hotkey-overlay-title="Open Browser: helium" { spawn "helium-browser"; }
Mod+L hotkey-overlay-title="Lock Screen: noctalia lock" { spawn-sh "qs -c noctalia-shell ipc call lockScreen lock"; }
Mod+Shift+Q hotkey-overlay-title="Session Menu: noctalia sessionMenu" { spawn-sh "qs -c noctalia-shell ipc call sessionMenu toggle"; }
Mod+L hotkey-overlay-title="Lock Screen: noctalia lock" { spawn-sh "noctalia msg session lock"; }
Mod+Shift+Q hotkey-overlay-title="Session Menu: noctalia sessionMenu" { spawn-sh "noctalia msg panel-toggle session"; }
// Please choose your own file manager.
Mod+E hotkey-overlay-title="File Manager: Nautilus" { spawn "nautilus"; }
// ─── Media Controls ───
XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call volume increase"; }
XF86AudioLowerVolume allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call volume decrease"; }
XF86AudioMute allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call volume muteOutput"; }
XF86AudioMicMute allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call volume muteInput"; }
XF86AudioNext allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call media next"; }
XF86AudioPrev allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call media previous"; }
XF86AudioPlay allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call media playPause"; }
XF86AudioPause allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call media playPause"; }
XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "noctalia msg volume-up"; }
XF86AudioLowerVolume allow-when-locked=true { spawn-sh "noctalia msg volume-down"; }
XF86AudioMute allow-when-locked=true { spawn-sh "noctalia msg volume-mute"; }
XF86AudioMicMute allow-when-locked=true { spawn-sh "noctalia msg mic-mute"; }
XF86AudioNext allow-when-locked=true { spawn-sh "noctalia msg media next"; }
XF86AudioPrev allow-when-locked=true { spawn-sh "noctalia msg media previous"; }
XF86AudioPlay allow-when-locked=true { spawn-sh "noctalia msg media toggle"; }
XF86AudioPause allow-when-locked=true { spawn-sh "noctalia msg media toggle"; }
// ─── Brightness Controls ───
XF86MonBrightnessUp allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call brightness increase"; }
XF86MonBrightnessDown allow-when-locked=true { spawn-sh "qs -c noctalia-shell ipc call brightness decrease"; }
XF86MonBrightnessUp allow-when-locked=true { spawn-sh "noctalia msg brightness-up"; }
XF86MonBrightnessDown allow-when-locked=true { spawn-sh "noctalia msg brightness-down"; }
// ─── Window Movement and Focus ───
Alt+H { focus-column-left; }
+7
View File
@@ -1,6 +1,7 @@
window-rule {
geometry-corner-radius 5 // Set every window radius to 20
clip-to-geometry true
default-floating-position x=10 y=10 relative-to="bottom-left"
}
// if you use steam you will probably like these
@@ -16,6 +17,12 @@
open-focused false
}
window-rule {
match title="^Picture-in-picture$"
open-floating true
default-floating-position x=50 y=50 relative-to="bottom-left"
}
layer-rule {
match namespace="^noctalia-wallpaper*"
place-within-backdrop true
+56
View File
@@ -0,0 +1,56 @@
# Ported from the old settings.json (noctalia-shell 4.x). Unlisted keys use defaults.
[theme]
mode = "dark"
source = "builtin"
builtin = "Catppuccin"
[wallpaper]
enabled = true
fill_mode = "crop"
transition = ["fade", "disc", "stripes", "wipe", "honeycomb"]
transition_duration = 1500
directory = "/home/bgrolleman/Documents/Resources/Backgrounds"
[weather]
enabled = true
unit = "celsius"
[location]
address = "Amersfoort, The Netherlands"
[idle.behavior.lock]
timeout = 660
action = "lock"
enabled = true
[idle.behavior.screen-off]
timeout = 600
action = "screen_off"
enabled = true
[dock]
enabled = true
position = "left"
auto_hide = true
[bar.main]
position = "top"
background_opacity = 0.93
capsule = true
margin_ends = 4
margin_edge = 4
widget_spacing = 6
start = ["launcher", "taskbar"]
center = ["clock", "media"]
end = ["workspaces", "tray", "network", "bluetooth", "notifications", "battery", "volume", "brightness", "control-center"]
[widget.clock]
format = "{:%H:%M %a, %b %d}"
tooltip_format = "{:%H:%M %a, %b %d}"
# 70% of the 5120px ultrawide: (5120 - 3584) / 2
[bar.main.monitor.ultrawide]
match = "DP-1"
margin_ends = 768
+55 -53
View File
@@ -87,6 +87,22 @@
"id": "Clock",
"tooltipFormat": "HH:mm ddd, MMM dd",
"useCustomFont": false
},
{
"compactMode": false,
"hideMode": "hidden",
"hideWhenIdle": true,
"id": "MediaMini",
"maxWidth": 500,
"panelShowAlbumArt": true,
"scrollingMode": "hover",
"showAlbumArt": true,
"showArtistFirst": true,
"showProgressRing": true,
"showVisualizer": false,
"textColor": "none",
"useFixedWidth": false,
"visualizerType": "linear"
}
],
"left": [
@@ -100,6 +116,42 @@
"id": "Launcher",
"useDistroLogo": false
},
{
"colorizeIcons": false,
"hideMode": "hidden",
"iconScale": 0.8,
"id": "Taskbar",
"maxTaskbarWidth": 40,
"onlyActiveWorkspaces": true,
"onlySameOutput": true,
"showPinnedApps": false,
"showTitle": true,
"smartWidth": true,
"titleWidth": 120
}
],
"right": [
{
"characterCount": 2,
"colorizeIcons": false,
"emptyColor": "secondary",
"enableScrollWheel": true,
"focusedColor": "primary",
"followFocusedScreen": false,
"fontWeight": "bold",
"groupedBorderOpacity": 1,
"hideUnoccupied": true,
"iconScale": 0.8,
"id": "Workspace",
"labelMode": "name",
"occupiedColor": "secondary",
"pillSize": 0.6,
"showApplications": true,
"showApplicationsHover": false,
"showBadge": true,
"showLabelsOnlyWhenOccupied": true,
"unfocusedIconsOpacity": 1
},
{
"compactMode": true,
"diskPath": "/",
@@ -122,56 +174,6 @@
"useMonospaceFont": true,
"usePadding": false
},
{
"compactMode": false,
"hideMode": "hidden",
"hideWhenIdle": false,
"id": "MediaMini",
"maxWidth": 145,
"panelShowAlbumArt": true,
"scrollingMode": "hover",
"showAlbumArt": true,
"showArtistFirst": true,
"showProgressRing": true,
"showVisualizer": false,
"textColor": "none",
"useFixedWidth": false,
"visualizerType": "linear"
},
{
"characterCount": 2,
"colorizeIcons": false,
"emptyColor": "secondary",
"enableScrollWheel": true,
"focusedColor": "primary",
"followFocusedScreen": false,
"fontWeight": "bold",
"groupedBorderOpacity": 1,
"hideUnoccupied": false,
"iconScale": 0.8,
"id": "Workspace",
"labelMode": "name",
"occupiedColor": "secondary",
"pillSize": 0.6,
"showApplications": false,
"showApplicationsHover": false,
"showBadge": true,
"showLabelsOnlyWhenOccupied": true,
"unfocusedIconsOpacity": 1
},
{
"colorizeIcons": false,
"hideMode": "visible",
"id": "ActiveWindow",
"maxWidth": 350,
"scrollingMode": "hover",
"showIcon": true,
"showText": true,
"textColor": "none",
"useFixedWidth": true
}
],
"right": [
{
"blacklist": [
],
@@ -453,7 +455,7 @@
},
"idle": {
"customCommands": "[]",
"enabled": false,
"enabled": true,
"fadeDuration": 5,
"lockCommand": "",
"lockTimeout": 660,
@@ -463,7 +465,7 @@
"screenOffCommand": "",
"screenOffTimeout": 600,
"suspendCommand": "",
"suspendTimeout": 1800
"suspendTimeout": 0
},
"location": {
"analogClockInCalendar": false,
@@ -488,7 +490,7 @@
"bluetoothRssiPollIntervalMs": 60000,
"bluetoothRssiPollingEnabled": false,
"disableDiscoverability": false,
"networkPanelView": "ethernet",
"networkPanelView": "wifi",
"wifiDetailsViewMode": "list"
},
"nightLight": {
+12 -9
View File
@@ -14,19 +14,22 @@ set -g @catppuccin_window_status_style "slanted"
# Load catppuccin
run ~/.config/tmux/plugins/catppuccin/tmux/catppuccin.tmux
# Make the status line pretty and add some modules
# Status line on top (tmux only supports top/bottom, no vertical sidebar)
set-option -g status-position top
set -g status-right-length 100
set -g status-left-length 100
set -g status-left "#[fg=#{@thm_teal},bg=#{@thm_crust}]#[fg=#{@thm_crust},bg=#{@thm_teal}] #(hostname -s) "
#set -g status-left "#[fg=$thm_green,bg=$thm_bg,nobold,nounderscore,noitalics]#[fg=$thm_bg,bg=$thm_green,nobold,nounderscore,noitalics] #[fg=$thm_fg,bg=$thm_bg]#(hostname -s) "
set -g status-left "#[fg=#{@thm_teal},bg=#{@thm_crust}]#[fg=#{@thm_crust},bg=#{@thm_teal}] #(hostname -s) "
set -g status-right "#{E:@catppuccin_status_application}"
#set -agF status-right "#{E:@catppuccin_status_cpu}"
set -ag status-right "#{E:@catppuccin_status_session}"
#set -ag status-right "#{E:@catppuccin_status_uptime}"
#set -agF status-right "#{E:@catppuccin_status_battery}"
#run ~/.config/tmux/plugins/tmux-plugins/tmux-cpu/cpu.tmux
#run ~/.config/tmux/plugins/tmux-plugins/tmux-battery/battery.tmux
# Per-window agent indicator: 🤖 = busy, ⏸ = waiting for input
set -g @catppuccin_window_text " #W#(~/.local/bin/tmux-window-agent-status '#{session_name}' '#I')"
set -g @catppuccin_window_current_text " #W#(~/.local/bin/tmux-window-agent-status '#{session_name}' '#I')"
# Refresh status regularly so agent indicators stay current
set -g status-interval 2
# Vertical window switcher ("sidebar"): prefix+Tab opens a popup listing all
# windows top-to-bottom with agent status; Enter jumps to the selected window
bind-key Tab choose-tree -Zw -F "#{?window_format,#W#(~/.local/bin/tmux-window-agent-status '#{session_name}' '#{window_index}'),}"