aboutsummaryrefslogtreecommitdiffstatshomepage
Commit message (Collapse)AuthorAgeFilesLines
* feat(git): pre-push also rejects commits with foreign committerLibravatar sommerfeld2026-05-131-8/+34
| | | | | | | | | | | | | Now flags any commit whose committer name+email doesn't match the local user.name / user.email (which respects the includeIf rules in ~/.config/git/config, so per-tree work/personal identities work). Author is left free: pulling someone else's commit and rebasing it locally re-stamps the committer to you, satisfies this gate, and the original author is preserved in the commit metadata. Both checks (signature + committer) run in one rev-list pass with tab-separated fields so awk parses unambiguously.
* feat(git): global pre-push hook rejecting unsigned commitsLibravatar sommerfeld2026-05-133-0/+65
| | | | | | | | | | | | | | Activated via core.hooksPath = ~/.config/git/hooks in the global git config. The hook walks each ref being pushed (range: remote..local or, for new branches, local --not --remotes) and checks %G? on every commit. Accepts G/U/X/Y (good signature variants), rejects N/B/E/R (no signature, bad, missing key, revoked). Bypass: git push --no-verify This repo overrides hooksPath to .githooks/ for its just-check pre-commit gate, so a thin .githooks/pre-push delegates to the global hook to keep the policy enforced here too.
* feat(sway,waybar): scratch nvim+ipython binds; bolder VPN visualsLibravatar sommerfeld2026-05-134-46/+54
| | | | | | | | | | | | | | | | | VPN module: - Pango markup colours the text directly so up/down is visually unambiguous even without CSS classes (green shield up, dim strikethrough down) - .down also gets a faint red background tint for at-a-glance scan Sway: - Super+Shift+t -> floating ghostty with nvim editing a fresh $XDG_RUNTIME_DIR/scratch-<epoch>.txt (auto-cleared on reboot via tmpfs) - Super+c -> floating ghostty with ipython (quick calculator / python scratch) KEYBINDS.md updated.
* feat(waybar,sway): htop click handler, app keybinds, VPN toggleLibravatar sommerfeld2026-05-137-0/+69
| | | | | | | | | | | | | | | | | | | | waybar: - cpu / custom/memory: on-click opens floating ghostty with htop - new custom/vpn module between custom/memory and network#bond: shows 'VPN' coloured by interface UP flag (green up, dim down); on-click toggles networkctl up/down hodor; SIGRTMIN+8 used for instant refresh after toggle sway: - Super+Shift+Return -> ghostty -e yazi - Super+Shift+b -> librewolf vpn-toggle.sh runs networkctl (no sudo) thanks to a new polkit rule allowing wheel-group members to invoke org.freedesktop.network1.* without a password prompt. systemd-networkd's polkit gate is a separate path from sudoers, so this is the idiomatic fix. KEYBINDS.md updated for both new sway bindings.
* feat(mako-history): reopen picker after each selectionLibravatar sommerfeld2026-05-131-22/+25
| | | | | | After Enter copies+dismisses an entry, reopen the wofi window so the remaining notifications can be processed without re-triggering the keybind. Esc closes the loop.
* fix(logind): ignore KEY_POWER long-press tooLibravatar sommerfeld2026-05-131-6/+12
| | | | | | | | | | | | The Shokz dongle emits KEY_POWER press without a matching release on USB disconnect; logind classified that as a long-press after 5s and fired HandlePowerKeyLongPress=poweroff (confirmed in journal: 'Power key pressed long. Powering off...'). There is no policy that distinguishes 'real 5s hold of power button' from 'misbehaving device that never sends release'. Ignore both. Clean shutdowns now require systemctl poweroff or GUI menus; a very long hold of the physical power button still force-offs via firmware.
* refactor(logind): drop device-specific rationale from power-key drop-inLibravatar sommerfeld2026-05-131-8/+5
| | | | | | The drop-in is generic policy, not tied to one device. Reword the comment to reflect that any USB device emitting spurious KEY_POWER (headsets, KVM switches, cheap keyboards) is covered.
* fix(logind): ignore KEY_POWER short-press to stop Shokz dongle shutdownsLibravatar sommerfeld2026-05-133-11/+14
| | | | | | | | | | | | | | | | | | | | The Shokz OpenMeet dongle (3511:2EF2) emits KEY_POWER on USB enumeration and on headset power transitions, which logind handles with HandlePowerKey=poweroff and immediately shuts the host down. The previous attempt — an hwdb scancode remap of c0030 to reserved — sets the udev property correctly but the kernel does not honor EVIOCSKEYCODE for this device's HID consumer-page mapping (verified: KEY_POWER 116 still appears in the evdev keymap after udevadm trigger and libinput still reports it). Drop the hwdb file and the systemd-hwdb hooks from the etc deploy script. Replace with a logind drop-in that sets HandlePowerKey=ignore and HandlePowerKeyLongPress=poweroff. Single-tap power events from any source become no-ops; a 5s hold still shuts the machine down, so the real hardware-power-button safety net is preserved. Add a HUP to systemd-logind in the deploy script so the change takes effect without restarting the daemon.
* feat(udev): replace shokz blacklist with hwdb keycode overrideLibravatar sommerfeld2026-05-133-1/+12
| | | | | | | | | | | | | | | The previous /etc/udev/rules.d/80-shokz-blacklist.rules deauthorized the entire usbhid interface for the Shokz OpenMeet dongle (3511:2EF2) to stop the host from powering off when the headset is turned off. That also killed mic-mute, volume, and media keys on the same HID Consumer Control node. Replace it with a narrow hwdb override that remaps just the offending scancode (Consumer page Power, c0030 -> KEY_POWER) to reserved on that specific vendor/product. KEY_MUTE / volume / media keys keep working. Add 'systemd-hwdb update' + an input-subsystem udevadm trigger to the etc deploy hook so new hwdb files take effect immediately.
* fix(mako-history): drop Alt-d; Enter copies+dismissesLibravatar sommerfeld2026-05-132-60/+47
| | | | | | | | wofi's key_custom_N only stages an exit code; it does not actually exit on the keybind, so Alt-d alone did nothing visible. Drop the custom keybind entirely and let Enter copy+dismiss in one stroke. Esc cancels. Since dismissed entries are now hidden, walking the list with Enter is a workable replacement for the dropped "dismiss without copy" path.
* fix(webcam-status): silence SC2086 on intentional word-splittingLibravatar sommerfeld2026-05-131-0/+1
|
* feat(mako-history): hide dismissed entries; consolidate keybindsLibravatar sommerfeld2026-05-132-81/+78
| | | | | | | | | | | | | | | | | Two behaviour changes: - Hide entries that were previously dismissed via the picker (the state file now acts as a hide-list, not a marker). The list shrinks as you process it; no more grey ' ' rows clogging the view. - Drop the secondary Alt-c custom key. wofi's '--define key_custom_N' appears unreliable past N=0, so Alt-c and Alt-d both silently failed. Reduce to a single custom slot (Alt-d) and remap actions: Enter -> copy + dismiss (was: re-emit + mark seen) Alt-d -> dismiss without copy Re-emit was rarely useful given mako already shows the bubble on arrival; copying is the common need. KEYBINDS.md updated to reflect the new action set.
* chore(python): add basedpyright type-checkingLibravatar sommerfeld2026-05-132-2/+15
| | | | ruff (format + check) was already wired into fmt/check-fmt/lint. Add basedpyright as the type-checker for python so 'just lint' covers correctness too. Pyright config sets standard mode (lenient enough to not flood on stdlib edges) and excludes ipython_config.py whose 'c' is injected by IPython at config load time.
* chore: drop dot_copilot tree; format clangd configLibravatar sommerfeld2026-05-138-290/+6
| | | | | - Remove dot_copilot/ entirely (no longer needed). - Run prettier on dot_config/clangd/config.yaml.
* style: apply formatter drift across repoLibravatar sommerfeld2026-05-1314-110/+126
| | | | | | | Pre-existing whitespace/style drift caught by `just check`. Touch nothing semantic — pure formatter output (shfmt -i 2 -ci -s, ruff, prettier, taplo). Excludes dot_config/clangd/config.yaml whose manual indentation is intentionally preserved.
* refactor(meta): flatten groups; only break out optional/hw-specificLibravatar sommerfeld2026-05-1326-309/+312
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Drop the per-domain group fragmentation in meta/ and the parallel group-per-file structure in systemd-units/. meta/ (18 -> 6 groups): keep base, flatpak (magic), intel, nvidia, work, btc fold browser, bt, cpp, dev, extra, fonts, mail, media, nix, sound, wayland -> base (with `# --- section ---` comments preserving at-a-glance structure) drop fortran (niche; install ad-hoc when needed) systemd-units/: flatten to a single system.txt + user.txt; .ignore files move up one level; group concept and pairing rule removed. justfile: unit-list/unit-apply/unit-status no longer take a group argument. unit-add/unit-forget infer scope by probing `systemctl [--user] cat <unit>` (system wins on tie). Top-level add/forget dispatcher updated: any unit-suffixed arg routes to unit-* without requiring a leading GROUP. docs: .github/copilot-instructions.md and README.md updated to describe the new flat layout. Pairing rule and group-token grammar gone. Pure layout refactor - no package contents change.
* fix(privesc): revert bogus AssumeInstalled directiveLibravatar sommerfeld2026-05-132-14/+5
| | | | | | | | | | | | | | AssumeInstalled is only a CLI flag (--assume-installed), not a pacman.conf directive. The line I added was emitting a warning at every pacman run and didn't actually keep base-devel from pulling sudo. Live with sudo installed: /usr/local/bin/sudo (-> sudo-rs) shadows it via PATH precedence, so the /usr/bin/sudo binary is dead code on disk. The alternative — maintaining a dummy 'provides=sudo' package — is more cost than the ~1.5 MB it would save. Update bootstrap.sh comment to reflect that sudo stays installed.
* feat(privesc): drop classic sudo via AssumeInstalledLibravatar sommerfeld2026-05-133-20/+29
| | | | | | | | | | | | | | | | base-devel hard-depends on the sudo package, so without help, pacman refuses to remove it. The Arch-native fix is pacman.conf's AssumeInstalled directive: tell pacman to pretend a virtual sudo=99.0 is installed and base-devel's dep is satisfied without actually pulling sudo in. - etc/pacman.conf: AssumeInstalled = sudo=99.0 - bootstrap.sh: after 'just init' (which writes the AssumeInstalled line and installs sudo-rs), Rns the leftover sudo package so a fresh install ends up with sudo-rs only. Also reformat bootstrap.sh and the etc deploy script with the project's shfmt style (-i 2 -ci -s).
* feat(privesc): migrate from opendoas to sudo-rsLibravatar sommerfeld2026-05-1315-320/+83
| | | | | | | | | | | | | | | | | | | | | | | | | | | doas's one-shot password and absent 'sudo -v' kept wasting hour-long paru AUR builds. sudo-rs is a memory-safe Rust rewrite (ISRG/Ferrous Systems), drop-in CLI compatible, and the same one Ubuntu 25.10 ships as default. We follow the Arch wiki 'Using sudo-rs without the sudo package' recipe verbatim — no custom shims. - meta/base.txt: -doas-sudo-shim +sudo-rs - etc/sudoers-rs (mode 0440): wiki minimal config + NOPASSWD reboot/poweroff - etc/pam.d/sudo: 4-line copy of upstream sudo's PAM file - run_onchange_after_deploy-etc.sh.tmpl: use real sudo, deploy sudoers-rs at 0440, create /etc/pam.d/sudo-i and /usr/local/bin/{sudo,sudoedit, su,visudo} → sudo-rs symlinks idempotently - delete etc/doas.conf, dot_local/bin/{doasedit,sudo} - zshrc: drop sudo=doas/sudoedit=doasedit aliases; rewrite ss/gimme/ pacdiff/ssys to call sudo - justfile: s/doas/sudo/g (status/diff/restore helpers) - nvim: rename :DoasWrite → :SudoWrite (uses sudo -S) - sway config: reboot/poweroff buttons call sudo - bootstrap.sh: update step-5 comment - README/KEYBINDS/copilot-instructions: flip the privesc convention No Defaults overrides: sudo's defaults (passwd_tries=3, timestamp_timeout=5) already fix the doas pain, and paru SudoLoop (kept) refreshes the 5-min window via real sudo -v.
* feat(doas): smarter sudo shim + paru SudoLoopLibravatar sommerfeld2026-05-132-1/+60
| | | | | | | | | | | | | | | | | | | The packaged doas-sudo-shim is just 'exec doas "$@"', which means 'sudo -v' (used by paru --sudoloop to keep the auth timestamp fresh during long AUR builds) hits doas, which doesn't implement -v, and the loop dies. Then when the build finally finishes and tries the real install, the cached timestamp has long expired, so we reprompt — and opendoas only allows one attempt before bailing, so a single mistype throws an hour of compilation away. Replace it (per-user, via $HOME/.local/bin precedence) with a shim that translates: -v -> doas true (refresh persist timestamp) -k / -K -> doas -L (clear) -E -H -i -S etc -> dropped (no doas equivalent) rest -> doas "$@" Then enable SudoLoop in paru.conf so the timestamp stays fresh.
* style(waybar): use real anchor U+2693 (⚓) for dock indicatorLibravatar sommerfeld2026-05-131-1/+1
| | | | | Plain Unicode anchor renders via the system emoji font everywhere instead of the nerd-font private-use-area glyph.
* style(waybar): swap dock glyph to anchor (nf-md-anchor)Libravatar sommerfeld2026-05-131-1/+1
| | | | | Pun on "ship docked at port" — and just looks better than the dock_window glyph at small sizes.
* feat(waybar): add dock indicator next to batteryLibravatar sommerfeld2026-05-133-0/+40
| | | | | | | | | | Detects the ThinkPad USB-C Dock Gen2 by its built-in ethernet adapter (USB 17ef:a387) — the dock's USB hubs share product IDs with internal ThinkPad hubs but the ethernet only exists when the dock is attached. The custom/dock module sits to the left of battery; collapses to empty text when undocked so the bar stays clean on the go. Green dock glyph when docked.
* revert(flatpak): drop font filesystem override (flatpak auto-shares)Libravatar sommerfeld2026-05-131-10/+0
| | | | | | | | flatpak refuses '/usr/share/fonts' ("Path /usr is reserved") and auto-mounts host fonts to /run/host/fonts and ~/.local/share/fonts to /run/host/user-fonts already. The override was a no-op. The remaining emoji/nerd-glyph rendering issue in browsers is browser-side font fallback, not flatpak sandboxing.
* feat(flatpak): expose host fonts globally so browsers render emojiLibravatar sommerfeld2026-05-131-0/+10
| | | | | | | | LibreWolf and ungoogled-chromium were rendering emoji and nerd-font glyphs as tofu because flatpaks don't see /usr/share/fonts by default. Apply a global override (no app argument) granting read-only access to the system font dirs and the user's fontconfig. noto-fonts-emoji is already in meta/fonts.txt.
* fix(emoji): split skin-tone filter into its own picker scriptLibravatar sommerfeld2026-05-132-5/+10
| | | | | | | | The previous one-liner stuffed an inline pipeline into BEMOJI_PICKER_CMD via 'sh -c' with three layers of nested quoting, which broke under bemoji's eval ("grep: 1: Syntax error: Unterminated quoted string"). Move the filter+wofi pipeline into emoji-wofi.sh and point the env var directly at it. No more quoting gymnastics.
* feat(emoji): filter out skin-tone variants in bemoji pickerLibravatar sommerfeld2026-05-132-1/+12
| | | | | | | | Skin-tone modifiers (U+1F3FB..U+1F3FF) clutter search results with five near-duplicates per people-emoji. New ~/.config/sway/emoji-picker.sh wraps bemoji and pipes its emoji list through grep -vP before handing it to wofi. Quoting was getting hairy inline in sway's exec, so the wrapper script makes it readable.
* fix(wofi): allow fuzzy search in emoji pickerLibravatar sommerfeld2026-05-132-11/+8
| | | | | | | | | The bemoji invocation passed --hide-search, and the shared wofi stylesheet additionally forced #input opacity to 0, so even without the flag the search box was unusable. Drop --hide-search from bemoji's picker cmd and replace the CSS hack with a normal styled input. Pickers that want arrow-only UI (mako-history, clip-picker) keep --hide-search and continue to render without an input row.
* feat: vim nav in wofi, bemoji, clip picker, webcam glyph fixLibravatar sommerfeld2026-05-137-5/+56
| | | | | | | | | | | | | | | | | | | | | | | - wofi config: key_up/key_down accept Up,k / Down,j; Ctrl-u/Ctrl-d for page jumps. Picker scripts auto-load this since they only pass --style. - waybar webcam glyph: U+F0D5D (camera/photo, looked Instagram-y) -> U+F0567 nf-md-video (handheld video camera). - Clipboard picker migrated from fuzzel to wofi for consistency with the notification picker. New driver dot_config/waybar/clip-picker.sh: pick (Mod+p) Enter pastes, Alt-d deletes delete (Mod+Shift+p) Enter deletes No clipboard "read" indicator: Wayland has no API for observing reads. - Emoji picker: bemoji on Mod+period, driven through wofi (so vim nav applies there too) and configured to type + copy via wtype. - LibreWolf flatpak: --device=all override so v4l2 webcams work. Flatpak has no finer-grained device flag. - KEYBINDS.md updated: Mod+p / Mod+Shift+p now describe wofi behavior; Mod+period documented.
* fix(waybar): dismiss/restore wrappers parse mako text formatLibravatar sommerfeld2026-05-132-3/+11
| | | | | | | | | | Same -f-doesn't-exist regression as 3205afc / d76ff3c. Without -f the inner pipeline produced no ids, so the dismissed-set never grew and notifications stayed pending forever after Mod+n. Switch to sed extraction of 'Notification N:' lines for both dismiss-visible.sh (list) and restore-pending.sh (history). Verified the dismissed-set is populated correctly for top/all modes.
* fix(waybar): mako-status counts ids by parsing text dumpLibravatar sommerfeld2026-05-131-9/+11
| | | | | | | | Same root cause as 3205afc: this makoctl version has no -f flag, so the '%i' lookup silently produced no ids and the bar always showed empty. Switch to a sed extraction of 'Notification N:' lines from list+history. Verified against simulated input matching the user's real makoctl output: 0/some/all dismissed all render correctly.
* fix(waybar): parse real makoctl text format (no -f support)Libravatar sommerfeld2026-05-131-24/+44
| | | | | | | | | | | | This makoctl version doesn't accept -f. Drop that path and parse the actual text dump: Notification N: <summary> <- summary on the same line App name: <app> [Category: <cat>] [Body: ...] <- absent on this version, kept anyway Urgency: <urgency> Verified against the user's pasted output.
* fix(waybar): use makoctl -f format for history pickerLibravatar sommerfeld2026-05-131-33/+25
| | | | | | | | | | The text-mode parser was looking for 'Notification N:' on a line by itself, but makoctl prints 'Notification N: <summary>' with the summary inline — so every record was dropped and the picker came up empty. Switch to makoctl list/history -f '%i\t%a\t%s\t%b' which emits one clean tab-separated record per notification (mako >= 1.4). Multi-line bodies are folded back into the previous record.
* fix(waybar): notification picker also lists currently-visible bubblesLibravatar sommerfeld2026-05-131-5/+21
| | | | | | | makoctl list and makoctl history are disjoint — visible notifications aren't in history yet. The picker was only reading history, so it came up empty whenever the bar showed pending bubbles that were still on screen. Merge both lists, dedupe by id, visible first.
* feat(notifications): persistent-pending model + wofi history pickerLibravatar sommerfeld2026-05-1310-49/+305
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Notifications now behave like a phone: pop briefly, auto-disappear, and remain "pending" until the user explicitly acknowledges them. The waybar count reflects pending only; idle uses a quieter glyph. State model: pending = ids in mako history/list MINUS dismissed-set state file: $XDG_RUNTIME_DIR/mako-dismissed (per-session id list) Glyph change: idle (0 pending) bell_outline U+F009C has pending bell_ring U+F009E (the previous bell_check_outline U+F11E8 "history present but nothing pending" branch is gone — there is no separate history concept now) Bindings (all now go through wrappers that maintain the dismissed-set): Super+n dismiss top visible + mark seen Super+Shift+n dismiss all visible + mark seen Super+Ctrl+n restore most recent + pop it from dismissed-set XF86Favorites history picker (rewritten on wofi) History picker (dot_config/waybar/executable_mako-history.py): - wofi --hide-search: arrow-only navigation, no fuzzy input - lines tagged [pending] / [seen] with app + summary + body - Enter re-emit via notify-send (re-shows the bubble) + mark seen - Alt-c copy "summary\nbody" to clipboard via wl-copy - Alt-d mark seen without re-showing - empty history shows a sentinel, no-op on Enter New scripts: executable_dismiss-visible.sh capture id(s) then makoctl dismiss executable_restore-pending.sh capture top-of-history id, restore, then drop that id from dismissed-set executable_mako-history.py Python rewrite (parses makoctl text output, drives wofi) Other: meta/wayland.txt add wofi (only used by this picker) dot_config/wofi/style.css minimal gruvbox style; hides input row as belt-and-suspenders even though --hide-search already does it
* style(waybar): swap obvious literal labels for Nerd Font glyphsLibravatar sommerfeld2026-05-136-29/+33
| | | | | | | | | | | | | | | | | | | | | | | Numeric/identity labels stay (CPU, MEM, °C, network arrows, clock). Iconic labels are replaced with codepoints from ttf-noto-nerd: battery BAT/CHR/PLG -> nf-md-battery_*, _charging, power_plug (U+F0079..F0084, U+F06A5) pulseaudio VOL/MUTE -> nf-md-volume_low/medium/high/off (U+F057E..F0581) bluetooth BT on/off -> nf-md-bluetooth/_off/_connect (U+F00AF/B0/B2) idle_inhib. INH/IDL -> nf-md-eye_off_outline/_outline (U+F06D1, F06D0) custom/wifi text only -> prefix nf-md-wifi/_off (U+F05A9, F05AA) custom/webcam CAM -> nf-md-camera (U+F0D5D) custom/notif. NTF -> nf-md-bell_outline/_check_outline/_ring (U+F009C, F11E8, F009E) custom/tb MAIL -> nf-md-email/_alert (U+F01EE, F0D42) style.css font-family widened from 'mono' to a declarative fallback chain so glyph rendering doesn't depend on fontconfig auto-fallback.
* feat(waybar): add webcam privacy indicatorLibravatar sommerfeld2026-05-133-0/+31
| | | | | | | | | | V4L2 capture goes directly through /dev/videoN and never traverses the PipeWire portal, so the built-in privacy module misses it. New custom/webcam module polls fuser on /dev/video* every 2s and shows a red 'CAM' badge when any device is held open. Empty text when idle, so the slot collapses and stays out of the way when the webcam is unused (i.e. always, on a usual day).
* fix(sway): call doas with absolute paths for reboot/poweroffLibravatar sommerfeld2026-05-131-2/+2
| | | | | | | | | | | doas matches the 'cmd' rule literally against argv[0], not against the resolved PATH lookup. With 'cmd /usr/bin/poweroff' in doas.conf, 'doas poweroff' is denied silently — works only as 'doas /usr/bin/poweroff'. The interactive shell aliases sudo->doas and was hiding the issue when typing the bare command in a terminal (PATH expansion happens in the shell before doas sees argv[0]... only when explicitly typed with absolute path).
* feat(sway): replace exit prompt with full session menu; drop fuzzel $PATH ↵Libravatar sommerfeld2026-05-132-3/+6
| | | | | | | | | | | listing - Mod+Shift+e: swaynag now offers Lock / Logout / Reboot / Poweroff instead of just 'Exit sway? Yes'. Reboot+Poweroff use doas; that's already nopass-permitted for wheel in etc/doas.conf - fuzzel.ini: drop list-executables-in-path=yes (back to upstream default). The launcher now shows only .desktop entries; power actions live in the Mod+Shift+e menu
* feat(waybar+sway): bluetooth module + unify wifi/bt toggle pathsLibravatar sommerfeld2026-05-135-8/+39
| | | | | | | | | | | | | | | - systemd-units/system/bt.txt: new file pairing the meta/bt.txt group; enables bluetooth.service via 'just unit-apply' - waybar: add the built-in bluetooth module; on-click runs the same bt-toggle.sh that XF86Bluetooth has always invoked. Status colors: blue when adapter is up, green when a device is connected, gray off - sway: XF86WLAN now runs wifi-toggle.sh (iwd D-Bus) instead of 'rfkill toggle wifi'. The latter required rfkill group membership (user is in wheel only), and aligning on the busctl path means the keybind and the waybar click drive the same code XF86RFKill (panic-disable all radios) keeps using 'rfkill toggle all' — that scope is genuinely rfkill-shaped.
* style(waybar): tighten right cluster — tray rightmost, drop disk, compact ↵Libravatar sommerfeld2026-05-132-17/+8
| | | | | | | | | | | | | MEM, drop LOAD label - modules-right: tray moved past clock to the rightmost slot; disk dropped (used% on btrfs is ambiguous and the value rarely moves) - custom/memory: drop the available-side readout, output 'MEM 3.2G 40%' instead of 'MEM 3.2G (40%) / 4.5G (56%)' - cpu: drop the 'LOAD' literal — bare '{load:0.2f}' next to the usage% is unambiguous in context The disk module config block is left intact for easy reactivation.
* style(waybar): group clickable modules on the right edgeLibravatar sommerfeld2026-05-131-3/+3
| | | | | | | Read-only stats (cpu, temp, memory, disk, network, battery, privacy) on the left half of modules-right; interactive ones (pulseaudio mute, wifi toggle, idle_inhibitor, mako history, thunderbird, tray, clock) clustered on the right.
* feat(waybar): more clickable modules + load avg in CPU readoutLibravatar sommerfeld2026-05-132-6/+34
| | | | | | | | | | | | | - cpu: append 'LOAD {load:0.2f}' (1-min load average) to every state - custom/wifi: left click toggles iwd Powered via D-Bus (new wifi-toggle.sh) - custom/notifications: left click opens fuzzel history picker (mako-history.sh, previously bound to middle-click); the awkward per-click 'makoctl dismiss' is dropped — dismiss-all stays on right, restore stays on middle - clock: left click runs tb-toggle.sh (closest practical proxy for 'open Calendar tab' — Thunderbird hasn't shipped a -calendar CLI flag since Lightning was integrated, so the user lands on whatever tab TB was last on)
* fix(sway): bump tb-autostart post-IMAP grace period 5s -> 10sLibravatar sommerfeld2026-05-131-1/+1
| | | | | 5s still wasn't enough on cold boot — Thunderbird kept racing the SMTP listener and showing the connection-failure dialog.
* fix(sway): import PASSWORD_STORE_DIR into user manager + dbus envLibravatar sommerfeld2026-05-131-2/+2
| | | | | | | | | | | | | zprofile sets PASSWORD_STORE_DIR to $XDG_DATA_HOME/password-store, but systemd-user-launched services (notably waybar's tb-unread.sh, which calls 'pass show') don't inherit it. Sway is started from the login shell so the var is in its environment — propagate it to the user manager and dbus activation env, same pattern as the XDG_SESSION_* vars. Resolves the same problem already worked around for protonmail-bridge.service via a drop-in override; that override is now redundant but kept as belt-and-braces.
* feat(waybar): add Thunderbird inbox-unread moduleLibravatar sommerfeld2026-05-133-1/+74
| | | | | | | | | | | Polls the protonmail-bridge IMAP socket every 60s with STATUS INBOX (UNSEEN), displays the count next to the tray, and clicking the badge runs tb-toggle.sh to bring TB out of the scratchpad (or launch it). Setup: store bridge credentials in pass at email/protonmail-bridge/{user, pass}. The bridge surfaces them via 'protonmail-bridge --cli' -> 'info'. With no entries (or with the bridge unreachable) the module shows 'MAIL ?' in red and is otherwise inert.
* fix(sway): extend post-IMAP SMTP grace period 1s -> 5sLibravatar sommerfeld2026-05-131-1/+1
| | | | | | The IMAP '* OK' banner arrives before the SMTP listener on 1025 is fully ready. 1s wasn't always enough — Thunderbird would still race into a 'failed to connect to 127.0.0.1, please retry' dialog.
* Revert "fix(sway): bump tb-autostart bridge IMAP wait 60s -> 180s"Libravatar sommerfeld2026-05-131-1/+1
| | | | This reverts commit 8b6d81742fa71aff76e602edc023c45ca4b38066.
* fix(sway): bump tb-autostart bridge IMAP wait 60s -> 180sLibravatar sommerfeld2026-05-131-1/+1
| | | | | | | ProtonMail Bridge cold-start (keyring unlock + account decryption) occasionally exceeds 60s, so the IMAP '* OK' banner never arrives in time and Thunderbird launches into a 'failed to connect to 127.0.0.1, please retry' dialog. Triple the budget to 180s.
* Revert "fix(sway): bump tb-autostart window-mark wait 20s -> 60s"Libravatar sommerfeld2026-05-131-1/+1
| | | | This reverts commit 9c051b2cb47ca6e60b6c76877be78cc529d9f4da.