Layouts
Shoji ships with several built-in layouts and supports custom layouts. This page provides layout guidance and examples. For the complete list of configuration options, see Configuration overview.
Built-in layouts
| Layout | Description |
|---|---|
tall | Main window on left, stack on right |
wide | Main window on top, stack below |
bsp | Binary space partitioning (recursive splits) |
grid | Dynamic grid arrangement |
column | Equal-width columns |
fullscreen | All windows stacked full-size |
floating | No automatic tiling |
Default layout
New macOS Spaces start with the default_layout:
spoon.Shoji:configure({ default_layout = "tall",})The default layout must appear in enabled_layouts.
Enabled layouts
Control which layouts are available when cycling (Ctrl+Alt+Space):
spoon.Shoji:configure({ enabled_layouts = { "tall", "wide", "fullscreen", "bsp" },})The cycle_layout action moves through this list in order. Layouts not in this
list cannot be cycled to but can still be set directly via set_layout_*
hotkeys.
Main area configuration
The tall and wide layouts split the screen into a main area and a stack.
Two settings control this split:
Main ratio
The proportion of screen space for the main area:
spoon.Shoji:configure({ main_ratio = 0.5, -- Default: 50% main, 50% stack})Valid range: 0.1 to 0.9. Adjust at runtime with increase_main_ratio and
decrease_main_ratio hotkeys (5% step).
main_ratio = 0.5:
┌─────────────────────────────┬─────────────────────────────┐│ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ Main │ Stack ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ │└─────────────────────────────┴─────────────────────────────┘main_ratio = 0.7:
┌─────────────────────────────────────────┬─────────────────┐│ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ Main │ Stack ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ ││ │ │└─────────────────────────────────────────┴─────────────────┘Master window count
The number of windows in the main area:
spoon.Shoji:configure({ nmaster = 1, -- Default: 1 master window})Minimum: 1. Adjust at runtime with increase_nmaster and decrease_nmaster
hotkeys.
nmaster = 1:
┌─────────────────────────────┬─────────────────────────────┐│ │ ││ │ ││ │ ││ │ Win 2 ││ │ ││ │ ││ │ ││ Win 1 ├─────────────────────────────┤│ │ ││ │ ││ │ ││ │ Win 3 ││ │ ││ │ ││ │ ││ │ ││ │ │└─────────────────────────────┴─────────────────────────────┘nmaster = 2:
┌─────────────────────────────┬─────────────────────────────┐│ │ ││ │ ││ │ ││ Win 1 │ Win 3 ││ │ ││ │ ││ │ ││ │ │├─────────────────────────────┼─────────────────────────────┤│ │ ││ │ ││ │ ││ Win 2 │ Win 4 ││ │ ││ │ ││ │ ││ │ │└─────────────────────────────┴─────────────────────────────┘Custom layouts
Register custom layout implementations with the layouts option:
local MyLayout = require("my_custom_layout")
spoon.Shoji:configure({ layouts = { MyLayout }, enabled_layouts = { "tall", "mylayout" },})See Creating custom layouts for implementation details.
Layout modifiers
Modify built-in layouts with decorators. For example, mirror a layout:
local Modifiers = require("layouts.modifiers")local Mirror = require("layouts.modifiers.mirror")local Tall = require("layouts.tall")
local tallRight = Modifiers.wrap(Tall, Mirror.horizontal(), { name = "tall-right", displayName = "Tall (Right)",})
spoon.Shoji:configure({ layouts = { tallRight }, enabled_layouts = { "tall", "tall-right", "wide" },})This creates a tall layout with the main area on the right instead of left. See Layout modifiers for all available modifiers.
Per-macOS Space layouts
Each macOS Space maintains its own layout. Changing layouts affects only the current macOS Space.
Bind hotkeys to switch directly to specific layouts:
spoon.Shoji:bindHotkeys({ set_layout_tall = { { "ctrl", "alt" }, "1" }, set_layout_wide = { { "ctrl", "alt" }, "2" }, set_layout_bsp = { { "ctrl", "alt" }, "3" },})Retile on focus
Some layouts (particularly those using the Magnifier modifier) benefit from retiling when focus changes:
spoon.Shoji:configure({ retile_on_focus = true,})This ensures focus-aware effects update immediately when switching windows. Leave it disabled for layouts that do not depend on focus state.