Splitting Your Config
Organize sweets.lua with bounded, root-confined includes
sweets.include(...) executes another Lua file at that point in the current
configuration layer. Use it to keep bindings, rules, outputs, and other settings
in focused files.
Suggested structure
A personal configuration can use this layout:
~/.config/sweets/
├── sweets.lua
├── bindings.lua
├── rules.lua
└── parts/
├── general.lua
├── layout.lua
└── startup.luaKeep the root file small and include files in the order they should execute:
sweets.include("parts/general.lua")
sweets.include("parts/layout.lua")
sweets.include("bindings.lua")
sweets.include("rules.lua")
sweets.include("parts/startup.lua")Each included file uses the normal typed Sweets API:
sweets.layout({
default = "tile",
master = 55,
})
sweets.gaps({
inner = 10,
outer = 10,
smart = true,
})sweets.bind("MOD+Return", "spawn", { "foot" })
sweets.bind("MOD+D", "spawn", { "fuzzel" })
for number = 1, 9 do
sweets.bind("MOD+" .. number, "workspace", number)
endPath resolution
Every include path must be a non-empty relative UTF-8 string. It resolves from
the file containing that sweets.include(...) call, not from the process
working directory.
-- Resolves to ~/.config/sweets/parts/pointer.lua
sweets.include("pointer.lua")Nested includes therefore work without repeating parent directories.
Absolute paths and any .. component are rejected. Includes cannot escape
the directory containing their root sweets.lua. A leading ~ is not
expanded to your home directory.
These paths are invalid:
sweets.include("/etc/sweets/shared.lua")
sweets.include("../shared.lua")sweets.include("~/shared.lua") looks for a literal ~ directory below the
including file; it does not refer to your home directory.
. path components are allowed, but simple paths are easier to read.
Root confinement and symlinks
Each installed or personal root file owns a separate permitted directory. All of its nested includes must resolve to regular files below that directory.
A symbolic link is accepted only when its canonical target is a regular file that remains below the same root. A link to a file outside the configuration root rejects the complete candidate.
The installed and personal configurations are already separate layers. Do not
include the installed /usr/share/sweets/sweets.lua from your personal file;
Sweets loads installed defaults automatically before the personal layer.
Execution and scope
An include executes immediately in the same constrained Lua VM and the same installed or personal layer as its parent.
- Sweets declarations take effect in include order.
- Window rules, input selectors, bindings, and startup commands retain their declaration order across file boundaries.
- A singleton section such as
sweets.general,sweets.layout, orsweets.gapsmay appear once across one root and all of its includes. sweets.layout_stylemay appear once for each layout across one root and all of its includes.- The installed and personal layers may each declare the same singleton because personal fields overlay installed fields.
Included chunks share Lua globals. Lexical local values belong only to the
file that declares them and are not visible in another included file. A shared
global must be assigned before an include reads it; reading a missing global
rejects the candidate at the included file and line.
palette = { accent = "#C27AFF" }
sweets.include("parts/border.lua")-- The global palette is visible here.
sweets.border({ focused = palette.accent })Prefer file-local helpers and direct API declarations where practical. Shared globals work, but accidental global names can make a large configuration harder to understand.
Repeats and cycles
Every canonical source may participate only once in one candidate. Including the same file twice is an error, even through two different symbolic links.
Include cycles are also errors:
sweets.include("b.lua")sweets.include("a.lua")Sweets reports the include chain so you can find the repeated file or cycle. The complete candidate is rejected; Sweets does not skip the repeated include.
Validation and reload
Validate the standard installed and personal layers with all includes:
sweets --check-configValidate one standalone root and its includes:
sweets --check-config ./test-config/sweets.luaThe validator uses the same path, sandbox, ordering, and resource rules as startup and reload. Errors identify the included source and Lua line while retaining the root file in the diagnostic.
Sweets watches every observed and resolved source. Saving an included file requests the same transactional reload as saving the root. If an include is missing, Sweets rejects the candidate but watches for that path to be created.
If any source or symlink changes during evaluation, Sweets rejects that candidate instead of combining files from different save states. A later settled save can then reload the complete tree.
Source limits
Limits apply to the complete candidate, including installed and personal roots:
| Limit | Maximum |
|---|---|
| Configuration sources | 32 files |
| Nested includes below a root | 16 levels |
| One source file | 256 KiB |
| All source files combined | 512 KiB |
| Canonical path length | 4,096 bytes |
The Lua instruction, time, memory, and recursion limits described in Basic Configuration also cover every included file. Exceeding any limit rejects the complete candidate.
Common errors
| Error | Cause |
|---|---|
include path must be relative | The include begins at / |
include path must not contain .. | The path attempts to leave its root |
cannot resolve configuration source | The file is missing or inaccessible |
include target escapes permitted root | A symlink resolves outside the root |
source included more than once | Two includes resolve to the same file |
include cycle | Included files eventually include an active parent |
sweets.SECTION may be declared only once | A singleton appears twice in one layer |
Fix the source and save it again, or request a manual retry:
sweets msg reloadInspect the active generation and last reload error with:
sweets msg configNext steps
- Basic Configuration for layering, validation, reload, and sandbox behavior
- Window Rules for ordered opening and live window appearance rules
- Layer Rules for ordered live layer-shell appearance rules
- Key Bindings for bindings and key sequences