app.system - System Information API
Retrieve system, hardware, and environment information.
Basic Info
app.system.osName()
Get the operating system name.
Returns: string - Always returns “macOS”
local os = app.system.osName() -- "macOS"
app.system.osVersion()
Get the operating system version.
Returns: string - Version number
local version = app.system.osVersion() -- "14.1.0"
app.system.osBuild()
Get the system build number.
Returns: string - Build number
local build = app.system.osBuild() -- "23B74"
app.system.hostName()
Get the host name.
Returns: string - Host name
local host = app.system.hostName() -- "MacBook-Pro.local"
app.system.userName()
Get the current user name.
Returns: string - User name
local user = app.system.userName() -- "username"
app.system.fullUserName()
Get the full user name.
Returns: string - Full name
local name = app.system.fullUserName() -- "John Doe"
Environment Variables
app.system.env(name)
Get an environment variable.
Parameters:
name(string) - Variable name
Returns: string|nil - Variable value or nil
local home = app.system.env("HOME") -- "/Users/username"
local path = app.system.env("PATH") -- "/usr/local/bin:..."
local custom = app.system.env("MY_VAR") -- nil (if not set)
app.system.envAll()
Get all environment variables.
Returns: table - Key-value pairs
local env = app.system.envAll()
for name, value in pairs(env) do
app.log.info(name .. " = " .. value)
end
app.system.setEnv(name, value)
Set an environment variable (only effective in the current process).
Parameters:
name(string) - Variable namevalue(string) - Variable value
Returns: boolean - Whether successful
app.system.setEnv("MY_VAR", "my_value")
Hardware Info
app.system.arch()
Get CPU architecture.
Returns: string - “arm64” or “x86_64”
local arch = app.system.arch() -- "arm64"
if arch == "arm64" then
app.log.info("Apple Silicon Mac")
else
app.log.info("Intel Mac")
end
app.system.cpuCount()
Get CPU core count.
Returns: number - Number of cores
local cores = app.system.cpuCount() -- 8
app.system.memory()
Get memory information.
Returns: table
total(number) - Total memory (bytes)available(number) - Available memory (bytes)used(number) - Used memory (bytes)
local mem = app.system.memory()
app.log.info("Total memory: " .. (mem.total / 1024 / 1024 / 1024) .. " GB")
app.log.info("Available: " .. (mem.available / 1024 / 1024 / 1024) .. " GB")
app.system.diskSpace(path?)
Get disk space information.
Parameters:
path(string, optional) - Disk path (default “/”)
Returns: table|nil
total(number) - Total space (bytes)available(number) - Available space (bytes)used(number) - Used space (bytes)
local disk = app.system.diskSpace("/")
app.log.info("Available space: " .. (disk.available / 1024 / 1024 / 1024) .. " GB")
-- Check an external drive
local external = app.system.diskSpace("/Volumes/MyDrive")
app.system.deviceModel()
Get the device model identifier (since 1.3.0).
Returns: string - e.g. "MacBookPro18,3", "Macmini9,1"
local model = app.system.deviceModel()
app.log.info("Device model: " .. model)
Hardware Identifiers (PII)
The following APIs return personally identifiable information that can uniquely identify a device. Plugins must declare the hardware_id permission in plugin.json; a consent dialog will appear on first use.
app.system.serialNumber()
Get the Mac serial number (since 1.3.0, requires hardware_id permission).
Returns: string|nil, err - e.g. "C02XXXXXXXXX"
-- plugin.json: "permissions": ["system", "hardware_id"]
local sn, err = app.system.serialNumber()
app.system.hardwareUUID()
Get the hardware UUID (since 1.3.0, requires hardware_id permission).
Returns: string|nil, err - UUID format string
local uuid, err = app.system.hardwareUUID()
app.system.diskSerial(path?)
Get the disk serial/UUID for a volume (since 1.3.0, requires hardware_id permission).
Parameters:
path(string, optional) - Disk path (default/)
Returns: string|nil, err - Disk UUID or device path
local sn, err = app.system.diskSerial("/")
Login Item (1.3.0)
Manage iRightMenu Pro’s own login-at-startup state. Writing requires the login_item permission; reading does not.
app.system.isLoginItem()
Check whether iRightMenu Pro is set to launch at login (since 1.3.0).
Returns: boolean
if app.system.isLoginItem() then
app.log.info("launch at login is enabled")
end
app.system.setLoginItem(enable)
Toggle iRightMenu Pro’s launch-at-login state (since 1.3.0, requires login_item permission, prompts on first use).
Parameters:
enable(boolean) - true to enable, false to disable
Returns: boolean, err
-- plugin.json: "permissions": ["system", "login_item"]
local ok, err = app.system.setLoginItem(true)
Language and Region
app.system.locale()
Get the system locale setting.
Returns: string - Locale code
local locale = app.system.locale() -- "zh_CN"
app.system.language()
Get the system preferred language.
Returns: string - Language code
local lang = app.system.language() -- "zh-Hans"
app.system.timezone()
Get the timezone.
Returns: string - Timezone identifier
local tz = app.system.timezone() -- "Asia/Shanghai"
Other
app.system.uptime()
Get system uptime.
Returns: number - Seconds
local uptime = app.system.uptime()
local hours = math.floor(uptime / 3600)
app.log.info("System has been running for " .. hours .. " hours")
app.system.uuid()
Generate a new UUID.
Returns: string - UUID string
local id = app.system.uuid() -- "A1B2C3D4-E5F6-..."
app.system.timestamp()
Get the current Unix timestamp.
Returns: number - Timestamp (seconds, with fractional part)
local ts = app.system.timestamp() -- 1701234567.123
Directory Paths
For directory paths, use the app.path module:
app.path.home() -- "/Users/username"
app.path.temp() -- "/var/folders/.../T"
app.path.desktop() -- "/Users/username/Desktop"
app.path.documents() -- "/Users/username/Documents"
app.path.downloads() -- "/Users/username/Downloads"
app.path.applications() -- "/Applications"
Event Watching
app.system.watch(event, callback)
Watch for system-level events.
Parameters:
event(string) - event name:"sleep"- fired when the system is about to sleep"wake"- fired when the system wakes from sleep"screenLocked"- fired when the screen locks"screenUnlocked"- fired when the screen unlocks"volumeMount"- fired when a volume is mounted, callback receives:{type, path, name}"volumeUnmount"- fired when a volume is unmounted, callback receives:{type, path, name}
callback(function) - callback function.sleep/wake/screenLocked/screenUnlockedreceive no arguments;volumeMount/volumeUnmountreceive:type(string) - event typepath(string) - mount path (e.g. “/Volumes/MyDisk”)name(string) - volume name
Returns: string, error - watcher handle ID
app.system.watch("sleep", function()
app.log.info("System is going to sleep")
end)
app.system.watch("wake", function()
app.log.info("System woke up")
end)
app.system.watch("volumeMount", function(e)
app.notification.show("Volume Mounted", e.name .. " (" .. e.path .. ")")
end)
app.system.watch("volumeUnmount", function(e)
app.log.info("Volume unmounted: " .. e.name)
end)
app.system.stopAllWatchers()
Stop all system event watchers registered by the current plugin.
Returns: boolean
app.system.stopAllWatchers()
app.system.listWatchers()
List all system event watchers registered by the current plugin.
Returns: array<table> - each item contains:
id(string) - watcher handle IDevent(string) - event name being watched
local watchers = app.system.listWatchers()
for _, w in ipairs(watchers) do
app.log.info(w.id .. " -> " .. w.event)
end
Examples
Check System Requirements
function MyPlugin:checkRequirements()
-- Check macOS version
local version = app.system.osVersion()
local major = tonumber(version:match("^(%d+)"))
if major < 12 then
app.dialog.alert({
title = "Not Supported",
message = "Requires macOS 12 or later"
})
return false
end
-- Check architecture
if app.system.arch() ~= "arm64" then
app.log.warning("Running on Intel Mac, performance may be reduced")
end
-- Check disk space
local disk = app.system.diskSpace("/")
local freeGB = disk.available / 1024 / 1024 / 1024
if freeGB < 1 then
app.dialog.alert({
title = "Insufficient Space",
message = "At least 1GB of free space is required"
})
return false
end
return true
end
Generate System Report
function MyPlugin:handleSystemInfo(context)
local mem = app.system.memory()
local disk = app.system.diskSpace("/")
local info = {
"System Information Report",
"================",
"",
"OS: " .. app.system.osName() .. " " .. app.system.osVersion(),
"Build: " .. app.system.osBuild(),
"Architecture: " .. app.system.arch(),
"Hostname: " .. app.system.hostName(),
"User: " .. app.system.fullUserName() .. " (" .. app.system.userName() .. ")",
"",
"CPU Cores: " .. app.system.cpuCount(),
"Memory: " .. string.format("%.1f GB", mem.total / 1024^3),
"Available Memory: " .. string.format("%.1f GB", mem.available / 1024^3),
"",
"Disk Total: " .. string.format("%.1f GB", disk.total / 1024^3),
"Disk Available: " .. string.format("%.1f GB", disk.available / 1024^3),
"",
"Language: " .. app.system.language(),
"Locale: " .. app.system.locale(),
"Timezone: " .. app.system.timezone(),
"",
"Uptime: " .. string.format("%.1f hours", app.system.uptime() / 3600),
"",
"Generated at: " .. os.date("%Y-%m-%d %H:%M:%S")
}
local report = table.concat(info, "\n")
-- Save the report
local path = app.path.join(context.currentDirectory, "system_info.txt")
app.file.write(path, report)
app.finder.reveal(path)
end
Adjust Behavior Based on System Configuration
function MyPlugin:getOptimalThreadCount()
local cores = app.system.cpuCount()
-- Reserve some cores for the system
local threads = math.max(1, cores - 2)
-- Check available memory
local mem = app.system.memory()
local freeGB = mem.available / 1024 / 1024 / 1024
-- Reduce threads if memory is low
if freeGB < 2 then
threads = math.min(threads, 2)
end
return threads
end