Skip to content

instantWM Configuration

instantWM is customized through a TOML configuration file at ~/.config/instantwm/config.toml.

After editing the config file, you can either restart instantWM or use instantwmctl to apply changes dynamically for certain settings.

Configuration File Location

~/.config/instantwm/config.toml

If the file doesn't exist, instantWM will use sensible defaults.

Config Includes

You can split your configuration into multiple files using the includes directive:

toml
# config.toml (main file)
[[includes]]
file = "keybinds.toml"

[[includes]]
file = "colors.toml"

Included files are merged into the main configuration. Paths can be absolute or relative to the main config file. Circular includes are detected and prevented.

Themes

instantWM ships with several built-in colour themes that style the status bar, tags, window titles, borders and close buttons together. Set the top-level theme key to pick one:

toml
theme = "nord"

That single line replaces the entire [colors] table — every colour is derived from the theme's palette. Themes are resolved when the config is read, so run instantwmctl reload (or restart instantWM) after changing theme.

Built-in themes

NameDescription
instantosThe default theme. Dark background with blue, green, yellow and red accents.
catppuccin-latteLight pastel theme (Catppuccin Latte).
catppuccin-frappeDark, muted theme (Catppuccin Frappé).
catppuccin-macchiatoDark theme (Catppuccin Macchiato).
catppuccin-mochaDark theme (Catppuccin Mocha).
nordDark, cool-blue theme (Nord).
gruvboxDark, warm earth-tone theme (Gruvbox).

Overriding theme colours

A theme is only the base. Anything you set under [colors] is merged on top of the selected theme, so you can keep a theme and tweak individual colours rather than redefining the whole palette:

toml
theme = "catppuccin-mocha"

# Keep the whole Mocha palette, but make the focused tiled-window
# border pink instead of the theme's blue.
[colors.border]
tile_focus = "#f5c2e7"

See Color Schemes for every key you can override. Because a theme resolves to the same [colors] structure, you can also keep a theme choice (and any overrides) in its own file and pull it in with includes.

INFO

An unknown theme name is not fatal. instantWM prints a warning and falls back to the default theme (instantos) — the rest of your config still loads normally.

Switching themes at runtime

You can switch themes on the running WM without editing the config:

bash
instantwmctl theme           # print the active theme
instantwmctl theme nord      # switch to a theme
instantwmctl theme --list    # list available themes

The bar, borders and tags recolour immediately. This is a runtime change only — instantwmctl reload reverts to whatever theme is set to in config.toml. To make a theme permanent, set theme = "..." in the config.

Full Configuration Example

toml
# Fonts - first font is primary, others are fallbacks
fonts = ["Cantarell-Regular:size=12", "JetBrains Mono:size=11"]

# Color configuration
[colors.tag.normal]
inactive = { fg = "#DFDFDF", bg = "#121212", detail = "#121212" }
filled = { fg = "#DFDFDF", bg = "#384252", detail = "#89B3F7" }
focus = { fg = "#121212", bg = "#89B3F7", detail = "#89B3F7" }
nofocus = { fg = "#DFDFDF", bg = "#292F3A", detail = "#3E485B" }
empty = { fg = "#5E6572", bg = "#121212", detail = "#121212" }

[colors.tag.hover]
inactive = { fg = "#DFDFDF", bg = "#1E2229", detail = "#1E2229" }
filled = { fg = "#DFDFDF", bg = "#4A5568", detail = "#A7BDD9" }
focus = { fg = "#121212", bg = "#A7BDD9", detail = "#A7BDD9" }
nofocus = { fg = "#DFDFDF", bg = "#353D4B", detail = "#475166" }
empty = { fg = "#6E7889", bg = "#1E2229", detail = "#1E2229" }

[colors.window.normal]
focus = { fg = "#DFDFDF", bg = "#292F3A", detail = "#3E485B" }
normal = { fg = "#6E7889", bg = "#292F3A", detail = "#3E485B" }
minimized = { fg = "#6E7889", bg = "#121212", detail = "#121212" }
sticky = { fg = "#F9D71C", bg = "#292F3A", detail = "#3E485B" }
sticky_focus = { fg = "#121212", bg = "#F9D71C", detail = "#F9D71C" }
edge_scratchpad = { fg = "#89B3F7", bg = "#292F3A", detail = "#3E485B" }
edge_scratchpad_focus = { fg = "#121212", bg = "#89B3F7", detail = "#89B3F7" }

