Files
moonarch/CLAUDE.md
T
nevaforget 806841d435
Update PKGBUILD version / update-pkgver (push) Successful in 3s
feat(portal): keep windowed browser video from sleeping the screen
Add /etc/xdg-desktop-portal/niri-portals.conf with Inhibit=none. The gtk
portal reports Inhibit success even though nothing implements it under Niri,
so Firefox/Waterfox skips the native Wayland idle-inhibit. With no backend the
browser falls back to zwp_idle_inhibit, which Niri honors.
2026-06-12 11:10:00 +02:00

6.6 KiB

Moonarch

Reproduzierbares Arch-Linux-Setup basierend auf archinstall + Post-Install-Automatisierung.

Projektstruktur

  • config/ — archinstall-Konfiguration (inkl. custom-commands die das Repo nach /opt/moonarch klonen, root-owned)
  • scripts/ — Post-Install- und Helper-Scripts
  • packages/ — Paketlisten (offiziell + AUR), getrennt gepflegt
  • defaults/ — XDG-Configs, Shell-Config, Helper-Binaries, systemd Services, udev-Regeln, greetd/moongreet-Config, Wallpaper

Battery Conservation Mode

Laptops mit charge_control_end_threshold-Support (ThinkPad, Framework, etc.) erhalten einen Waybar-Toggle:

  • Klick auf das Battery-Modul schaltet zwischen 80% und 100% Ladegrenze um
  • Bei aktiver Conservation erscheint ein ♥-Icon neben der Battery-Anzeige
  • Zustand wird in /var/lib/moonarch/batsaver-threshold persistiert und beim Boot via systemd-Service (moonarch-batsaver-restore) wiederhergestellt
  • Toggle-Flow: moonarch-batsaver-toggle (User-Script) liest sysfs, entscheidet 80↔100, ruft pkexec /usr/bin/moonarch-batsaver-apply $NEW für den privilegierten sysfs+state-Schreibschritt. Standard-pkexec-Prompt (Passwort einmal pro Session-Cache)
  • Auf Desktops ohne Battery-Support versteckt sich das Feature komplett

Nightlight (Blaufilter)

Waybar-Toggle für wlsunset (Wayland-nativer Blaufilter), persistenter Zustand via systemd:

  • wlsunset.service (systemd User-Service) mit After=kanshi.service — startet erst wenn alle Outputs konfiguriert sind
  • Default OFF — frische Installs starten ohne Filter. PKGBUILD legt für wlsunset bewusst KEINEN Symlink in /etc/systemd/user/graphical-session.target.wants/ an, post-install.sh enabled den Service nicht.
  • Klick auf das Nightlight-Modul in group/brightness toggled wlsunset an/aus (enable --now / disable --now)
  • Zustand überlebt Reboots (User-Scope-Symlink in ~/.config/systemd/user/...wants/)
  • Aktiver Zustand zeigt 󰌵 in Catppuccin Yellow, inaktiv 󰌶 in Standard-Textfarbe
  • Signal SIGRTMIN+11 für sofortiges Waybar-Refresh
  • Scripts: moonarch-nightlight (Toggle), moonarch-waybar-nightlight (Status-JSON)
  • Wichtig: Auf gar keinen Fall einen Global-Scope-Symlink in /etc/systemd/user/...wants/wlsunset.service anlegen — der überstimmt jedes User-disable und macht den Filter de-facto unausschaltbar.

Waybar Config Merger (moonarch-waybar)

Waybar wird über moonarch-waybar gestartet (nicht direkt). Der Wrapper merged eine optionale User-Config (~/.config/waybar/userconfig) mit der System-Config (/etc/xdg/waybar/config):

  • prepend/append-Keys in der userconfig erweitern modules-left/modules-center/modules-right Arrays
  • Alle anderen Top-Level-Keys werden als Modul-Definitionen per Object-Merge eingefügt
  • Merge wird nur bei Änderungen ausgeführt (Timestamp-Vergleich)
  • Bei Fehler: notify-send + logger, Waybar startet mit System-Config
  • Generiert ~/.config/waybar/style.css mit @import der System-Styles falls nicht vorhanden
  • Benötigt jq (in PKGBUILD als Dependency)
  • System-Config muss valides JSON sein (kein JSONC)

mpv + ModernZ OSC

