5.5 KiB
5.5 KiB
name, description
| name | description |
|---|---|
| niri-config-edit-validate | Locate, edit, validate, and commit niri compositor config on Frank's workstations: desk/display profiles, EDID-keyed outputs, layout, keybind grepping, dotfiles mirror, forced hot-reload. |
Editing niri config on Dank workstations
Layout of the config
- Live config:
~/.config/niri/config.kdlis a thin file ofinclude "./cfg/*.kdl"lines. Never conclude "not bound" from grepping onlyconfig.kdl— keybinds live incfg/keybinds.kdl, rules incfg/rules.kdl, layout incfg/layout.kdl, etc. Grep~/.config/niri/cfg/recursively. - niri notation:
Mod= Super/Win key. Chords likeMod+R { switch-preset-column-width; }. ~/.config/niriis a REAL directory, not a symlink; the version-controlled copies are a partial mirror under~/.omp/dotfiles/zz-blankpad/niri/.config/niri/. Trees can drift: diff them before/after edits. (Hardlink wiring is FRAGILE — editor/agent atomic-rename writes silently break hardlinks; verify live↔mirror by CONTENT diff, never by link trust.)
Desk/display profiles (monitor arrangement)
- Profiles:
cfg/desk-<n>-<name>.kdl(e.g.desk-1-home.kdl,desk-2-portable.kdl); ACTIVE profile is symlinked ascfg/display.kdl—readlinkit to know which.scripts/desk.shmanages switching;desk.sh captureprints connected outputs' EDID long names. - Panels are keyed by EDID long name (
output "Lenovo Group Limited 0x40A9 Unknown"= the laptop eDP-1 panel), not connector — connector names reshuffle between desks. Long-name blocks BEAT connector-keyed blocks when both match one output (legacy connector blocks likeoutput "eDP-1"linger as duplicates; niri applies the EDID block'sposition). - Position math: x,y = top-left of each output in the logical layout; right edge = x + mode width. To place panel A left of panel B:
A.x = B.x - A.width; bottom-align:A.y = B.y + (B.height - A.height). - Verify:
niri validate→ hot-reload →niri msg outputs | grep -iE 'Output |Position'(printsLogical position: x, y).
Schema gotchas (niri 26.04)
preset-column-widthsANDpreset-window-heightsare children oflayout { }as SIBLING blocks — wiki wording misleads; nesting orwindow-ruleplacement failsniri validatewithexpected one of proportion, fixed/unexpected node.- Preset list order = cycle order for
Mod+R(switch-preset-column-width);Mod+Shift+Rcycles backwards. WITH custom preset lists the cycle contains ONLY the configured presets — no implicit full/maximize tail (verified: [0.25, 0.5] cycles period 2). Maximize = separateMod+Fmaximize-column. Built-in defaults without the node: 1/3, 1/2, 2/3. - WITHOUT
preset-window-heights,switch-preset-window-heightFALLS BACK to the width presets — user sees width-fractions as heights; define the node explicitly to stop it. - Ground truth for node placement: the binary's embedded template —
grep -a -B4 -A8 "preset-column-widths {" $(which niri).
Workflow
- Edit the live file under
~/.config/niri/cfg/. niri validate(exit 0 + "config is valid") — mandatory before done.- Hot-reload is NOT reliable after harness edits (atomic-rename writes are missed by niri's watcher; user then tests against the OLD config and reports "no change"). ALWAYS follow with
niri msg action load-config-file(NOTreload-config). - Sync changed file into the mirror:
cp ~/.config/niri/cfg/<f>.kdl ~/.omp/dotfiles/zz-blankpad/niri/.config/niri/cfg/<f>.kdl(repo root is~/.omp, branchmain, remote = dankclaw Giteadank/command-center; push there is pre-authorized). Verify bydiff, not by cp success. - Untracked mirror files:
config.kdl,noctalia.kdl,animation.kdl,display.kdl,input.kdl— flag drift, don't silently add. - Mirror files often carry pre-existing uncommitted drift (desk.sh captures); a commit of your edit folds it in — say so in the report/commit body.
Live-behavior verification without disturbing Frank's windows
niri msg --json <subcmd>— the--jsonflag goes BEFORE the subcommand.- Targeting differs per action: WINDOW-scoped actions take
--id <window-id>(NOT--window) — e.g.switch-preset-window-height --id N. COLUMN-scoped actions (switch-preset-column-width,set-column-width,maximize-column) have NO id — they hit the FOCUSED column; onlyset-column-width <px|±N%>positional CHANGE, no flags. - Spawned test apps do NOT reliably take focus, so blind
spawn + actioncycles resize whatever Frank is looking at. For column actions you mustfocus-window --id Nfirst — and that STEALS focus; if Frank is actively testing chords, your probes and his keystrokes interleave and corrupt both. STOP probing, deliver config + validate, and have him press the chord himself. niri msg --json focused-windowcan report a different window than assumed (focus moves); for per-window measurement readniri msg --json windowsand filter byid. Present height of proportion p with gaps g over work-area H renders ≈ p*(H+g) − g.- If Frank reports "still seeing old values" after a config edit: run
load-config-filefirst, then verify empirically before believing anything else.
"What does chord X do?" triage
For "mod+" questions, check in order: ~/.config/niri/cfg/keybinds.kdl (compositor wins first), terminal configs (~/.config/ghostty, foot, kitty), tmux, then omp TUI chords (omp://keybindings.md; modifiers are ctrl/shift/alt/super only, no Mod; Ctrl+R=history search, Alt+R=app.retry).