[colors.window.hover]
focus = { fg = "#DFDFDF", bg = "#353D4B", detail = "#475166" }
normal = { fg = "#7E8899", bg = "#353D4B", detail = "#475166" }
minimized = { fg = "#7E7889", bg = "#1E2229", detail = "#1E2229" }
sticky = { fg = "#F9D71C", bg = "#353D4B", detail = "#475166" }
sticky_focus = { fg = "#121212", bg = "#F9D71C", detail = "#F9D71C" }
edge_scratchpad = { fg = "#89B3F7", bg = "#353D4B", detail = "#475166" }
edge_scratchpad_focus = { fg = "#121212", bg = "#89B3F7", detail = "#89B3F7" }

[colors.close_button.normal]
normal = { fg = "#6E7889", bg = "#292F3A", detail = "#3E485B" }
locked = { fg = "#6E7889", bg = "#292F3A", detail = "#3E485B" }
fullscreen = { fg = "#F9D71C", bg = "#292F3A", detail = "#3E485B" }

[colors.close_button.hover]
normal = { fg = "#DFDFDF", bg = "#81C995", detail = "#5EA984" }
locked = { fg = "#DFDFDF", bg = "#E16A98", detail = "#B7416E" }
fullscreen = { fg = "#121212", bg = "#F9D71C", detail = "#D4A61A" }

[colors.border]
normal = "#384252"
tile_focus = "#89B3F7"
float_focus = "#81C995"
snap = "#FDD663"

[colors.status]
fg = "#DFDFDF"
bg = "#121212"
detail = "#3E485B"

# Keyboard layout configuration
[keyboard]
layouts = [
  { name = "us" },
  { name = "de", variant = "nodeadkeys" }
]
options = "compose:ralt"

# Input configuration (touchpad, mouse, etc.)
[input]
# Example: enable tap-to-click on touchpads
# [input."type:touchpad"]
# tap = "enabled"
# natural_scroll = "enabled"

# Custom keybinds
[[keybinds]]
modifiers = ["Super"]
key = "Return"
action = { spawn = ["alacritty"] }

[[keybinds]]
modifiers = ["Super", "Shift"]
key = "q"
action = "kill"

[[keybinds]]
modifiers = ["Super"]
key = "F3"
action = "next_keyboard_layout"

# Desktop keybinds (work without a focused window)
[[desktop_keybinds]]
modifiers = ["Super"]
key = "d"
action = { spawn = ["instantmenu"] }

Color Schemes

Each color property has normal and hover variants that switch when hovered with the mouse.

Color Types

Each element has three colors:

  • fg (foreground): text color
  • bg (background): behind the text
  • detail: shading details below the element

Element Types

ElementDescription
tagTag number indicator
windowWindow title
close_buttonClose button on active window title
borderWindow border colors
statusStatus bar text

Color States

Tags:

  • inactive: Tag not selected, no windows
  • filled: Tag has windows but none focused
  • focus: Tag selected and has focused window
  • nofocus: Tag not selected but has windows
  • empty: Tag selected but no windows

Windows:

  • focus: Currently focused window
  • normal: Regular unfocused window
  • minimized: Minimized window
  • sticky: Sticky window (visible on all tags)
  • sticky_focus: Sticky window that is focused
  • edge_scratchpad: Window assigned to the edge overlay
  • edge_scratchpad_focus: Focused edge-overlay window

Close Button:

  • normal: Default close button
  • locked: Locked window close button
  • fullscreen: Fullscreen window close button

Border:

  • normal: Unfocused window border
  • tile_focus: Focused tiled window border
  • float_focus: Focused floating window border
  • snap: Snapped window border

Keyboard Configuration

The [keyboard] section configures XKB keyboard layouts:

toml
[keyboard]
layouts = [
  { name = "us" },
  { name = "de", variant = "nodeadkeys" },
  { name = "fr" }
]
options = "compose:ralt"          # XKB options
model = "pc105"                   # Keyboard model (optional)
swapescape = false                # Swap Caps Lock and Escape

Set swapescape = true to swap Caps Lock and Escape without having to spell out the XKB option string yourself.

Input Configuration

Configure touchpad and mouse settings:

toml
# Global settings
[input]
[input."type:touchpad"]
tap = "enabled"
natural_scroll = "enabled"
accel_profile = "adaptive"
pointer_accel = 0.5

[input."type:mouse"]
pointer_accel = 0.3

Valid values:

  • tap: "enabled" or "disabled"
  • natural_scroll: "enabled" or "disabled"
  • accel_profile: "flat" or "adaptive"
  • pointer_accel: Floating point number
  • scroll_factor: Floating point multiplier applied to scroll events (defaults to 1.0 when unset)
  • left_handed: "enabled" or "disabled" — swaps the primary/secondary buttons for left-handed use

