Native on every major desktop.

Wayland-first. Each platform has a dedicated backend with its own window query mechanism. No X11 fallback hacks.

Platform matrix.

HPR reads $XDG_CURRENT_DESKTOP at startup and dispatches to the correct backend automatically.

Platform Backend Display Server Extra Setup
Hyprland hyprctl IPC Wayland None
GNOME Custom GNOME Shell Extension Wayland Extension
KDE Plasma 6+ KWin scripting Wayland X11 None
Cinnamon org.Cinnamon.Eval D-Bus X11 Wayland None
niri niri msg --json focused-window IPC Wayland None
Windows 10/11 Win32 API None

Hyprland

The cleanest backend. Hyprland exposes a Unix socket IPC interface that returns the active window directly. HPR queries via hyprctl and parses the JSON output natively in C++ — no jq required.

How it works

HPR calls hyprctl activewindow -j every 50ms and parses the JSON response natively in C++ to extract the window class and title. Zero overhead, zero hacks, zero extra dependencies.

Wayland Native hyprctl IPC No Extra Deps Zero Setup
Backend
// Platform: Hyprland (Wayland)
// Mechanism: Unix socket IPC
// Parsing: native C++ std::string (no jq)

hyprctl activewindow -j
// extracts "class" and "title" keys
// via std::string::find() — no shell pipe

// Direct, fast, no hacks needed.
// This is what good Wayland
// integration looks like.

GNOME (Wayland)

GNOME on Wayland does not expose the active window to external processes. HPR solves this with a custom GNOME Shell extension — lol-another-window-extension — built specifically for HPR.

⚠ One-Time Setup Required

Run the bundled installWindowCallsExtension.sh, which clones the extension and enables it. Then log out and back in once — GNOME on Wayland cannot hot-reload shell extensions.

Auto-Detection

On first launch, HPR checks whether its GNOME extension is active. If it isn't, HPR sets its internal platform to GNOME_NO_EXTENSION and tells you directly rather than silently returning garbage. It will not attempt to install the extension autonomously.

Setup
# One-time extension install
chmod +x installWindowCallsExtension.sh
./installWindowCallsExtension.sh

# Log out and back in (required)
# GNOME Wayland can't hot-reload
# shell extensions

# Every launch after that is automatic
Wayland Native GNOME Shell Extension D-Bus One-Time Setup

KDE Plasma 6+ (Wayland / X11)

The KDE backend uses Kwin scripting (Just like kdotool without relying on kdotool itself).

⚠ Honest Engineering Note

HPR uses the same underlying KWin scripting approach as kdotool — so it's accurate to say that wherever kdotool works, HPR also works.

How It Works
// Platform: KDE Plasma
// Works on both Wayland and X11

// Every 50ms:
1. Get window data via Kwin script
2. Parse output into required format
3. Parse window class + title
4. Filter out js:: noise

// Validated on multiple KDE configs
Wayland + X11 KWin Scripting Zero Setup

Cinnamon (X11 + Wayland)

Cinnamon runs on top of Muffin (a fork of GNOME's Mutter). Unlike other Linux backends, Cinnamon exposes org.Cinnamon.Eval — a D-Bus method that evaluates JavaScript directly inside the live Cinnamon process.

D-Bus Eval

HPR queries the internal global.display.focus_window object for the window class via get_wm_class() and the title via get_meta_window().get_title().

Cross-Session

Because this goes through Cinnamon's own compositor internals rather than X11 display properties, it works identically on both the X11 session (default on Linux Mint) and the experimental Wayland session without any code branching.

D-Bus Queries
// Window class (application name)
global.display.focus_window
  .get_wm_class()

// Window title (active tab/document)
global.get_window_actors()
  .filter(a => 
    a.meta_window.has_focus()
  )[0]
  .get_meta_window()
  .get_title()

// Both go through Muffin's compositor
// Works on X11 and Wayland identically
X11 + Wayland D-Bus Eval Muffin/Mutter Zero Setup

niri (Wayland)

The scrollable-tiling Wayland compositor niri is natively supported via its direct command-line IPC interface.

Niri Msg IPC

HPR runs niri msg --json focused-window every 50ms and parses the JSON response natively in C++ to query the active application's app_id and window title.

Wayland Native niri IPC Zero Setup
IPC Command
// Platform: niri
// Works natively on Wayland
// Runs every 50ms:

niri msg --json focused-window
// parses "app_id", "title" and "pid"


Windows 10 / 11

The simplest backend. Win32 API provides direct access to the foreground window. No injection, no scraping, no extensions.

Tray Mode

Built without a console window. HPR sits in your system tray and stays out of your way. No terminal flash on launch.

Performance

Around 13 MB RSS in real use. That's HPR's own code plus the Windows runtime. The lightest footprint of any platform.

Backend
// Platform: Windows 10/11
// Mechanism: Win32 API

GetForegroundWindow()
GetWindowText(hwnd, buffer, size)

// Direct API. No tricks needed.
// ~13 MB RSS in real use.
// No console window — tray only.
~13 MB
RAM Usage
Win32
API

Platform detection & architecture.

All platform window detection is contained inside CurrentWindowManager. The constructor reads $XDG_CURRENT_DESKTOP and dispatches to the right backend.

Detection Flow
getCurrentWindow() {
  if (platform.contains("Hyprland"))
    return getCurrentWindow_Hyprland();
  else if (platform.contains("GNOME"))
    return getCurrentWindow_GNOME();
  else if (platform.contains("KDE"))
    return getCurrentWindow_KDE();
  else if (platform.contains("Cinnamon"))
    return getCurrentWindow_Cinnamon();
  else if (platform.contains("niri"))
    return getCurrentWindow_niri();
  // Windows handled at compile time
}
⚠ Known Limitation

HPR reads $XDG_CURRENT_DESKTOP and matches substrings via std::string::contains. Non-standard desktop session variables or nested compositor configurations may not resolve correctly.

Cross-Platform Normalization

validateAndUpdateWindow_Cross runs on every return from every platform getter automatically. It filters known system noise — including plasmashell, searchhost, and KWin JS runtime artifacts (js:: prefix outputs) — so they never appear in your tracking data. New backends inherit all of this for free.

Full feature parity across all platforms

Every HPR feature — the Lua extension engine, per-app limits and goals, multi-day historical data queries, interpreted UI mode, and the alias system — works identically on Hyprland, GNOME, KDE, Cinnamon, niri, and Windows. There is no platform-specific feature subset.

Your platform is supported.

HPR runs natively on Hyprland, GNOME, KDE Plasma, Cinnamon, niri, and Windows. No compatibility layers.