# How to Set Up Global Keyboard Bindings in OpenLogi: A Complete Configuration Guide

> Learn how to set up global keyboard bindings in OpenLogi using its TOML configuration file. Customize key combos for seamless control of HID++ devices.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: how-to-guide
- Published: 2026-09-08

---

**OpenLogi stores global keyboard bindings in a TOML configuration file, typically located at `~/.config/openlogi/config.toml`, where the `[keyboard.bindings]` table maps key-combo strings to `Action` enum variants that the background agent pushes to HID++ devices via [`crates/openlogi-agent-core/src/orchestrator.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-agent-core/src/orchestrator.rs).**

OpenLogi is an open-source utility for customizing Logitech input devices across macOS, Windows, and Linux. Learning how to set up global keyboard bindings in OpenLogi requires understanding its centralized configuration system, where a single TOML file serves as the source of truth for both the GUI application and the background agent. This guide walks through the exact file locations, schema definitions, and runtime behavior based on the current OpenLogi source code.

## Where OpenLogi Stores Keyboard Binding Definitions

The codebase separates configuration logic into distinct crates, with binding definitions, schema validation, and runtime execution handled by different components.

### Configuration File and Schema

User settings reside in a platform-specific configuration directory, typically `~/.config/openlogi/config.toml` on Linux and macOS. The TOML schema is implemented with Serde in [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs), which defines the top-level `[keyboard]` table containing a `bindings` sub-table. When the file loads, the parser deserializes this section into a `HashMap<KeyCombo, Action>` that the agent uses to program devices.

### Core Binding Logic

The logical actions and key-combination parsing live in [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs). This file exposes the **`Action`** enum—which includes variants like `Copy`, `PlayPause`, and `ShowActionsRing`—and the **`KeyCombo`** struct. The `KeyCombo` parser normalizes human-readable strings such as `shift+command+f5` into a standardized representation for the HID++ write layer.

## How to Configure Global Keyboard Bindings in TOML

Global shortcuts are defined under the `[keyboard.bindings]` table, where each entry associates a key combination with a specific action.

### Supported Modifier Aliases

OpenLogi recognizes the following modifier key aliases when parsing combination strings:

- **shift**: `shift`
- **control**: `control`, `ctrl`
- **option**: `option`, `alt`
- **command**: `command`, `cmd`

### Configuration File Structure

The left-hand side of each binding entry represents the **action name** (matching the Rust enum variant exactly), while the right-hand side defines the trigger. Simple shortcuts use plain strings, while complex actions requiring parameters use inline TOML tables.

Create or edit your [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) with the following structure:

```toml
[keyboard.bindings]

# Simple shortcut to copy the current selection

Copy = "Cmd+C"

# Open the user's Downloads folder (custom shortcut)

OpenDownloads = { OpenApplication = { path = "~/Downloads", display_name = "Downloads" } }

# Show the Actions Ring – a global UI overlay

ShowRing = "Ctrl+Option+Space"

# Override the media play/pause key

PlayPause = "F8"

```

When you save the file, the GUI writes changes atomically while preserving comments. The `KeyCombo` parser in [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs) automatically handles the string normalization for standard shortcuts, while Serde deserializes inline tables for parameterized actions like `OpenApplication`.

## How the Agent Applies Your Bindings

Understanding the runtime pipeline ensures you know when and how changes take effect.

### Config File Monitoring and Hot Reloading

The agent core in [`crates/openlogi-agent-core/src/orchestrator.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-agent-core/src/orchestrator.rs) watches the configuration file for modifications using a file system monitor. Upon detecting a save event, the agent reloads the TOML configuration immediately without requiring a process restart. If the file contains syntax errors, the GUI refuses to overwrite it and presents a readable error message, preventing the agent from loading corrupted data.

### HID++ Device Programming

After reloading the configuration, the agent translates the `KeyCombo → Action` mapping into low-level HID++ commands. The write layer in [`crates/openlogi-hid/src/write/key_combo.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hid/src/write/key_combo.rs) handles the protocol-specific communication, pushing the new global binding map to the connected Logitech device. This ensures your shortcuts work at the hardware level regardless of which application is currently focused.

## Managing Bindings via the CLI

The `openlogi` command-line tool in [`crates/openlogi/src/main.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi/src/main.rs) reads the same configuration file as the GUI, maintaining a single source of truth across interfaces. To inspect your current configuration from the terminal:

```bash
openlogi list --show-config

```

Direct edits to [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) are detected by the agent's file watcher, so you can safely modify the file using any text editor or version control system without launching the GUI.

## Summary

- **Configuration Location**: Edit `~/.config/openlogi/config.toml` (platform-specific) to define global shortcuts.
- **Schema Definition**: The `[keyboard.bindings]` table in [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs) deserializes into `HashMap<KeyCombo, Action>`.
- **Binding Logic**: [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs) defines the `Action` enum and `KeyCombo` parser for normalizing modifier aliases.
- **Runtime Application**: [`crates/openlogi-agent-core/src/orchestrator.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-agent-core/src/orchestrator.rs) hot-reloads changes and dispatches them to [`crates/openlogi-hid/src/write/key_combo.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hid/src/write/key_combo.rs) for HID++ programming.
- **Validation**: The GUI performs atomic writes and syntax validation to prevent corrupted configurations from reaching the agent.

## Frequently Asked Questions

### Where is the OpenLogi configuration file located?

OpenLogi stores user settings in a platform-specific directory, typically `~/.config/openlogi/config.toml` on Linux and macOS. The CLI and GUI both read from this location, ensuring consistent behavior across interfaces.

### What happens if I make a syntax error in the TOML file?

The GUI validates the file before writing and will refuse to save changes that contain syntax errors, displaying a readable error message instead. This prevents the background agent in [`crates/openlogi-agent-core/src/orchestrator.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-agent-core/src/orchestrator.rs) from crashing or loading an invalid `HashMap<KeyCombo, Action>`.

### Do I need to restart the agent after changing keyboard bindings?

No. The agent monitors the configuration file for changes and hot-reloads the binding map immediately upon detecting a save. The new shortcuts are pushed to the HID++ device without requiring a service restart.

### Can I bind actions that require custom parameters like opening specific folders?

Yes. While simple actions use plain strings like `"Cmd+C"`, parameterized actions use inline TOML tables. For example, `OpenDownloads = { OpenApplication = { path = "~/Downloads", display_name = "Downloads" } }` demonstrates how to pass custom arguments to the `Action` enum variants defined in [`crates/openlogi-core/src/binding.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding.rs).