OpenLogi TOML Config Schema: How to Write Configuration Files by Hand
OpenLogi uses a single TOML configuration file where the top-level structure mirrors the Config struct in crates/openlogi-core/src/config.rs, requiring schema_version = 7 alongside global settings, device blocks keyed by physical identifiers, and optional keyboard bindings.
All user preferences in the AprilNEA/OpenLogi repository are serialized into a flat config.toml file that the application automatically migrates from older schema versions on load. Understanding the exact schema definitions in the core Rust source allows you to hand-craft or edit configurations without the GUI.
Top-Level Document Structure
The root of every OpenLogi TOML config must declare the schema version and can contain five optional top-level keys:
schema_version = 7 # Required: must match current SCHEMA_VERSION
selected_device = "receiver:aabbccdd:slot:1" # Optional: default device to display
[app_settings] # Global preferences
[devices] # Map of physical device configurations
[keyboard] # Global keyboard shortcuts
According to the source code in crates/openlogi-core/src/config.rs, the Config struct defines these fields with schema_version as a mandatory u32, while app_settings maps to the AppSettings struct and devices is a BTreeMap<String, DeviceConfig> keyed by stable physical identifiers like "receiver:..." or "unit:...".
Global Application Settings [app_settings]
The [app_settings] section controls application-wide behavior and maps directly to the AppSettings struct defined in crates/openlogi-core/src/settings.rs. All fields are optional; missing values fall back to AppSettings::default().
Common configuration options include:
[app_settings]
launch_at_login = true # Start OpenLogi when the user logs in
check_for_updates = false # Disable automatic update checks
show_in_menu_bar = true # Display tray icon
capture_mouse_events = true # Enable mouse-event capture
smooth_scroll = false # Disable smooth scrolling
vertical_scroll_sensitivity = 14 # Scroll speed range: 1-30
auto_download_assets = true # Download missing assets automatically
asset_source = "automatic" # Asset fetch strategy
language = "en" # UI language ISO code
thumbwheel_sensitivity = 14 # Thumb-wheel speed
appearance = "system" # UI theme: system / light / dark
ui_scale = "normal" # UI scale: normal / larger / larger-2x
device_view_mode = "grid" # Device view layout: grid or list
app_icon = "openlogi" # macOS icon variant: openlogi or prism
Additional booleans such as auto_install_updates control silent update installation behavior.
Per-Device Configuration [devices.""]
Device-specific settings live in tables keyed by stable physical identifiers. The DeviceConfig struct in crates/openlogi-core/src/device.rs defines the available fields.
Device Identifiers
Keys follow the pattern "receiver:<id>:slot:<n>" for Logitech receivers or "unit:<uuid>" for direct USB connections:
[devices."receiver:aabbccdd:slot:1"]
custom_name = "Office mouse"
dpi = 1600
dpi_presets = [800, 1600, 3200]
thumbwheel_sensitivity = 20
invert_scroll = false
scroll_resolution = "high"
Common Device Fields
The DeviceConfig struct supports these primary fields:
- custom_name – Human-readable label displayed in the UI.
- dpi – Integer sensor DPI value.
- dpi_presets – Array of preset DPI integers for cycling.
- thumbwheel_sensitivity – Integer override for wheel speed (1-30).
- invert_scroll – Boolean to reverse scroll direction.
- scroll_resolution – String enum:
"high"or"low".
Button Bindings [devices."".bindings]
Button mappings are defined under the bindings sub-table. Simple actions use string values, while complex actions use inline tables:
[devices."receiver:aabbccdd:slot:1".bindings]
Back = "BrowserBack"
Forward = "BrowserForward"
MiddleClick = { HoldShortcut = "Ctrl+Space" } # Hold while button is pressed
DpiToggle = { short = "ShowDesktop", long = "MissionControl" } # Short vs long press
Thumbwheel = "AppExpose"
Gesture Button Configuration
Gesture buttons (like the Logitech MX Master gesture puck) require a nested table defining actions per direction:
[devices."receiver:aabbccdd:slot:1".bindings.GestureButton]
Click = "MissionControl"
Up = "MissionControl"
Down = "AppExpose"
Left = "PreviousDesktop"
Right = "NextDesktop"
Per-Application Overrides
Override bindings when specific applications are foreground using the per_app_bindings table. Keys are bundle identifiers (macOS) or exe:<filename> (Windows):
[devices."receiver:aabbccdd:slot:1".per_app_bindings."com.microsoft.VSCode"]
Back = "Undo"
Action Ring [devices."".action_ring]
Configure the circular "Actions Ring" UI overlay:
[devices."receiver:aabbccdd:slot:1".action_ring]
enabled = true
haptics = true
[devices."receiver:aabbccdd:slot:1".action_ring.default.slots]
Top = { action = "Copy", icon = "Keyboard" }
Right = { action = { OpenApplication = { path = "/Applications/Safari.app", display_name = "Safari" } }, icon = "Applications" }
Bottom = { action = "ShowDesktop", label = "Desktop" }
Slots support action, icon, and optional label fields.
Lighting [devices."".lighting]
Control device RGB LEDs:
[devices."receiver:aabbccdd:slot:1".lighting]
enabled = true
color = "ff0000"
brightness = 80
SmartShift Wheel [devices."".smartshift]
Configure the SmartShift ratchet wheel behavior:
[devices."receiver:aabbccdd:slot:1".smartshift]
mode = "ratchet" # Options: ratchet, freespin, or automatic
auto_disengage = 16 # Threshold for automatic mode
tunable_torque = 50 # Mechanical resistance level
Global Keyboard Bindings [keyboard.bindings]
These shortcuts apply system-wide to all keyboards, independent of mouse devices. The syntax is defined in crates/openlogi-core/src/key_trigger.rs:
[keyboard.bindings]
f1 = "MissionControl"
"shift+command+f5" = "ShowDesktop"
Keys can be single identifiers or quoted combinations of modifiers (shift, command, ctrl, option) plus key names.
Minimal Working Example
A complete, hand-written configuration derived from docs/config.example.toml:
schema_version = 7
selected_device = "receiver:aabbccdd:slot:1"
[app_settings]
launch_at_login = true
show_in_menu_bar = true
ui_scale = "normal"
appearance = "system"
[devices."receiver:aabbccdd:slot:1"]
custom_name = "Office mouse"
dpi = 1600
dpi_presets = [800, 1600, 3200]
[devices."receiver:aabbccdd:slot:1".bindings]
Back = "BrowserBack"
Forward = "BrowserForward"
MiddleClick = { HoldShortcut = "Ctrl+Space" }
[devices."receiver:aabbccdd:slot:1".action_ring]
enabled = true
haptics = true
[devices."receiver:aabbccdd:slot:1".action_ring.default.slots]
Top = { action = "Copy", icon = "Keyboard" }
[keyboard.bindings]
f1 = "MissionControl"
Key Source Files
| File | Purpose |
|---|---|
crates/openlogi-core/src/config.rs |
Defines the Config, AppSettings, DeviceConfig, and related structs that map directly to the TOML schema. |
docs/config.example.toml |
Full example illustrating every supported section and field. |
crates/openlogi-core/src/device.rs |
Contains per-device structures (DeviceConfig, LinkConfig, LinkOverrides) used in the [devices] map. |
crates/openlogi-core/src/settings.rs |
Defines AppSettings and related enums (AppIcon, Appearance, AssetSourcePreference, etc.). |
crates/openlogi-core/src/key_trigger.rs |
Describes the syntax for global keyboard shortcuts (KeyTrigger). |
Summary
- Schema version 7 is required in the
schema_versionfield; OpenLogi automatically migrates configurations from versions 1-6 on load. - Device identifiers use the format
"receiver:<hex>:slot:<n>"or"unit:<uuid>"as defined incrates/openlogi-core/src/device.rs. - Button bindings support simple strings for actions, inline tables for hold shortcuts, and sub-tables for gesture directions.
- Global settings under
[app_settings]are optional and default to Rust struct defaults. - Per-application overrides use bundle IDs or
exe:<filename>keys underper_app_bindings.
Frequently Asked Questions
What is the current schema version for OpenLogi TOML configs?
The current schema_version is 7, defined as a constant in crates/openlogi-core/src/config.rs. OpenLogi automatically migrates older configuration files from versions 1 through 6 to version 7 when the application starts, but manually writing configs should target version 7 to avoid migration warnings.
How do I find the correct device identifier for the [devices] table?
Device identifiers are stable physical addresses generated by OpenLogi. They appear as strings like "receiver:aabbccdd:slot:1" for Logitech Unifying Receivers or "unit:<uuid>" for Bluetooth or Bolt devices. You can find your device's identifier by checking the UI dropdown or examining the automatically generated config file after initially pairing a device through the GUI.
Can I configure different button actions for specific applications?
Yes. Use the [devices."<id>".per_app_bindings."<bundle_id>"] table where <bundle_id> is the macOS application bundle identifier (e.g., "com.microsoft.VSCode") or exe:<filename> on Windows. Actions defined here override the default device bindings only when that application is the foreground window.
Where are the default values defined if I omit fields in app_settings?
Default values are hardcoded in the AppSettings::default() implementation located in crates/openlogi-core/src/settings.rs. For example, language defaults to "en", appearance defaults to "system", and ui_scale defaults to "normal" when not explicitly specified in the TOML file.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →