Perch
Lua APIperch.apps & perch.open

perch.apps & perch.open

The app tracker, recorded-ref launching, and validated outward links.

2 min readUpdated Jul 21, 2026

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.

esc
Type to search
navigate open