HPR is built solo by a 16-year-old developer in India. My Dad is pushing me to focus on JEE - India's national engineering entrance exam, one of the most brutally competitive exams in the world - so HPR development happens in whatever time I can steal from that. If I were an adult I would not have made HPR free at all because I would've needed money to survive, but I am a teen and I live under my Dad so I could "afford" HPR to be fully free and open source. If donations are enough to show this is worth continuing, I can justify spending time on HPR and try my hand at other things instead of just grinding JEE prep. If HPR has been useful to you, a Ko-fi donation genuinely helps.
A huge thank you to our supporters keeping HPR active!
- Jesse Kramer ($20) - First Supporter 💖
On Slint 1.17 and tray support: I'm aware Slint 1.17 shipped with built-in tray icon support. I'm not upgrading to it. Slint's tray implementation doesn't work reliably across all platforms HPR targets - Waybar in particular has no usable support. Until Slint's tray story improves across the board, I'm keeping my native
libdbus-1/ Win32 approach which I know works everywhere HPR runs.
A compiled, offline, zero-account activity tracker.
Watches your active window. Builds your history. Never phones home.
"HPR is an excellent tool for time management on Linux! It far outweighs any other option available and is developing very quickly! I highly recommend it!"
-- @dotsupershow, Niri user
Important
HPR is fully free and open source. Every feature - current and future - is available to everyone at no cost. If HPR saves you time or you want to support continued development, a Ko-fi donation goes a long way.
See HPR in action
Live window tracking, switch history, and the Insights engine - all running locally, zero accounts.
video.mp4
- What It Does
- Platform Support
- Comparison With Other Trackers
- Installation
- Browser Tab Tracking
- Code Editor & IDE Project Tracking
- App Limits and Goals
- Idle Tracking
- Day Construction Timeline
- Advanced Pattern Analysis
- Theme Management
- Extensions
- System Tray
- Data Storage
- Privacy
- Aliases
- Config
- Customizing the UI
- Building From Source
- Contributing
You open your computer. You work. Hours pass. You have no idea where they went.
HPR fixes that. It watches which window is in focus every 50 milliseconds, all day. It builds a running log of exactly where your time actually went - not where you think it went. Switch from your browser to your editor, it records the transition. Switch back two hours later, it records that too. Every switch. Every minute. Every day.
At any point you get three things live:
- What you are in right now, updating in real time
- Total time per application today, displayed as
2h 14m 30s - Your complete switch history: every transition, timestamped, in order
Tray controls:
| Action | Windows | Linux (Waybar / KDE / Cinnamon) |
|---|---|---|
| Open HPR | Right click > Show HPR | Left or right click |
| Quit HPR | Right click > Quit | Middle click |
Note
On Linux, hovering over the tray icon shows "HPR - Human Pattern Recorder" as the tooltip title and "Left/Right click: Open HPR | Middle click: Quit" as the description.
HPR features native, lightweight tracking backends for major Linux desktop environments, window managers, and Windows.
| OS | Desktop / WM | Session Type | Tracking Backend | Setup Required | Status |
|---|---|---|---|---|---|
| Linux | Hyprland | Wayland | hyprctl IPC |
None | ✅ |
| Linux | GNOME | Wayland | Custom Shell Extension | Install Extension (Interactive prompt) | ✅ |
| Linux | KDE Plasma 6+ | Wayland / X11 | KWin D-Bus scripting | None | ✅ |
| Linux | Cinnamon | X11 / Wayland | org.Cinnamon.Eval D-Bus |
None | ✅ |
| Linux | niri | Wayland | niri msg IPC |
None | ✅ |
| Windows | Windows 10 / 11 | Native Desktop | Win32 API (GetForegroundWindow) |
None | ✅ |
Note
GNOME Window Tracking: On GNOME desktop environments, HPR requires the custom lol-another-window-extension to fetch active window titles. If you install HPR via the interactive Linux installer script, it will automatically prompt and install this extension for you. On GNOME Wayland, a session logout/login is required once to allow GNOME Shell to discover the newly cloned extension.
A comparison between HPR and other popular automatic time trackers:
| Feature | HPR | ActivityWatch | RescueTime | Toggl Track |
|---|---|---|---|---|
| Data Privacy | 100% Offline / Local | Local (Self-hosted) | Cloud (Remote servers) | Cloud (Remote servers) |
| Account Required | No | No | Yes | Yes |
| Telemetry / Tracking | Opt-in telemetry only | None by default | Proprietary analytics | Proprietary analytics |
| Executable Size | ~5 MB (Compiled C++) | 200 MB+ (Python/Rust/JS) | Cloud agent size varies | ~100 MB+ (Electron/Web wrapper) |
| RAM Footprint | 8 - 27 MB (Extremely low) | 200 MB+ (High) | Moderate | High |
| CPU Overhead | <3% during active tracking | Moderate | Low | Low |
| Tracking Autonomy | Fully Automated | Fully Automated | Fully Automated | Primarily Manual (start/stop) |
| Editor/Browser Detail | Native (No extensions needed) | Requires watchers/plugins | Requires browser extension | Requires extensions/plugins |
| Extensibility | Embedded Lua VM engine | Custom Python/Rust watchers | Proprietary API | Web hooks / API integrations |
| UI Customization | Customizable Slint templates | Custom web dashboard CSS | None | None |
| License / Cost | Free & Open Source (GPL-3) | Free & Open Source | Closed source (Paid premium) | Closed source (Paid team tiers) |
Arch Linux (AUR)
yay -S hprLinux (Universal)
You can install or update HPR on Linux automatically with a single command:
curl -fsSL https://raw.githubusercontent.com/plexescor/HPR/main/install.sh | bashThe interactive installation script performs the following actions:
- Dependency Verification: Checks for required CLI tools (
curl,tar,xz,dbus-send,git). - Re-installation Prevention: Before running a clean installation, the script verifies if HPR is already installed and warns you to use the update mode instead.
- Flexible Version Selection: Prompts you to select between installing the Latest release (automatically fetching and displaying the latest tag) or specifying a Custom version (e.g.,
v0.9.3or0.9.3, with input normalization to prependvautomatically if omitted). - System Binary Installation: Prompts you for your preferred system-wide installation path (defaults to
/usr/local/bin/HPR) and installs the binary (usessudofor binary copy only). - Configuration Setup: Creates the config directories (
~/.config/HPRand~/.local/share/HPR) and writes the default CSV files if they do not exist. - User Customization Protection: Detects if you have modified your CSV configuration files or the custom
ui/folder, and preserves your changes. Only untouched default configuration files/folders are updated. - Wipe Confirmation and Safe Abort: Before updating or removing HPR, prompts you for a directory wipe confirmation. If you choose to cancel, the entire process aborts immediately, keeping your files safe.
- GNOME Extension Installation: Detects if you are running the GNOME Desktop and prompts you to install the custom window-tracking extension (
lol-another-window-extension) if it's missing. - Launcher Creation: Configures high-resolution app icon paths, creates a desktop launcher entry (
~/.local/share/applications/hpr.desktop), and refreshes application menu databases.
Note
If you installed via the AUR, the system-wide desktop entry is already managed by the package. HPR detects this and skips the local entry entirely.
Windows
Download and run the setup executable. The Inno Setup installer handles placing aliases.csv, tabAliases.csv, config.csv, and the ui/ folder into your config directory. It also drops the latest default UI into ui-REFERENCEONLY/ every update so you always have a clean reference to diff against.
Where does everything go?
Config
Linux: ~/.config/HPR/
Windows: %APPDATA%\HPR\HPR_Config\
Data
Linux: ~/.local/share/HPR/HPR_DB/
Windows: %APPDATA%\HPR\HPR_DB\
Note
Microsoft Visual C++ Runtime (64-bit)
HPR depends on the Microsoft Visual C++ Runtime. If you're using Windows 10 or **Windows 11 which are installed fresh, install the 64-bit Microsoft Visual C++ Redistributable before launching HPR.
Download (x64): https://aka.ms/vc14/vc_redist.x64.exe
HPR supports tracking browser tabs per site and per tab without requiring any browser extensions. When the active window is a supported browser (Chrome, Edge, Firefox, Brave, or Zen Browser), HPR automatically queries the window title alongside the application name. This tab usage time is aggregated and tracked separately, giving you a detailed breakdown of which websites and tabs you spend time on.
| Browser | Platform Support | Status | Extension Required | Parsing Strategy / Notes |
|---|---|---|---|---|
| Google Chrome | Windows / Linux | ✅ Working | No | Matches chrome (case-insensitive) in window title/process name |
| Microsoft Edge | Windows / Linux | ✅ Working | No | Matches edge (case-insensitive) in window title/process name |
| Mozilla Firefox | Windows / Linux | ✅ Working | No | Matches firefox (case-insensitive) in window title/process name |
| Brave | Windows / Linux | ✅ Working | No | Matches brave (case-insensitive) in window title/process name |
| Zen Browser | Windows / Linux | ✅ Working | No | Matches zen (case-insensitive) in window title/process name |
In the UI, toggle display mode with the Tab View and Site View buttons:
- Tab View: Shows raw, unaliased tab names - lets you differentiate between specific pages.
- Site View: Applies rules from
tabAliases.csvto group tabs by website, collapsing specific pages into parent domains.
HPR tracks which project you are currently working in, not just whether the editor is open. No editor extensions, plugins, or marketplace installs are required.
Note
On Windows, HPR currently supports only 64-bit JetBrains IDEs. 32-bit builds are not supported.
| Application | Platform Support | Status | Extension Required | Parsing Strategy / Notes |
|---|---|---|---|---|
| Visual Studio Code | Windows / Linux | ✅ Working | No | Matches code, vscode, or visual studio code (case-insensitive) in window title/process name |
| IntelliJ IDEA | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| WebStorm | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| PyCharm | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| CLion | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| Rider | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| GoLand | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| RustRover | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| PhpStorm | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| RubyMine | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| DataGrip | Windows / Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
| DataSpell | Linux | ✅ Working | No | Matches jetbrains (case-insensitive) in window title/process name; extracts project name before the en dash (–). |
VS Code puts the active project name directly in its window title in the format filename - project - Visual Studio Code. HPR reads that title on every poll tick and parses it:
- Strip the trailing
- Visual Studio Codesuffix. - Find the last
-separator in what remains. - Everything after that separator is the project name.
HPR prepend jetbrains: to the active project window title (resolving to jetbrains: ProjectName – file [module] or just jetbrains: ProjectName using an en dash –). HPR parses it:
- Strip the
jetbrains:prefix. - Find the first occurrence of the en dash
–(\xe2\x80\x93). - Everything before the en dash is the project name. If no en dash is found, the whole cleaned string is used.
The result goes into timeLog_PerProject, a separate time accumulator running in parallel with the normal per-app log. The UI has a dedicated Project View showing time broken down by project name for the day. Toggle between Raw View (unprocessed title substring) and the default parsed view which applies projectAliases.csv.
This works on every supported platform because each backend already has a window title getter, and the supported editors put the project name in the title.
Set a daily time limit or daily usage goal on any tracked application directly from the Goals view in the sidebar.
Limits cap an app to a maximum number of minutes per day. When usage crosses that threshold:
- HPR sends a system notification.
- Optionally, HPR can force-quit the application automatically.
Goals set a minimum number of minutes you want to spend in an app each day. HPR tracks progress and notifies you when you hit it.
How to configure:
- Click the Goals icon in the sidebar - every tracked app appears automatically.
- Click any app row to expand it inline - a minute input with +/- step buttons appears alongside three actions: SET LIMIT, SET GOAL, RESET.
- Done. A dedicated background thread (
LimitsManager) monitors usage continuously. No restart required.
Badges on each row show remaining time live. Limit rows have a red accent; goal rows have green.
Note
Advanced users can intercept the limit-reached function call via the Function Overriding API to run custom Lua logic - log it, send a webhook, suppress the notification, or anything else.
HPR supports automatic Idle Detection & Tracking to pause or separate active time logging when you step away from your keyboard and mouse.
Idle tracking is powered by the official HPR-Idle-Detection-Extension, available for instant 1-click download and installation directly from HPR-Store!
Rebuild your daily narrative with a visual, contiguous timeline of your system activity. Instead of just looking at raw accumulated numbers, the Day Construction Timeline maps your active window transitions chronologically onto a zoomable, scrollable canvas.
Key timeline features:
- Scrollable & Zoomable Viewports: Focus on specific intervals or view the entire day. Click presets to zoom into
1h,3h, or8hviews, or zoom out to24handAll Dayspans. - Adaptive Hour Markers: Axis markers dynamically adjust spacing based on zoom level. Zoomed modes place markers every hour; high-span modes space them every 3 hours to prevent overlapping text.
- Continuity Gap Capping: If HPR is closed or your computer is off for a period, a naive timeline would stretch the last active app across the entire gap. HPR detects focus gaps and caps the preceding active segment to a maximum of 1 minute upon transitioning to Unknown states.
- Live HPR Tracking: HPR tracks itself as an application, giving you visibility into time spent configuring goals or managing extensions.
- Hover Micro-interactions: Hover over any timeline block to view its details. The status panel updates with the application's aliased name, exact active duration, and start/end time range.
Go beyond basic daily statistics with HPR's multi-day correlation engine. Under the Insights tab, HPR processes your historical database files to extract 9 advanced cross-day metrics:
- Escape Pattern: Average daily switches from your primary work application to distraction/browser apps.
- Return Rate: Percentage of times you immediately bounce back to your work app after a browser escape.
- Average Focus Session: Average duration of uninterrupted focus stretches before switching windows.
- Most Distracted Day: The day of the week with the highest average multitasking frequency across all logged data.
- Productive Days: Days during the current week where your hourly switch frequency stayed below the focus threshold.
- Screen Time vs Average: Today's cumulative screen time compared against your N-day historical average.
- Focus Dip Hour: The hour of the day where your switches spike most consistently across days.
- Deep Work Before Noon: Percentage of days where your longest focus session began before 12:00 PM local time.
- Weekend vs Weekday: Percentage difference in work-app usage between weekdays and weekends.
Note
Work and browser applications are automatically resolved from your historical data or can be explicitly overridden in config.csv.
HPR supports external themes loaded dynamically at runtime. No recompilation needed.
Themes live in:
- Linux:
~/.config/HPR/themes/ - Windows:
%APPDATA%\HPR\HPR_Config\themes\
Each theme is a subfolder containing an app-window.slint (the layout), a required metadata.csv (name, author, version info), and up to 9 preview images (1.png through 9.png).
The Themes View in the sidebar shows all discovered themes with a horizontal preview carousel, description, version info, and apply/refresh controls. Applying a theme reloads the Slint component live with no restart. Selecting default reverts to the built-in layout.
Looking for custom community themes? Easily browse, preview, and 1-click install custom themes directly from inside HPR using HPR-Store!
Warning
Theme management requires use-interpreter,true in config.csv. Interpreter mode increases RAM usage by 20-50% due to Slint's runtime compiler and decoded preview image buffers.
Full theme authoring guide at hpr-cpp.netlify.app/themes.html.
HPR ships with a built-in Sandboxed Lua 5.4 Extension Engine. Drop a .lua file into your extensions folder and HPR loads it automatically. No compilers, no package managers, no boilerplate.
Browse, install, and hot-update community extensions directly from inside the HPR application interface using HPR-Store — the native extension & theme store manager for HPR!
Each extension runs in its own isolated VM on a dedicated background thread, completely decoupled from the main tracking and rendering pipelines. A slow or misbehaving extension cannot block HPR's core loop or freeze the UI.
What you can do with extensions:
- Read the currently active window in real time
- Run shell commands and query the HPR database directly
- Register fully custom window detection backends for compositors HPR doesn't natively support (Note that dynamic backend registration via Lua is currently an experimental feature and may exhibit unstable behavior or minor bugs depending on your desktop setup)
- Subscribe to HPR's internal event bus and react to state changes
- Build interactive custom UI panels that render inside HPR via Slint callback bindings
- Function Overriding (Advanced): Intercept, block, or modify 24+ core C++ functions directly from Lua
- Native Shared Libraries (Supercharged): Load external
.so/.dllbinary files to perform low-level OS operations, custom tray integration, high-performance tasks, or anything you want (must enable "Allow Extensions to Load Native Libraries" in Settings) - AND yes, you can run Budget Doom (software rendering only)
Where to put your extensions:
Linux: ~/.config/HPR/extensions/
Windows: %APPDATA%\HPR\HPR_Config\extensions\
HPR scans recursively, so subdirectory organization like extensions/my-backend/sway.lua works fine.
A minimal extension - prints the active app every tick:
function onTick(delta)
print(HPR.getCurrentWindow_E())
endExtension lifecycle hooks:
| Hook | When it runs |
|---|---|
init() |
Once on load. Return an integer to set tick interval in ms (default 1000). |
onTick(delta) |
Periodically on the extension's thread. delta is actual elapsed ms since last tick. |
onExit() |
Once on shutdown. Must complete within 200ms or HPR force-detaches the thread. |
Documentation:
| Guide | Link |
|---|---|
| QuickStart + Common Mistakes | hpr-cpp.netlify.app/quickstart.html |
| Function Overriding API | hpr-cpp.netlify.app/overrides.html |
| Building a Custom Window Backend | hpr-cpp.netlify.app/custom-app-extension.html |
| EventHub & Extension Communication | hpr-cpp.netlify.app/comm-bw-extension.html |
| Custom Themes & UI Hacking | hpr-cpp.netlify.app/themes.html |
| Full API Reference | hpr-cpp.netlify.app/api.html |
HPR lives in your system tray and keeps running when you close the window. The only way to quit is through the tray.
Windows: Right click for a context menu with Show HPR and Quit. Closing the window hides to tray.
Linux (Waybar, KDE, Cinnamon): HPR registers as a org.kde.StatusNotifierItem on the session D-Bus. No GTK. No Qt. Pure libdbus-1. Left or right click opens HPR. Middle click quits. Waybar routes both left and right click to the same D-Bus method - this is a Waybar limitation.
~/.local/share/HPR/HPR_DB/ (Linux)
%APPDATA%\HPR\HPR_DB\ (Windows)
05-26/
01-05-26.db
02-05-26.db
...
One .db file per day. One folder per month. Standard SQLite3 that any viewer can open. Delete last month by deleting the folder. No export step. No proprietary format. No account required.
A normal day of use is 30 to 100 KB. A full year sits under 50 MB total.
No accounts.
No telemetry (unless opted-in).
No analytics (unless opted-in).
100% offline core by default.
Networking code (WinHTTP on Windows, libcurl on Linux) is compiled into the HPR binary to power the Lua extension engine, opt-in anonymous analytics. By default, HPR runs entirely offline and never phones home.
Network controls:
-
Allow Network Activity: Disable all outgoing network calls globally under the Settings view. When disabled, HPR's HTTP client skips all outgoing GET/POST/PUT requests entirely.
-
Anonymous Telemetry (opt-in, off by default): If you enable it, HPR generates a random UUIDv4 and reports two anonymous numbers: a one-time registration ping and a weekly active ping (only sent if you used HPR 4 or more days in a single week). No window titles, URLs, project names, or personal logs ever leave your machine. Toggle it on or off at any time under the Settings view.
Warning
Extension Security Warning:
Extensions have access to the networking API (HPR.httpGet_E) and can read your focus databases and active window titles. A malicious script could read your window history and exfiltrate it. Only install extensions you fully trust and have reviewed.
HPR resolves inconsistent OS window titles and tab names to clean display labels via CSV mapping files. You can customize your mappings by editing the aliases.csv (for apps), tabAliases.csv (for browser tabs), and projectAliases.csv (for VS Code projects) files located in HPR's configuration directory (~/.config/HPR/ on Linux, %APPDATA%\HPR\HPR_Config\ on Windows).
HPR's runtime parameters—such as poll interval, headless mode, hardware acceleration, and telemetry options—are customized via the config.csv settings file. This file is located at ~/.config/HPR/config.csv on Linux and %APPDATA%\HPR\HPR_Config\config.csv on Windows, and can be edited directly or modified via HPR's in-app Settings view.
HPR's UI is built using the Slint UI Framework. You can load custom themes without modifying any C++ code or recompiling.
use-interpreter,trueThemes are loaded from:
- Windows:
%APPDATA%\HPR\HPR_Config\themes\ - Linux:
~/.config/HPR/themes\
Each theme lives in its own subdirectory and must contain:
metadata.csv: Properties likename,My Theme,author,My Name, andversion,0.9.8.types.slint: Defines data models. (Optional; omitting specific properties or models is fine, but you won't receive data for those fields).app-window.slint: The main layout file, loaded at runtime.- Previews (Optional): Up to 9 screenshots (
1.pngthrough9.png) shown in the Themes carousel.
Theme creators have full freedom to build any layout they want and can add or remove any other files as long as the mandatory files are present.
Note
The UI/C++ contract is optional. If you choose to omit any of the bindings or properties specified in the contract, the application will still load and function normally, but you will not get the data or callbacks associated with the omitted properties.
For the complete UI contract and required bindings, refer to hpr-cpp.netlify.app/themes.html.
Requirements:
- CMake 3.21+
- GCC 13+, Clang 16+, or MSVC 2022+ with C++23 support
- Rust toolchain (
cargo/rustc) — Slint is compiled directly from source during CMake configuration - Linux only:
jq,gdbus,libdbus-1-dev,libcurl4-openssl-dev(or distro equivalents) - Windows only: bundled
WinToastcompiles out-of-the-box
git clone https://github.com/plexescor/HPR
cd HPRInstall Dependencies (choose one):
# Linux system-wide / user-local dependencies (DBus, Curl, Rust, dev tools):
./installDependencies.shWindows: run installDependencies.bat.
Build:
cmake -B build
cmake --build build --parallel 8HPR uses slightly patched versions of sol2, lua, and sqlite3 in external/ to avoid compile errors under C++23 strict mode. Use the bundled ones for a clean build. CMake automatically downloads and compiles Slint from source via FetchContent using Cargo, static-linking it for maximum runtime performance and lowest memory footprint. It also copies aliases.csv, config.csv, ui/, assets/, and install scripts next to the output binary automatically - a fresh build is immediately runnable from the build directory.
The full codebase is readable in one sitting if you go in this order:
main.cpp -> startup, config loading, thread orchestration
appState.hpp -> the shared data model, the center of everything
currentWindowManager.cpp -> platform-specific window polling per backend
databaseManager.cpp -> persistence, lock file, midnight rollover, historical load
limitsManager.cpp -> per-app usage limit and goal monitoring, force-quit, notification dispatch
extensionManager.cpp -> Lua VM lifecycle, sol2 bindings, hot-reload, RAII subscription tracking
uiModelManager.cpp -> how C++ state becomes Slint models in both UI modes
One rule for all new code: anything that touches shared state goes through AppState::stateMutex. Lock, copy, release, work on the copy.
No formal process. Open an issue, submit a pull request, or join our Discord server to chat.
If HPR has been useful to you, a Ko-fi helps keep development going: ko-fi.com/plexescor
Active development | v0.9.8 | Hyprland · GNOME · KDE Plasma · Cinnamon · niri · Windows 10/11 | C++23 · Slint 1.16.1 · SQLite3 amalgamation · sqlite_modern_cpp · Lua 5.4 · sol2





