perch.apps — scope apps
The provider tracks window focus natively, keeping a 30-day usage store — which apps, when last focused, how long today. Packages read the digest and launch from it; they never see raw focus events.
perch.apps.read()
local a = perch.apps.read()
-- {
-- recent = { { name = "Neovim", icon = "file:///…/nvim.png", sub = "2m ago" }, … },
-- top = { { name = "Firefox", icon = "…", sub = "3h 12m today" }, … },
-- }
Two ranked lists (up to 6 each): recent by last focus, top by a
half-life-weighted usage score. Entries are view-ready — real resolved app
icons ("" = paint your monogram fallback) and a prebuilt sub line.
perch.apps.launch(list, index)
perch.apps.launch("recent", 2) -- launch the 3rd recent app (0-based)
Launches by recorded reference only — the desktop entry / executable the tracker itself observed. There is no path or command argument and never will be; arbitrary exec is structurally impossible. Wire it from a repeater:
-- displays.lua
{ type = "list", bind = "recent", item = { ..., action = "open:{i}" } }
-- logic.lua
function M.on_command(host, widget, action)
local i = action:match("^open:(%d+)$")
if i then perch.apps.launch("recent", tonumber(i)) end
end
perch.apps.set_config(tbl)
Forwards your settings table to the tracker (list length, exclusions — whatever your settings page exposes).
perch.open — scope open
Validated outward launches — the only path from a package to anything outside Perch.
perch.open.url(url)
perch.open.url("https://github.com/you/your-mod")
https:// only — anything else is refused and logged. Every launch is
audit-logged as the trust surface it is.
perch.open.steam(appid)
perch.open.steam("4980700") -- steam://run/<appid>
Numeric appid only; opens through the Steam client.