Skip to content

Instantly share code, notes, and snippets.

@b0o
Created June 27, 2025 22:35
Show Gist options
  • Save b0o/8e2e83b20eee0b3ad6294e3a6c7c4f80 to your computer and use it in GitHub Desktop.
Save b0o/8e2e83b20eee0b3ad6294e3a6c7c4f80 to your computer and use it in GitHub Desktop.
// https://github.com/YaLTeR/niri/wiki/Configuration:-Input
input {
keyboard {
numlock
repeat-delay 240
repeat-rate 40
}
mouse {
accel-speed 0.0
accel-profile "adaptive"
}
warp-mouse-to-focus mode="center-xy"
workspace-auto-back-and-forth
}
cursor {
xcursor-theme "macOS"
xcursor-size 28
hide-when-typing
}
// Left monitor (BenQ EW3280U)
output "DP-2" {
mode "[email protected]"
position x=0 y=0
scale 1
focus-at-startup
// Fix flickering in Chrome with GPU acceleration.
variable-refresh-rate
}
// Right monitor (Samsung U32E850)
output "DP-1" {
mode "[email protected]"
position x=3840 y=0
scale 1
}
overview {
zoom 0.5
backdrop-color "#2b2645"
workspace-shadow {
softness 40
spread 10
offset x=0 y=10
color "#00000050"
}
}
// https://github.com/YaLTeR/niri/wiki/Configuration:-Layout
layout {
gaps 16
center-focused-column "never"
background-color "#41396b"
preset-column-widths {
proportion 0.33333
proportion 0.5
proportion 0.66667
}
default-column-width { proportion 0.5; }
focus-ring {
width 2
active-gradient from="#9074ff" to="#6627ff" angle=45 relative-to="window"
inactive-gradient from="#61598d" to="#4a3f88" angle=45 relative-to="window"
}
border {
width 1
urgent-color "#FF7D90"
active-gradient from="#9074ff" to="#6627ff" angle=45 relative-to="window"
inactive-gradient from="#61598d" to="#4a3f88" angle=45 relative-to="window"
}
shadow {
on
softness 20
spread 3
offset x=0 y=5
color "#130e3799"
}
struts {
left 16
right 16
}
}
prefer-no-csd
gestures { hot-corners { off; }; }
hotkey-overlay { skip-at-startup; }
screenshot-path "~/Documents/screenshots/%Y-%m-%d_%H-%M-%S.png"
spawn-at-startup "xwayland-satellite"
spawn-at-startup "zsh" "-c" "swaybg -i ~/Documents/pictures/wallpapers/Neon\\ Paint.jpg"
spawn-at-startup "zsh" "-c" "brightness -d"
spawn-at-startup "zsh" "-c" "stream_monitor.py"
spawn-at-startup "waybar"
environment {
DISPLAY ":0"
}
// https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules
// Float firefox PiP
window-rule {
match app-id=r#"firefox$"# title="^Picture-in-Picture$"
open-floating true
}
// Float pavucontrol
window-rule {
match app-id="org.pulseaudio.pavucontrol"
match title="Task Manager - Google Chrome"
open-floating true
}
// Block out password managers from screen capture.
// (This example rule is commented out with a "/-" in front.)
window-rule {
match app-id=r#"^org\.keepassxc\.KeePassXC$"#
match app-id=r#"^org\.gnome\.World\.Secrets$"#
block-out-from "screen-capture"
}
// Enable rounded corners for all windows.
window-rule {
geometry-corner-radius 6
clip-to-geometry true
}
binds {
Mod+Return { spawn "ghostty"; }
Mod+Space { spawn "zsh" "-c" "wlr-which-key"; }
XF86Sleep { spawn "zsh" "-c" "system lock"; }
XF86AudioLowerVolume { spawn "zsh" "-c" "audioctl -n vol down"; }
XF86AudioRaiseVolume { spawn "zsh" "-c" "audioctl -n vol up"; }
XF86AudioMute { spawn "zsh" "-c" "audioctl -n vol mute"; }
XF86AudioPlay { spawn "zsh" "-c" "audioctl -n play toggle"; }
XF86AudioPrev { spawn "zsh" "-c" "audioctl -n play prev"; }
XF86AudioNext { spawn "zsh" "-c" "audioctl -n play next"; }
Shift+XF86AudioPlay { spawn "zsh" "-c" "audioctl -n fav toggle"; }
Super+Shift+XF86AudioPlay { spawn "zsh" "-c" "audioctl -n fav toggle"; }
Shift+XF86AudioLowerVolume { spawn "zsh" "-c" "audioctl -n vol -b down"; }
Shift+XF86AudioRaiseVolume { spawn "zsh" "-c" "audioctl -n vol -b up"; }
Super+XF86AudioNext { spawn "zsh" "-c" "audioctl -n sink next"; }
Super+XF86AudioPrev { spawn "zsh" "-c" "audioctl -n sink prev"; }
Super+Shift+XF86AudioMute { spawn "zsh" "-c" "audioctl -n sink unify"; }
Super+Shift+XF86AudioNext { spawn "zsh" "-c" "audioctl -n sink -u next"; }
Super+Shift+XF86AudioPrev { spawn "zsh" "-c" "audioctl -n sink -u prev"; }
Mod+Up repeat=false { toggle-overview; }
Mod+Shift+O repeat=false { toggle-overview; }
Mod+Shift+Backspace { close-window; }
Mod+H { focus-column-left; }
Mod+J { focus-window-down; }
Mod+K { focus-window-up; }
Mod+L { focus-column-right; }
Mod+Alt+H { move-column-left; }
Mod+Alt+J { move-window-down; }
Mod+Alt+K { move-window-up; }
Mod+Alt+L { move-column-right; }
Mod+Home { focus-column-first; }
Mod+End { focus-column-last; }
Mod+Ctrl+Home { move-column-to-first; }
Mod+Ctrl+End { move-column-to-last; }
Mod+Shift+H { focus-monitor-left; }
Mod+Shift+L { focus-monitor-right; }
Mod+Shift+Ctrl+H { move-window-to-monitor-left; }
Mod+Shift+Ctrl+J { move-window-to-workspace-down; }
Mod+Shift+Ctrl+K { move-window-to-workspace-up; }
Mod+Shift+Ctrl+L { move-window-to-monitor-right; }
Mod+Alt+Ctrl+H { move-workspace-to-monitor-left; }
Mod+Alt+Ctrl+J { move-workspace-down; }
Mod+Alt+Ctrl+K { move-workspace-up; }
Mod+Alt+Ctrl+L { move-workspace-to-monitor-right; }
Mod+Page_Down { focus-workspace-down; }
Mod+Page_Up { focus-workspace-up; }
Mod+Shift+J { focus-workspace-down; }
Mod+Shift+K { focus-workspace-up; }
Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
Mod+Ctrl+Page_Up { move-column-to-workspace-up; }
Mod+Ctrl+U { move-column-to-workspace-down; }
Mod+Ctrl+I { move-column-to-workspace-up; }
Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; }
Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; }
Mod+WheelScrollRight { focus-column-right; }
Mod+WheelScrollLeft { focus-column-left; }
Mod+Ctrl+WheelScrollRight { move-column-right; }
Mod+Ctrl+WheelScrollLeft { move-column-left; }
Mod+Shift+WheelScrollDown { focus-column-right; }
Mod+Shift+WheelScrollUp { focus-column-left; }
Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
Mod+Ctrl+Shift+WheelScrollUp { move-column-left; }
// You can refer to workspaces by index. However, keep in mind that
// niri is a dynamic workspace system, so these commands are kind of
// "best effort". Trying to refer to a workspace index bigger than
// the current workspace count will instead refer to the bottommost
// (empty) workspace.
//
// For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on
// will all refer to the 3rd workspace.
Mod+1 { focus-workspace 1; }
Mod+2 { focus-workspace 2; }
Mod+3 { focus-workspace 3; }
Mod+4 { focus-workspace 4; }
Mod+5 { focus-workspace 5; }
Mod+6 { focus-workspace 6; }
Mod+7 { focus-workspace 7; }
Mod+8 { focus-workspace 8; }
Mod+9 { focus-workspace 9; }
Mod+0 { focus-workspace 10; }
Mod+Shift+1 { move-window-to-workspace 1; }
Mod+Shift+2 { move-window-to-workspace 2; }
Mod+Shift+3 { move-window-to-workspace 3; }
Mod+Shift+4 { move-window-to-workspace 4; }
Mod+Shift+5 { move-window-to-workspace 5; }
Mod+Shift+6 { move-window-to-workspace 6; }
Mod+Shift+7 { move-window-to-workspace 7; }
Mod+Shift+8 { move-window-to-workspace 8; }
Mod+Shift+9 { move-window-to-workspace 9; }
Mod+Shift+0 { move-window-to-workspace 10; }
// Switches focus between the current and the previous workspace.
Mod+Shift+A { focus-monitor-previous; }
Mod+A { focus-window-previous; }
// The following binds move the focused window in and out of a column.
// If the window is alone, they will consume it into the nearby column to the side.
// If the window is already in a column, they will expel it out.
Mod+BracketLeft { consume-or-expel-window-left; }
Mod+BracketRight { consume-or-expel-window-right; }
// Consume one window from the right to the bottom of the focused column.
// Mod+Comma { consume-window-into-column; }
// Expel the bottom window from the focused column to the right.
// Mod+Period { expel-window-from-column; }
Mod+R { switch-preset-column-width; }
Mod+Shift+R { switch-preset-window-height; }
Mod+Ctrl+R { reset-window-height; }
Mod+F { maximize-column; }
Mod+Shift+F { fullscreen-window; }
Mod+Ctrl+F { toggle-windowed-fullscreen; }
// Expand the focused column to space not taken up by other fully visible columns.
// Makes the column "fill the rest of the space".
// Mod+Ctrl+F { expand-column-to-available-width; }
Mod+Apostrophe { center-column; }
// Center all fully visible columns on screen.
Mod+Shift+Apostrophe { center-visible-columns; }
// Finer width adjustments.
// This command can also:
// * set width in pixels: "1000"
// * adjust width in pixels: "-5" or "+5"
// * set width as a percentage of screen width: "25%"
// * adjust width as a percentage of screen width: "-10%" or "+10%"
// Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0,
// set-column-width "100" will make the column occupy 200 physical screen pixels.
Mod+Minus { set-column-width "-10%"; }
Mod+Equal { set-column-width "+10%"; }
// Finer height adjustments when in column with other windows.
Mod+Shift+Minus { set-window-height "-10%"; }
Mod+Shift+Equal { set-window-height "+10%"; }
// Move the focused window between the floating and the tiling layout.
Mod+Y { toggle-window-floating; }
Mod+Shift+Y { switch-focus-between-floating-and-tiling; }
// Toggle tabbed column display mode.
// Windows in this column will appear as vertical tabs,
// rather than stacked on top of each other.
Mod+F3 { toggle-column-tabbed-display; }
// Actions to switch layouts.
// Note: if you uncomment these, make sure you do NOT have
// a matching layout switch hotkey configured in xkb options above.
// Having both at once on the same hotkey will break the switching,
// since it will switch twice upon pressing the hotkey (once by xkb, once by niri).
// Mod+Space { switch-layout "next"; }
// Mod+Shift+Space { switch-layout "prev"; }
// TODO
// Print { spawn "zsh" "-c" "snag --dir $HOME/Documents/screenshots -xNR"; }
Ctrl+Print { screenshot-screen; }
Print { screenshot-window; }
// Applications such as remote-desktop clients and software KVM switches may
// request that niri stops processing the keyboard shortcuts defined here
// so they may, for example, forward the key presses as-is to a remote machine.
// It's a good idea to bind an escape hatch to toggle the inhibitor,
// so a buggy application can't hold your session hostage.
//
// The allow-inhibiting=false property can be applied to other binds as well,
// which ensures niri always processes them, even when an inhibitor is active.
Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
// The quit action will show a confirmation dialog to avoid accidental exits.
// Mod+Shift+E { quit; }
// Ctrl+Alt+Delete { quit; }
// Powers off the monitors. To turn them back on, do any input like
// moving the mouse or pressing any other key.
// Mod+Shift+P { power-off-monitors; }
Mod+O { spawn "zsh" "-c" "wlr-which-key -k o"; }
Mod+S { spawn "zsh" "-c" "wlr-which-key -k s"; }
Mod+B { spawn "zsh" "-c" "wlr-which-key -k b"; }
Mod+T { spawn "zsh" "-c" "wlr-which-key -k t"; }
Mod+Period { spawn "zsh" "-c" "wl-kbptr"; }
// Scratchpads
Mod+Slash { spawn "zsh" "-c" "scratchpad.py -n term -a com.mitchellh.ghostty -s 60%x60% -p 34%,20% -c ghostty"; }
Mod+M { spawn "zsh" "-c" "scratchpad.py -n web-m -a google-chrome -s 60%x60% -p 34%,20% -c 'xdg-launch -A new-window google-chrome https://mail.google.com/mail/u/0/#inbox'"; }
Mod+D { spawn "zsh" "-c" "scratchpad.py -n web-d -a google-chrome -s 75%x75% -c 'xdg-launch -A new-window google-chrome https://devdocs.io'"; }
Mod+N { spawn "zsh" "-c" "scratchpad.py -n web-t -a google-chrome -s 65%x65% -p 30%,20% -c 'xdg-launch -A new-window google-chrome https://home.nest.com/thermostat https://home.google.com/u/1/'"; }
Mod+C { spawn "zsh" "-c" "scratchpad.py -n claude -a Claude -s 40%x90% -p 45%,5% -c 'xdg-launch claude-desktop'"; }
Mod+Shift+D { spawn "zsh" "-c" "scratchpad.py -n discord -t '^[a-zA-Z0-9]* - Discord$' -s 50%x90% -p 42%,5% -c 'gtk-launch discord'"; }
Mod+Shift+E { spawn "zsh" "-c" "scratchpad.py -n element -a Element -s 50%x90% -p 42%,5% -c 'gtk-launch io.element.Element'"; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment