Commit Graph
37 Commits
Author SHA1 Message Date
nevaforget a3bd6a04a1 feat(quickshell): power popout replaces moonset
Five rows over a model, registered from Launcher.qml under "power" with
the borrowed anchor the clipboard popout uses, so shell.qml and every
user copy of it stay unchanged. Mod+Escape calls the popout by IPC.

Logout goes through `loginctl terminate-session self`, which needs no
XDG_SESSION_ID in the shell environment. Glyph codepoints were read out
of UbuntuSansNerdFont-Regular.ttf.

The reserve Waybar's power button keeps the IPC call and says in its
tooltip that it needs the Quickshell bar; there is no way to reach a
Quickshell popout from a session where Quickshell was killed.
2026-08-14 17:47:06 +02:00
nevaforget 77eb787b61 feat: replace moongreet with regreet, moonlock with swaylock
Greeter and lock screen move to the official repos. The greeter keeps
running inside its own niri instance, so niri-greeter.kdl only changes
which binary it spawns; regreet.toml and regreet.css return from 7e29246^
with current theme and font names.

swaylock replaces moonlock in the stasis lid and lock_screen actions. Its
config is seeded to the user home, because swaylock never reads /etc/xdg
and the system-wide path does not work on NixOS.

moonlock stays installed: moonset invokes it by name and has no
lock_command option yet.
2026-08-14 14:21:13 +02:00
nevaforget de142ef73f feat(quickshell): replace walker's clipboard picker
Super+C opened walker's clipboard provider — the last keybind that still
reached walker at all. ClipboardPopout takes over and shells out to
cliphist: list on every open (cliphist has no change signal, so the open
is the refresh point), decode | wl-copy on Enter or click, and delete
with the entry's raw list line on stdin. Every call carries -db-path,
because the history lives in the session db that cliphist-text.service
creates, not in cliphist's ~/.cache default; every shell argument is
positional, so no clipboard content becomes part of a script.

Delete is Ctrl+D, not Del: focus sits in the search field, where Del is
a character delete. It is also what walker's provider used. A footer
hint spells the keys out, since a destructive shortcut is not guessable.

Image entries have no text preview, only a "[[ binary data 6 KiB png
128x128 ]]" placeholder. That placeholder now yields both the thumbnail
extension and a readable "png · 128x128 · 6 KiB" label, and the entry is
decoded to $XDG_RUNTIME_DIR/moonarch-clip for an Image to load — one
decode process per row, so rows do not serialize. The directory is
tmpfs, so thumbnails expire with the session like the history itself.

The popout is keybind-only, but register() needs an on-screen item for
the anchor rect, so it registers from Launcher.qml and borrows that one.
That also leaves shell.qml — and therefore every user copy of it —
unchanged. walker stays installed: moonarch-sink-switcher,
moonarch-cpugov and moonarch-vpn use it as a dmenu, and those are live
in the Waybar reserve config.
2026-08-10 17:04:39 +02:00
nevaforget b5fabbc0be feat(quickshell): open a calendar on clock click
The clock's click toggled the date between short and long form, which the
tooltip already showed in full. It now opens a calendar popout instead.

CalendarPopout uses MonthGrid + WeekNumberColumn + DayOfWeekRow from
QtQuick.Controls (already imported by TrayMenu) so the locale rules —
week start, ISO week numbers, weekday and month names — come from Qt
rather than being re-implemented; only the delegates are ours. Leading
and trailing days stay visible but dimmed, since the grid always renders
six weeks and hiding them would leave the week-number column labelling
blank rows.

Clock takes the full bar height on `height`, not `implicitHeight`: on a
Text root that property is read-only, and the assignment fails the config
load outright.
2026-08-03 11:06:50 +02:00
nevaforget b710b48c0e feat(quickshell): add camera switch module
Cameras are off after every boot and get switched on per camera from the
bar. This inverts the privacy problem instead of chasing it: the previous
entry point, detecting camera *use*, cannot see raw V4L2 access at all,
and inotify on /dev/video* cannot tell a real capture from a device query.
An unauthorized camera cannot be opened in the first place.

