niri's layout block maps almost one to one onto ChainYourMac. preset-column-widths becomes preset_column_widths, gaps becomes gap_inner + gap_outer, and center-focused-column becomes center_focused_column with the same never / on-overflow / always values. focus-follows-mouse stays focus_follows_mouse. Outputs, workspaces, startup apps and compositor effects are handled by macOS itself. Can't run niri on a Mac at all? Start here.
Niri config on macOS: your config.kdl, translated
niri is configured in one KDL file. On a Mac the same ideas live in a settings window — and, if you keep dotfiles, in a small TOML file. Here's every niri option that has a macOS equivalent, and the honest list of ones that don't.
Try it right here — this is a working model of ChainYourMac, not a video.
A working model of ChainYourMac, not a video. Drag a title bar to reorder, click a Dock icon to open an app, close a window with its red button. In the real app you hold ⌃⌥ with each key. The demo answers to both.
- Notarized by Apple
- Signed with Developer ID
- No account, no telemetry in the app
- Only needs the Accessibility permission
- Automatic updates
How configuration differs
niri reads a single KDL file, ~/.config/niri/config.kdl, and live-reloads it. Because niri is the whole compositor, that file covers everything: input devices, monitors, layout, window rules, animations, startup programs and every key bind.
On macOS, a window manager is one app among many. Keyboards, trackpads, displays and login items are configured in System Settings, and the window manager configures only the layout. In ChainYourMac every option is in a settings window and applies the moment you change it. The same options are saved to a TOML file, ~/.paneru, that you can keep in your dotfiles if you like. Nothing here requires editing it.
The layout block, option by option
niri's defaults below come from its default-config.kdl (main branch, checked 6 October 2026). ChainYourMac's come from version 2.1.
| niri option (default) | ChainYourMac option (default) | Notes |
|---|---|---|
preset-column-widths (1/3, 1/2, 2/3) | preset_column_widths (0.25, 0.33, 0.5, 0.66, 0.75) | Same idea: ⌃⌥R cycles them, like Mod+R. Fractions of the screen. niri also accepts fixed pixel widths; ChainYourMac takes fractions only. |
gaps (16) | gap_inner (8) + gap_outer (8) | One niri value becomes two: between windows, and at the screen edges. 0–64 points each. |
center-focused-column ("never") | center_focused_column ("never") | Same three values: never, on-overflow, always. |
default-column-width (proportion 0.5) | No equivalent in 2.1 | Press ⌃⌥R to snap a new window to a preset. |
struts | gap_outer, plus Dock-aware sizing (dock_aware, on) | Not identical: niri struts can keep the next column peeking in; ChainYourMac reserves space for the Dock and edges. |
focus-ring (on) / border (off) | focus_border (off), focus_border_width, focus_border_color, focus_border_radius | An overlay border around the focused window. Colour as #RRGGBB or #RRGGBBAA. |
| no built-in dimming | dim_inactive (off), dim_inactive_opacity | Dims everything behind the focused window. |
| tabbed columns (Mod+W) | tabbed columns (⌃⌥⇧T) | Toggled per column by a shortcut in both. |
Input: mouse, focus and trackpad
| niri option | ChainYourMac option | Notes |
|---|---|---|
focus-follows-mouse (commented out = off) | focus_follows_mouse (off) | On/off only; niri's max-scroll-amount has no equivalent. |
warp-mouse-to-focus (off) | mouse_follows_focus (off) | Moves the pointer to the window you focus with the keyboard. |
touchpad { natural-scroll } | swipe_natural (true) | Direction of the strip swipe. |
| 3-finger horizontal swipe (built in) | swipe_gesture_fingers (4; 3, 5 or 0 = off) | macOS uses 3 fingers for Spaces by default; see the setup guide before switching to 3. |
keyboard { xkb { … } } | System Settings → Keyboard | Layouts are macOS's job. ChainYourMac's shortcut recorder respects AZERTY, QWERTZ and Dvorak. |
Window rules
niri's window-rule matches on app-id and title regexes, then sets things like open-floating, default widths, opacity or corner radius. ChainYourMac's rules match a bundle ID (macOS's version of an app ID) and/or a title regex, and can make a window float or give it a fixed slot on the strip. You usually create them with an app picker in the settings window. In the file, they look like this:
[windows.pip]
title = "Picture.*(in)?.*[Pp]icture"
floating = true
[windows.settings]
title = ".*"
bundle_id = "com.apple.systempreferences"
floating = true
Small fixed-size windows like Calculator and ChainYourMac's own settings already float automatically, so you need fewer rules than in niri. Visual rules such as opacity, corner radius and block-out-from have no equivalent, because on macOS Apple's WindowServer draws the windows.
Outputs and workspaces
niri's output "eDP-1" { … } blocks set mode, scale, position and transform. On a Mac that's System Settings → Displays. ChainYourMac adds one per-display option: Configuration → Displays can switch it off for a single display (saved as ignored_displays) and leave that screen's windows alone. As in niri, every managed display has its own strip.
niri's dynamic vertical workspaces and named workspaces have no direct counterpart. ChainYourMac uses macOS Spaces, and each Space gets its own strip. Use Mission Control to add Spaces, and System Settings → Keyboard → Keyboard Shortcuts → Mission Control for "Switch to Desktop N" keys.
Animations
niri's animations { } block can slow everything down, tune springs per animation, or load custom shaders. ChainYourMac has one spring for strip motion, synced to your display's refresh rate:
animation_duration_ms(default 500): the spring's perceived duration.0turns animation off, like niri'soff.animation_damping(default 0.9): 1.0 settles with no overshoot, and lower values bounce.
Shaders, blur and open/close effects are compositor features, and no macOS window manager can add them.
Everything else in config.kdl
| niri section | On macOS |
|---|---|
binds { … } | ChainYourMac Shortcuts page (or [bindings]). Full map: niri keybindings on Mac |
spawn-at-startup | System Settings → General → Login Items. ChainYourMac has its own launch-at-login switch |
prefer-no-csd | Not applicable: Mac apps draw their own title bars |
screenshot-path | macOS screenshot tool (⌘⇧5 → Options) |
hotkey-overlay | The Shortcuts page in the app |
layer-rule, environment, xwayland-satellite | Not applicable on macOS |
A niri-flavoured starting config
If you want ChainYourMac to behave like a stock niri install, set these in the settings window, or put them in ~/.paneru:
[options]
preset_column_widths = [0.33333, 0.5, 0.66667] # niri's three presets
gap_inner = 16 # niri: gaps 16
gap_outer = 16
center_focused_column = "never" # or "on-overflow" / "always"
focus_follows_mouse = false
mouse_follows_focus = false
swipe_gesture_fingers = 4 # 3 = niri's count, see /setup first
focus_border = true # closest thing to niri's focus-ring
Pair it with the default ⌃⌥ shortcuts, which already follow niri's layout, and the strip will feel familiar within a few minutes. If you're still deciding between Mac tools, see niri for macOS for every option, free ones included.
FAQ
Where is the niri config file?
On Linux, niri reads ~/.config/niri/config.kdl and reloads it live when you save. niri's documentation lives at niri-wm.github.io/niri. None of it applies on macOS, because niri itself can't run there.
Where is ChainYourMac's config file?
In your home folder as ~/.paneru (it also accepts ~/.paneru.toml or $XDG_CONFIG_HOME/paneru/paneru.toml). It's TOML. The settings window writes it for you, so editing it is optional.
Can ChainYourMac read KDL?
No. The option names are close to niri's (e.g. preset_column_widths, center_focused_column) but the format is TOML. Translating a niri layout block takes a few lines — see the example on this page.
Is there a default-column-width equivalent?
Not as a setting in 2.1. Use ⌃⌥R once to snap a new window to a preset width, or ⌃⌥F for full width.
Does focus-follows-mouse work the same way?
It's an on/off switch, off by default — the same default as niri. niri's extra max-scroll-amount limit has no equivalent. The opposite direction, niri's warp-mouse-to-focus, is mouse_follows_focus.