diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..a6fc601 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,46 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this repo is + +Documentation and planning for a GNOME → Hyprland migration on Fedora 43. No build system, no tests, no executables. The actual system configuration lives in `~/.dotfiles/` (separate Forgejo repo), managed with GNU Stow. + +## Key locations outside this repo + +| What | Where | +|------|-------| +| Hyprland config | `~/.dotfiles/hypr/.config/hypr/hyprland.conf` | +| DMS source configs | `~/.dotfiles/hypr/.config/hypr/dms/` | +| Symlink target | `~/.config/hypr/` → symlinked via `stow hypr` | +| Hyprland log | `~/.cache/hyprland/hyprland.log` | +| Dotfiles remote | `git@forgejo.swansoncloud.com:jared/dotfiles.git` | + +## Hyprland configuration + +**Installed version:** 0.51.1 (Fedora 43). See `docs/hyprland/version-history.md` before applying patterns from the official wiki — the wiki tracks git HEAD, which is ahead of the installed version. + +**Window rule syntax for 0.48–0.51** (not the block syntax shown in current wiki): +``` +windowrule = match:class classname, effect +windowrule = match:class classname, match:title titlepattern, effect1, effect2 +``` +Do NOT use `^(...)$` wrapping — Hyprland 0.51 rejects it as "Invalid rulev2". Use plain names or bare regexes (e.g. `^org\.gnome\.` for a prefix match). + +**Block syntax** (`windowrule { }`) is 0.52+ only — do not use until after a Fedora upgrade. + +## Docs structure + +- `docs/window-manager/` — migration plan, phased progress log, keybindings cheatsheet +- `docs/hyprland/` — version-aware Hyprland config reference; update these when Hyprland is upgraded + +## Project status + +Phases 0–3 complete (install, config, dotfiles integration). Phase 4 (first successful Hyprland login and smoke tests) is in progress. Phase 5 (tuning) is deferred. + +Known workaround in place: `hyprpolkitagent` replaced with `lxpolkit` due to Qt 6 ABI issue on Fedora 43. + +## Hardware + +- AMD Vega iGPU (primary display, Wayland) +- NVIDIA RTX 3060 dGPU (unused — `akmod-nvidia` intentionally not installed) diff --git a/docs/hyprland/README.md b/docs/hyprland/README.md new file mode 100644 index 0000000..4cb74ba --- /dev/null +++ b/docs/hyprland/README.md @@ -0,0 +1,24 @@ +# Hyprland Reference + +Quick-access docs for AI-assisted config work. Covers the version installed on this machine. +Update this index when upgrading Hyprland. + +**Installed version:** 0.51.1 (Fedora 43, Sept 2025) +**Next expected upgrade path:** Fedora 44 → likely Hyprland 0.54+ + +## Index + +| File | What it covers | +|------|---------------| +| [window-rules.md](window-rules.md) | windowrule syntax, effects, props — with version notes | +| [layer-rules.md](layer-rules.md) | layerrule syntax for bars, wallpapers, launchers | +| [version-history.md](version-history.md) | Breaking syntax changes across versions | + +## Official sources (always check version) + +- Wiki: https://wiki.hypr.land/Configuring/ +- Example conf (HEAD/latest): https://github.com/hyprwm/Hyprland/blob/main/example/hyprland.conf +- Window Rules wiki: https://wiki.hypr.land/Configuring/Window-Rules/ + +> **Warning:** The wiki and example conf track the latest git HEAD, not the installed version. +> Always cross-reference with [version-history.md](version-history.md) before applying patterns from the wiki. diff --git a/docs/hyprland/layer-rules.md b/docs/hyprland/layer-rules.md new file mode 100644 index 0000000..c0bb61f --- /dev/null +++ b/docs/hyprland/layer-rules.md @@ -0,0 +1,37 @@ +# Layer Rules — Hyprland 0.48–0.51 + +Layers are non-window surfaces: status bars, wallpapers, launchers, notifications. + +## Syntax (current: 0.48–0.51) + +``` +layerrule = match:namespace ^(regex)$, effect +``` + +Use `hyprctl layers` to find a layer's namespace. + +## Effects + +| Effect | Notes | +|--------|-------| +| `no_anim` | Disable animations | +| `blur` | Enable blur | +| `blur_popups` | Blur popups too | +| `dim_around` | Dim everything behind layer | +| `animation style` | Override animation style | + +## Our rules + +``` +layerrule = match:namespace ^(quickshell)$, no_anim +layerrule = match:namespace ^dms:.*, no_anim +``` + +## 0.52+ block syntax (not yet installed) + +``` +layerrule { + match:namespace = ^(quickshell)$ + no_anim = on +} +``` diff --git a/docs/hyprland/version-history.md b/docs/hyprland/version-history.md new file mode 100644 index 0000000..9784875 --- /dev/null +++ b/docs/hyprland/version-history.md @@ -0,0 +1,78 @@ +# Hyprland Version History — Breaking Config Changes + +Focus: syntax changes that affect our config. Not a full changelog. + +## Installed: 0.51.1 (Sept 2025) + +## windowrule syntax timeline + +### Pre-0.48 (old — do not use) +``` +windowrule = float, ^(class-regex)$ # v1: positional class, no prefix +windowrulev2 = float, class:^(regex)$ # v2: explicit class: prefix +``` + +### 0.48–0.51 (CURRENT — use this) +Both `windowrule` and `windowrulev2` keywords work, but `windowrulev2` is deprecated. +Use `windowrule` with `match:` prefixed props. Patterns are plain strings or bare regexes — +do NOT use the old rulev2 `^(...)$` wrapping; Hyprland 0.51 rejects it as "Invalid rulev2". +``` +windowrule = match:class classname, effect +windowrule = match:class classname, match:title titlepattern, effect1, effect2 +windowrule = match:class ^org\.gnome\., rounding 12 # prefix regex — anchor ok, no outer () +``` +Props can come in any order relative to effects. +Boolean effects: `float`, `tile`, `pin`, `no_initial_focus` (no "on" suffix needed) +Value effects: `rounding 12`, `opacity 0.9` + +### 0.52+ (not yet installed — do not use until upgrade) +Block syntax introduced: +``` +windowrule { + name = optional-name + match:class = ^(regex)$ + float = yes + rounding = 12 +} +``` +Anonymous flat block syntax also available: +``` +windowrule = match:class regex, effect value +``` + +## layerrule syntax timeline + +### Pre-0.48 (old) +``` +layerrule = no_anim, ^(namespace)$ # positional namespace +``` + +### 0.48–0.51 (CURRENT — use this) +``` +layerrule = match:namespace namespacename, no_anim +``` +Same rule as windowrule: plain string or bare regex, no `^(...)$` wrapping. + +### 0.52+ (block syntax) +``` +layerrule { + match:namespace = ^(regex)$ + no_anim = on +} +``` + +## Other notable changes + +| Version | Change | +|---------|--------| +| 0.48 | `windowrulev2` deprecated; new `windowrule` with `match:` prefix | +| 0.48 | `layerrule` updated to use `match:namespace` prefix | +| 0.52+ | Block syntax for `windowrule` and `layerrule` | + +## Upgrade checklist + +When upgrading Hyprland: +1. Check `hyprland --version` (or `rpm -q hyprland`) +2. Scan release notes for "windowrule", "layerrule", "deprecated" +3. Update this file +4. Update the comment in `hyprland.conf` window rules section diff --git a/docs/hyprland/window-rules.md b/docs/hyprland/window-rules.md new file mode 100644 index 0000000..98ed3f3 --- /dev/null +++ b/docs/hyprland/window-rules.md @@ -0,0 +1,87 @@ +# Window Rules — Hyprland 0.48–0.51 + +Reference for the syntax currently used on this machine. +See [version-history.md](version-history.md) for what changes on upgrade. + +## Syntax (current: 0.48–0.51) + +``` +windowrule = match:class classname, effect +windowrule = match:class classname, match:title titlepattern, effect1, effect2 +``` + +Patterns are plain names or bare regexes. **Do NOT use `^(...)$` wrapping** — Hyprland 0.51 +rejects it as "Invalid rulev2" (that was the old windowrulev2 class-matching format). +Anchors are fine without outer grouping: `^org\.gnome\.` matches any GNOME reverse-DNS class. + +Multiple props and effects can be on one line, comma-separated, any order. + +## Match props (filtering) + +| Prop | Example | Notes | +|------|---------|-------| +| `match:class` | `match:class firefox` | Window class (app ID) | +| `match:title` | `match:title Picture-in-Picture` | Window title | +| `match:xwayland` | `match:xwayland true` | XWayland windows only | +| `match:float` | `match:float true` | Currently floating | +| `match:fullscreen` | `match:fullscreen true` | Currently fullscreen | + +Use `hyprctl clients` to find a window's class and title. + +## Static effects (applied once at window open) + +| Effect | Example | Notes | +|--------|---------|-------| +| `float` | `float` | Force float | +| `tile` | `tile` | Force tile | +| `fullscreen` | `fullscreen` | Force fullscreen | +| `maximize` | `maximize` | Force maximize | +| `rounding` | `rounding 12` | Pixel rounding (overrides global) | +| `no_initial_focus` | `no_initial_focus` | Don't steal focus on open | +| `pin` | `pin` | Show on all workspaces (float only) | +| `move` | `move 100 200` | Position (float only) | +| `size` | `size 800 600` | Size (float only) | +| `workspace` | `workspace 2` | Open on specific workspace | +| `monitor` | `monitor 1` | Open on specific monitor | +| `suppress_event` | `suppress_event maximize` | Ignore window events | + +## Dynamic effects (re-evaluated on change) + +| Effect | Example | +|--------|---------| +| `opacity` | `opacity 0.9` or `opacity 0.9 0.7` (active inactive) | +| `border_color` | `border_color rgb(FF0000)` | +| `no_blur` | `no_blur` | +| `no_shadow` | `no_shadow` | +| `no_anim` | `no_anim` | +| `no_focus` | `no_focus` | +| `idle_inhibit` | `idle_inhibit always` | + +## Our rules (reference) + +``` +# Force-tile apps that default to floating +windowrule = match:class gnome-control-center, tile +windowrule = match:class pavucontrol, tile + +# Force-float small utilities +windowrule = match:class gnome-calculator, float +windowrule = match:class org\.gnome\.Nautilus, float + +# Rounded corners for all GNOME apps (prefix match) +windowrule = match:class ^org\.gnome\., rounding 12 + +# Multi-prop (steam toasts) +windowrule = match:class steam, match:title notificationtoasts, no_initial_focus, pin + +# Firefox PiP +windowrule = match:class firefox, match:title Picture-in-Picture, float +``` + +## Finding window class/title + +```bash +hyprctl clients | grep -E "class:|title:" +# or run this in a terminal, then open the window: +hyprctl -j clients | jq '.[] | {class, title}' +``` diff --git a/docs/window-manager/cheatsheet.pdf b/docs/window-manager/cheatsheet.pdf new file mode 100644 index 0000000..01e553b Binary files /dev/null and b/docs/window-manager/cheatsheet.pdf differ diff --git a/docs/window-manager/progress.md b/docs/window-manager/progress.md index 52daaa6..f05f7ac 100644 --- a/docs/window-manager/progress.md +++ b/docs/window-manager/progress.md @@ -81,3 +81,11 @@ GNOME and Sway stay installed as GDM fallback sessions. - Created ~/.config/hypr/hyprpaper.conf; hyprpaper added to autostart; ~/Pictures/wallpapers/ created (drop default.jpg there before first login) - Moved hypr config into ~/.dotfiles/hypr stow package; symlink verified; committed 60f57df to dotfiles repo - DMS config will be added to stow after confirming dms setup output is stable (per plan note) + +## 2026-04-19 — Phase 4: windowrule syntax fix + +- On first Hyprland login: config errors on all windowrule lines — "Invalid rulev2 found: match:class ^(...)$" +- Root cause: `^(...)$` wrapping was the old windowrulev2 regex format; Hyprland 0.51 explicitly rejects it even with the new `windowrule` keyword. Correct 0.51 syntax uses plain names or bare regexes with no outer grouping parens. +- Fixed all windowrule and layerrule patterns in hyprland.conf (stripped `^(...)$`; kept `^org\.gnome\.` prefix anchor without outer group). +- Updated docs: CLAUDE.md, docs/hyprland/version-history.md, docs/hyprland/window-rules.md all corrected to show actual 0.51 syntax. +- Noted: solopasha COPR still at 0.51.1 for Fedora 43; upstream latest is 0.54.0. Upgrade deferred until COPR catches up.