# How to Configure Per-Application Profiles in OpenLogi: A Complete Guide

> Learn to configure per-application profiles in OpenLogi. Customize button bindings and Actions-Ring layouts for specific apps by editing the config.toml file with this complete guide.

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

---

**Configure per-application profiles in OpenLogi by editing the [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) file to define app-specific button bindings and Actions-Ring layouts using bundle IDs, WM classes, or executable paths as keys.**

OpenLogi supports sophisticated per-application customization that lets you override global button bindings and Actions-Ring layouts when specific apps are in the foreground. These profiles are stored in the central TOML configuration file that both the GUI and background agent consume. Understanding how to structure these overrides allows you to create context-aware workflows for any supported Logitech device.

## Locate the Configuration File

OpenLogi stores all per-application settings in a single [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) file. The default location varies by platform:

- **macOS / Linux**: `~/.config/openlogi/config.toml`
- **Windows**: `%USERPROFILE%\.config\openlogi\config.toml`

You can also open this file directly from the GUI by navigating to **Settings → Open Config**. Both the desktop application and the background agent read from this file, ensuring your per-application profiles remain synchronized across the system.

## Identify the Application Identifier

Before configuring profiles, you must determine the correct application key for your target software. OpenLogi uses different identification methods depending on the operating system:

- **macOS**: Use the app's **bundle identifier**, such as `com.microsoft.VSCode` or `org.mozilla.firefox`.
- **Linux (X11 / Wayland)**: The system reads the X11 **WM_CLASS** property. Note that on Wayland, you need XWayland for per-app profile switching to function correctly, as documented in the installation notes.
- **Windows**: Use the exact lower-cased executable path or the shortcut format `exe:<filename>.exe`.

The identifier serves as the key in the `per_app_bindings` and `action_ring.apps` maps defined in [`crates/openlogi-core/src/config/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/device.rs).

## Set Up Per-Application Button Bindings

Per-application bindings override the global `bindings` table when the specified app is active. Inside your device configuration table, create a `per_app_bindings` sub-table keyed by the app identifier.

The underlying structure in `DeviceConfig::per_app_bindings` is defined as `BTreeMap<String, BTreeMap<ButtonId, Action>>`, mapping application identifiers to button-to-action pairs.

Here is a complete example for a Logitech mouse with the device key `receiver:12345:slot:1`:

```toml
[devices."receiver:12345:slot:1"]

# Global bindings used as fallback

bindings = { Button5 = "Back", Button6 = "Forward" }

# Per-application overrides for VS Code

[devices."receiver:12345:slot:1".per_app_bindings."com.microsoft.VSCode"]
Button5 = "Copy"
Button6 = "Paste"

# Per-application overrides for Firefox

[devices."receiver:12345:slot:1".per_app_bindings."org.mozilla.firefox"]
Button5 = "Back"
Button6 = "Forward"

```

When Visual Studio Code is the foreground window, **Button5** triggers **Copy** instead of **Back**. The GUI can edit these entries via **Device → Per-App Bindings**, writing changes atomically back to [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml).

## Configure Per-Application Actions-Ring Layouts

Beyond button remapping, you can define a complete eight-slot **Actions-Ring** layout for each application. The `DeviceConfig::action_ring` field accepts an `ActionRingConfig` that supports per-app customization through an `apps` sub-table.

The global ring serves as the default, while entries under `action_ring.apps` take precedence when the corresponding application is focused:

```toml
[devices."receiver:12345:slot:1".action_ring]

# Global ring layout (fallback)

Top = { action = "Copy", icon = "Keyboard" }
Bottom = { action = "Paste", icon = "Keyboard" }

# VS Code specific ring

[devices."receiver:12345:slot:1".action_ring.apps."com.microsoft.VSCode"]
Top = { action = "ShowTerminal", icon = "Terminal" }
Bottom = { action = "ShowExplorer", icon = "Folder" }

# Firefox specific ring

[devices."receiver:12345:slot:1".action_ring.apps."org.mozilla.firefox"]
Top = { action = "Back", icon = "ArrowLeft" }
Bottom = { action = "Forward", icon = "ArrowRight" }

```

When the foreground application matches one of the keys in `action_ring.apps`, OpenLogi renders that specific layout; otherwise, it falls back to the global configuration defined in the base `action_ring` table.

## Apply and Verify Changes

After editing [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml), you must ensure the running agent recognizes the new profiles:

1. **Reload the configuration**: The GUI automatically reloads when you save the file. For manual edits, reopen the GUI or select **Reload Config** from the tray menu so the agent picks up changes.
2. **Verify active profile**: Switch to your target application, then trigger the **Actions-Ring** using your configured shortcut. Confirm the per-app layout appears rather than the global default.
3. **Test button overrides**: Press a button you remapped in `per_app_bindings` and verify the specific action fires instead of the global binding.

If the profile fails to activate, double-check the application identifier against the requirements in the previous section and ensure the key exists in the TOML map.

## Summary

- **Per-application profiles** in OpenLogi are stored in [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) and interpreted by both the GUI and background agent.
- **Application keys** use macOS bundle IDs, Linux WM_CLASS strings, or Windows executable paths.
- **Button overrides** are defined in the `per_app_bindings` map within each device table, as implemented in [`crates/openlogi-core/src/config/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/device.rs).
- **Actions-Ring layouts** support per-app customization via the `action_ring.apps` sub-table, falling back to global settings when no match exists.
- **Changes apply** immediately when edited through the GUI, or require a manual reload when editing [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) directly.

## Frequently Asked Questions

### Why isn't my per-application profile activating on Linux Wayland?

Wayland does not expose window class information in the same manner as X11. OpenLogi relies on the X11 `WM_CLASS` property to identify foreground applications, so you must run your applications under XWayland for per-app profile switching to function. This limitation is documented in [`docs/INSTALL-linux.md`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/INSTALL-linux.md).

### Can I use the GUI to create per-application profiles instead of editing TOML?

Yes. The OpenLogi GUI provides a **Device → Per-App Bindings** interface that writes to the same [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) file atomically. However, understanding the raw TOML structure is essential for manual backups, version control, or complex configurations involving multiple applications.

### What happens if an application matches both global and per-app bindings?

**Per-app bindings always take precedence.** When the foreground application matches a key in `per_app_bindings`, OpenLogi uses that specific action map. If no match exists, the system falls back to the global `bindings` table defined at the device level.

### How do I find the bundle ID for a macOS application?

You can locate the **bundle identifier** by right-clicking the app in Finder, selecting **Show Package Contents**, and opening `Contents/Info.plist` to find the `CFBundleIdentifier` key. Alternatively, run `osascript -e 'id of app "Application Name"'` in Terminal to retrieve the identifier directly.