Mechanism is `authorized` on the USB device. Measured: writing 0 drops the
/dev/videoN nodes and the PipeWire node, writing 1 brings them back and
uvcvideo rebinds itself.

A camera is identified by USB interface class 0x0e in the descriptor blob,
which stays complete while the device is deauthorized (the interface
directories do not) — so no state of our own is needed to keep a
switched-off camera listable and switchable.

The privileged helper re-derives every precondition from kernel data: id
shape, resolved path under /sys/devices, DEVTYPE=usb_device, and a video
interface class. It cannot be used to deauthorize a hub, keyboard or disk.

Switching a camera on authorizes the whole USB device, so the popout names
every other function it carries and flags in red what does not belong on a
camera. Shown rather than blocked: the internal camera carries a DFU
interface and multimedia devices commonly expose HID for their buttons, so
a class filter would lock out legitimate hardware.

Device-supplied labels are rendered as plain text and stripped of the
invisible and directional Unicode range, so a name cannot masquerade as
another device's.

A hot-plugged camera stays on — plugging one in is a deliberate act.
2026-07-29 16:46:56 +02:00
nevaforget f489495240 fix(quickshell): repair privacy indicator detection
The indicator never became visible. Three causes, each measured with
throwaway probe configs against quickshell 0.3.0:

- Link groups report state Unlinked (-1) unless bound by a
  PwObjectTracker, so the "is the link active" guard rejected
  everything. Node properties need the same binding.
- PwNodeType flags share bits between in- and out-streams
  (AudioInStream 13, AudioOutStream 21), so the bitwise test also
  matched playback — browser audio alone set micActive.
- Video streams are left as Untracked with isStream false, so no
  screencast or camera could ever match.

Match media.class of active link endpoints instead, the signal waybar's
privacy module uses. Desktop-audio recording is excluded via the peer
class Audio/Sink, since quickshell does not expose stream.monitor.

Raw V4L2 camera use stays undetectable (no pipewire node exists);
rationale for not observing /dev/video* is in DECISIONS.md.
2026-07-29 14:28:12 +02:00
nevaforget dd81b39635 feat(quickshell): bar height 36, invert geometry coupling, unify centering
moduleHeight (24) becomes the primary vertical token and barHeight is
derived as moduleHeight + moduleMarginV * 2. Previously ModuleBox sized
its pill as barHeight - moduleMarginV * 2, so lowering the bar shrank
every pill by the same amount — the margin is absolute and does not
scale. Bar height is now set via moduleMarginV while the pills hold.

Widget implicitHeight stays on barHeight: ModuleBox has no clip, so the
items overflow the pill and keep the whole bar height clickable, which
matters because the display edge stops the pointer.

Also fixes pre-existing vertical centering. anchors.verticalCenter
centers the Text layout box (ascent + descent) and rounds down on an odd
layout height, which put the network and bluetooth glyphs 1 px above the
bar mid and several others off by 0.5 px. Replaced across 13 widgets with
height: parent.height + verticalAlignment: Text.AlignVCenter, which
centers by font metrics. Workspace dots move from a hardcoded 22 to
moduleHeight.

Verified by pixel measurement: all 7 pills on rows 6-29 (mid 17.50 = bar
mid) and all 14 glyphs with even ink height exactly on 17.50. The
remaining 7 have odd ink height, where 17.50 is not representable on the
pixel grid; two of those are Image, where verticalAlignment does not
apply.
2026-07-28 12:03:32 +02:00
nevaforget ff8c9c393b fix(quickshell): prefer wired over wifi in network widget
When both a wired and a wifi connection are up, NetworkManager routes
over ethernet (lower metric) and nm-applet shows the wired icon. The
network indicator and popout checked wifi first, so an ethernet-connected
machine with wifi still associated wrongly showed the wifi glyph and
SSID. Check wiredDev first in the icon, tooltip, popout activeDev, and
compact connection text.
2026-07-16 15:13:56 +02:00
nevaforget 78762d7f40 feat(qt): theme Qt apps with Catppuccin via Kvantum
Qt apps (e.g. VLC) rendered in the default Fusion style — GTK theming
does not cover Qt. Add the Kvantum style engine + Catppuccin Mocha
Lavender theme, wired via QT_STYLE_OVERRIDE, which covers both Qt5 and
Qt6 (QT_QPA_PLATFORMTHEME can select only one plugin at a time).

