Runtime API
Most noctalia.* functions are synchronous. Methods that start subprocesses, HTTP requests, or downloads return a
boolean immediately to say whether the work was accepted, then deliver results to a callback.
Runtime and settings
Section titled “Runtime and settings”| Method | Returns | Description |
|---|---|---|
noctalia.setUpdateInterval(ms) | nothing | Sets how often this entry’s update() function runs. Values below 16 ms are clamped. |
noctalia.log(msg) | nothing | Writes a message to Noctalia’s log with this plugin’s script context. |
noctalia.isDarkMode() | bool | Returns whether the active theme mode is dark. |
noctalia.focusedOutputName() | string or nil | Returns the focused output’s connector name, falling back to the preferred interactive output when needed. |
noctalia.getConfig(key) | setting value or nil | Reads a declared plugin or entry setting. Undeclared keys log a warning and return nil. |
Outputs, wallpaper, and panels
Section titled “Outputs, wallpaper, and panels”| Method | Returns | Description |
|---|---|---|
noctalia.outputs() | array | Returns connected outputs as { name, description, width, height, x, y, scale, focused } tables. |
noctalia.setWallpaperEnabled(connector, enabled) | nothing | Enables or disables Noctalia’s own wallpaper surface on one output. This is runtime-only and clears on restart. |
noctalia.setWallpaper(path) | nothing | Applies and persists a wallpaper image on every output. |
noctalia.setWallpaper(connector, path) | nothing | Applies and persists a wallpaper image on one output. |
noctalia.wallpaperDirectory() | string or nil | Returns the resolved wallpaper folder for the current theme mode, or nil when unset. |
noctalia.togglePanel("author/plugin:panel") | nothing | Opens or closes a plugin panel by full entry id. |
outputs() uses the DRM connector name in name; that is the same connector string expected by compositor tools such
as mpvpaper. A [[service]] may also define onOutputsChanged(), which Noctalia calls whenever the output set or
geometry changes.
setWallpaper(path) behaves like the built-in wallpaper panel. Prefer it and togglePanel(id) over shelling out to the
noctalia CLI from a plugin; the API path runs in-process and avoids an IPC round trip.
Time, notifications, and clipboard
Section titled “Time, notifications, and clipboard”| Method | Returns | Description |
|---|---|---|
noctalia.formatTime(pattern) | string | Formats the current local time with the same tokens as Noctalia clock and filename settings. |
noctalia.formatTime(pattern, unixSeconds) | string | Formats a specific Unix timestamp in local time. |
noctalia.notify(title, body) | nothing | Shows an informational notification. body is optional. |
noctalia.notifyError(title, body) | nothing | Shows an error notification. body is optional. |
noctalia.copyToClipboard(text, mime) | bool | Copies text to the clipboard with an explicit MIME type, for example "text/plain" or "text/uri-list". |
noctalia.clipboardText() | string or nil | Latest text clipboard content (nil when empty or non-text). |
%s in formatTime() expands to Unix epoch seconds.
Subprocesses and environment
Section titled “Subprocesses and environment”| Method | Returns | Description |
|---|---|---|
noctalia.runAsync(cmd) | bool | Starts a detached shell command and returns whether it launched. No output is captured. |
noctalia.runAsync(cmd, cb) | bool | Runs a shell command with output capture, then calls cb(result). |
noctalia.runStream(cmd, onLine) | bool | Runs a long-lived shell command and calls onLine(line) for each stdout line. |
noctalia.runInTerminal(cmd) | bool | Starts a shell command in the configured terminal. |
noctalia.commandExists(name) | bool | Checks whether an executable is available on PATH. |
noctalia.processMatches(cb, ...needles) | bool | Asynchronously checks running processes; cb(matched) receives a boolean. |
noctalia.flatpakAppInstalled(id) | bool | Checks whether a Flatpak app id is installed. |
noctalia.portalAvailable() | bool | Checks whether the desktop portal is available. |
noctalia.getenv(name) | string or nil | Reads an environment variable. |
noctalia.expandPath(path) | string | Expands a path such as ~/Pictures to an absolute user path. |
runAsync(cmd, cb) calls cb(result) once with:
{ exitCode = 0, stdout = "...", stderr = "...", timedOut = false, stdoutTruncated = false, stderrTruncated = false,}runStream() is meant for long-running processes. The runtime terminates active streams when the script reloads, the
entry is removed, or Noctalia stops the plugin.
Filesystem
Section titled “Filesystem”| Method | Returns | Description |
|---|---|---|
noctalia.readFile(path) | string, or nil, err | Reads a file as bytes. |
noctalia.writeFile(path, content) | bool, optional error | Writes a file, replacing existing contents. |
noctalia.mkdirAll(path) | bool, optional error | Creates a directory and any missing parents (an existing directory is success). |
noctalia.removeFile(path) | bool, optional error | Deletes a file. Refuses directories. |
noctalia.renameFile(from, to) | bool, optional error | Renames or moves a file. |
noctalia.fileExists(path) | bool | Checks whether a path exists. |
noctalia.fileInfo(path) | table, or nil, err | { size, mtime, isDir }, size in bytes, mtime in unix seconds. |
noctalia.listDir(path) | array, or nil, err | Lists filenames in a directory. |
noctalia.pluginDir() | string or nil | Returns this plugin’s runtime directory. |
noctalia.loadFont(path) | string, or nil, err | Registers a font file and returns its family name. |
Filesystem paths resolve as follows: ~ expands to $HOME, absolute paths are used as-is, and relative paths resolve
against the plugin’s own directory. Plugins are trusted code, so these helpers are not sandboxed.
HTTP and downloads
Section titled “HTTP and downloads”| Method | Returns | Description |
|---|---|---|
noctalia.http(request, cb) | bool | Starts an async HTTP request and calls cb(response). |
noctalia.download(url, dest, cb) | bool | Downloads a URL to a file and calls cb(ok) with a boolean. |
request is a table:
{ url = "https://example.com", method = "GET", body = "", headers = { "Accept: application/json" }, basic_username = "user", basic_password = "pass", follow_redirects = false,}Only url is required. http() calls cb(response) once with:
{ ok = true, status = 200, body = "...",}download() resolves dest like other filesystem paths, so a relative destination writes inside the plugin directory.
Translations and data helpers
Section titled “Translations and data helpers”| Method | Returns | Description |
|---|---|---|
noctalia.tr(key) | string | Looks up a translated string from translations/<lang>.json, falling back to the key. |
noctalia.tr(key, subst) | string | Looks up a string and replaces {name} placeholders from a table. |
noctalia.trp(key, count) | string | Plural translation helper; prefers <key>.one or <key>.other, then the bare key. |
noctalia.trp(key, count, subst) | string | Plural translation helper with substitutions. count is also available as {count}. |
noctalia.json.decode(str) | value, or nil, err | Parses JSON into Luau values. |
noctalia.json.encode(value) | string, or nil, err | Encodes a Luau value as compact JSON. |
noctalia.json.encode(value, true) | string, or nil, err | Encodes a Luau value as pretty JSON. |
noctalia.string.trim(str) | string | Trims leading and trailing whitespace. |
noctalia.string.urlEncode(str) | string | Percent-encodes a string for use in URLs. |
noctalia.string.urlDecode(str) | string | Decodes percent-encoded URL text. |
noctalia.fuzzyScore(pattern, text) | number or nil | Scores a fuzzy match with Noctalia’s native matcher. nil means no match. |
json.* and string.* are synchronous pure transforms. Prefer string.urlEncode() when building query strings for
http() or download().
Sharing state across entries
Section titled “Sharing state across entries”Entries are isolated VMs - they don’t share Lua memory. Instead they exchange plain values through a per-plugin state channel:
| Method | Returns | Description |
|---|---|---|
noctalia.state.set(key, value) | nothing | Publishes a plain value for other entries in the same plugin. |
noctalia.state.get(key) | value or nil | Reads the latest value for a key. |
noctalia.state.watch(key, fn) | nothing | Calls fn(value) whenever the key changes. |
Values are copied across entries, so they must be plain data - strings, numbers, booleans, and tables of those (not
functions). A typical pattern is a [[service]] publishing data that the widget and shortcut watch.
-- ticker.luau (service)local n = 0noctalia.setUpdateInterval(1000)function update() n = n + 1 noctalia.state.set("count", n)end
-- widget.luaunoctalia.state.watch("count", function(value) barWidget.setText(tostring(value))end)