Skip to content

Workspaces

Each output has its own workspaces. Choose a dynamic or fixed model, then use workspace rules to customize individual entries.

Omit workspaces or set it to "dynamic":

[output.DP-1]
workspaces = "dynamic"
min_workspaces = 3

A dynamic output keeps an empty workspace at the end and creates another when that workspace gains a window. Empty inactive anonymous workspaces are removed again. min_workspaces sets a floor, not a maximum.

Set empty_above = true under the global [workspaces] section to keep an additional empty workspace at the beginning.

A name-based [[workspace]] entry creates a persistent named workspace:

[[workspace]]
name = "CHAT"
layout.mode = "master"
[[workspace]]
name = "STATS"
output = "DP-1"
layout.mode = "dwindle"

Names are case-sensitive and local to an output. An entry without output applies independently to every dynamic output. Named workspaces remain when empty while anonymous neighbors continue their normal dynamic lifecycle.

Each output supports up to 64 workspaces.

Use an integer for a fixed count or a string array for an ordered list of names:

[output.DP-1]
workspaces = 5
[output.DP-2]
workspaces = ["WEB", "CHAT", "VIDEO"]

A count creates anonymous positions. A string list creates exact names, so position 3 and the name "3" remain different selectors. Static workspaces are never pruned.

Workspace changes apply on a valid configuration reload. Umbriel preserves matching names and positions where possible. Windows from a removed workspace move to the nearest remaining workspace.

Changing to a dynamic model keeps active and populated workspaces, then restores the required empty workspace.

Set the workspace arrangement per output:

[output.DP-1]
workspace_axis = "horizontal"
ValueBehavior
"vertical"Workspaces stack top to bottom; scrolling layouts run left to right.
"horizontal"Workspaces sit side by side; scrolling layouts run top to bottom.

A three-finger swipe along the axis changes workspaces. A swipe across it moves the scrolling strip. The overview follows the same arrangement.

Actions such as workspace-switch and window-move-to-workspace use these forms:

  • Bare digits from 1 to 64 select a one-based position.
  • Other text selects an exact, case-sensitive name.
  • Double quotes force name lookup for an all-digit name.
  • /output restricts selection to that output. A named selector can also use its unavailable original output to find an evacuated workspace.
workspace-switch:3
workspace-switch:3/DP-2
workspace-switch:CHAT/DP-2
workspace-switch:"3"/DP-2

Duplicate names resolve on the pointer-preferred output when possible. Otherwise the selector is ambiguous. On a dynamic output, a numeric position beyond the current count selects the last workspace.

Window move bindings also work on a focused scratchpad window: they remove it from the scratchpad and restore its saved tiled or floating state on the destination workspace. Silent variants keep the current workspace active. See Moving scratchpad windows.

Evacuated named workspaces keep their names even when appended at different positions on another output. Within one output, a native workspace takes precedence over evacuated workspaces with the same name. Multiple evacuated workspaces with the same name are ambiguous unless qualified by their original output. For example, workspace-switch:"4"/DP-1 follows the named workspace "4" while DP-1 is unavailable; workspace-switch:4/DP-1 remains a position on a live DP-1. Disabled outputs are excluded from global name lookup.

Run umbriel workspaces to list workspaces and their effective layout:

* DP-1: 1 [scrolling] (focused)
DP-1: 2 [dwindle]
* DP-2: WEB [master]

Use umbriel workspaces --json for scripts. Each entry includes its stable id, display name, one-based index, output, active and focused states, and effective layout.

[workspaces]
back_and_forth = true
empty_above = false
KeyDefaultDescription
back_and_forthfalseSelecting the active workspace returns to the previous one on that output.
empty_abovefalseKeep a leading empty workspace on dynamic outputs.

[[workspace]] entries customize one workspace. Select it with exactly one of name or index, and optionally restrict it to an output:

[[workspace]]
name = "VIDEO"
output = "DP-2"
layout.mode = "dwindle"
layout.gap = 4

On dynamic outputs, name also creates a persistent named workspace. index follows whichever workspace currently occupies that position. On static outputs, rules only customize members already present in the configured inventory.

Settings apply from least to most specific:

  1. Global [layout]
  2. Matching output scrolling extent
  3. Matching workspace rule without output
  4. Matching workspace rule with output

Later values replace earlier ones. Strut edges are resolved independently, so a rule can override only layout.struts.top.

KeyDescription
nameSelect an exact name and create it on matching dynamic outputs.
indexSelect a current one-based position from 1 to 64.
outputRestrict the rule to a connector or monitor name.
layout.modeUse "scrolling", "dwindle", "master", or "floating".
layout.gapSet the window gap.
layout.struts.{left,right,top,bottom}Reserve signed logical pixels at each edge.
layout.extent_presetsSet extent-cycle fractions.
layout.new_exits_fullscreenChoose which arriving windows exit fullscreen; see Leaving fullscreen.
layout.client_maximizeChoose "column" or "edges" for a tiled window’s own maximize request; see Maximize and fullscreen.
layout.scrolling.default_extent_fractionSet the initial scrolling-column extent.
layout.scrolling.center_underfull_stripCenter or start-align an underfull strip.
layout.scrolling.center_focusedControl when focus changes center a column.
layout.scrolling.center_on_overview_selectCenter the column picked in the overview.
layout.master.positionPlace the master area left, right, or center.
layout.master.default_width_fractionSet the master-area fraction.
layout.master.new_on_topPlace new stack windows at the top or bottom.
layout.master.new_becomes_masterGive the master slot to new windows.
layout.dwindle.preserve_splitKeep split directions fixed.
layout.dwindle.new_toward_cursorOpen new windows on the pointer’s side of the split.
[[workspace]]
output = "HDMI-A-1"
name = "CHAT"
layout.mode = "scrolling"
layout.scrolling.center_focused = "always"
[[workspace]]
output = "HDMI-A-1"
name = "STATS"
layout.mode = "dwindle"
[[workspace]]
index = 4
output = "DP-1"
layout.gap = 0
layout.struts.top = 24
layout.scrolling.default_extent_fraction = 0.667