Layout tree and gaps

The layout section controls spacing and interaction with instantWM's persistent manual tree:

toml
[layout]
inner_gap = 8
outer_gap = 8
smart_gaps = true
maximized_gaps = false
keyboard_resize_step = 0.05
minimum_weight = 0.15
pointer_edge_fraction = 0.34
new_window_placement = "auto-resize"
SettingTypeDefaultDescription
inner_gapinteger0Spacing between tiled windows (logical pixels)
outer_gapinteger0Spacing between tiled windows and the monitor edge (logical pixels)
smart_gapsbooleanfalseDisable all gaps when only one or zero tiled windows are present
maximized_gapsbooleanfalseApply configured gaps during maximized presentation
keyboard_resize_stepfloat0.05Fraction of an axis transferred by one tree resize command
minimum_weightfloat0.15Preferred minimum weight of a child in a split run
pointer_edge_fractionfloat0.34Fraction of a target occupied by pointer placement edge bands
new_window_placementstring"auto-resize"How a new window joins the tiling tree (see below)

new_window_placement controls where a window that is not yet in a tag's persistent tiling tree gets inserted:

  • "auto-resize" (default) — place the newcomer automatically and resize the existing tree to give it room.
  • "auto" — split the best existing leaf without deliberately rebalancing the rest of the tree.
  • "force" — give the first newcomer a leading half of a new vertical root split; consecutive untouched insertions adapt that region into balanced rows or columns, and any manual tree edit starts a new sequence.

Inner gaps are split evenly between adjacent windows. Outer gaps shrink the layout area inward from all four edges. Both values are clamped to a minimum of 0.

Floating windows are not affected.

Layout presets such as Grid are one-shot tree rewrites. These settings govern the manual edits which remain afterward; see Layouts.

Floating windows and click-to-raise

toml
# Raise a floating window to the top of the stack when its client area is
# left-clicked. Disabled by default so click-to-focus and focus-follows-mouse
# do not disturb the explicit floating-window stacking order.
raise_floating_on_click = false

With the default (false), clicking inside a floating window focuses it without changing the stacking order, which keeps manually arranged floating windows where you put them. Set it to true if you prefer each click to also bring the window to the front.

Animation speed

toml
[animations]
# 1.0 = designed speed; 0.5 = half speed (durations doubled);
# 2.0 = twice as fast (durations halved)
speed = 1.0
SettingTypeDefaultDescription
speedfloat1.0Global animation speed multiplier; valid range 0.01100.0

Below 1.0 slows animations down, above 1.0 speeds them up. Because durations are scaled, a factor of 2.0 does not skip frames — it halves every animation's duration. Use instantwmctl toggle animated (or super+shift+alt+s) to disable animations entirely; the speed multiplier then has no effect until animations are re-enabled.

The speed can also be changed at runtime:

bash
instantwmctl config get animations.speed
instantwmctl config set animations.speed 1.5

instantwmctl config set applies immediately but is not persisted — keep the value in config.toml for a permanent setting.

Custom Keybinds

Add or override keybinds:

toml
# Spawn a command
[[keybinds]]
modifiers = ["Super"]
key = "Return"
action = { spawn = ["alacritty"] }

# Named actions
[[keybinds]]
modifiers = ["Super", "Shift"]
key = "q"
action = "kill"

# Remove a default binding
[[keybinds]]
modifiers = ["Super"]
key = "f"
action = { unbind = true }

# Apply a tree preset
[[keybinds]]
modifiers = ["Super"]
key = "g"
action = { set_layout = "grid" }

# Adjust master window count
[[keybinds]]
modifiers = ["Super"]
key = "i"
action = { inc_master_count = 1 }

# Enter a mode
[[keybinds]]
modifiers = ["Super"]
key = "r"
action = { set_mode = "resize" }

Available Modifiers

  • Super or Mod4 - Windows/Super key
  • Shift - Shift key
  • Ctrl or Control - Control key
  • Alt or Mod1 - Alt key

Available actions

Simple actions use a string, for example action = "begin_tree_placement" or action = "toggle_tiling_maximized". The most relevant tree actions are:

  • focus_left/right/up/down
  • key_move_left/right/up/down
  • key_resize_left/right/up/down
  • tree_grow and tree_shrink
  • begin_tree_placement
  • layout_tile, layout_grid, layout_horiz_grid, layout_bottom_stack, and layout_bstack_horiz
  • layout_float, layout_maximized, and toggle_tiling_maximized
  • edge_scratchpad_create and edge_scratchpad_toggle

