/** * Titlebar Spinner Extension * * Shows a braille spinner animation in the terminal title while the agent is working. * Uses `ctx.ui.setTitle()` to update the terminal title via the extension API. * * Usage: * pi --extension examples/extensions/titlebar-spinner.ts */ import path from "node:path"; import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; const BRAILLE_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; function getBaseTitle(pi: ExtensionAPI): string { const cwd = path.basename(process.cwd()); const session = pi.getSessionName(); return session ? `π - ${session} - ${cwd}` : `π - ${cwd}`; } export default function (pi: ExtensionAPI) { let timer: ReturnType | null = null; let frameIndex = 0; function stopAnimation(ctx: ExtensionContext) { if (timer) { clearInterval(timer); timer = null; } frameIndex = 0; ctx.ui.setTitle(getBaseTitle(pi)); } function startAnimation(ctx: ExtensionContext) { stopAnimation(ctx); timer = setInterval(() => { const frame = BRAILLE_FRAMES[frameIndex % BRAILLE_FRAMES.length]; const cwd = path.basename(process.cwd()); const session = pi.getSessionName(); const title = session ? `${frame} π - ${session} - ${cwd}` : `${frame} π - ${cwd}`; ctx.ui.setTitle(title); frameIndex++; }, 80); } pi.on("agent_start", async (_event, ctx) => { startAnimation(ctx); }); pi.on("agent_end", async (_event, ctx) => { stopAnimation(ctx); }); pi.on("session_shutdown", async (_event, ctx) => { stopAnimation(ctx); }); }