Configuration Reference - MorgenWM

Configuration Reference

Deutsche Version

MorgenWM reads its config from $XDG_CONFIG_HOME/morgenwm/config.toml (usually ~/.config/morgenwm/config.toml). Reference configs are provided in example/:

  • config-minimal.toml - bare window-manager config, no extras
  • config-full.toml - a desktop that works out of the box (panel + notifications via vibepanel, wallpaper via wbg, launcher via fuzzel)

Copy one of them to ~/.config/morgenwm/config.toml.

All fields are optional - missing values fall back to built-in defaults.

[general]

General window manager behavior.

KeyTypeDefaultDescription
window_gapint12Gap between windows in pixels
border_widthint2Window border width in pixels
workspace_countint9Number of workspaces (max 9)
overview_visible_countint3Number of windows shown in overview mode
keyboard_layoutstring"us"XKB keyboard layout (e.g. "de", "us", "fr")
autostart_delayint0Seconds to wait before running autostart commands
mod_keystring"Mod4"Main modifier: Mod1 = Alt, Mod4 = Super/Win
windows_visibleint2Default visible count for new frames; visible_inc/visible_dec change it per frame
windows_visible_maxint4Ceiling visible_inc/visible_dec cycle to per frame (1..windows_visible_max)
wide_first_windowbooltrueFirst window in a frame takes full width
frame_border_enabledbooltrueShow colored border around the focused frame
xdg_autostartboolfalseAutomatically start XDG autostart applications
auto_remove_empty_framesbooltrueRemove empty frames when the last window closes
scroll_scopestring"output"Scope for scroll_left/scroll_right and the window overview: "output" = focused monitor only, "workspace" = all windows on the active workspace across monitors
focus_follow_pointerboolfalseFocus the window under the pointer on hover (mouse-follow focus)
per_output_workspacesboolfalseGive each monitor its own independent active workspace. When true, Mod+1-9 and the IPC workspace actions switch only the focused monitor; when false (default) all monitors switch together
show_welcomebooltrueShow the welcome/quick-launch menu on startup. The menu is opened by the ~/.local/bin/welcome helper (installed by setup.sh from example/welcome.sh); the docs entry opens `glow` on the installed docs directory so you can browse them; when this is false MorgenWM exports MOGENWM_SHOW_WELCOME=0 so the helper skips itself
animation_framesint9Number of animation frames for transitions
autostart_commandsarray of strings[]Shell commands to run on startup (see below)

autostart_commands

A list of shell commands run on startup, defined inside [general]:

[general]
autostart_commands = [
  "pipewire",
  "wbg -s /path/to/wallpaper.jpg",
  "/home/user/.local/bin/vibepanel",
]

Commands are spawned in order via /bin/sh -c. They run in the background (fire-and-forget) - MorgenWM does not wait for them to finish.

If xdg_autostart = true, XDG autostart entries from /etc/xdg/autostart/ and ~/.config/autostart/ are also started, unless they duplicate a command already listed in autostart_commands.

Hot Reload

MorgenWM watches the config file for changes and reloads it automatically, no restart needed. Save the file and the new settings apply within ~0.5s.

What reloads live:

  • Keybindings and pointer bindings (including spawn_commands)
  • window_gap, border_width, windows_visible, windows_visible_max, wide_first_window
  • colors (focused, unfocused, focused_frame_border)
  • scroll_scope, overview_visible_count
  • frame_border_enabled
  • per_output_workspaces (seeds per-output state from the current global when turned on, and folds it back into the global when turned off, so the toggle is safe to flip live)
  • keyboard_layout (applied live to every xkb keyboard via the river-xkb-config-v1 protocol, no restart needed)

