# How to Create Per-Application Profiles in OpenLogi

> Learn how to create per-application profiles in OpenLogi. Customize button bindings and Action-Ring layouts for individual apps by editing your config.toml file.

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

---

**Per-application profiles in OpenLogi allow you to override global button bindings and Actions-Ring layouts for specific applications by defining entries in the `per_app_bindings` and `action_ring.apps` tables within your [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) file.**

OpenLogi is an open-source input device manager for Logitech hardware that supports context-aware configuration. Creating per-application profiles enables automatic switching of button behaviors and radial menu layouts based on the currently focused window. This functionality is implemented in the core configuration structures defined in [`crates/openlogi-core/src/config/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/device.rs) and exposed through the TOML configuration file shared between the GUI and background agent.

## Locate Your Configuration File

OpenLogi stores per-application overrides in the shared [`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 the configuration file directly from the GUI by navigating to **Settings → Open Config**.

## Identify the Application Key

Per-application profiles are keyed using platform-specific identifiers that OpenLogi detects when windows gain focus:

- **macOS**: Use the app's bundle identifier (e.g., `com.microsoft.VSCode`)
- **Linux**: The system uses the X11 `WM_CLASS` string; note that on Wayland, XWayland is required for per-app profile switching to function (as documented in [`docs/INSTALL-linux.md`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/INSTALL-linux.md) at line 183)
- **Windows**: Use the exact lower-cased executable path or the shortcut format `exe:<filename>.exe`

## Configure Per-Application Button Bindings

According to the source code in [`crates/openlogi-core/src/config/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/device.rs) (lines 17-24), the `DeviceConfig` struct stores per-app bindings in `per_app_bindings`, which is defined as a `BTreeMap<String, BTreeMap<ButtonId, Action>>` keyed by the application identifier.

Inside your device table (`[devices."<physical-key>"]`), create a `per_app_bindings` sub-table for each application:

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

# Global bindings used when no per-app match exists

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 the foreground application matches the specified key, OpenLogi executes the override actions instead of the global bindings.

## Set Up Per-Application Actions-Ring Layouts

The `DeviceConfig::action_ring` field supports per-application layout customization through an `apps` sub-table. As documented in [`docs/CONFIGURATION.md`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/CONFIGURATION.md) (lines 59-60), you can define a complete eight-slot ring configuration for specific applications.

Add an `action_ring` table with an `apps` section containing your per-application layouts:

```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 layout

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

# Firefox specific ring layout

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

```

When you open the Actions-Ring (`ShowActionsRing` shortcut), OpenLogi displays the layout corresponding to the current foreground application, falling back to the global configuration if no match exists.

## Reload and Verify Changes

After editing the configuration:

1. Save the [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) file
2. Reload the configuration using the **Reload Config** option in the system tray menu, or restart the OpenLogi GUI
3. Switch to your target application and verify:
   - The Actions-Ring displays the per-app layout
   - Overridden buttons execute the correct actions

If the profile does not activate, verify the application identifier matches exactly and ensure the TOML structure follows the `devices."<key>".per_app_bindings."<app-id>"` pattern.

## Summary

- Per-application profiles are stored in [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) under device-specific `per_app_bindings` and `action_ring.apps` tables
- The configuration uses `BTreeMap` structures defined in [`crates/openlogi-core/src/config/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/device.rs) to map application identifiers to button actions and ring layouts
- Application keys vary by platform: macOS bundle IDs, Linux `WM_CLASS` values (requiring XWayland on Wayland), and Windows executable paths
- Changes take effect immediately after reloading the configuration through the GUI or tray menu

## Frequently Asked Questions

### How does OpenLogi detect which application is currently active?

OpenLogi detects the foreground window's application identifier using platform-specific APIs. On macOS, it reads the bundle identifier; on Linux, it queries the X11 `WM_CLASS` property; and on Windows, it examines the executable path. Note that Wayland systems require XWayland for this detection to work, as native Wayland windows do not expose compatible window class information.

### Can I use the GUI to edit per-application profiles instead of editing the config file?

Yes. The OpenLogi GUI provides a **Device → Per-App Bindings** interface that writes changes atomically to [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml). However, for advanced configurations like custom Actions-Ring layouts with specific icon assignments, manually editing the TOML file according to the schemas in [`docs/CONFIGURATION.md`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/CONFIGURATION.md) provides more granular control over the available parameters.

### What happens if an application has both per-app bindings and a per-app Actions-Ring defined?

OpenLogi applies both configurations independently when the application gains focus. Button inputs use the overrides specified in `per_app_bindings` while the radial menu displays the layout defined in `action_ring.apps`. If either configuration is missing for the active application, the system falls back to the global device-level settings for that specific feature.

### Why don't per-application profiles work on my Linux Wayland setup?

Per-application profile switching requires window class detection that relies on X11 protocols. On Wayland, OpenLogi can only detect the application identifier if the window runs under XWayland. Native Wayland windows do not expose `WM_CLASS` in a compatible manner, preventing automatic profile switching as noted in [`docs/INSTALL-linux.md`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/INSTALL-linux.md) at line 183.