From f4b1d888d6b91d7fc3a08debfaf64f6fffa1b917 Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Thu, 12 Mar 2026 10:44:55 -0600 Subject: [PATCH] fix(extension): guard ctx.ui.theme access for RPC mode (#121) Theme proxy throws when accessed in RPC mode since initTheme() is never called without a TUI. Wrap header rendering in try/catch so the GSD extension loads cleanly in both TUI and RPC modes. Closes #121 Co-Authored-By: Claude Opus 4.6 --- src/resources/extensions/gsd/index.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/resources/extensions/gsd/index.ts b/src/resources/extensions/gsd/index.ts index b353b2917..066944c2b 100644 --- a/src/resources/extensions/gsd/index.ts +++ b/src/resources/extensions/gsd/index.ts @@ -158,14 +158,19 @@ export default function (pi: ExtensionAPI) { // ── session_start: render branded GSD header + remote channel status ── pi.on("session_start", async (_event, ctx) => { - const theme = ctx.ui.theme; - const version = process.env.GSD_VERSION || "0.0.0"; + // Theme access throws in RPC mode (no TUI) — header is decorative, skip it + try { + const theme = ctx.ui.theme; + const version = process.env.GSD_VERSION || "0.0.0"; - const logoText = GSD_LOGO_LINES.map((line) => theme.fg("accent", line)).join("\n"); - const titleLine = ` ${theme.bold("Get Shit Done")} ${theme.fg("dim", `v${version}`)}`; + const logoText = GSD_LOGO_LINES.map((line) => theme.fg("accent", line)).join("\n"); + const titleLine = ` ${theme.bold("Get Shit Done")} ${theme.fg("dim", `v${version}`)}`; - const headerContent = `${logoText}\n${titleLine}`; - ctx.ui.setHeader((_ui, _theme) => new Text(headerContent, 1, 0)); + const headerContent = `${logoText}\n${titleLine}`; + ctx.ui.setHeader((_ui, _theme) => new Text(headerContent, 1, 0)); + } catch { + // RPC mode — no TUI, skip header rendering + } // Notify remote questions status if configured try {