What does NOT reload (applies only at startup):

  • autostart_commands / xdg_autostart (already-spawned processes aren't restarted)
  • outputs (use wlr-randr directly to change modes at runtime)

If the new config fails to parse, the previous config stays in effect and an error is logged to stderr (~/morgenwm.log when launched via launch_morgenwm).

You can also trigger a reload explicitly without touching the file:

morgenwm_msg action reload-config

This is useful after fixing a parse error that left the old config in place (the file watcher only fires on mtime changes, so editing without saving again wouldn't trigger it).

[colors]

Window and frame colors in RGBA (0-255).

KeyDefaultDescription
focused{ r = 96, g = 144, b = 255, a = 255 }Border color for the focused window
unfocused{ r = 160, g = 160, b = 160, a = 255 }Border color for unfocused windows
focused_frame_border{ r = 203, g = 212, b = 44, a = 128 }Border color for the focused frame

Example:

[colors]
focused = { r = 96, g = 144, b = 255, a = 255 }
unfocused = { r = 160, g = 160, b = 160, a = 255 }
focused_frame_border = { r = 70, g = 254, b = 196, a = 80 }

[[pointer_bindings]]

Pointer bindings map mouse buttons to actions. Each binding has a button, modifiers, and an action.

[[pointer_bindings]]
button = "left"
modifiers = ["Mod"]
action = "move"

[[pointer_bindings]]
button = "right"
modifiers = ["Mod"]
action = "resize"

button can be left, right, middle, side, or extra. "Mod" expands to whatever mod_key is set to in [general]; other valid modifier names are the same as for keybindings. Any of the actions listed under `[[keybindings]]` can be used.

The default bindings preserve classic river behavior: Mod + left mouse drag moves the window, Mod + right mouse drag resizes it.

Snap-to-grid drag. Dragging a tiled window with Mod + left drag lifts it out of the layout for the duration of the drag so it follows the pointer freely, and on release snaps it back into the tiling grid at the frame under the pointer. If you drop it over a panel or outside the usable area, it falls back to the focused frame. Dragging a window that is already floating just moves it and leaves it floating. Resizing a tiled window with Mod + right drag floats it (resize does not snap back).

[[keybindings]]

Keybindings are defined as an array of tables. Each binding has a key, modifiers, and an action.

[[keybindings]]
key = "Return"
modifiers = ["Mod"]
action = "spawn:foot"

"Mod" expands to whatever mod_key is set to in [general]. Other valid modifier names: Shift, Ctrl, Mod1 (Alt), Mod4 (Super).

Actions

ActionDescription
spawn:<command>Spawn a program (e.g. spawn:firefox, spawn:foot)
close / killClose the focused window
exit / quitExit MorgenWM
toggle_fullscreen / fullscreenToggle fullscreen for the focused window
toggle_wide / wideToggle wide mode (focused window takes full width; clears when a sibling in the same frame is focused)
visible_inc / windows_visible_incIncrease windows visible per frame (cycles 1..windows_visible_max)
visible_dec / windows_visible_decDecrease windows visible per frame (cycles 1..windows_visible_max)
toggle_floatingToggle floating for the focused window
floatSnap a floating window back into the tiling layout
toggle_stickyToggle sticky (visible on all workspaces)
scroll_left / scroll_prevScroll the frame left
scroll_right / scroll_nextScroll the frame right
focus_left / focus_prevFocus the window to the left
focus_right / focus_next_winFocus the window to the right
split_horizontalSplit the current frame horizontally
split_verticalSplit the current frame vertically
remove_frameRemove the current frame
cycle_window_forwardCycle to the next window in the frame
cycle_window_backwardCycle to the previous window in the frame
focus_frame_leftFocus the frame to the left
focus_frame_rightFocus the frame to the right
focus_frame_upFocus the frame above
focus_frame_downFocus the frame below
move_window_leftMove the focused window to the left frame
move_window_rightMove the focused window to the right frame
move_window_upMove the focused window to the frame above
move_window_downMove the focused window to the frame below
resize_window_leftShrink the frame from the left edge
resize_window_rightShrink the frame from the right edge
resize_window_upShrink the frame from the top edge
resize_window_downShrink the frame from the bottom edge
toggle_overviewToggle the window overview
recent_window_nextSwitch to the next most-recently-used window
recent_window_prevSwitch to the previous most-recently-used window
workspace_NSwitch to workspace N (1-9)
move_to_workspace_NMove the focused window to workspace N (1-9)
move_to_output_NMove the focused window to output N (1-9), keeping its active workspace
move_to_output_left / move_to_output_rightMove the focused window to the adjacent output (Mod+Shift+Left/Right)

[[outputs]]

Configure per-output resolution, refresh rate, and position via wlr-randr. Requires wlr-randr to be installed. Use morgenwm_msg outputs to discover output names.

[[outputs]]
name = "DP-1"
width = 2560
height = 1440
refresh = 240.001
position_x = 0
position_y = 0

[[outputs]]
name = "DP-2"
width = 2560
height = 1440
refresh = 240.001
position_x = 2560
position_y = 0

KeyTypeDefaultDescription
namestringn/aOutput connector name (e.g. DP-1, HDMI-A-1)
widthintn/aHorizontal resolution in pixels
heightintn/aVertical resolution in pixels
refreshfloatn/aRefresh rate in Hz (exact value, e.g. 240.001)
position_xint0Horizontal position in the layout (pixels)
position_yint0Vertical position in the layout (pixels)

Output modes are applied 2 seconds after startup (a fixed sleep 2 prefix gives the compositor time to initialize). The refresh field must match a mode your monitor actually supports - check with wlr-randr (run without arguments to list modes).

Validating Your Config

Use morgenwm validate to check that your config file parses correctly without starting the compositor:

morgenwm validate

Exit codes: 0 = OK, 1 = parse error, 2 = parsed with warnings.

The command prints a summary of parsed values and warns about suspicious settings (e.g. workspace_count out of range, empty keybinding keys, outputs without dimensions).

This is recommended after every config edit. MorgenWM silently falls back to built-in defaults if the config fails to parse at runtime, so a syntactically broken config may appear to "work" while your settings are ignored.

Environment Variables

VariableDescription
MORGENWM_NO_IPCIf set, disables the IPC server entirely
NIRI_SOCKETOverride the IPC socket path (set automatically by MorgenWM)
XDG_RUNTIME_DIRUsed to locate the default socket path
XDG_CONFIG_HOMEUsed to locate the config file
XKB_DEFAULT_LAYOUTSet automatically from keyboard_layout in config
XDG_CURRENT_DESKTOPSet to morgenwm if not already set (affects XDG autostart filtering)
MOGENWM_FOCUSED_OUTPUTSet to the focused output name before spawning a Spawn: binding, so launchers (fuzzel, wbg, ...) can open on the right monitor
MOGENWM_SHOW_WELCOMESet to 1/0 from the resolved show_welcome config before running autostart commands, so the welcome helper can skip itself without re-parsing the config