OpenLogi

Configuration

Reference for the TOML config file: location, schema, all keys, actions, and gesture bindings.

OpenLogi stores everything in a single TOML file. The GUI writes it for you: the main window edits button bindings, the Actions Ring, DPI presets, SmartShift, scrolling, lighting, and camera controls, and the Settings window (⌘,) covers the app-wide preferences, but the file is plain text and safe to hand-edit. Per-app binding overlays have no dedicated editor yet, so those are authored here directly.

The agent reads the config on startup and rewrites it atomically on every change. Hand-edit it while OpenLogi is quit, or the running agent will overwrite your edits the next time it saves. Before its first save in each process, OpenLogi copies the previous file to config.toml.backup.1 and rotates up to config.toml.backup.5.

File location

PlatformPath
macOS / Linux$XDG_CONFIG_HOME/openlogi/config.toml (default ~/.config/openlogi/config.toml)
Windows%USERPROFILE%\.config\openlogi\config.toml

The file is written atomically (temp file + rename) and, on Unix, with 0600 permissions.

Top-level layout

schema_version = 4                             # required; a newer version is refused
selected_device = "receiver:aabbccdd:slot:1"   # physical key of the device shown in the carousel

[app_settings]                                 # app-wide preferences (omitted entirely when default)
# …

[devices."receiver:aabbccdd:slot:1"]           # one block per physical device
# …

[keyboard.bindings]                            # OS-level function-key remapper
# …
  • schema_version — the layout version (currently 4). Older files are migrated on load; a file declaring a newer version is refused rather than silently misread. v4 dropped the one-gesture-button-per-device owner lock (gesture_owner), v3 moved the device map from model keys to physical-device keys, and v2 merged button_bindings / gesture_bindings into one bindings map.
  • selected_device — remembers which device the carousel was on; omitted when unset.
  • [app_settings] — see below; the whole block is omitted while every field is at its default.
  • [devices.<key>] — per-device settings, keyed by physical device identity (see below).
  • [keyboard] — device-independent function-key remapping, driven by the OS hook rather than HID++.

Device keys

Since schema v3 a device block is keyed by the physical device, not by model, so two identical mice never share one entry:

FormUsed for
receiver:<receiver-uid>:slot:<n>Paired to a Bolt / Unifying / Lightspeed receiver
direct:<vid>:<pid>:serial:<serial> (or :unit:<hex>)Bluetooth-direct or USB-wired HID++ device
raw:<vid>:<pid>:<usage-page>:<usage-id>:serial:<serial>Raw-HID device such as a Litra light

Keys are lower-case hex. The GUI writes the right key for you; the reliable way to get one is to configure the device once in the app, then read the key back out of config.toml. A device that reports no serial and no unit id has no stable identity, so OpenLogi does not persist settings for it.

[app_settings]

KeyDefaultMeaning
launch_at_loginfalseStart the agent on login. A LaunchAgent plist on macOS, a systemd user unit on Linux.
check_for_updatesfalseOpt-in. One HEAD request to the GitHub latest-release per launch; logs whether a newer version exists; never downloads on its own.
auto_install_updatesfalseOpt-in, and only acts when check_for_updates is on: downloads and stages a newer version in the background, applied on the next restart.
update_prompt_seenfalseSet once the first-run "check for updates?" prompt has been answered, so it is never shown again.
show_in_menu_bartruemacOS menu-bar status item and Windows tray icon. Ignored on Linux.
capture_mouse_eventstrueWhether the agent installs the OS mouse hook at all. false stops button remapping and grabs no input device; DPI, SmartShift, and the other HID++ features keep working. Takes effect on agent restart.
auto_download_assetstrueFetch device renders when a device appears. false makes no asset network requests; Refresh assets in Settings still fetches on demand.
asset_sourceautomaticAsset mirror: automatic (race every built-in mirror), openlogi, cloudflare, or fastly.
language(follow system)UI locale, one of the 20 bundled locales (en, de, pt-BR, zh-CN, …). Unset follows the system locale.
thumbwheel_sensitivity14Thumb-wheel responsiveness on a 1100 scale; the default is 1× native scroll (the wheel is only diverted from native scrolling once this leaves the default).
appearancesystemsystem, light, or dark.
theme_light(brand theme)Theme name used in light mode, e.g. "OpenLogi Light".
theme_dark(brand theme)Theme name used in dark mode.
ui_radius(theme default)Corner-radius override in pixels; the Appearance page offers 0 / 6 / 12.

