Perch
Lua APIperch.discord

perch.discord

The call model, notifications, rings, and voice verbs — scopes discord and discord.control.

3 min readUpdated Jul 21, 2026

The Discord provider speaks RPC to the running client. Read side under scope discord, the five call verbs under discord.control.

on_call(host, c) — scope discord

Fires on call presence edges (joining or leaving a call), carrying the full call model:

FieldTypeMeaning
inCallboolthe edge itself
dmboola DM call (no server info)
server / serverIcon / channelstringwhere the call is
startednumberwall-epoch ms when the call began — feed a ticker with mode = "elapsed"
selfMute / selfDeafboolyour own states — button faces
namesstring[]participants; [0] is the local user
avatarsstring[]per participant; "" = use initials
speaking / streaming / video / muted / deafenedint[]index sets into names
countnumberparticipant count
solotablethe provider’s sticky one-face pick (below)

solo is a ready-made face for compact contexts — the last speaker, sticky until a different participant speaks:

solo. fieldMeaning
name / initial / avataridentity, with monogram fallback
hue_cssa per-person gradient string — feed it to bg_bind
speaking / streaming / muted / deafenedlive flags
function M.on_call(host, c)
  host.set_presence("mycall", c.inCall, c)   -- the model is already view-ready
end

Live within-call changes (speaking rings, joins/leaves) stream to the builtin call widgets natively; a third-party ambient that only needs presence and the solo face is fully served by the edges.

on_dnote(host, n) — scope discord

A mirrored Discord notification:

-- n = { from = "maya", text = "you up?", avatar = "file://…",
--       context = "#general — perch", at = <wall-epoch ms> }

at rides the event because the sandbox clock has no epoch — use it for “2m ago” math against later events.

on_ring(host, r) — scope discord

An incoming call: { active, from, avatar }. active = false means the ring ended (answered elsewhere, timed out) — always handle the retraction.

on_status(host, s) / perch.discord.status()

{ connected, needsAuth } — the RPC link state, as an event and as a pull-seed for late-starting packages. needsAuth = true means the user must approve Perch in their Discord client.

perch.discord.control(verb) — scope discord.control

perch.discord.control("toggleMute")
VerbEffect
toggleMute / toggleDeafenself states
hangupleave the call
acceptRing / declineRinganswer the incoming ring

A hard whitelist — these five strings are the only ones that ever reach the RPC socket from any package.

perch.discord.reconnect() — scope discord.control

Kicks a reconnect attempt — the settings Connect button’s verb. Pair with on_status to show the result.

esc
Type to search
navigate open