How to Configure Global Keyboard Remapping in OpenLogi: Complete Guide

Global keyboard remapping in OpenLogi is configured by editing the [keyboard.bindings] table in the application's TOML configuration file, where key triggers map to actions defined in openlogi-core/src/binding.rs, and changes are committed through AppState::commit_keyboard_binding.

OpenLogi's desktop client provides a unified way to remap function keys across all connected Logitech devices. Unlike per-device bindings stored under config.devices, global keyboard bindings apply universally and persist through the AppState management layer. This article explains the configuration schema, source code implementation, and both manual and programmatic approaches to customization.


Configuration File Location and Structure

OpenLogi stores user settings in a TOML file, typically located at ~/.config/openlogi/config.toml on Linux or equivalent platform-specific paths. The global keyboard remapping section lives at the top level of this file, separate from device-specific configurations.

File Purpose
docs/config.example.toml Complete reference showing valid keyboard.bindings syntax
crates/openlogi-desktop/src/features/keyboard/mod.rs UI module declaring global scope of keyboard bindings
crates/openlogi-desktop/src/features/keyboard/function_row.rs Visual editor implementation for key selection
crates/openlogi-core/src/binding.rs Action enum defining all assignable actions

The [keyboard.bindings] table uses key trigger strings as keys and action values that deserialize into openlogi_core::binding::Action.


TOML Configuration Syntax

Basic Key-to-Action Mapping

Simple bindings use unquoted key names for single keys or quoted strings for combinations with modifiers:

[keyboard.bindings]
f1 = "MissionControl"
f2 = "ShowDesktop"
f3 = "Launchpad"
"shift+command+f5" = "ScreenSaver"

Supported Key Trigger Formats

  • Simple keys: f1, f2, escape, space, tab
  • Modifier combinations: shift+f1, command+space, "ctrl+alt+delete" (quoted when containing +)
  • Multiple modifiers: shift+command+f5, ctrl+shift+alt+t

Complex Action Types

Beyond simple string actions, OpenLogi supports structured action definitions for advanced use cases:

[keyboard.bindings]

# Custom shortcut executed on key hold

f9 = { HoldShortcut = "Ctrl+Space" }

# Application launcher with metadata

f10 = { OpenApplication = { path = "/Applications/iTerm.app", display_name = "Terminal" } }

Available actions are defined in crates/openlogi-core/src/binding.rs as the Action enum, including variants like MissionControl, ShowDesktop, Launchpad, ScreenSaver, HoldShortcut, OpenApplication, and CustomShortcut.


Using the Function-Row UI

The desktop client provides a visual editor accessible through the Function-Row view, implemented in crates/openlogi-desktop/src/features/keyboard/function_row.rs.

The UI workflow:

  1. Renders a graphical keyboard layout with interactive key hotspots
  2. Captures click events on function keys (F1-F12 and beyond)
  3. Displays an action picker populated from openlogi_core::binding::Action variants
  4. Calls AppState::commit_keyboard_binding when a selection is confirmed

This method automatically validates against supported key triggers and action types, preventing malformed configurations.


Programmatic Configuration with commit_keyboard_binding

For automation or CLI tooling, modify bindings directly through the same API the UI uses:

use openlogi_core::binding::{Action, KeyTrigger};
use openlogi_desktop::state::AppState;
use std::str::FromStr;

fn add_global_binding() {
    // Access the global application state
    let app_state = AppState::global();
    
    // Parse key trigger from string representation
    let trigger = KeyTrigger::from_str("F4")
        .expect("Valid key trigger");
    
    // Select action from the core enum
    let action = Action::MissionControl;
    
    // Commit and persist the binding
    app_state.commit_keyboard_binding(trigger, action);
}

The commit_keyboard_binding method in crates/openlogi-desktop/src/state.rs performs three operations:

  1. Updates the in-memory AppState.config.keyboard.bindings HashMap
  2. Marks the configuration as dirty for dirty-tracking purposes
  3. Serializes and writes the complete config back to the TOML file on disk

Source Code References

Key implementation details from the repository:


Summary

  • Global keyboard remapping lives in the [keyboard.bindings] table of OpenLogi's TOML config, distinct from per-device bindings
  • Key triggers support simple names and modifier-rich quoted strings; actions are type-safe variants from openlogi_core::binding::Action
  • Visual editing is available through the Function-Row view, which validates and commits via AppState::commit_keyboard_binding
  • Programmatic changes use the same commit_keyboard_binding API, ensuring consistency between UI and automation workflows

Frequently Asked Questions

What is the difference between global keyboard bindings and device-specific bindings?

Global keyboard bindings under [keyboard.bindings] apply to all connected Logitech keyboards universally, while device-specific bindings under config.devices[<id>].bindings are scoped to individual hardware. The global configuration takes precedence when no device-specific override exists, and it is the recommended approach for function-key remapping that should remain consistent across multiple devices.

Can I use modifier combinations like Ctrl+Shift+F1 in global keyboard remapping?

Yes. Modifier combinations are supported by quoting the key trigger string in TOML, such as "ctrl+shift+f1" = "MissionControl". The KeyTrigger type in openlogi-core parses these strings during deserialization, supporting any combination of shift, ctrl, alt, command, and super modifiers combined with standard key names.

Where is the configuration file stored on different platforms?

The configuration file follows platform conventions: ~/.config/openlogi/config.toml on Linux, ~/Library/Application Support/openlogi/config.toml on macOS, and %APPDATA%\openlogi\config.toml on Windows. The exact path can be verified at runtime through OpenLogi's settings panel or by checking the logs at application startup, which emit the resolved configuration directory.

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 →