Configuration overview
You will learn
- How to set gaps between windows
- How to choose and enable layouts
- How to exclude apps from tiling
- How validation catches configuration errors
Shoji uses a single configure method that accepts a table of options. All
options have sensible defaults, so you can start simple and add configuration
as you discover what works for your workflow.
This page is the single source of truth for all options. The linked pages provide examples and rationale, not additional settings.
At a glance
- Defaults favor no gaps and the
talllayout main_ratiorange: 0.1 to 0.9;main_countminimum: 1strict_validationistrueand rejects invalid values- Use the tables below for every available option
Basic setup
hs.loadSpoon("Shoji")
spoon.Shoji:configure({ gap_outer = 0, gap_inner = 0, default_layout = "tall", enabled_layouts = { "tall", "wide", "monocle" },})
spoon.Shoji:start()Nested configuration (optional)
For better organization, you can group related options using nested tables:
spoon.Shoji:configure({ gaps = { outer = 8, inner = 4 }, cheatsheet = { style = "dark" }, alerts = { show = true, duration = 0.5 }, filter = { mode = "blocklist", apps = { "com.apple.finder" } },})Both flat (gap_outer) and nested (gaps = { outer = ... }) styles work. Flat
keys take precedence if both are specified. The flat style remains fully
supported for SpoonInstall compatibility.
Configuration reference
The tables below list every available option. Links after each section point to examples and rationale.
Spacing
| Option | Type | Default | Nested path | Description |
|---|---|---|---|---|
gap_outer | integer | 0 | gaps.outer | Gap around screen edges (pixels, min: 0) |
gap_inner | integer | 0 | gaps.inner | Gap between windows (pixels, min: 0) |
For examples and visual diagrams, see Gaps.
Layouts
| Option | Type | Default | Description |
|---|---|---|---|
default_layout | string | "tall" | Layout for new macOS Spaces |
enabled_layouts | string[] | see below | Layouts in cycle order |
main_ratio | number | 0.5 | Main area ratio (0.1–0.9) |
main_count | integer | 1 | Windows in main area (min: 1) |
layouts | Layout[] | nil | Custom layouts to register |
Default enabled_layouts: { "tall", "wide", "monocle" }
Built-in layouts: tall, wide, monocle, bsp, grid, column,
floating, three_columns.
For layout examples and guidance, see Layouts.
Window filtering
| Option | Type | Default | Nested path | Description |
|---|---|---|---|---|
filter_mode | "blocklist" ǀ "allowlist" | "blocklist" | filter.mode | Filtering mode |
filter_apps | string[] | {} | filter.apps | App bundle IDs to filter |
min_width | integer | 0 | — | Minimum window width (pixels) |
min_height | integer | 0 | — | Minimum window height (pixels) |
For filtering examples and bundle ID guidance, see Window filtering.
Window rules
| Option | Type | Default | Description |
|---|---|---|---|
rules | WindowRule[] | nil | Per-app/per-title window behavior rules |
Each rule is a table with app (bundle ID), title
(substring), and action ("float"). At least one of
app or title is required.
For rule examples, matching semantics, and filter interaction, see Window rules.
Alerts
| Option | Type | Default | Nested path | Description |
|---|---|---|---|---|
show_layout_alerts | boolean | true | alerts.show | Show alerts on layout change |
alert_duration | number | 0.5 | alerts.duration | Alert duration (seconds, 0–10) |
For alert behavior and customization examples, see Alerts.
Cheatsheet
| Option | Type | Default | Nested path | Description |
|---|---|---|---|---|
cheatsheet_style | "light" ǀ "dark" ǀ "system" | "system" | cheatsheet.style | Color scheme |
For cheatsheet usage and keybinding customization, see Default keybindings.
Hooks
| Option | Type | Default | Description |
|---|---|---|---|
hooks | table | nil | Event callbacks |
For hook names and arguments, see Hooks.
Extensions
| Option | Type | Default | Description |
|---|---|---|---|
extensions | ShojiExtension[] | nil | Extensions to load on start |
For writing extensions, see Extensions guide.
Partition
| Option | Type | Default | Description |
|---|---|---|---|
partition_region_indicator | boolean | true | Flash focused region on switch |
Validation
| Option | Type | Default | Description |
|---|---|---|---|
strict_validation | boolean | true | Fail on invalid config |
Validation
Shoji validates configuration on startup. With the default
strict_validation = true, invalid values produce clear
error messages in the Hammerspoon console.
Error messages
Invalid values are rejected with the constraint that failed:
spoon.Shoji:configure({ gap_outer = -5,})-- [Shoji] Invalid configuration: gap_outer: must be >= 0, got -5Unknown keys produce a warning listing all valid keys, which helps catch typos:
spoon.Shoji:configure({ gap = 10, -- Typo: should be gap_outer or gap_inner})-- [Shoji] Unknown config key(s): 'gap'. Valid keys: alert_duration,-- cheatsheet_style, default_layout, enabled_layouts, ...Multiple errors are reported together:
spoon.Shoji:configure({ gap_outer = -5, main_ratio = 1.5,})-- [Shoji] Invalid configuration: gap_outer: must be >= 0, got -5-- [Shoji] Invalid configuration: main_ratio: must be <= 0.9, got 1.5Permissive validation
Set strict_validation = false to fall back to defaults
instead of failing:
spoon.Shoji:configure({ strict_validation = false, gap_outer = -5, -- Falls back to 0})