Raw Extension API Reference
HPR embeds a powerful C++ Lua engine. This document describes the raw lifecycle hooks and all functions exposed to the Lua namespace through the global HPR table.
Lifecycle Hooks
Your Lua extensions are driven by two main entry points executed on a dedicated background thread spawned specifically for your script.
Called exactly once by HPR when the extension is loaded at startup. This is the place to perform one-time initialization, such as registering a window-tracking backend.
You can return an integer value (in milliseconds) from init(). This sets the tick interval (sleep duration) for your extension thread. If no value is returned or if the hook is omitted, the tick rate defaults to 1000 ms (1 second).
function init() print("Initializing extension...") return 500 -- configure this extension thread to tick every 500 milliseconds end
Called periodically on your extension's isolated background thread based on the tick interval configured in init().
HPR passes a single argument delta (a float) representing the actual elapsed time in milliseconds since the last tick occurred. This allows for extremely precise timing, rate calculation, or event tracking within your script.
function onTick(delta) print("Time since last tick: " .. delta .. " ms") end
Called exactly once by HPR when the application is closing or when the extension is being stopped. This is the optimal place to perform teardown operations, execute final database writes, and clean up active listeners.
function onExit() flushToDatabase() print("Extension is shutting down cleanly.") end
The HPR Global Table
Extension Identity
HPR uses global state fields to register extension identities. Defining these properties enables HPR to track your extension details and display them directly in HPR's Loaded Extensions manager.
Type: string (property)
Configures the author or developer name of the loaded extension. This must be defined inside your extension's init() function alongside the extension name to register your module's identity.
HPR.authorName = "Plexescor"
Type: string (property)
Configures the custom display name of the loaded extension. Must be set inside your extension's init() function alongside the author name to register your module's identity.
HPR.extensionName = "My Custom HPR Extension"
General Utilities
Core helper functions for timing, thread control, and UI state inspection available to every extension.
Returns: uint64 (Unix timestamp in milliseconds)
Returns the current system time as a Unix timestamp in milliseconds. Useful for timestamping events, measuring elapsed durations, or seeding time-series database entries.
local now = HPR.getTime_MS() print("Current time (ms): " .. now)
Parameters: ms: int (milliseconds) — Returns: nothing
Blocks the calling extension's background thread for the specified number of milliseconds. Since every extension runs on its own isolated OS thread, this only pauses your script — HPR and all other extensions remain fully responsive. Useful for rate-limiting inside a callback or performing a one-shot delayed action without restructuring your tick loop.
HPR.sleep_E(2000) -- pause this extension thread for 2 seconds
Returns: boolean
Returns true if the HPR Slint UI window is currently loaded and active, false otherwise. Use this as a guard before calling HPR.setUiProperty_E or HPR.registerUiCallback in situations where you need an explicit check (e.g. in a tick loop rather than a one-time init() call). Note that both UI functions already silently ignore calls when the UI is not active.
if HPR.isUiActive_E() then HPR.setUiProperty_E("statusLabel_S", "Ready") end
Window State Information
Returns: string (the raw window class name)
Reads directly from HPR's active tracking backend state using a thread-safe C++ lambda. It returns the raw window class name of the currently focused window (before applying aliases or filters). Useful for checking active status or inspecting the currently running window.
local windowClass = HPR.getCurrentWindow_E() print("Raw active window class: " .. windowClass) -- e.g. "firefox" or "kitty"
Returns: string (the raw window title)
Reads and returns the raw window title string of the currently focused window. This is critical for extensions tracking browser websites, active files in editors, or terminal commands.
local title = HPR.getCurrentTitle_E() print("Raw active window title: " .. title) -- e.g. "Google — Mozilla Firefox"
Returns: nothing
Instructs HPR's CurrentWindowManager to pause all active window-tracking polling. Useful when an extension needs to temporarily suppress tracking — for example, during a screen-lock event or a privacy-sensitive period. Pair with HPR.startTracking_E() to resume.
HPR.stopTracking_E()
-- ... do sensitive work ...
HPR.startTracking_E()
Returns: nothing
Resumes HPR's CurrentWindowManager window-tracking polling after it has been paused with HPR.stopTracking_E(). Has no effect if tracking is already running.
HPR.startTracking_E()
Parameters: command: string — Returns: string (stdout)
Executes a shell command synchronously and returns the standard output (stdout) as a string. Any trailing whitespace is preserved. The function blocks until completion; keep commands fast.
To prevent accidental or malicious destruction from extensions, HPR actively filters and blocks dangerous commands. If you plan/planned to use dangerous commands, FUCK OFF 🖕🖕.
Some examples of blocked commands:
rm, rmdir, chmod, sudo, su, mkfs, fdisk, shutdown, reboot, curl, wget, python, bash, del, reg, apt, pip, systemctl, and common shell injection patterns like | sh or $(rm).
local output = HPR.runSystemCommand_E("uptime") print(output)
Alias Management
HPR provides high-performance lookup in Lua matching its internal configurations for mapping raw window names to user-friendly pretty-names.
Parameters: command: string (raw name) — Returns: string (aliased pretty name)
Returns the user's defined alias pretty-name for a given application class (e.g. mapping kitty to Terminal).
Parameters: command: string — Returns: string (aliased pretty name)
Returns the user's configured alias for browser tab patterns (website pretty-names).
Parameters: command: string — Returns: string (aliased pretty name)
Returns the user's configured pretty alias for active development projects.
Parameters: aliasName: string — Returns: string (original raw name)
Looks up the reverse cache of application aliases to resolve a pretty name (e.g. Terminal) back to its original raw identifier (e.g. kitty).
Parameters: aliasName: string — Returns: string (original raw tab)
Resolves a pretty tab website alias back to the original raw web title representation.
Parameters: aliasName: string — Returns: string (original raw project name)
Resolves a pretty project name back to the original raw project workspace directory or file path keyword.
Backend Registration
Parameters: (name, matchesEnvironment, initialize, isUsable, getCurrentWindow, getCurrentTitle)
Registers a completely new custom tracking backend dynamically. HPR's backend manager calls the registered functions during startup to inspect compositors and get current window classes/titles. For a detailed guide on using this, please consult the Custom Backend Tutorial.
function init() HPR.registerBackend_E( "MyCompositor", function(env) return env:find("MyCompositor") ~= nil end, function() print("Loaded!") end, function() return true end, function() return "browser" end, function() return "Home Page" end ) end
Event Hub & Messaging
The Event Hub is HPR's high-performance messaging core, acting as a real-time bridge to dispatch lifecycle signals, system changes, or dynamic messages between C++ and Lua extensions.
Parameters: eventName: string, callback: function — Returns: int (subscription ID)
Subscribes a Lua callback function to a system or custom named event. Whenever the event is emitted, your callback will run. Returns a unique subscription ID integer that must be saved to disconnect later.
Whenever you subscribe to an event using HPR.connect_E, HPR allocates a persistent listener hook in its C++ event registry. If your extension shuts down, gets reloaded, or is disabled, and you fail to call HPR.disconnect_E, this hook becomes a zombie reference.
Zombie hooks prevent the Lua garbage collector from freeing up memory, leading to application memory leaks, UI lag, and potential crashes.
Rule of thumb: every single subscription created with HPR.connect_E must have a matching HPR.disconnect_E inside your onExit() handler.
LOAD_DATABASE_SINGULAR, HISTORY_LOADED_SINGULAR, LOAD_LIVE_DATA, APP_ERROR, MIDNIGHT_ROLLOVER, WINDOW_CHANGEDAny other string is treated as a custom dynamic event shared between extensions.
local subId = HPR.connect_E("MIDNIGHT_ROLLOVER", function(data) print("Day rolled over!") end)
Parameters: eventName: string, data: table (optional) — Returns: nothing
Broadcasts a named signal to the Event Hub, triggering all active callbacks connected to this event name. You can optionally pass a Lua table/value containing a custom payload structure.
HPR.emit_E("my_custom_alarm", { temp = 82.5, warning = true })
Parameters: eventName: string, subscriptionId: int — Returns: nothing
Unsubscribes a specific listener using its unique subscription ID. Always invoke this inside onExit() to release hooks and prevent memory leaks.
function onExit() HPR.disconnect_E("MIDNIGHT_ROLLOVER", subId) end
Network & JSON Utilities
HPR provides high-performance utility helpers to query REST APIs and serialize or parse JSON payloads without needing slow external scripting dependencies.
Parameters: port: int, handler: function — Returns: boolean (success)
Starts an embedded HTTP server on the given port, delegating all incoming requests to the provided Lua handler function. Returns true if the server bound successfully, false otherwise. The handler is called on the extension's background thread for each incoming request. Useful for exposing a local REST API or webhook receiver from within your extension.
function init() local ok = HPR.startServer_E(8080, function(request) print("Incoming request: " .. request) end) print("Server started: " .. tostring(ok)) end
Parameters: host: string, path: string, secure: boolean (optional, default true) — Returns: (string, int) (body, status)
Performs a synchronous HTTP or HTTPS GET request using HPR's native, multithreaded network engine. Since each extension is run inside its own background operating system thread, GET requests block only the calling extension's thread, keeping HPR completely responsive.
Loopback DNS Caveat (localhost vs. 127.0.0.1): On modern operating systems, passing "localhost" triggers the system's standard name resolution (getaddrinfo), which prioritizes the IPv6 loopback address [::1] over the IPv4 address 127.0.0.1. If a local server binds strictly to the IPv4 address 127.0.0.1, any request targeting localhost will fail. Always use literal IPv4 addresses like "127.0.0.1" instead of "localhost" for local communication.
local body, status = HPR.httpGet_E("127.0.0.1:5600", "/api/0/buckets/", false)
Parameters: host: string, path: string, body: string, secure: boolean (optional, default true) — Returns: (string, int) (responseBody, status)
Performs a synchronous HTTP or HTTPS POST request. Very useful for pushing tracked events out to local controllers or dispatching Discord webhooks.
Loopback DNS Caveat (localhost vs. 127.0.0.1): Just like GET requests, local POST targets should use the literal IPv4 "127.0.0.1" instead of "localhost". See httpGet_E for the full explanation.
local res, status = HPR.httpPost_E("api.webhook.com", "/send", jsonString)
Parameters: str: string (ISO 8601 datetime) — Returns: uint64 (Unix timestamp in milliseconds, or 0 on parse failure)
Parses an ISO 8601 datetime string (e.g. "2024-05-21T14:30:00.500Z") and returns the corresponding Unix timestamp in milliseconds. Subsecond precision up to milliseconds is preserved. Returns 0 if the string cannot be parsed. Commonly used when consuming timestamps from external REST APIs (such as Spotify or calendar services) that return ISO 8601 formatted dates.
local ms = HPR.parseISO8601_E("2024-05-21T14:30:00.500Z") print("Timestamp ms: " .. ms)
Parameters: jsonStr: string, fieldPath: string (optional) — Returns: table or any
A fast convenience transmuter that instantly translates a raw JSON string into a Lua table, sparing you from bundling slow manual string parsers. An optional dot-separated key path can be passed to pluck nested elements directly.
local data = HPR.parseJSON_E(rawJson) local nestedValue = HPR.parseJSON_E(rawJson, "data.url")
Parameters: luaTable: table — Returns: string (JSON representation)
A convenience utility that serializes a standard Lua table into a minified JSON string representation, ready for outgoing POST requests.
local jsonStr = HPR.toJSON_E({ name = "firefox", active = true })
Database Operations
HPR gives every extension direct access to its SQLite database. All extensions share the same database file, so choose unique table names to avoid conflicts.
Parameters: sql: string, params: table (optional) — Returns: nothing
Executes a write SQL statement (CREATE, INSERT, UPDATE, DELETE) against HPR's SQLite database. The optional second argument is a Lua table of strings bound to ? placeholders in the SQL query, preventing SQL injection. Always use parameterized queries when inserting user-derived data.
-- Create a table HPR.dbExecute_E([[ create table if not exists my_data ( key text unique, value text ); ]]) -- Insert with parameterized values HPR.dbExecute_E( "insert or replace into my_data (key, value) values (?, ?);", { "active_app", "firefox" } )
Parameters: sql: string, params: table (optional) — Returns: table (array of row tables)
Executes a read SQL statement (SELECT) and returns the results as a Lua table. Each element in the returned table is a row, represented as a Lua table with column names as keys.
local rows = HPR.dbQuery_E("select key, value from my_data;") for i, row in ipairs(rows) do print(row.key .. " = " .. row.value) end
Parameters: none — Returns: string (full absolute file path)
Returns the absolute, resolved filesystem path of the currently loaded historical database. Returns an empty string if HPR is currently in live-tracking mode.
local histPath = HPR.getLoadedHistDbPath_E() print("Loaded past DB path: " .. histPath)
Parameters: sql: string, params: table (optional) — Returns: table (array of rows)
Executes a read SQL query against the currently active historical database file (set during a "LOAD_DATABASE_SINGULAR" calendar switch). This is a safe, high-level helper that completely abstracts database opening, folder traversal, and closing operations. Blocks for up to 5 seconds waiting for the async historical DB load to complete before running the query.
local rows = HPR.dbQueryHistorical_E("select song_name from spotify_songs;")
UI Integration
Extensions can push data directly into HPR's Slint UI and register callbacks for UI events. Values are converted from Lua types to Slint types automatically — strings, numbers, booleans, arrays of structs are all supported. For a step-by-step guide on building a UI-connected extension, see the Custom App Extension Tutorial.
Parameters: name: string, value: any — Returns: nothing
Sets a named property on the root Slint UI component. The property name must exactly match an in property defined in app-window.slint. HPR converts the Lua value to a C++ intermediate on the extension thread, then dispatches the Slint update to the main UI thread. Supported types: string, number, boolean, table (array → Slint model, key-value → Slint struct). If the UI is not yet loaded, the call is silently ignored.
-- Set a simple string property HPR.setUiProperty_E("windowName_S", "firefox") -- Set an array of structs (each struct maps to a Slint struct) HPR.setUiProperty_E("spotifySongs_S", { { name = "Song A", artist = "Artist 1", duration = "01:23:45", duration_i = 5025000 }, { name = "Song B", artist = "Artist 2", duration = "00:45:30", duration_i = 2730000 }, })
Parameters: name: string, luaFunction: function — Returns: nothing
Registers a Lua function as a handler for a Slint callback. When the named callback is triggered from the Slint UI (e.g. a button click), HPR invokes your Lua function. The callback name must exactly match a callback defined in the Slint component. If the UI is not yet loaded, the call is silently ignored.
HPR.registerUiCallback("myButtonClicked", function() print("Button was clicked in the UI!") end)
Time & Date Utilities
HPR exposes its internal time formatting and parsing functions to Lua. All time values are in milliseconds unless noted otherwise.
Parameters: ms: int (milliseconds) — Returns: string
Converts a duration in milliseconds to a human-readable "HH:MM:SS" formatted string. Commonly used for displaying tracked time in the UI.
local formatted = HPR.formatTime_HHMMSS_E(5025000) print(formatted) -- "01:23:45"
Parameters: ms: int (Unix timestamp in ms) — Returns: string
Converts a Unix timestamp in milliseconds to a date string in "DD-MM-YY" format.
Parameters: ms: int (Unix timestamp in ms) — Returns: string
Converts a Unix timestamp in milliseconds to a date string in "MM-YY" format (month and year only).
Parameters: ms: int (Unix timestamp in ms) — Returns: string
Converts a Unix timestamp in milliseconds to a 12-hour time string in "HH:MM:SS AM/PM" format.
Parameters: dateStr: string ("DD-MM-YY") — Returns: int (Unix timestamp in ms)
Parses a "DD-MM-YY" date string and returns the corresponding Unix timestamp in milliseconds. The inverse of convertToDate_DDMMYY_E.
Parameters: dateStr: string ("MM-YY") — Returns: int (Unix timestamp in ms)
Parses a "MM-YY" date string and returns the corresponding Unix timestamp in milliseconds. The inverse of convertToDate_MMYY_E.
Parameters: dateStr: string ("DD-MM-YY") — Returns: string ("MM-YY")
Extracts the month-year portion from a full "DD-MM-YY" date string, returning just "MM-YY". Useful for grouping daily records by month.