Skip to content

Window Rules

Window rules live in rules.toml. Aqueous watches the file, re-evaluates managed windows after a change, and reloads it with the rest of the configuration when you press Super+R.

Use aqueousctl instead of guessing an application’s identifiers:

Terminal window
aqueousctl windows
aqueousctl windows --json
aqueousctl inspect --rule

aqueousctl inspect --rule emits a ready-to-paste [[window]] block. Native Wayland applications normally match by app_id; XWayland applications use their WM_CLASS through class.

Rules are checked from top to bottom and the first matching rule wins. Each rule needs at least one of app_id, class, or title. When a rule has more than one matcher, all of them must match.

Matchers are anchored, case-sensitive globs:

  • * matches any number of characters.
  • ? matches exactly one character.
  • A value without wildcards must match the entire identifier.
[[window]]
app_id = "org.example.Editor"
title = "Preferences*"
layout = "float"
floating = true
width = 900
height = 640

Put narrow rules before broad ones:

[[window]]
app_id = "org.example.Editor"
title = "Preferences*"
layout = "float"
floating = true
width = 900
height = 640
[[window]]
app_id = "org.example.Editor"
layout = "tile"
workspace = 2
[[window]]
class = "Pavucontrol"
title = "Volume Control"
layout = "float"
floating = true
workspace = 2
width = 960
height = 640
x = 80
y = 60
fullscreen = false
ignore_struts = false
opacity = 0.96

width and height are positive pixel dimensions. x and y are offsets from the usable area’s origin; a zero value centers that axis. Setting layout = "float" also enables floating placement, so the explicit floating = true is optional but can make a complete rule easier to scan.

Rules can set workspace, floating, and fullscreen, but Aqueous does not fight the user. A manual workspace move, floating toggle, or fullscreen toggle overrides that property until a different matcher becomes active.

[[window]]
app_id = "org.example.Video"
layout = "monocle"
workspace = 4
fullscreen = true
ignore_struts = true
opacity = 1.0

ignore_struts = true uses the full output instead of the configured usable area. A fullscreen rule is treated as actual fullscreen rather than as a game mode anchor.

Game mode gives one matched window an anchor rectangle and arranges companion windows in the remaining left and right columns.

[game_mode]
remainder_layout = "grid"
fallback_layout = "tile"
gaps_inner = 8
[[window]]
app_id = "steam_app_*"
title = "*"
layout = "game-mode"
workspace = 9
anchor = "center"
size = "0.70x0.80"
scale = 1.0
fullscreen = false
ignore_struts = false
opacity = 1.0
blur = false

Anchor options are:

  • anchor: center, top, bottom, left, or right
  • size = "native": use the client’s requested size
  • size = "2560x1440": request an exact pixel size
  • size = "0.70x0.80": use fractions of the output area
  • scale: multiply the resolved size by a positive factor

remainder_layout and fallback_layout accept any layout except game-mode. The fallback is used when game mode is selected but no matching anchor is present. If the anchor touches an edge, the column on that edge collapses and all companion windows use the surviving column.

reload_rules has no default chord. Bind it when you are iterating on rules and do not want to run reload-time commands from wm.toml:

[keybinds]
reload_rules = "Super+Shift+R"
© 2026 Seafoam LabsShelly Chel