Also move all GUI-toolkit env vars (QT_*/GDK/SDL/CLUTTER) from zshrc to
niri's environment{} block: niri is systemd-started, so zsh exports
never reached niri-spawned GUI apps (verified via /proc/environ), only
terminal-launched ones — the app launcher included.

- packages: kvantum, kvantum-qt5, qt6ct + kvantum-theme-catppuccin-git (AUR)
- niri config.kdl: environment{} block; zshrc: GUI-toolkit vars removed
- qt6ct.conf (style=kvantum, icon_theme=Colloid), Kvantum/kvantum.kvconfig
  (theme=catppuccin-mocha-lavender, the Lavender accent)
- CLAUDE.md + DECISIONS.md
2026-07-15 15:20:21 +02:00
nevaforget 7bd15e36f3 feat(niri): bind Mod+Space to the quickshell launcher
Replace walker on Mod+Space with the quickshell launcher popout
(qs ipc call popout toggle launcher). walker stays installed and keeps
Super+C clipboard plus its run/calc modes (no longer keybound).
2026-07-15 13:13:46 +02:00
nevaforget ce879c64f0 feat(quickshell): show connecting, VPN, and wired state on the network indicator
The bar icon only knew off/no-connection/signal strength: an NM (re)connect
read as "no connection", an active VPN was invisible, and a wired-only
machine showed a dead wifi glyph.

- Connecting: cycle the strength ramp (nm-applet style) while the wifi
  device is in ConnectionState.Connecting (covers reconnects too)
- VPN: swap to MDI wifi-strength-N-lock glyphs; wired+VPN uses
  security-network (MDI has no ethernet-lock); tooltip lists active VPNs
- Wired: ethernet glyph, ranked above wifi-off so ethernet-only machines
  show their connection

VPN state moves from NetworkPopout (2s poll while shown) into a shared
NetworkService singleton — the indicator needs it permanently, and an
always-on poll is wasteful. Event-driven via a long-running `nmcli monitor`
(300ms debounce, events burst) with a 60s fallback poll. Rationale:
DECISIONS.md (2026-07-08).
2026-07-08 15:42:26 +02:00
nevaforget aac717867b feat(quickshell): add application launcher + hover affordance
New Launcher bar widget (first in the left cluster) opening a LauncherPopout
over DesktopEntries — search field + keyboard-navigable app list, launches via
entry.execute(). Icon-click only for now; Mod+Space stays on walker (drun-only
scope, walker keeps dmenu/run/calc).

Placing a popout in the left cluster forced the shared host anchor to become
side-aware: left-cluster triggers left-align (body grows rightward), right
cluster keeps the original right-align — otherwise a left-anchored popout
renders off-screen. The anchor rect now carries the trigger's left edge + width
(PopoutState.openByName, Tray).

Clickable bar widgets gain a hover affordance via opacity (0.8), not color:
the icon color already encodes status (muted/off/active/critical), so a
color-based hover would clobber that signal. Launcher keeps an accent hover as
it carries no status color.
2026-07-08 11:09:28 +02:00
nevaforget 54b22a9141 feat(quickshell): operate popouts fully by keyboard
Popouts can now be opened by niri keybind and driven entirely without a
mouse — the whole point of the keybinds.

