Plugin development Reference

Hook catalog

Every main-process and renderer lifecycle hook a plugin can listen to, with payloads and when they fire.

Hooks are typed lifecycle events. You subscribe with ctx.hooks.on(name, fn) — in the main-process context for main hooks, and in the renderer context for renderer hooks. Subscriptions are tracked and removed automatically when the plugin deactivates.

ctx.hooks.on("session:spawned", ({ sessionId, shell, args }) => {
  ctx.log(`session ${sessionId} spawned: ${shell} ${args?.join(" ") ?? ""}`);
});

Main-process hooks

MainHookMap (src/shared/plugin-hooks.ts):

HookPayloadWhen
app:ready{}Electron ready, windows created
window:created{ windowId }A BrowserWindow was created
session:spawned{ sessionId, spriteName?, daemonHost?, shell?, args? }A terminal session spawned (shell/args echo the spawn command, e.g. ssh + argv)
session:exited{ sessionId, exitCode }A terminal session exited
connection:lost{ sessionId, transport }A remote session’s transport died unexpectedly; auto-reconnect started (transport: "sprite" exec WS or durable "daemon")
connection:reconnected{ sessionId, transport, attempts }Auto-reconnect re-established the session
connection:reconnect-failed{ sessionId, transport, attempts }Auto-reconnect gave up; the session exits (durable remotes survive on the host)
config:changed{ config }The persisted config changed
gpu:restarted{ reason }A GPU 2d context was lost and recovered — GPU process crash+respawn, or system resume from suspend (reason: "system-resume"); renderers drop glyph caches + repaint terminal engines
app:will-quit{}App quitting (after workspace persist)

Renderer hooks

RendererHookMap:

HookPayloadWhen
tab:activated{ tabId }The active top-level tab changed
pane:focused{ paneId }Pane focus moved
theme:changed{ themeId }The UI theme/accent was applied
workspace:flyout-opened{ tabId }The workspace flyout (left-rail session list) opened for a workspace
agent:state-changed{ sessionId, phase }A tracked agent’s run phase changed (event-driven telemetry: working/blocked/idle) — emitted by the agent-telemetry registry’s IPC push. Use for notifications, sounds, automations.

The agent:state-changed hook is the supported way to react to agent awareness state — fire a notification, play a sound, or kick off an automation when an agent becomes blocked or idle.

Adding hooks

Per the project rule, every notable new lifecycle moment must add a hook to MainHookMap / RendererHookMap and emit it at that point — and document it in this catalog. See Security & publishing.