Basic Configuration
Create, validate, and reload your Sweets Lua configuration
Sweets is configured in Lua. It loads the installed defaults first, then your personal file as an override.
Create a personal configuration
sweets --init-configThis creates ~/.config/sweets/sweets.lua with commented examples. It never
overwrites an existing file, and it checks the result.
| Command | Result |
|---|---|
sweets --init-config | Commented examples. Every default stays active. |
sweets --init-config --full | A copy of every default to edit in place. |
sweets --init-config PATH | Writes to PATH instead. |
A full copy overrides every setting it declares. Later changes to those defaults will not reach you. Delete the parts you do not change.
Put only the values you want to change in ~/.config/sweets/sweets.lua:
sweets.general({
mod_key = "SUPER",
})
sweets.gaps({
inner = 12,
outer = 12,
smart = true,
})
sweets.bind("MOD+D", "spawn", { "fuzzel" })Do not edit the installed sweets.lua. Package upgrades and source installs
replace it.
Load order
| Order | File |
|---|---|
| 1 | PREFIX/share/sweets/sweets.lua — installed defaults |
| 2 | ~/.config/sweets/sweets.lua — yours, optional |
PREFIX follows the binary. /usr/bin/sweets reads
/usr/share/sweets/sweets.lua, /usr/local/bin/sweets reads
/usr/local/share/sweets/sweets.lua. XDG_CONFIG_HOME is honored when set.
With neither file present, Sweets starts with built-in defaults and a small set of emergency bindings.
How the layers combine
Your file does not replace the installed one wholesale. Each API merges differently:
| Declaration | Merge |
|---|---|
| Singleton sections | Your fields override; omitted fields stay unchanged |
| Layout styles | Overlays fields for the same layout only |
| Key bindings | Replaces the same key; sweets.unbind removes it |
| Environment entries | Replaces the same variable name |
| Monitor and workspace rules | Replaces the rule for the same connector or number |
| Window and layer rules | Installed rules run first, yours append |
| Input selectors | Global block overlays; selector rules append |
| Startup commands | Both layers run, installed first |
| Animations | Your fields overlay the installed timing |
A singleton such as sweets.general, sweets.layout, or sweets.gaps may be
declared once per layer. Declaring one twice in the same layer, includes
counted, is an error.
Validate
sweets --check-config # installed and personal together
sweets --check-config ./test.lua # one file on its ownA successful check prints the resolved path and exits 0. Syntax errors,
unknown fields, wrong types, duplicate declarations, and unsafe include paths
exit nonzero with the failing source and message. Neither form opens a Wayland
socket.
Reload
Sweets watches the installed file, your file, and every
included file, and reloads on save.
To reload manually, press MOD+Shift+R or run:
sweets msg reloadA reload is all or nothing. A rejected candidate leaves the last valid configuration active and shows the error on every monitor until you fix it.
Inspect the active path, generation, and latest error:
sweets msg configIndividual pages note when a valid reload affects only future actions or future windows.
The sweets table
The global sweets table is the only API available to your configuration.
| Call | Configures |
|---|---|
sweets.general | Modifier, background, workspace mode, cross-monitor policy |
sweets.xwayland | Private rootless XWayland startup |
sweets.layout | Layout defaults, master position, insertion, cycling |
sweets.layout_style | Per-layout appearance overrides |
sweets.gaps, sweets.border, sweets.window, sweets.special | Gaps, borders, corners, special-workspace appearance |
sweets.notify | Configuration-error bar appearance |
sweets.keyboard, sweets.cursor | XKB, repeat, Num Lock, cursor theme |
sweets.pointer | Automatic pointer-follow behavior |
sweets.input | Global and per-device libinput settings |
sweets.gesture, sweets.gestures | Touchpad swipe actions and recognition policy |
sweets.bind_switch | Lid and tablet-mode bindings |
sweets.monitor | Mode, scale, transform, position, adaptive sync |
sweets.workspace | Workspace-to-monitor pins |
sweets.window_rule | Opening behavior and appearance for matching windows |
sweets.layer_rule | Appearance for matching layer-shell surfaces |
sweets.blur | Global backdrop-blur policy |
sweets.shadow | Global drop-shadow policy |
sweets.animations | Window and workspace transitions |
sweets.curve | Names a curve for reuse |
sweets.env | Environment for programs Sweets launches |
sweets.exec_once | Programs started once per session |
sweets.bind, sweets.unbind | Key bindings and sequences |
sweets.include | Additional Lua files |
Unknown names and fields are rejected.
Strict globals
Reading an undeclared global rejects the configuration. This catches typos that Lua would otherwise turn into a silently absent field:
local enabled = true
sweets.pointer({ follow_focus = enabled }) -- valid
sweets.input({ natural_scroll = falsed }) -- error: unknown global `falsed`Declare variables before reading them. An explicit nil still omits the entry
as usual.
Sandbox
Lua functions, loops, tables, and the string, table, math, and utf8
libraries are available. Filesystem, process, and native-module access is not:
io, os, package, require, debug, dofile, loadfile, load,
pcall, xpcall, collectgarbage, and print are all removed.
Use sweets.include instead of
require, and sweets.exec_once or a spawn
binding to start programs. Commands are argument arrays and are never passed to
a shell.
Each load is bounded:
| Limit | Value |
|---|---|
| Instructions | 5 million |
| Evaluation time | 250 ms |
| Memory | 16 MiB |
| Call depth | 128 |
| Sources / include depth | 32 / 16 |
| Per file / all files | 256 KiB / 512 KiB |
Exceeding a limit rejects the configuration like any other error. Numbers must
be finite; math.huge and 0/0 are rejected.
Next steps
- Split the configuration across files
- General settings for workspaces and focus
- Key bindings for actions and commands