Per-device blocks

Each [devices.<key>] block holds the settings for one physical device.

KeyTypeMeaning
enabledboolfalse leaves the device completely native: no HID++ capture session, no settings re-applied on reconnect. Default true.
bindingstableMaps a logical button to a binding: a single action, or a per-direction gesture table (see Buttons and Gesture bindings).
per_app_bindingstable of tablesOverlays keyed by app id. While that app is frontmost its entries win; everything else falls through to bindings.
action_ringtableActions Ring enable state, haptics, default layout, and per-app layouts.
dpi_presetsarray of intsOrdered DPI values cycled by CycleDpiPresets and indexed by SetDpiPreset.
dpiintThe committed sensor DPI. Lives in device RAM, so the agent re-applies it on reconnect.
smartshifttablemode (ratchet / free), auto_disengage, tunable_torque; re-applied on reconnect.
invert_scrollboolReverse this device's native wheel direction without touching the system trackpad direction.
scroll_resolutionstringlow or high. Persisted HID++ 0x2121 wheel resolution. Absent leaves the device's own setting alone.
thumbwheel_sensitivityintPer-device override of the app-wide value.
lightingtableStatic RGB for HID++ keyboards; see below.
lighttableStandalone light (Litra) power, brightness, temperature; see Lights & webcams.
camera_controlstableWebcam UVC controls, keyed by control name.
camera_profilestable of tablesUser-saved camera profiles (name → control snapshot).
camera_profilestringThe camera profile last applied from the GUI.
host_switch_targetsarray of keysDevice keys of mice that follow this keyboard's Easy-Switch channel.
fn_lockboolKeyboards only. true makes the F-row send F1–F12 without holding Fn; absent leaves the keyboard's own state alone. Re-applied on reconnect.
identitytableWritten by the app: last-known name, kind, and capabilities, so a sleeping device still renders its panels. Not meant to be hand-authored.
disabled_gesturestableWritten by the app: the direction map of a button whose gesture mode is currently off, so re-enabling restores it.

lighting

KeyDefaultMeaning
enabledtrueWhether the static color is applied.
color"ffffff"Static color as six hex digits RRGGBB (no leading #).
brightness1000100; clamped on load.

light

KeyDefaultMeaning
enabledtrueWhether the light should be on.
auto_camerafalseTurn the light on while any camera is in use, off when camera use stops (macOS).
brightness_percent1000100, mapped to the device's native range (a Litra's 20–250 lumens, for example).
temperature_kelvin(unset)Colour temperature, when the device supports it (Litra: 2700–6500 K in 100 K steps).

Buttons

bindings and per_app_bindings are keyed by a logical button.

Mouse controls: LeftClick, RightClick, MiddleClick, Back, Forward, DpiToggle (the mode-shift button under the wheel), Thumbwheel (its click), ThumbwheelScrollUp, ThumbwheelScrollDown, GestureButton, HapticPanel (the MX Master 4 Haptic Sense Panel).

Keyboard F-row controls, diverted over HID++ only when you bind them: KeySearch, KeyDictation, KeyEmoji, KeyScreenCapture, KeyMicMute, KeyPlayPause, KeyMute, KeyVolumeDown, KeyVolumeUp. See Keyboards.

Actions

Binding values are action names, written verbatim:

  • SuppressNone (capture the input but do nothing)
  • MouseLeftClick, RightClick, MiddleClick, MouseBack, MouseForward (the real extra-button events most apps treat as native back/forward)
  • EditingCopy, Paste, Cut, Undo, Redo, SelectAll, Find, Save
  • Browser & tabsBrowserBack, BrowserForward, NewTab, CloseTab, ReopenTab, NextTab, PrevTab, ReloadPage
  • Window & desktop (macOS)MissionControl, AppExpose, PreviousDesktop, NextDesktop, ShowDesktop, LaunchpadShow
  • SystemLockScreen, Screenshot, CaptureRegion, Sleep, ShowActionsRing, OpenApplication
  • MediaPlayPause, NextTrack, PrevTrack, VolumeUp, VolumeDown, MuteVolume
  • DPI & wheelCycleDpiPresets, SetDpiPreset, ToggleSmartShift
  • ScrollScrollUp, ScrollDown, HorizontalScrollLeft, HorizontalScrollRight
  • Power userCustomShortcut, TypeText, RunAppleScript, RunShellCommand, Workflow