Do not copy a static action catalog from the web and assume it matches a custom build. instantwm --list-actions or instantwmctl action --list prints the authoritative, parser-backed list with descriptions and argument examples.

Structured actions accepted in TOML are:

  • spawn: action = { spawn = ["alacritty"] }
  • unbind: action = { unbind = true }
  • none: use action = "none" to remove a binding (equivalent to unbind)
  • set_layout: action = { set_layout = "tile" }
  • focus_stack: action = { focus_stack = "next" }
  • inc_master_count: action = { inc_master_count = 1 }
  • keyboard_layout: action = { keyboard_layout = "us(intl)" }
  • set_mode: action = { set_mode = "resize" }

See Modes for mode-local bindings and the built-in placement mode.

Window rules

Window rules apply placement and tag settings automatically when a window matching a given class, instance, or title appears. A window matches a rule when every criterion you supply matches; criteria you leave out match anything. class, instance, and title are case-sensitive substring matches.

toml
# Centre pavucontrol as a floating window
[[rules]]
class = "pavucontrol"
is_floating = "float_center"

# Open mpv floating on tag 3 (bit 2 → value 4)
[[rules]]
class = "mpv"
is_floating = "float"
tags = 4

# Match on the window title
[[rules]]
class = "steam"
title = "Friends List"
is_floating = "float"

# Pin a game to fullscreen on the second monitor
[[rules]]
class = "complex-game"
is_floating = "float_fullscreen"
monitor = { index = 1 }
FieldDescription
classMatch the window's WM class (substring).
instanceMatch the window's WM instance (substring).
titleMatch the window title (substring).
tagsBitmask of tags to assign. Bit 0 (value 1) is tag 1, bit 1 (value 2) is tag 2, bit 2 (value 4) is tag 3, and so on. Combine tags with bitwise OR (tags 1 + 3 = `1
is_floatingInitial mode: "tiled", "float", "float_center", "float_fullscreen", or "scratchpad".
monitor"any" (default) or { index = N } for a specific monitor by 0-based index.

Only the first matching rule is applied to a window.

Control Commands

Runtime control is provided by instantwmctl. See the canonical instantwmctl command reference for commands and examples. For actions usable in keybindings, instantwmctl action --list is the current runtime-generated list.

Runtime Control

instantWM provides the instantwmctl command-line tool for runtime control. See the instantwmctl documentation for a complete reference.

instantWM reads status text from the X11 root window name property (X11) or writes to the status bar directly (Wayland). Configure a status command in your config:

toml
status_command = "i3status-rs"

Or set status manually:

bash
instantwmctl update-status "My Status"

Custom modes

Modes use the same binding format and can invoke the tree actions above. See Modes for a complete, current example and for customizing the built-in placement mode.

Startup commands

Like sway's exec / exec_once and Hyprland's exec-once, you can run commands when instantWM starts:

toml
# Run once at startup (not repeated on reload)
exec_once = ["xmobar", "wal -R"]

# Run at startup and again on every `instantwmctl reload`
exec = ["killall picom; picom"]

exec_once is only fired during the initial startup sequence; exec is also re-run on each config reload, so it suits commands that need to be kept alive or restarted when the config changes.

Monitor Configuration

Configure specific monitor settings:

toml
[monitors."DP-1"]
resolution = "1920x1080"
refresh_rate = 144.0
position = "0,0"
scale = 1.0
enable = true
transform = "normal"      # rotation / reflection
vrr = "auto"              # variable refresh rate policy

[monitors."HDMI-A-1"]
position = "left-of:DP-1"

Position can be specified as:

  • Absolute: "X,Y" (e.g., "1920,0")
  • Relative: "left-of:OUTPUT", "right-of:OUTPUT", "above:OUTPUT", "below:OUTPUT"

transform rotates or mirrors the output. Valid values are "normal", "90", "180", "270", "flipped", "flipped-90", "flipped-180", and "flipped-270".

vrr controls variable refresh rate (FreeSync / G-Sync) and accepts "off", "auto" (default — let the driver decide), or "on".

Bar height

toml
# Bar height in logical pixels. 0 = derive from the configured fonts.
bar_height = 0

By default (0) the bar height is derived from the font metrics of the configured fonts. Set a fixed pixel height if you want the bar to stay a specific size regardless of font choice.

Cursor (Wayland)

On the Wayland backend, the cursor theme and size are taken from the [cursor] section (this has no effect on X11):

toml
[cursor]
theme = "Adwaita"   # xcursor theme name
size = 24           # cursor size in logical pixels

These mirror the XCURSOR_THEME and XCURSOR_SIZE environment variables; the config values take precedence. Reload the config with instantwmctl reload to apply a change.