- keybind: PopoutRouter singleton + IpcHandler (target "popout") route
  toggle/open/close to the focused monitor's PopoutState via
  Niri.activeOutput; each widget registers its popout by name and its
  click handler toggles by name. Mod+A now opens the audio popout
  (replacing walker's audio menu).
- navigation: shared controls (Toggle/ListRow/VolumeSlider) and the new
  IconButton are focusable (activeFocusOnTab, focus ring, Space/Enter,
  slider Left/Right); PopoutPanel focuses the first control on open and
  maps Up/Down onto Qt's Tab chain; an open popout grabs the keyboard.
- ad-hoc glyph buttons (audio mute, media transport, notif dismiss, BT
  forget) folded into IconButton; destructive actions turn red.

Tray stays mouse-only (per-icon menu, not keybind-addressable).
2026-07-08 09:46:01 +02:00
nevaforget be259afb51 fix(quickshell): tie up loose ends from the popout composition refactor
The composition + composable-popouts refactor (5120b77, 411d8b0) left
three rough edges:

- 6 popouts still read the removed PopoutState.currentName in their
  `shown` gate (undefined === "x" → permanently false), so wifi scan,
  bluetooth discovery, threshold reread, governor refresh, toast-silence
  and tray drill-down reset never fired again. Only the current component
  is ever instantiated, so `hasCurrent` alone is the correct gate.
- ModuleBox stopped self-hiding when empty: the Battery box on a desktop
  (no battery) and an empty tray rendered a bare rounded pill. Gate the
  shared container on `inner.implicitWidth > 0` so the fix covers both.
- CLAUDE.md customization example missed `import Quickshell` (unloadable
  as written) and called a Row's rejected centerIn anchor "harmless"
  (Row warns at runtime and ignores it).
2026-07-06 23:34:35 +02:00
nevaforget 411d8b03bb feat(quickshell): composable popouts — each widget owns its popout
The composition refactor left Popouts.qml a hardcoded switch, so a
user-composed widget could join the bar but couldn't open a popout in
the shared animated overlay — second-class, and a widget without a
popout is useless for most cases. quickshell's native PopupWindow would
be composable but drops the unfold/morph animation; keep the animation,
make the registry composable instead (caelestia's central Panels.qml
registry was considered and rejected — it fits a few author-owned edge
drawers, not many user-composable per-widget popouts).

PopoutState.open() now takes a Component instead of a name; each widget
carries its popout inline and hands it to the shared host, which renders
whatever is current. Popouts.qml is gone — no central registry, a user
widget brings its own popout and it renders in the same morphing frame.

Verified: qmllint clean, and an end-to-end config where a user widget
opens its own popout on startup instantiates with no errors or binding
loops. Visual/animation not machine-verifiable.
2026-07-06 17:17:59 +02:00
nevaforget 5120b777a5 refactor(quickshell)!: replace toggle-config with QML composition
The user-extension layer (moonarch.json + UserConfig singleton +
per-widget enabled() gates + UserWidgets slot) was a bespoke graft.
quickshell has no native settings/toggle/override concept — a config
is composable QML, and $XDG_CONFIG_HOME wins over $XDG_CONFIG_DIRS
(verified in the docs and src/launch/command.cpp).

Ship the bar as a named config (/etc/xdg/quickshell/moonarch/, launched
`-c moonarch`) of importable components; the composition (which widgets,
in what order) lives in shell.qml. Users customize by copying shell.qml
to ~/.config/quickshell/moonarch/ (wins by XDG precedence) and editing
it — reorder, add, and replace all fall out of plain composition, which
also retires the deferred reorder/user-popout/override items.

Also fixes the ModuleBox childrenRect binding loop (Item -> Row).

BREAKING CHANGE: ~/.config/quickshell/moonarch.json and UserWidgets.qml
are no longer read; per-widget toggles are gone in favor of composition.

Verified: qmllint clean (only quickshell C++ type-resolution artifacts),
quickshell loads the default config and a cross-dir composed config with
no binding loops or errors.
2026-07-06 13:17:36 +02:00
nevaforget aeb611f762 feat: make quickshell the default bar + notification daemon
The quickshell pilot proved out in daily use; promote it from manual
pilot to the session default. Additive — no hard deletes: Waybar and
swaync stay installed as reserves.

- niri spawns `quickshell` instead of `moonarch-waybar`; Alt+W toggles
  quickshell ⇄ Waybar for the rare fallback
- swaync's spawn-at-startup is commented out so it releases
  org.freedesktop.Notifications for quickshell's own server (verified:
  quickshell owns the name; flip the comment to return to swaync)
