How OpenLogi Identifies Applications for Per-App Profiles: A Deep Dive into Platform-Specific Detection

OpenLogi identifies applications for per-app profiles using the ForegroundApp type, which stores a platform-specific identifier (id) as the lookup key and a human-readable display_name for the UI, with observers in the openlogi-hook crate extracting bundle IDs on macOS, WM_CLASS on X11, app_id on Wayland, and executable paths on Windows.

OpenLogi's per-app profile system relies on precise identification of the currently active foreground application. The system is built around a unified abstraction—the ForegroundApp struct—that normalizes platform differences while maintaining a strict contract between running applications and user-defined configuration overrides.

The ForegroundApp Abstraction

At the heart of OpenLogi's detection logic is the ForegroundApp struct defined in crates/openlogi-core/src/app.rs. This type serves as the canonical representation of the active application across all supported platforms:

Field Purpose Platform Mapping
id Exact lookup key for per-app profile matching Platform-specific identifier
display_name Human-readable label shown in the UI Falls back to id when unavailable

The id field is the sole identifier used for configuration lookups. The UI never exposes this raw value to users; instead, it renders the display_name for readability.

Platform-Specific Extraction Mechanisms

OpenLogi implements dedicated foreground-app observers in the openlogi-hook crate, with each platform using native APIs to extract application identity:

macOS: Bundle Identifier Extraction

In crates/openlogi-hook/src/macos.rs, OpenLogi leverages the Launch Services framework to obtain the bundle identifier (e.g., com.apple.Safari) and localized application name when available.

X11 (Linux): WM_CLASS Parsing

The X11 implementation in crates/openlogi-hook/src/linux/wlr_foreign_toplevel.rs extracts the WM_CLASS class string from the X11 window properties. This string typically matches the application's .desktop file name.

Wayland (Linux): app_id Retrieval

For Wayland compositors, crates/openlogi-hook/src/linux/gnome_shell.rs reads the xdg_app_id (or simply app_id) provided by the compositor. This follows the app_id convention established by xdg-shell.

Windows: Executable Path Normalization

On Windows, crates/openlogi-hook/src/windows.rs uses the lower-cased full executable path as the identifier. This provides a stable, file-system-backed key that remains consistent across application versions.

Unified API and IPC Propagation

Each platform observer returns an Option<ForegroundApp>, handling detection failures gracefully. These implementations are consolidated through the public API in crates/openlogi-hook/src/lib.rs:

/// Returns the current foreground application, if one can be determined.
pub fn frontmost_application() -> Option<ForegroundApp> {
    // internally dispatches to the appropriate platform module
}

The ForegroundApp value traverses the IPC channel defined in crates/openlogi-ipc/src/ipc.rs, connecting the GUI and agent processes. Upon foreground changes, the agent recomputes effective bindings via Config::effective_bindings in crates/openlogi-core/src/config.rs, applying any per-app overrides from the user's TOML configuration.

Working with ForegroundApp in Code

The following examples demonstrate practical usage of the detection API:

use openlogi_hook::frontmost_application;
use openlogi_core::app::ForegroundApp;

/// Get the current foreground app and print its identifier.
fn print_foreground_app() {
    if let Some(app) = frontmost_application() {
        println!("App ID: {}", app.id);
        println!("App Name: {}", app.display_name);
    } else {
        println!("No foreground application detected");
    }
}

For cases where platform detection fails or no friendly name exists, the unnamed constructor provides a fallback:

/// Create a dummy app entry when the platform cannot provide a name.
fn make_unnamed_app(id: &str) -> ForegroundApp {
    ForegroundApp::unnamed(id.to_owned())
}

Key Source Files

Path Responsibility
crates/openlogi-core/src/app.rs ForegroundApp definition and identifier semantics
crates/openlogi-hook/src/lib.rs Unified frontmost_application() API
crates/openlogi-hook/src/macos.rs macOS Launch Services integration
crates/openlogi-hook/src/linux/wlr_foreign_toplevel.rs X11 WM_CLASS extraction
crates/openlogi-hook/src/linux/gnome_shell.rs Wayland app_id retrieval
crates/openlogi-hook/src/windows.rs Windows executable path handling
crates/openlogi-ipc/src/ipc.rs IPC structures for cross-process communication
crates/openlogi-core/src/config.rs Per-app profile resolution logic

Summary

  • OpenLogi identifies applications through the ForegroundApp struct, which encapsulates both a stable lookup key (id) and a human-readable label (display_name)
  • Platform-specific observers extract native identifiers: bundle IDs on macOS, WM_CLASS on X11, app_id on Wayland, and executable paths on Windows
  • The frontmost_application() function in openlogi-hook provides a unified, cross-platform API
  • IPC propagation carries detection results from the GUI to the agent core for configuration resolution
  • Per-app profile matching occurs exclusively against the ForegroundApp.id field, ensuring consistent behavior across platforms

Frequently Asked Questions

How do I find the correct app ID for my per-app profile configuration?

Query the currently running application using frontmost_application() or check OpenLogi's logs. On macOS, use mdls -name kMDItemCFBundleIdentifier -r /Applications/AppName.app to verify bundle identifiers. On X11, run xprop WM_CLASS and click the target window. On Wayland, swaymsg -t get_tree or equivalent compositor commands expose app_id values.

Why does Windows use executable paths instead of more stable identifiers?

Windows lacks a universal, user-friendly application identifier comparable to macOS bundle IDs. The lower-cased executable path provides deterministic, version-agnostic identification without requiring registry parsing or heuristic name matching. This trades occasional path sensitivity for reliability and implementation simplicity.

Can ForegroundApp.id change for the same application across versions?

Platform-dependent. macOS bundle IDs and X11 WM_CLASS values rarely change. Windows executable paths remain stable unless the installation directory changes. Wayland app_id values are controlled by the application and compositor, making them generally consistent but not guaranteed.

What happens when foreground detection fails?

The frontmost_application() function returns None, and the agent falls back to global default bindings. Detection failures may occur during rapid application switching, fullscreen direct-rendering contexts, or when platform APIs are temporarily unavailable. OpenLogi's architecture treats None as a valid state, ensuring continuous operability.

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 →