diff --git a/.claude/adr/0003-hyprland-compositor.md b/.claude/adr/0003-hyprland-compositor.md new file mode 100644 index 0000000..bebf64e --- /dev/null +++ b/.claude/adr/0003-hyprland-compositor.md @@ -0,0 +1,34 @@ +--- +status: accepted +--- + +# Hyprland as the keyboard-driven desktop compositor + +The graphical desktop is built on **Hyprland**, a keyboard-driven Wayland tiling compositor, as a single choice serving both the laptop (neogaia) and the future desktop (zeus). +It matches how the operator already works: an i3 model of numbered workspaces and manual tiling, ported to bindings reachable entirely on a 60% keyboard. +Among true tilers it comes closest to "just works" through its cohesive first-party companion tools (lock, idle, wallpaper, portal) and a large ecosystem, which buys down the assembly-and-breakage cost that made past minimal tiling setups expensive for the operator. + +The gaming and driver dimension does not constrain the choice, because both Hosts drive Wayland without caveats: neogaia is Intel and zeus is AMD. +Notably zeus is AMD, not Nvidia — Raichu is the only Nvidia machine, and it is a server with no desktop — so no Nvidia-on-Wayland pressure shapes the decision. +With gaming survival off the table, the choice rests on workflow and low-friction rather than on tolerating a hostile driver. + +## Considered Options + +- **Sway.** Rejected: its i3-faithful minimalism is precisely what historically cost the operator hours of assembly and breakage. + On AMD it games fine, but its only remaining edge over Hyprland was stability and purity — which the repo's pinning already provides, and which the operator's stated "just works" priority actively discounts. +- **KDE Plasma.** Rejected: the most integrated and lowest-friction option, the best AMD gaming desktop, and the operator's prior environment — but mouse-first at its core and only keyboard-navigable at the margins, which works against the primary keyboard-first requirement. + Its custom-tile-layout feature is an approximation of tiling on a floating desktop, not real automatic tiling. +- **niri.** Rejected: its scrollable-tiling paradigm abandons numbered workspaces, which breaks the operator's core muscle memory of switching by number. + It also has the smallest community of the candidates, a low-friction risk for a daily-driver desktop. +- **A different compositor per Host** (a keyboard-pure laptop plus a separate gaming desktop). Rejected: it doubles the configuration and maintenance and defeats the goal of one transferable setup. + It is unnecessary once AMD removes any gaming penalty from a keyboard-first compositor. + +## Consequences + +- One desktop Module set serves both Hosts. + zeus adopts the identical desktop by enabling a single flag, with battery-sensitive knobs such as blur flipped on for its AMD headroom. +- Hyprland's churn and occasional breakage are absorbed by the pinned, declarative, reversible configuration rather than by live fixing, so upgrades happen on the operator's schedule. +- The desktop's lock, idle, keybind syntax, and portal are Hyprland-specific, so a future move to another compositor would be a rewrite rather than a swap. + This is the accepted cost of the first-party-cohesion benefit. +- Hyprland is taken from nixpkgs, with no compositor plugins this pass. + Adopting the upstream Hyprland flake later, for a plugin or a bleeding-edge feature, is a contained change that mirrors the existing chaotic-nyx input pattern (an input that must not follow nixpkgs, carrying its own binary cache). diff --git a/.claude/spec/hyprland-desktop.md b/.claude/spec/hyprland-desktop.md new file mode 100644 index 0000000..82a07b3 --- /dev/null +++ b/.claude/spec/hyprland-desktop.md @@ -0,0 +1,173 @@ +## Problem Statement + +Neogaia currently boots to a console only. +The laptop minimum viable install deliberately deferred everything graphical, so the operator works entirely from the terminal (fish, tmux, nvim, Claude Code) with no desktop to live in. + +The operator wants a graphical desktop, and it must be primarily keyboard-driven. +Their mental model is i3: numbered workspaces, `Super`+number to switch, manual tiling. +They type on a 60% keyboard where arrow keys and the navigation cluster live behind a layer, so a keyboard-first workflow that never reaches for those keys matters. + +The same desktop has to transfer to the future desktop Host (zeus), which must game well and stay low-friction in general. +The operator previously ran KDE Plasma 6 bent into an i3 imitation and valued above all that it "just worked", but remembers past i3/Sway minimalism costing hours of fixing random breakage. +That concern is now largely mitigated: NixOS makes the whole stack declarative, pinned, and reversible, and the agent absorbs the discovery and debugging that used to eat evenings. + +## Solution + +Add a keyboard-driven Wayland desktop built on Hyprland, expressed as a new grouped set of Modules. +Enable it on neogaia now, and design it Host-agnostic so zeus adopts the identical desktop later by flipping a single flag. + +Deliver a complete, daily-drivable session in one pass rather than a bare stub, because unlike the reimage this is fully reversible ("edit and rebuild"), so there is no safety reason to under-scope. +The session covers the compositor, a text login, Nord theming, a status bar, a launcher, notifications, lock and idle, a wallpaper, clipboard history, screenshots, screen recording, and the desktop portals, together with the operator's ported keybinds and input tuning. + +Theme the whole graphical layer Nord from a single source (Stylix), scoped so it owns only the new graphical surface and leaves the existing terminal Modules' hand-themes untouched. +Leave gaming out entirely; it belongs to a future zeus-oriented Module, and neogaia is not a gaming machine. + +## User Stories + +1. As the operator, I want neogaia to boot into a keyboard-driven Hyprland session, so that I can live in a graphical desktop without leaving my keyboard-first workflow. +2. As the operator, I want the desktop expressed as Host-agnostic Modules enabled by a single flag, so that zeus can adopt the identical desktop later without rework. +3. As the operator, I want a text-based login, so that I log in mouse-free without a heavy graphical display manager. +4. As the operator, I want the whole graphical layer themed Nord from one source, so that GTK, Qt, the bar, the lock screen, and the launcher cohere without me hand-theming each, while my existing nvim, tmux, and fish themes stay exactly as they are. +5. As the operator, I want a fast modern terminal launched on `Super+Return`, so that my tmux and nvim stack has a clean frame and my old muscle memory for opening a terminal carries over. +6. As the operator, I want a status bar showing workspaces with per-application icons, clock, battery, network, audio, media controls, and a do-not-disturb toggle, so that I can read system state at a glance. +7. As the operator, I want a search-everything launcher covering applications, open windows, math evaluation, and emoji, reused as the frontend for clipboard history and a power menu, so that one keybound tool handles launching and utility menus. +8. As the operator, I want notification toasts with do-not-disturb and history recall, so that I see notifications and can retrieve ones I missed. +9. As the operator, I want a secure lock screen and idle management, so that going idle, suspending, or closing the lid always lands me at a locked screen, and the lock survives even if the locker process crashes. +10. As the operator, I want a single static Nord wallpaper, so that the desktop looks coherent with no extra moving parts and no battery cost. +11. As the operator, I want clipboard history picked through the launcher, so that I can paste from recent copies entirely by keyboard. +12. As the operator, I want keyboard-driven screenshots for a region, the active window, or the full screen that open in an annotation editor by default and land in both the clipboard and a file, so that capturing and marking up is a single reflex. +13. As the operator, I want a keybound screen recorder that selects a region and then toggles recording, so that capturing demos becomes a habit. +14. As the operator, I want screen sharing to work inside applications, so that video calls and browser screen-share function. +15. As the operator, I want my keybinds ported from my KDE/i3 scheme but expressed entirely in `hjkl` and letters with no arrow or navigation-cluster keys, so that every binding is reachable on my 60% keyboard. +16. As the operator, I want numbered-workspace bindings, so that my i3 muscle memory of `Super`+number to switch and `Super`+`Shift`+number to move carries over unchanged. +17. As the operator, I want Caps mapped to Escape, a US-only layout, snappy key-repeat, and touchpad tap-to-click, natural scroll, and disable-while-typing with flat mouse acceleration, so that input feels like home on the laptop. +18. As the operator, I want subtle animations with rounding and small gaps but no blur on the laptop, so that the desktop feels modern without draining the battery. +19. As the operator, I want the desktop built from granular single-purpose Modules grouped together with an explicit aggregator, so that a Host enables the whole desktop with one flag yet can still override any single piece. +20. As the operator, I want gaming deliberately excluded from this pass, so that neogaia's desktop stays focused and the gaming stack lands with zeus. +21. As the operator, I want the whole Host to still build green under the existing check, so that I gain confidence before switching a live machine. + +## Implementation Decisions + +**Direction and compositor** + +- Hyprland is the compositor, on neogaia now and zeus later, chosen as a single keyboard-driven tiler that serves both Hosts. + It matches the operator's i3 workflow (numbered workspaces, manual tiling) while getting closest to "just works" among true tilers through its cohesive first-party companion tools and large ecosystem. +- The choice was made over Sway (its minimalism is the very thing that cost the operator evenings), KDE Plasma (mouse-first at heart), and niri (its scrollable-tiling paradigm abandons numbered workspaces and so breaks the operator's core muscle memory). +- The gaming/driver dimension does not discriminate here: neogaia is Intel and zeus is AMD, both of which drive Wayland flawlessly, so the decision rested on workflow and low-friction rather than on surviving a hostile driver. + This corrects a stale assumption in the laptop spec (see Further Notes). +- Hyprland is sourced from nixpkgs rather than the upstream Hyprland flake. + The NixOS-level program integration owns the session, portals, and polkit, and home-manager owns the user configuration, sharing one Hyprland package so there is never a version split. + The session is launched through the universal Wayland session manager from the greeter for clean systemd session and environment integration. + No compositor plugins are adopted this pass, which removes the main reason to take the flake; moving to the flake later is a contained change that mirrors the existing chaotic-nyx pattern (an input that must not follow nixpkgs, with its own binary cache). + +**Session and theming** + +- Login uses greetd with the tuigreet text greeter. + This is mouse-free and lightweight, avoiding a heavy graphical display manager and its Qt/GTK weight. +- Theming uses Stylix, scoped to the graphical layer. + A single Nord base16 scheme drives colors, system fonts, cursor, and the static wallpaper across the new graphical surface (GTK, Qt, bar, lock, launcher, notifications, compositor colors). + Stylix targets for the existing terminal tools (nvim, tmux, fish) are left off so their established hand-themes stand unchanged. + The terminal is themed by Stylix where its target is mature, with hand-written Nord as a fallback otherwise. + This decision is highly reversible: Stylix toggles per target, so the graphical layer can migrate toward or away from manual theming later at low cost. + +**Components** + +- Terminal: Ghostty. +- Status bar: Waybar, showing workspaces with per-application icons plus clock, battery, network, audio, MPRIS media controls, and a do-not-disturb toggle. + No overview/exposé plugin is used; the workspace indicators are sufficient. +- Launcher: rofi (the Wayland fork), combining application-run, binary-run, and window-switch modes into one prompt, plus math-evaluation and emoji modes. + It is reused as the dmenu-style frontend for clipboard history and a power menu, so one tool serves several jobs. +- Notifications: mako, with do-not-disturb and history recall. + Media controls and the do-not-disturb toggle live in the bar rather than in a separate notification center. +- Lock and idle: hyprlock and hypridle. + hyprlock uses the compositor session-lock protocol, so the lock surface is owned by the compositor and survives a locker crash. + hypridle is wired for lock-on-idle, screen-off, lock-before-suspend, and lid-close, with tunable timeouts. +- Wallpaper: a single static image set by Stylix. +- Clipboard: cliphist with wl-clipboard, storing text and image history, picked through rofi. +- Screenshots: grim and slurp wrapped by grimblast, routed through the satty annotation editor so that annotation is the default on region, active-window, and full-screen captures, each exporting to both the clipboard and a file. +- Screen recording: wf-recorder, region-select-first and video-only (no audio), toggled by a keybind with a bar recording indicator and notifications. +- Portals: the Hyprland desktop portal (screencast, screenshot, global shortcuts) plus the GTK portal (file dialogs and appearance). + Screen sharing in applications depends on these regardless of whether the recorder is present. + +**Keybinds** + +The scheme ports the operator's KDE/i3 bindings but is expressed entirely in `hjkl` and letters, with no arrow or navigation-cluster keys, so it is fully reachable on a 60% keyboard. +Bindings that were quick-tile-to-half on the floating KDE desktop are reclaimed for real tiling actions, because that gesture is meaningless in an automatic tiler. + +| Action | Bind | +|---|---| +| Switch to workspace N | `Super`+`1`..`9` | +| Move window to workspace N | `Super`+`Shift`+`1`..`9` | +| Move focus | `Super`+`h`/`j`/`k`/`l` | +| Move window in layout | `Super`+`Shift`+`h`/`j`/`k`/`l` | +| Resize | `Super`+`Alt`+`h`/`j`/`k`/`l` | +| Terminal | `Super`+`Return` | +| Launcher | `Super`+`R` | +| Lock | `Super`+`X` | +| Toggle floating | `Super`+`Space` | +| Fullscreen | `Super`+`F` | +| Toggle split | `Super`+`T` | +| Close window | `Super`+`Shift`+`Q` | +| Force-kill | `Super`+`Ctrl`+`Q` | +| Screenshot region / window / full (to satty) | `Super`+`L` / `Super`+`Shift`+`L` / `Super`+`Ctrl`+`L` | +| Clipboard history | `Super`+`Shift`+`V` | +| Record toggle (region first) | `Super`+`Shift`+`R` | +| Volume / brightness / media | `XF86` hardware keys | + +**Input** + +- US-only keyboard layout, with no layout switcher. +- Caps mapped to Escape, with Shift+Caps still producing a real CapsLock. +- Key-repeat tuned snappy (a short delay before repeat begins, a fast repeat rate). +- Touchpad with tap-to-click, natural scroll, and disable-while-typing. +- Mouse with flat acceleration. + +**Feel** + +- Tasteful, subtle animations with modest rounding and small gaps. +- Blur is off on the laptop, where it is the single biggest battery cost; it remains a knob a Host such as zeus can enable. + +**Module structure** + +- The desktop is a set of granular, single-purpose Modules grouped under a desktop directory, each independently toggleable so pieces stay reusable and the files stay focused. + The tightly coupled Hyprland-native pieces (compositor, lock, idle) are grouped in a subdirectory within that group. +- An explicit aggregator Module turns the desktop on. + Guarded by its own enable, it sets each piece's enable at default priority so that a Host enables the whole desktop with one flag while retaining the ability to override any single piece. + The aggregator hand-lists the pieces it enables rather than scanning the directory, so a newly added file stays inert until deliberately added to that list; this keeps the whole desktop legible from one file. +- The desktop's enable options are namespaced under a single desktop group, so a Host's checklist gains one desktop entry and the aggregator itself reads as the sub-checklist of what that entry means. +- This uses the existing recursive Auto-loader as-is: every file in the group is imported unconditionally (inert until enabled), so no Skeleton change is needed. + The aggregator/namespaced-group pattern is a deliberate evolution of the flat Module plus Host-as-checklist convention (see Further Notes). + +## Testing Decisions + +- A good test asserts externally-observable evaluation and build success of the whole Host, not the internals of any individual Module. + This mirrors the laptop MVI's stance, where the config-merge model makes the whole-Host build the meaningful unit and the highest available seam. +- Primary seam (required, existing): the neogaia Host evaluates and its system toplevel builds under the flake check. + Building the toplevel drives the Auto-loader discovering the new Modules, the aggregator fan-out, home-manager integration, the full Stylix wiring, the Hyprland program integration, and package availability, surfacing nearly all config-authoring errors short of rendering a frame. +- Cheap targeted checks: evaluate specific configuration paths to confirm the desktop aggregator fans out, the Stylix scheme resolves to Nord, and Hyprland is enabled, reusing the repo's existing lightweight eval-probe pattern. +- No Module-level unit tests are added; there is no seam below the whole-Host build worth testing here, and the prior art is the laptop MVI's build-the-toplevel check. +- The genuine end-to-end confirmation is manual and irreducible: switch the configuration on neogaia, log in through the greeter, and exercise the live session (keybinds, lock, screenshot, clipboard, launcher). + A graphical session cannot self-test headless, but unlike the reimage this is reversible, so verification is done by living in it with a safety net (roll back a generation, drop to a console, or disable the desktop flag). +- VM-based graphical CI (boot assertions under a NixOS test) is deferred, consistent with the laptop MVI's stated stance. + +## Out of Scope + +- The gaming stack (Steam, gamescope, Proton, replay-buffer recording, OBS), which belongs to a future zeus-oriented Module. +- The zeus Host itself, and multi-monitor/output configuration, since there is no second display to design against yet; monitor focus and move bindings are deferred with it. +- Any non-Hyprland desktop; KDE, Sway, and niri were considered and rejected. +- The upstream Hyprland flake and compositor plugins, including workspace-overview/exposé, which are explicitly not adopted this pass. +- Migrating the existing nvim, tmux, and fish themes into Stylix; they stay hand-themed. +- Dynamic, animated, or video wallpaper, and wallpaper cycling. +- Screen-recording audio and a full-screen recording variant. +- A slide-out notification-center panel and a batteries-included desktop panel; both were considered and rejected in favor of the minimal, Stylix-coherent stack. +- Any change to the Skeleton or the Auto-loader; the structure uses them unchanged. +- Any secret wiring. + +## Further Notes + +- The compositor decision (Hyprland over Sway, KDE, and niri) is hard to reverse and the result of a real trade-off, so it should be recorded as an ADR. +- The aggregator plus namespaced-group Module pattern is a deliberate departure from the flat, Host-as-full-checklist convention, and is worth recording as a short ADR or a conventions note so its intent is not relearned. +- The laptop MVI's out-of-scope line attributing Nvidia to zeus is factually wrong: zeus runs an AMD GPU, and Raichu (a server with no desktop) is the only Nvidia machine. + The laptop MVI is a historical document and is left unchanged, so the accurate fact is recorded here and in ADR 0003 instead. +- The ported keybind scheme is derived from the operator's prior KDE Plasma 6 configuration (nine numbered desktops, `Super`+number bindings, a terminal on `Super`+`Return`, Caps mapped to Escape, and custom per-desktop tile layouts), which lives in this repo's git history under the old reference config. +- Neogaia is Intel and zeus is AMD, both of which drive Wayland without driver caveats; this is what lets one keyboard-first compositor serve both Hosts rather than forcing a per-Host divergence. diff --git a/.claude/tasks/0021-desktop-group-and-hyprland-session.md b/.claude/tasks/0021-desktop-group-and-hyprland-session.md new file mode 100644 index 0000000..248b6e3 --- /dev/null +++ b/.claude/tasks/0021-desktop-group-and-hyprland-session.md @@ -0,0 +1,34 @@ +--- +spec: hyprland-desktop +--- + +## What to build + +The tracer bullet for the whole desktop: a keyboard-driven Hyprland session that neogaia can log into and open a terminal in. + +Create the `modules/desktop/` group with an explicit aggregator, guarded by its own `modules.desktop.enable`, that hand-lists and turns on each piece at default priority so a host enables the whole desktop with one flag yet can still override any single piece. +Namespace every desktop enable under one desktop group so a host's checklist gains one entry. +Place the tightly coupled Hyprland-native pieces (starting with the compositor) in a subdirectory within the group. + +Wire Hyprland from nixpkgs: the NixOS program integration owns the session and polkit, home-manager owns the user configuration, and both share one Hyprland package so there is never a version split. +The session is launched through the universal Wayland session manager from the greeter. +Login is greetd with the tuigreet text greeter, mouse-free and lightweight. + +Port the operator's KDE/i3 keybinds expressed entirely in `hjkl` and letters with no arrow or navigation-cluster keys: numbered-workspace switch and move, focus and window movement, resize, terminal, floating, fullscreen, split, close, and force-kill, per the spec's keybind table. +Tune input: US-only layout with no switcher, Caps mapped to Escape with Shift+Caps still producing CapsLock, snappy key-repeat, touchpad tap-to-click plus natural scroll plus disable-while-typing, and flat mouse acceleration. +Set the feel: subtle animations, modest rounding, small gaps, and blur off (left as a knob a host such as zeus can enable). +Install Ghostty as the terminal on `Super+Return`. + +Enable the desktop on neogaia. + +## Acceptance criteria + +- [ ] `modules/desktop/` exists with an aggregator exposing `modules.desktop.enable` that hand-lists and enables its pieces at default priority, each piece independently overridable. +- [ ] Desktop enable options are namespaced under a single desktop group; the Hyprland-native compositor lives in a subdirectory of the group. +- [ ] Hyprland is sourced from nixpkgs; the NixOS integration and the home-manager user config share one Hyprland package. +- [ ] The session launches through the universal Wayland session manager from a greetd/tuigreet text login. +- [ ] Keybinds match the spec's table, using only `hjkl`, letters, and number rows — no arrow or navigation-cluster keys. +- [ ] Input is tuned: US-only layout, Caps→Escape (Shift+Caps = CapsLock), snappy key-repeat, touchpad tap-to-click + natural scroll + disable-while-typing, flat mouse acceleration. +- [ ] Animations, rounding, and small gaps are on; blur is off and remains host-overridable. +- [ ] Ghostty opens on `Super+Return`. +- [ ] neogaia enables `modules.desktop` and builds green under `nix flake check`. diff --git a/.claude/tasks/0022-stylix-nord-theming.md b/.claude/tasks/0022-stylix-nord-theming.md new file mode 100644 index 0000000..4e4c1cf --- /dev/null +++ b/.claude/tasks/0022-stylix-nord-theming.md @@ -0,0 +1,20 @@ +--- +spec: hyprland-desktop +blocked-by: 0021-desktop-group-and-hyprland-session +--- + +## What to build + +Theme the whole new graphical layer Nord from a single source, and set the wallpaper. + +Add Stylix as a flake input and a desktop theming module that drives colors, system fonts, and cursor from one Nord base16 scheme across the graphical surface (GTK, Qt, and the compositor colors), plus a single static Nord wallpaper set by Stylix. +Scope Stylix to the graphical layer only: leave its targets for the existing terminal tools (nvim, tmux, fish) off so their established hand-themes stand unchanged. +The theming is reversible per target, so individual surfaces can migrate toward or away from manual theming later. + +## Acceptance criteria + +- [ ] Stylix is a flake input, wired into the host build. +- [ ] A desktop theming module resolves a single Nord base16 scheme and applies it to GTK, Qt, cursor, and system fonts. +- [ ] A single static Nord wallpaper is set by Stylix; no dynamic, animated, or cycling wallpaper. +- [ ] Stylix targets for nvim, tmux, and fish are off, leaving their existing themes untouched. +- [ ] neogaia builds green under `nix flake check`, and an eval probe confirms the resolved scheme is Nord. diff --git a/.claude/tasks/0023-waybar-status-bar.md b/.claude/tasks/0023-waybar-status-bar.md new file mode 100644 index 0000000..e3ccd5e --- /dev/null +++ b/.claude/tasks/0023-waybar-status-bar.md @@ -0,0 +1,19 @@ +--- +spec: hyprland-desktop +blocked-by: 0021-desktop-group-and-hyprland-session +--- + +## What to build + +A Waybar status bar that reads system state at a glance. + +Add a Waybar module to the desktop group, enabled through the aggregator, showing workspaces with per-application icons plus a clock, battery, network, audio, MPRIS media controls, and a do-not-disturb toggle. +No overview/exposé plugin: the workspace indicators are sufficient. +The do-not-disturb toggle and media controls live in the bar rather than in a separate notification center. + +## Acceptance criteria + +- [ ] A Waybar module exists in the desktop group and is enabled by the aggregator. +- [ ] The bar shows workspaces with per-application icons, a clock, battery, network, audio, MPRIS media controls, and a do-not-disturb toggle. +- [ ] No overview/exposé plugin is used. +- [ ] neogaia builds green under `nix flake check`. diff --git a/.claude/tasks/0024-rofi-launcher.md b/.claude/tasks/0024-rofi-launcher.md new file mode 100644 index 0000000..42f8b5a --- /dev/null +++ b/.claude/tasks/0024-rofi-launcher.md @@ -0,0 +1,20 @@ +--- +spec: hyprland-desktop +blocked-by: 0021-desktop-group-and-hyprland-session +--- + +## What to build + +A search-everything launcher, so one keybound tool handles launching and utility menus. + +Add a rofi (Wayland fork) module to the desktop group, enabled through the aggregator, combining application-run, binary-run, and window-switch into one prompt, plus math-evaluation and emoji modes. +Bind it on `Super+R`. +Structure it so it is reusable as the dmenu-style frontend for later utility menus (clipboard history, power menu), and provide a power menu that uses it. + +## Acceptance criteria + +- [ ] A rofi module exists in the desktop group and is enabled by the aggregator. +- [ ] rofi combines application-run, binary-run, and window-switch modes, plus math evaluation and emoji. +- [ ] rofi opens on `Super+R`. +- [ ] rofi is usable as a dmenu-style frontend for utility menus, and a power menu is provided through it. +- [ ] neogaia builds green under `nix flake check`. diff --git a/.claude/tasks/0025-mako-notifications.md b/.claude/tasks/0025-mako-notifications.md new file mode 100644 index 0000000..4a3acff --- /dev/null +++ b/.claude/tasks/0025-mako-notifications.md @@ -0,0 +1,18 @@ +--- +spec: hyprland-desktop +blocked-by: 0021-desktop-group-and-hyprland-session +--- + +## What to build + +Notification toasts with do-not-disturb and history recall, so missed notifications can be retrieved. + +Add a mako module to the desktop group, enabled through the aggregator, rendering notification toasts with a do-not-disturb mode and history recall. +The do-not-disturb toggle and media controls live in the bar, not in a separate notification-center panel. + +## Acceptance criteria + +- [ ] A mako module exists in the desktop group and is enabled by the aggregator. +- [ ] Notification toasts appear, with do-not-disturb and history recall. +- [ ] No separate slide-out notification-center panel is added. +- [ ] neogaia builds green under `nix flake check`. diff --git a/.claude/tasks/0026-hyprlock-and-hypridle.md b/.claude/tasks/0026-hyprlock-and-hypridle.md new file mode 100644 index 0000000..e6edd21 --- /dev/null +++ b/.claude/tasks/0026-hyprlock-and-hypridle.md @@ -0,0 +1,21 @@ +--- +spec: hyprland-desktop +blocked-by: 0021-desktop-group-and-hyprland-session +--- + +## What to build + +A secure lock screen and idle management, so going idle, suspending, or closing the lid always lands at a locked screen. + +Add hyprlock and hypridle modules in the Hyprland-native subdirectory of the desktop group, enabled through the aggregator. +hyprlock uses the compositor session-lock protocol so the lock surface is owned by the compositor and survives a locker crash. +hypridle is wired for lock-on-idle, screen-off, lock-before-suspend, and lid-close, with tunable timeouts. +Bind lock on `Super+X`. + +## Acceptance criteria + +- [ ] hyprlock and hypridle modules exist in the Hyprland-native subdirectory and are enabled by the aggregator. +- [ ] hyprlock uses the compositor session-lock protocol. +- [ ] hypridle triggers lock-on-idle, screen-off, lock-before-suspend, and lid-close, with tunable timeouts. +- [ ] Lock is bound on `Super+X`. +- [ ] neogaia builds green under `nix flake check`. diff --git a/.claude/tasks/0027-cliphist-clipboard-history.md b/.claude/tasks/0027-cliphist-clipboard-history.md new file mode 100644 index 0000000..41df264 --- /dev/null +++ b/.claude/tasks/0027-cliphist-clipboard-history.md @@ -0,0 +1,18 @@ +--- +spec: hyprland-desktop +blocked-by: 0024-rofi-launcher +--- + +## What to build + +Clipboard history picked entirely by keyboard. + +Add a cliphist module (with wl-clipboard) to the desktop group, enabled through the aggregator, storing both text and image history and picked through rofi. +Bind the picker on `Super+Shift+V`. + +## Acceptance criteria + +- [ ] A cliphist module (with wl-clipboard) exists in the desktop group and is enabled by the aggregator. +- [ ] Text and image copies are recorded to history. +- [ ] The history is picked through rofi and bound on `Super+Shift+V`. +- [ ] neogaia builds green under `nix flake check`. diff --git a/.claude/tasks/0028-screenshot-capture.md b/.claude/tasks/0028-screenshot-capture.md new file mode 100644 index 0000000..cc0dadd --- /dev/null +++ b/.claude/tasks/0028-screenshot-capture.md @@ -0,0 +1,19 @@ +--- +spec: hyprland-desktop +blocked-by: 0021-desktop-group-and-hyprland-session +--- + +## What to build + +Keyboard-driven screenshots that open in an annotation editor by default and land in both the clipboard and a file. + +Add a screenshot module to the desktop group, enabled through the aggregator, using grim and slurp wrapped by grimblast and routed through the satty annotation editor so annotation is the default. +Cover region, active-window, and full-screen captures, each exporting to both the clipboard and a file. +Bind region on `Super+L`, active window on `Super+Shift+L`, and full screen on `Super+Ctrl+L`. + +## Acceptance criteria + +- [ ] A screenshot module exists in the desktop group and is enabled by the aggregator. +- [ ] Region, active-window, and full-screen captures work, each opening in satty and exporting to both clipboard and file. +- [ ] Captures are bound on `Super+L`, `Super+Shift+L`, and `Super+Ctrl+L`. +- [ ] neogaia builds green under `nix flake check`. diff --git a/.claude/tasks/0029-screen-recording.md b/.claude/tasks/0029-screen-recording.md new file mode 100644 index 0000000..8c9cfc8 --- /dev/null +++ b/.claude/tasks/0029-screen-recording.md @@ -0,0 +1,20 @@ +--- +spec: hyprland-desktop +blocked-by: [0023-waybar-status-bar, 0025-mako-notifications] +--- + +## What to build + +A keybound screen recorder that selects a region and then toggles recording. + +Add a wf-recorder module to the desktop group, enabled through the aggregator, that selects a region first and then toggles video-only recording (no audio), bound on `Super+Shift+R`. +Surface a recording indicator in the Waybar bar and notification toasts on start and stop. +No audio capture and no full-screen recording variant. + +## Acceptance criteria + +- [ ] A wf-recorder module exists in the desktop group and is enabled by the aggregator. +- [ ] The recorder selects a region first, then toggles video-only recording on `Super+Shift+R`. +- [ ] A recording indicator appears in the bar, and notifications fire on start and stop. +- [ ] No audio is captured and no full-screen variant is provided. +- [ ] neogaia builds green under `nix flake check`. diff --git a/.claude/tasks/0030-desktop-portals.md b/.claude/tasks/0030-desktop-portals.md new file mode 100644 index 0000000..f18d3a5 --- /dev/null +++ b/.claude/tasks/0030-desktop-portals.md @@ -0,0 +1,18 @@ +--- +spec: hyprland-desktop +blocked-by: 0021-desktop-group-and-hyprland-session +--- + +## What to build + +Screen sharing that works inside applications, so video calls and browser screen-share function. + +Add a portals module to the desktop group, enabled through the aggregator, wiring the Hyprland desktop portal (screencast, screenshot, global shortcuts) plus the GTK portal (file dialogs and appearance). +In-app screen sharing depends on these regardless of whether the recorder is present. + +## Acceptance criteria + +- [ ] A portals module exists in the desktop group and is enabled by the aggregator. +- [ ] The Hyprland desktop portal (screencast, screenshot, global shortcuts) and the GTK portal (file dialogs, appearance) are both configured. +- [ ] In-app screen sharing is available independent of the screen recorder. +- [ ] neogaia builds green under `nix flake check`. diff --git a/CLAUDE.md b/CLAUDE.md index bcfa577..7b5d2da 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -94,3 +94,7 @@ The domain model (Host, Module, Skeleton, Auto-loader, Enable convention, overla The interpolated key makes it a dynamic attribute, which nix will not merge the way it merges static paths. Nest both under a single `home-manager.users.${user} = { ... }`. - **Verifying a nixvim change headless:** `programs.nixvim.build.package`'s wrapper has **no `-u`**, so running `$OUT/bin/nvim` loads the caller's `~/.config/nvim` (the dev host's real config), *not* the built config — silently. To exercise the built config, launch with `-u "$(nix build --no-link --print-out-paths .#…programs.nixvim.build.initFile)"` and a scratch `HOME`/`XDG_CONFIG_HOME`. `conceallevel` is window-local: set it with `opt_local`/`vim.wo`, never `vim.bo[buf]` (which errors). +- Host GPUs: `neogaia` is Intel and `zeus` (the desktop) is **AMD**. + `raichu`, a server with no desktop, is the only Nvidia machine. + `laptop-mvi.md`'s out-of-scope line calls zeus Nvidia, but that is stale and the document is kept historical and unchanged, so do not infer any host's GPU from it. + The corrected fact lives in ADR 0003 and the `hyprland-desktop` spec.