- quickshell added to packages/official.txt (config ships automatically
  via moonarch-git's defaults/xdg install loop)

Remaining: push → CI rebuilds moonarch-git → pacman -Syu; niri changes
take effect on relogin.
2026-07-05 21:00:36 +02:00
nevaforget e9c12c1790 feat(quickshell): user-extendable bar via config toggles + widget slot
quickshell has no native config merge, so the system bar could only be
adopted wholesale (fork it, lose system updates). This adds an in-repo
extension path: users toggle widgets and add their own without forking.

- UserConfig singleton reads ~/.config/quickshell/moonarch.json
  ({"widgets":{"<key>":false}}); absent/broken = all on, live-reloaded
- qmldir (generated) exposes singletons + components so user QML can
  import "file:///etc/xdg/quickshell" and reuse Theme/ModuleBox/…
- Bar gates its 16 widgets on UserConfig.enabled(key) and loads an
  optional UserWidgets.qml into a right-cluster slot
- verified against quickshell 0.3.0: toggles hide widgets, user widget
  themes correctly, empty/broken config keeps everything on, no binding loops

Pilot only — qmldir must ship when the pilot is packaged. See DECISIONS.md.
2026-07-05 20:00:58 +02:00
nevaforget a6a81e0bca fix(nightlight): keep wlsunset alive when Waybar is absent
ExecStartPost signalled Waybar via `pkill -RTMIN+11 waybar`; with no Waybar
running (e.g. a quickshell-only session) pkill exits 1, which failed the unit
and — via Restart=on-failure — spun wlsunset in a ~3s restart loop that
flickered the screen and could not be switched off (stuck "activating").

Prefix the ExecStartPost with `-` so a missing Waybar is non-fatal. The
refresh signal still fires when Waybar is present.
2026-07-05 10:09:26 +02:00
nevaforget 61a05005c1 docs: translate CLAUDE.md to English
Per the committed=English rule. Also documents the windowed-video idle-inhibit added in the same series.
2026-06-16 10:46:05 +02:00
nevaforget 5cae137938 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
nevaforget 2590ab7ea8 fix(fonts): repair Waybar font and add system-wide fontconfig defaults
Nerd Fonts renamed "Ubuntu" -> "UbuntuSans"; Waybar's dead family name token-matched to Hack. Correct the explicit name and ship owned conf.d defaults mapping the generic families to the moonarch fonts.

- waybar/style.css: "Ubuntu Nerd Font" -> "UbuntuSans Nerd Font"
- conf.d/65-moonarch-fonts.conf: sans-serif/monospace, binding="strong" (weak prefer ranks behind the generic fallback)
- document fontconfig defaults in CLAUDE.md and DECISIONS.md
2026-06-08 13:39:25 +02:00
nevaforget 4c0ade5cdf fix(nightlight): default OFF, drop wlsunset from auto-enable list
Coordinated fix with moonarch-pkgbuilds: post-install.sh enabled
wlsunset by default, while the PKGBUILD shipped a global-scope
WantedBy symlink. Together that made the toggle's user-scope disable
a no-op — filter persisted across reboots regardless of user intent.

Removing wlsunset from USER_SERVICES makes "off" the install default;
the toggle now works in user scope only, where disable can take effect.
2026-05-04 14:15:58 +02:00
nevaforget f3a863f755 batsaver: switch to pkexec helper, drop broken udev permission hack
The wheel-write-via-udev approach for charge_control_end_threshold has
been broken since 2026-04-08: the audit-remediation commit added
ACTION=="add" to the rule, but the threshold attribute doesn't exist
yet at the add event on Lenovo, so chmod fails silently and permissions
are never set. moonarch-batsaver-toggle has been returning Permission
denied since.

Replace the udev-rule approach with a pkexec helper:

  defaults/bin/moonarch-batsaver-apply    privileged: validate + write
  defaults/bin/moonarch-batsaver-toggle   user: read sysfs, dispatch via pkexec
  defaults/bin/moonarch-batsaver-restore  boot-time root restore (extracted
                                          from inline ExecStart for clarity)

Default Standard-pkexec prompt — password cached per session for the
~5min auth window; no polkit no-password rule, no privilege escalation
surface from misvalidated input. Same pattern Battery-Health-Charging
GNOME extension uses.

The boot-time restore service now skips the kernel write when the
sysfs value already matches the saved state (Lenovo drivers reject
same-value writes with EINVAL).

DECISIONS.md documents the failure analysis and trade-offs.
CLAUDE.md updated to describe the new flow.
moonarch-doctor: udev-effectiveness check removed.
2026-05-04 12:17:31 +02:00
nevaforget 30f952190d refactor(mpv): move ModernZ overrides into mpv.conf via script-opts-append
- drop defaults/etc/mpv/script-opts/modernz.conf (deploy timing conflict
  with mpv-modernz-git)
- put all ModernZ tweaks in mpv.conf: Catppuccin Lavender accent, scale
  0.75, title font 18, ontop_button off, autofit-larger 80%
- quote hex values to survive mpv's mid-line # comment parsing
- niri window-rule opens mpv floating
- doctor no longer compares mpv configs (now directly owned by pkg)
2026-04-24 17:52:12 +02:00
nevaforget a4fa48593d feat: add mpv with ModernZ OSC as default video player
- mpv-modernz-git + mpv-thumbfast-git in aur.txt
- /etc/mpv/mpv.conf disables stock OSC + title bar
- /etc/mpv/script-opts/modernz.conf overrides colors to Catppuccin Mocha (lavender accent)
- moonarch-doctor checks deployed mpv configs
2026-04-24 17:32:05 +02:00
nevaforget 00a774d0d8 fix(doctor): drop obsolete paru repo check, cover walker + nautilus
The `[moonarch-pkgbuilds]` paru-repo check was a false failure: that
mechanism was retired on 2026-04-20 and the install hook strips the
legacy paru.conf section on upgrade.

Audit of the rest of the doctor surfaced two related gaps — the
user-services loop skipped `walker.service` and `nautilus.service`,
even though moonarch-git ships both and enables them via
graphical-session.target.wants. Added them to the loop and filled in
the missing `wlsunset` in the CLAUDE.md listing.
2026-04-22 08:56:23 +02:00
nevaforget d6e61b4f0b refactor(install): restore fresh-install flow, drop transform.sh and personas
Long-standing gaps in post-install.sh plus cleanup:

- post-install.sh:18 was `sudo pacman -S paru` on the wrong
  assumption paru had landed in [extra]. Verified: paru/paru-bin
  are AUR-only. Restored the original git-clone + makepkg
  bootstrap, added the rust buildep that archinstall does not
  pull in.
- post-install.sh never installed AUR extras — walker, elephant,
  waypaper, stasis, themes all silently skipped. Now pulls
  packages/aur.txt after moonarch-git.
- packages/official.txt: drop glab, go, npm (unused) and rustup
  (only needed for the paru build, handled imperatively now).
- packages/aur.txt: add walker-bin (was missing entirely).
- transform.sh + legacy update.sh shim removed — transform was
  never used in practice.
- Apollo persona block out of CLAUDE.md, prior DECISIONS entries
  rewritten from Apollo/Ragnar to ClaudeCode.
- README Transform section and scripts/ listing trimmed.
- lib.sh ABOUTME updated — only post-install.sh sources it now.
2026-04-21 09:04:23 +02:00
nevaforget 5f475195e4 feat: manage wlsunset via systemd user service
Move nightlight from niri spawn-at-startup to a systemd user service
with After=kanshi.service to ensure all outputs are configured before
wlsunset starts. Toggle now uses enable/disable --now for persistent
state across reboots.
2026-04-14 17:42:24 +02:00
nevaforget c669fc7bfc docs: add moonarch-doctor and shorthand aliases to README and CLAUDE.md 2026-04-10 08:21:38 +02:00
nevaforget cda7a1eca7 feat: add moonarch-waybar config merger wrapper
Waybar's include directive cannot merge arrays, making per-machine
module customization impossible without duplicating the entire config.

moonarch-waybar merges an optional ~/.config/waybar/userconfig with
the system config, supporting prepend/append on module arrays and
object merge for module definitions. Generates user style.css with
@import of system styles on first run.

System waybar config converted from JSONC to valid JSON for jq
compatibility. Niri startup and hotkey updated to use the wrapper.
2026-04-09 17:04:24 +02:00
nevaforget da6b492e20 feat: add wlsunset nightlight toggle with Waybar module
Add blue light filter support via wlsunset, toggleable through a Waybar
module in the brightness group. Nightlight icon is the primary element,
backlight slider expands on click.

- Add wlsunset package to official.txt
- Add moonarch-nightlight toggle script (kill/restart wlsunset)
- Add moonarch-waybar-nightlight status script (JSON output)
- Add custom/nightlight module to group/brightness in Waybar config
- Add Catppuccin Yellow highlight for active nightlight state
- Add wlsunset autostart in Niri config (5000K night temperature)
2026-04-09 12:08:35 +02:00
nevaforget 1ebe0fac2b feat: add battery conservation mode with Waybar toggle
Laptops with charge_control_end_threshold support get a click-to-toggle
on the battery module (80% ↔ 100%). A ♥ icon appears when conservation
is active, hidden when inactive. State persists across reboots via
systemd oneshot service. udev rule grants wheel group write access
so no sudo is needed for toggling.
2026-04-08 09:55:46 +02:00
nevaforget 955486c7a8 docs: fix remaining stale references in README and CLAUDE.md
- scripts/: replace update.sh with moonarch-update, fix description
- Update section: remove stale "syncs repo, deploys XDG" claim
- User services: add stasis to table
- CLAUDE.md: mention systemd user services in defaults/ description
2026-04-07 11:37:44 +02:00
nevaforget 4bd853c2a0 Make /opt/moonarch root-owned for multi-user support
Remove chown from archinstall custom-commands so the repo stays
root:root. Use sudo for git operations in update.sh. Any user with
sudo can now run moonarch-update without owning the repo.
2026-03-29 15:23:39 +02:00
nevaforget 7e292468bf feat: regreet durch moongreet ersetzen, einheitliches Default-Wallpaper
Greeter von regreet (niri-Wrapper) auf moongreet (GTK4 + gtk4-layer-shell)
umgestellt. moongreet wird direkt aus dem Gitea-Repo gebaut.

Ein einziges Wallpaper unter /usr/share/moonarch/wallpaper.jpg dient jetzt
als Default fuer Desktop (waypaper), Lockscreen (gtklock) und Greeter
(moongreet).
2026-03-26 12:17:18 +01:00
nevaforget 2e5ecf57f5 Initial commit: Moonarch reproduzierbares Arch-Linux-Setup
Niri-basierter Wayland-Desktop mit greetd/regreet, Catppuccin Mocha
Theming, Rofi-Menus, Waybar und vollstaendiger Post-Install-Automatisierung.

Archinstall-Config klont das Repo automatisch via custom-commands,
danach genuegt ein einzelner Befehl fuer die komplette Einrichtung.
2026-03-23 17:42:26 +01:00