The picker lists 44 plain actions. ShowActionsRing is written by hand (it isn't in the picker), and the parameterized actions are written as a single-key table:

MiddleClick = "MissionControl"                              # plain action
DpiToggle = { SetDpiPreset = 2 }                            # preset index
Back = { CustomShortcut = "Cmd+Shift+P" }                   # key chord
Forward = { OpenApplication = { path = "~/Downloads", display_name = "Downloads" } }

OpenApplication takes an application, folder, filesystem path, or URL; a leading ~ is expanded when the action runs. CustomShortcut stores a platform-neutral chord such as Cmd+Shift+P, Ctrl+Alt+Left, or F5. The GUI can author all of these: custom shortcuts and Open application from the action picker, and TypeText / RunAppleScript / RunShellCommand / Workflow under its Power User submenu.

Gesture bindings

Any capable button can be in gesture mode: its bindings entry becomes a sub-table keyed by Up, Down, Left, Right, and Click (the plain press, no swipe) instead of holding a single action. Since schema v4 that is a per-button fact; several buttons can be in gesture mode at once, and the old device-wide gesture_owner key is gone (a v3 file's owner is migrated to the equivalent binding shapes on load).

[devices."receiver:aabbccdd:slot:1".bindings.GestureButton]
Up = "MissionControl"
Down = "ShowDesktop"
Left = "PrevTab"
Right = "NextTab"
Click = "AppExpose"

The dedicated Gesture Button and the MX Master 4 Haptic Sense Panel are captured over HID++ raw-XY; middle / back / forward gestures ride the OS hook.

[keyboard]

A device-independent remapper for function keys on any keyboard, driven by the OS hook. Keys are triggers of the form [modifier+]…key, with modifiers shift, control (ctrl), option (alt), command (cmd), and keys esc and f1f19:

[keyboard.bindings]
f1 = "MissionControl"
"shift+f2" = "ShowDesktop"
"cmd+f5" = { CustomShortcut = "Cmd+Shift+P" }

This is separate from a Logitech keyboard's HID++ F-row bindings under [devices.<key>.bindings]; see Keyboards for when to use which.

Example

schema_version = 4
selected_device = "receiver:aabbccdd:slot:1"

[app_settings]
launch_at_login = true
language = "zh-CN"
thumbwheel_sensitivity = 14
appearance = "system"

# MX Master 4 in slot 1 of a Bolt receiver.
[devices."receiver:aabbccdd:slot:1"]
dpi_presets = [800, 1600, 3200]
dpi = 1600
invert_scroll = true
scroll_resolution = "high"

[devices."receiver:aabbccdd:slot:1".bindings]
Back = "BrowserBack"
Forward = "BrowserForward"
MiddleClick = "MissionControl"
HapticPanel = "ShowActionsRing"

# The gesture button binds per direction; Click is the plain press.
[devices."receiver:aabbccdd:slot:1".bindings.GestureButton]
Left = "PrevTab"
Right = "NextTab"
Click = "PlayPause"

# Back becomes Undo only while VS Code is frontmost.
[devices."receiver:aabbccdd:slot:1".per_app_bindings."com.microsoft.VSCode"]
Back = "Undo"

[devices."receiver:aabbccdd:slot:1".smartshift]
mode = "ratchet"
auto_disengage = 16
tunable_torque = 0

[devices."receiver:aabbccdd:slot:1".action_ring]
enabled = true
haptics = true

[devices."receiver:aabbccdd:slot:1".action_ring.default.slots]
Top = { action = "Cut" }
TopRight = { action = "Copy" }
Right = { action = "Paste", label = "Paste It" }
BottomRight = { action = "BrowserForward" }
Bottom = { action = "PlayPause" }
BottomLeft = { action = "BrowserBack" }
Left = { action = "Undo" }
TopLeft = { action = "Redo" }

# A Signature-series keyboard: F-row keys diverted over HID++, Fn-lock off.
[devices."receiver:aabbccdd:slot:2"]
fn_lock = false
host_switch_targets = ["receiver:aabbccdd:slot:1"]

[devices."receiver:aabbccdd:slot:2".bindings]
KeySearch = "MissionControl"
KeyScreenCapture = "CaptureRegion"

[devices."receiver:aabbccdd:slot:2".lighting]
enabled = true
color = "ff0000"
brightness = 80

# A Litra Glow, keyed by its raw-HID identity.
[devices."raw:046d:c900:ff43:0202:serial:YOUR-SERIAL".light]
enabled = true
auto_camera = true
brightness_percent = 65
temperature_kelvin = 4600

Source: CONFIGURATION.md

On this page