Videoplayer ist mpv mit ModernZ als OSC, Thumbnails via thumbfast:

  • mpv-modernz-git liefert modernz.lua + Font + Default-Config nach /etc/mpv/
  • mpv-thumbfast-git liefert thumbfast.lua nach /etc/mpv/scripts/ (wird von ModernZ automatisch erkannt)
  • defaults/etc/mpv/mpv.conf wird von moonarch-git direkt nach /etc/mpv/mpv.conf installiert (owned)
  • Stock-OSC + Titelleiste deaktiviert, autofit-larger=80%x80% cappt übergroße Fenster
  • ModernZ-Overrides per script-opts-append in mpv.conf: Orange-Akzent → Catppuccin Lavender (#b4befe), OSC-Scale 0.75, window_title_font_size=18, ontop_button=no
  • Wichtig: mpv behandelt # als Mid-Line-Kommentar; Hex-Farben müssen gequotet werden: script-opts-append="modernz-seekbarfg_color=#b4befe" (nicht \#, das escaped nur und verschluckt den Rest)
  • Niri öffnet mpv floating (window-rule in defaults/xdg/niri/config.kdl)

System Health Check (moonarch-doctor / moondoc)

Diagnose-Script das den Systemzustand gegen moonarch-Defaults prüft:

  • Pakete (official.txt + aur.txt installiert? Orphans?)
  • System-Services (NetworkManager, bluetooth, greetd, ufw, auto-cpufreq, etc.)
  • User-Services (kanshi, wlsunset, stasis, walker, nautilus, cliphist-text, cliphist-image)
  • Config-Dateien (SHA256-Vergleich deployed vs. moonarch-Default)
  • Helper-Scripts + Symlinks (moonup, moondoc)
  • System-Config (UFW, Pacman/Paru Repos, Default Shell)
  • Verzeichnisse + Permissions

Fontconfig Defaults

Systemweite generic-family Defaults via defaults/etc/fonts/conf.d/65-moonarch-fonts.conf (owned by moonarch-git):

  • sans-serif → UbuntuSans Nerd Font, monospace → UbuntuSansMono Nerd Font
  • Nummer 65: lädt nach 60-latin.conf, sodass die moonarch-Prefs den Stock-Default (Noto/DejaVu) schlagen. local.conf (bei 51 via 51-local.conf) lädt zu früh und wird von 60-latin überstimmt — daher nicht verwenden (außerdem für lokale User-Overrides reserviert).
  • Aliases brauchen binding="strong" — ein weak <prefer> (fontconfig-Default) rankt hinter dem effektiven generischen Fallback und greift nicht.
  • Greift nur für Apps die generische Familien nutzen (z.B. Firefox-Web-Fallback). moonarch-Apps (Waybar, foot, GTK, walker, swaync) setzen den Font explizit.

Browser Idle-Inhibit (xdg-desktop-portal)

Damit Fenster-Browservideo (Firefox/Waterfox) den Screen wachhält, via defaults/etc/xdg-desktop-portal/niri-portals.conf (owned by moonarch-git, höhere Priorität als niris /usr/share/xdg-desktop-portal/niri-portals.conf):

  • xdg-desktop-portal-gtk meldet das Inhibit-Interface als success, obwohl es unter Niri niemand implementiert → Firefox glaubt, der Idle-Inhibit lief über den Portal, und nutzt den nativen Wayland-idle-inhibit nicht. Ergebnis: kein Inhibitor, Screen schläft.
  • Fix: org.freedesktop.impl.portal.Inhibit=none → Firefox fällt auf zwp_idle_inhibit zurück, den Niri honoriert. Die übrigen [preferred]-Zeilen sind 1:1 von niris Default übernommen (portals.conf wird nicht gemerged — die höchstpriore Datei gilt komplett).
  • stasis ist hier unbeteiligt: monitor_media (pactl) erfasst Browser-Audio per Design nicht (nur Non-Browser-Player); Browser laufen über den Inhibit-Pfad.
  • Aktivierung: xdg-desktop-portal + Browser neu starten — Firefox fragt den Portal-Support beim Start ab.

Konventionen

  • Paketlisten sind einfache Textdateien, ein Paket pro Zeile, Kommentare mit #
  • Shell-Scripts müssen POSIX-kompatibel oder explizit bash/zsh sein
  • Alle Pfade im archinstall-Config relativ zum Installationsziel