← Otto User GuideConfiguration
Otto uses TOML configuration files to customize your experience. This page explains how config files are loaded and merged; the individual settings are documented in their own pages.
Configuration Files
Otto searches for configuration files in the following order (later files override earlier ones):
System config:
/etc/otto/config.toml- System-wide defaults managed by administrators
- Lowest priority
- Installed by the package, copied from
otto_config.example.toml. With no config at all Otto falls back to compiled-in defaults, which means an empty dock and no bookmarks, so the packages ship a populated one. It is marked as a config file, so an upgrade leaves your edits alone and writes.pacnew(Arch) or.rpmnew(Fedora) beside them. The Arch packages also install an untouched copy at/etc/otto/config.example.tomlto diff against.
User config:
$XDG_CONFIG_HOME/otto/config.toml- Per-user configuration (defaults to
~/.config/otto/config.toml) - Follows XDG Base Directory specification
- Recommended location for user customization
- Per-user configuration (defaults to
Local override:
./otto_config.toml- Config file in the current working directory
- Useful for development and testing
Backend-specific:
./otto_config.{backend}.toml- Backend-specific overrides (e.g.,
otto_config.winit.toml,otto_config.udev.toml) - Highest priority
- Useful for maintaining different settings per backend during development
- Backend-specific overrides (e.g.,
Values from higher-priority files are merged recursively into lower-priority ones, so you only need to specify the options you want to override.
Config files are read once, when the session starts, so an edit you make by hand takes effect on the next login. Changing the same setting through the Settings app is different: most of them apply straight away. See How everything connects below.
Which file gets written
Changes made from the Settings app, or from the desktop itself such as dragging the dock handle, are written to the highest-priority file that exists, because that is the one whose values actually take effect. With no otto_config.toml around, that is ~/.config/otto/config.toml, and it is created if it is not there yet. The system-wide /etc/otto/config.toml is never written.
This is worth knowing when a setting appears not to stick. A leftover otto_config.toml in the directory the session was started from (the current directory is the home directory for a normal login, and the checkout for cargo run) overrides ~/.config/otto/config.toml for every key it sets, and quietly becomes the file the Settings app edits. Otto logs a warning at startup when the writable file is not your own config; delete the stray file, or the keys it repeats, to go back to configuring from ~/.config/otto.
How everything connects
There are three ways into the same configuration, and they all end at the same file.
Settings app ─┐
your script ─┼─▶ org.otto.Settings (D-Bus) ─▶ the compositor ─▶ config.toml
the desktop ─┘ │
(dragging the dock handle, and the like) └─▶ the Settings portal ─▶ other apps
The file is the whole truth. Everything else is a way of editing it, and nothing is stored anywhere else.
The Settings app (otto-settings) is not special. It is an ordinary D-Bus
client: it asks the compositor to describe every setting it knows, draws that
description, and asks it to change values. See Settings.
The D-Bus interface is org.otto.Settings, which the compositor itself
owns. Anything on your session bus can use it, so a setting is scriptable
without touching TOML:
# What is there, and what it is set to now
busctl --user call org.otto.Settings /org/otto/Settings org.otto.Settings GetAll
busctl --user call org.otto.Settings /org/otto/Settings org.otto.Settings \
Get s "dock.size"
# Change one. Replies "applied", or "pending-restart" if it needs a new session
busctl --user call org.otto.Settings /org/otto/Settings org.otto.Settings \
Set sv "dock.size" d 1.25
# Put it back to the default
busctl --user call org.otto.Settings /org/otto/Settings org.otto.Settings \
Reset s "dock.size"
A value set this way is validated, applied and written to the config file, the
same as if you had used the app. A bad value is refused rather than saved. The
compositor emits a Changed signal, so an open Settings app follows along.
Most settings apply live. The dock, the keyboard and touchpad, appearance and accent colour, sound, power and lock all take effect as soon as they change. Six need a new session: the interface scale, the interface font, the GTK theme, the display language, and the greeter command and its arguments.
Applications outside Otto are told about the appearance settings through the desktop’s standard Settings portal, which is how GTK, Qt and browser apps follow your light or dark preference and your accent colour without knowing anything about Otto.
Editing the file by hand is still the most direct route, and it is the only route for the things that have no single value behind them: shortcuts, dock bookmarks and display profiles are not in the D-Bus schema.
The wire contract, if you are writing a client, is documented in org.otto.Settings. Windows and tiling have a separate interface of their own; see Scripting.
Getting Started
# Create user config directory
mkdir -p ~/.config/otto
# Copy the example config (contains all options with documentation)
cp otto_config.example.toml ~/.config/otto/config.toml
# Edit as needed
$EDITOR ~/.config/otto/config.toml
Configuration Topics
| Topic | Description |
|---|---|
| Display | Scaling, display profiles, monitor arrangement, virtual outputs, layer shell zones |
| Theming | Theme scheme, accent color, fonts, background, cursors, icons |
| Input | Keyboard layout and repeat, touchpad, pointer acceleration |
| Keyboard Shortcuts | Binding syntax and the complete action list |
| Dock | Dock appearance, bookmarks, autohide, magnification |
| Top Bar | Clock format, tray, global menus (topbar.toml) |
| Audio | Sound effects and sound themes |
| Power Management | Lid switch, power button, suspend, clamshell |
| Lock Screen | Locker command, idle auto-lock, PAM setup |
| Login Greeter | --login mode and the greeter command |
| Night Shift | Color temperature and brightness control |
| Autostart | exec_once, XDG autostart, systemd integration |
| Clipboard | Clipboard persistence and managers |
| File search | The folders file search looks in, code repositories and removable drives ([search]) |
To use the desktop rather than configure it, start from the User Guide index.
Tips
- Start with the example. Copy
otto_config.example.tomlto~/.config/otto/config.tomland modify as needed. - Use XDG paths.
~/.config/otto/config.tomlpersists across updates. - System-wide defaults. Administrators can set defaults in
/etc/otto/config.toml. - Backend-specific settings. Use
otto_config.winit.tomlin the current directory for development/testing. - Scaling. Adjust
screen_scalebased on your display DPI (1.0 for 96 DPI, 2.0 for HiDPI).
Troubleshooting
Configuration not loading:
- Verify the TOML syntax (matching brackets, quotes, commas).
- Check Otto’s log output for parsing errors and which config files were loaded.
- Ensure the config file is in one of the searched locations listed above.
An edit to /etc/otto/config.toml does nothing:
- The user config wins. Check whether
~/.config/otto/config.tomlsets the same key — a key present there shadows the system file even if you never typed it, since older builds copied the whole[dock]table into it (see Dock). - Restart the session: config is only read at startup.
Icon/cursor theme not found:
- Verify the theme is installed:
ls /usr/share/icons/ ~/.local/share/icons/ - Theme names are case-sensitive.
- Some themes may require additional packages.
Keyboard shortcuts not working:
- Modifiers are
Ctrl,Alt,ShiftandLogo(aliases accepted, case-insensitive). - An unparsable trigger or action is skipped with a warning, not an error.
Grep the log for
skipping shortcut. - Some shortcuts may conflict with an application’s shortcut inhibitor.
Touchpad settings ignored:
- Settings only apply to touchpad devices, not mice.
- Some hardware may not support all features.
- Check
libinputcapabilities for your device.
For a fuller list, see Troubleshooting.