Files
command-center/agent/managed-skills/niri-output-rotation-pinning/SKILL.md
T
Frank 135bb2194d agent: repoint roles to frank-medium/dankclaw-3090; sync niri tweaks, memories, managed skills
- config.yml: default/commit -> frank-medium (dankserver); task/tiny/smol/vision -> frank-small (dankclaw-3090); vision xhigh
- models.yml: add llamacpp (dankclaw-3090) provider; frank-large preserve_thinking + context notes
- niri: focus-ring/border/shadow layout, hot-corners off, re-add noctalia.kdl include; blankpad eDP-1 scale 1.0
- memories: flush rollouts; retire frank_large + marreta_authentik skills; add auth-chain/kv-pool/quadlet-log skills
- managed-skills: 40+ new fleet runbook skills
- agent/skills: import built-in skill set
2026-09-17 12:27:08 -07:00

3.8 KiB

name, description
name description
niri-output-rotation-pinning Rotate/re-arrange niri monitors (portrait transforms, positions, scale) persistently and verify — covers the output-block-resets-defaults trap and auto-layout reflow that flings unpinned outputs, plus the counter-clockwise transform convention.

Rotating and pinning outputs on niri

Verified on blankpad, niri 26.04, 2026-09-15 (two PM1601 externals + eDP-1 laptop panel).

0. Ground truth first

niri msg outputs            # connector names, current mode, scale, transform, logical pos/size
niri --version

Niri output names are connector names (eDP-1, DP-2, HDMI-A-1), not EDID model strings. The EDID strings printed before them in niri msg outputs are decoration — use the parenthesized name.

On blankpad the live config is split by include "./cfg/*.kdl" from ~/.config/niri/config.kdl, and cfg/display.kdl is a symlink into the dotfiles repo (~/.omp/dotfiles/zz-blankpad/niri/.config/niri/cfg/display.kdl). Edit the repo path, not the symlink target path — they are the same file, but the repo path is the one that gets committed. Check with ls -ld.

1. Transform direction is counter-clockwise

niri msg output <NAME> transform --help   # "Transform to set, counter-clockwise"
value effect
90 content rotated 90° CCW ⇒ the panel's top bezel sits on the LEFT
270 top bezel on the RIGHT
180 upside down
flipped-90 / flipped-270 mirrored variants

90 vs 270 is a physical-stand fact no tool can read (portable monitors expose no orientation in EDID/MCCS). Pick one, apply it, and give the user the one-liner to flip — don't stall on the question.

2. Two traps that bite when you edit the config

  1. An output "X" { … } block resets every property you don't restate to its default. Pinning position on eDP-1 without repeating scale 1.25 silently drops the laptop panel to scale 1.0. Restate scale (and mode if you care) in every block you touch.
  2. Niri re-runs auto-layout for outputs with no pinned position. Pinning only the externals shoved eDP-1 from 0,0 to 3936,0 (laptop became rightmost). If you want the pre-existing left-to-right order, pin every output's position.

Positions are logical pixels at each output's own scale. Original order preserved example:

output "DP-2" {
    scale 1
    transform "90"
    position x=1536 y=0
}

output "HDMI-A-1" {
    scale 1
    transform "90"
    position x=2736 y=0
}

output "eDP-1" {
    scale 1.25          // MUST restate: dashed-out by the block otherwise
    position x=0 y=0
}

x-offsets chain: eDP-1 logical width 1536 → DP-2 at 1536 → +1200 (portrait width) → HDMI-A-1 at 2736.

3. Apply and verify

niri validate -c ~/.config/niri/config.kdl          # exit 0, "config is valid"
niri msg action load-config-file                    # live reload; load-config-file, NOT reload-config
sleep 1
niri msg outputs | grep -E '^Output|Transform|Logical|Scale'

Success looks like Logical size: 1200x1920 (swapped) plus Transform: 90° counter-clockwise on each rotated panel, with positions matching the intended chain.

One-off rotation without touching config (temporary, forgotten on next config change):

niri msg output DP-2 transform 90

4. Commit

Dotfiles repo is dank/command-center (main); push to the local Gitea is permitted.

cd ~/.omp && git pull --ff-only
git add dotfiles/zz-blankpad/niri/.config/niri/cfg/display.kdl
git commit -m "blankpad(niri): <what changed>"
git push

Pitfalls

  • reload-config is not a niri subcommand — it's niri msg action load-config-file.
  • Never SIGUSR1 a terminal to "reload"; niri config reloads do not touch ghostty themes.
  • No man page for niri on this host; niri <sub> --help and /usr/share/doc/niri/default-config.kdl are the docs.