Skip to main content
otter-settings is the main config UI, with one tab per app, a theme browser, and drag-and-drop bar layout. It writes the same ~/.config/otter-shell/*.conf files you would edit by hand, so the GUI and text stay in sync.
Launch from otter-launcher, bind a compositor hotkey, or run the command above. See otter-settings for tabs, features, and theme presets.
Click Apply to reload most running apps via inotify without restarting them.

What you can configure in otter-settings

Compositor hotkeys (screenshot, launcher, overview, lock) are not in otter-settings. Bind those in your compositor config. See Keybinds.

Manual config files

App settings live under $XDG_CONFIG_HOME/otter-shell/, defaulting to ~/.config/otter-shell/. Paths below use that default. Edit by hand when you want to script changes, or keep comments the UI might not show. Lua code belongs in data directories, not here. System defaults may live under /etc/otter-shell/. User configs always win.

File format

Quote strings with double quotes. Booleans are true or false. Empty-string behavior depends on the field; it is not a universal request for a default. Omit optional color overrides to inherit the shared theme. Apps that normalize config add missing defaults and remove unknown fields at startup. Back up hand-edited files before upgrading. Hot-reload paths should read settings without rewriting them.

Lua plugins and surface scripts

Bar widgets and launcher providers use hosted Lua plugins. The Zig .so ABI is unsupported. Put a plugin’s plugin.toml and init.lua in a directory named after its ID. Hosts search these roots in order; the first matching plugin ID wins:
  1. Colon-separated roots in $OTTER_PLUGIN_PATH
  2. $XDG_DATA_HOME/otter-shell/plugins/ (default ~/.local/share/otter-shell/plugins/)
  3. /usr/lib/otter-shell/plugins/
  4. otter-shell/plugins/ under each $XDG_DATA_DIRS entry (default /usr/local/share:/usr/share)
plugins.conf holds enable gates and capability policy, for example:
A capability allow-list narrows what a plugin declares in its manifest; it does not grant undeclared capabilities. Review plugins before enabling them. See Plugins for installation and Writing plugins for manifests and bindings. Surface UI scripts use $XDG_DATA_HOME/otter-shell/ui/, then otter-shell/ui/ under $XDG_DATA_DIRS. $OTTER_UI_DIR overrides that search for development. Scripts in the old config-directory ui/ location are not loaded by default. For hosts that support per-app UI choices, ui.conf selects automatic Lua loading or native fallback:
auto uses a valid script when available and falls back to native UI otherwise. Privileged surfaces ignore user overrides and only accept trusted root-owned system scripts. Use UI Scripts in Settings to see which scripts and controls a host supports. See UI scripts for the host contract and Runtime safety for trust boundaries.

Hot reload

Most daemons watch their config (and often theme.conf) with inotify:
  • otter-bar: reloads otter-bar.conf on save; theme.conf changes refresh widget colors without a full bar config reload
  • otter-notifications, otter-wallpaper, otter-osd, otter-idle: reload on save
  • otter-term: hot-reloads otter-term.conf and shared theme.conf
  • otter-monitor: hot-reloads theme.conf only; restart to pick up otter-monitor.conf changes
  • otter-transcribe: reloads settings and watches theme.conf; restarts automatically after a model unload when idle
otter-settings and manual saves hit the same reload path.

System-wide defaults

Lookup order (example for otter-term):
  1. ~/.config/otter-shell/otter-term.conf (user: highest priority)
  2. /etc/otter-shell/otter-term.conf (system defaults)
  3. Compiled-in defaults
Set system defaults in /etc/otter-shell/ without touching home directories.