How to Use Physical-Key Device Entries in OpenLogi Config: A Complete Guide

Physical-key device entries in OpenLogi config use stable hardware identifiers—such as USB serial numbers, Bluetooth addresses, or receiver slot IDs—as table names under the [devices] section, enabling persistent per-device settings that survive hardware changes and session restarts.

OpenLogi stores each discovered Logitech device under a unique config key that acts as the physical device identifier inside your TOML configuration. When you need to customize DPI, SmartShift, or button mappings for a specific mouse or keyboard, you reference this physical key to create targeted device entries. The desktop client automatically resolves these keys at startup and migrates transient identifiers to persistent ones as hardware details become available.

Understanding Physical-Key Device Entries

In OpenLogi, every device record contains a config_key field defined in crates/openlogi-desktop/src/state/devices.rs. This string uniquely identifies the physical unit using stable hardware identifiers rather than volatile port assignments.

The key format follows these patterns:

  • Unit keys: unit:4f4c4401 (based on device serial number)
  • Receiver keys: receiver:da2699e1:slot:1 (based on USB receiver ID and slot)
  • Camera keys: camera:046d:0893:serial:abc123 (based on VID:PID and serial)

The DeviceRecord struct in crates/openlogi-desktop/src/state/devices.rs stores this value, with the helper method persistent_config_key() providing the stable identifier for configuration purposes.

Transient vs. Persistent Physical Keys

OpenLogi distinguishes between two types of physical keys to handle device detection gracefully.

Transient keys appear when a device is first connected via a USB receiver or unknown port. These follow the pattern receiver:{id}:slot:{n} and may change if you move the receiver to a different USB port.

Persistent keys replace transient ones once the device reports a stable serial number or Bluetooth address, typically formatted as unit:{hex_id}. The migration logic in crates/openlogi-desktop/src/state/inventory.rs automatically folds transient records onto persistent ones, ensuring your settings transfer automatically when OpenLogi discovers the stable identifier.

Configuring Physical-Key Device Entries in TOML

All device-specific configurations belong under the top-level devices map using the physical key as the table name. The example configuration in docs/config.example.toml demonstrates this structure:

[devices."unit:4f4c4401"]
dpi = 1200
smartshift = { enabled = true }
button = { "button1" = "back" }

Note the quoted key format [devices."unit:..."] required for keys containing colons or other special characters.

For a Logitech MX Master 3 with unit key unit:4f4c4402, a complete configuration looks like:

[devices."unit:4f4c4402"]
dpi = 1600
smartshift = { enabled = true, threshold = 15 }

[devices."unit:4f4c4402".button]
"button1" = "back"
"button2" = "forward"
"gesture_button" = "mission_control"

How OpenLogi Resolves Config Entries at Runtime

When the OpenLogi desktop client starts, it loads the TOML configuration via openlogi-core::config::Config and matches each DeviceRecord against the physical keys defined in your config file.

The resolution logic in crates/openlogi-desktop/src/state/devices.rs (around line 58) performs a lookup using config.devices.get(&record.config_key). If the physical key exists in the configuration map, OpenLogi applies the custom DPI, SmartShift, and button mappings. If no match exists, the device falls back to default settings.

You should never manually edit the physical key itself. Instead, modify only the values inside the table. If you rename a device or move it to a different port, OpenLogi automatically migrates the old transient key to the new persistent one while preserving your configured settings.

Summary

  • Physical keys use stable hardware identifiers (unit:..., receiver:...:slot:...) as configuration table names in OpenLogi TOML files.
  • Transient keys handle initial device detection and automatically migrate to persistent keys once stable serial numbers are available, as implemented in crates/openlogi-desktop/src/state/inventory.rs.
  • Configuration tables use the quoted format [devices."unit:..."] to define per-device settings for DPI, SmartShift, and button mappings.
  • Runtime resolution occurs in crates/openlogi-desktop/src/state/devices.rs, where OpenLogi matches device records against the physical keys loaded from your config file.

Frequently Asked Questions

How do I find the physical key for my Logitech device?

OpenLogi provides a CLI command to display device keys. Run openlogi list --show-keys to see all connected devices with their current physical keys, including both transient receiver slots and persistent unit identifiers.

Can I change the physical key in my configuration file?

Do not attempt to modify the physical key string itself. The key is derived from hardware identifiers and should remain immutable in your config. If your device appears under a new key due to hardware changes, OpenLogi automatically migrates the configuration from the old transient key to the new persistent key.

What happens if I move my mouse to a different USB receiver slot?

Initially, OpenLogi assigns a transient key based on the receiver ID and slot number (e.g., receiver:da2699e1:slot:2). Once the mouse reports its stable serial number, the system migrates your settings to a persistent unit:... key in crates/openlogi-desktop/src/state/inventory.rs, preserving all customizations regardless of which slot or port you use.

Can I use the same configuration for multiple identical Logitech devices?

Each physical device requires its own unique entry because the physical key contains device-specific identifiers like serial numbers. While you can copy the configuration values between entries, you must create separate tables for each physical key (e.g., [devices."unit:4f4c4402"] and [devices."unit:4f4c4403"]) to maintain distinct settings for each unit.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →