From feb7add71786d518d02a4611d78bc0b312c63375 Mon Sep 17 00:00:00 2001 From: Joakim Persson Date: Sat, 9 May 2026 16:31:20 +0200 Subject: [PATCH] ext-toggle: self-guard against disabling /ext Disabling ext-toggle through its own /ext UI would rename the file to ext-toggle.ts.off, which pi's auto-discovery skips, so the next /reload silently drops the /ext command itself. The .ts.off rename also persists across pi restarts and \u2014 in containerized setups (opencode-devbox) where ~/.pi is mounted on the devbox-pi-config named volume \u2014 across container recreate, so even nuking the container doesn't recover the surface. Add ext-toggle to the existing DISABLE_GUARDS map so the toggle is refused at stage-time with an explanation pointing at the manual recovery path: mv ~/.pi/agent/extensions/ext-toggle.ts.off \ ~/.pi/agent/extensions/ext-toggle.ts Same shape as the existing ssh-controlmaster guard. Sibling slash commands (/mcp from mcp-loader) don't need this guard because settings.json is their source of truth and remains editable by hand even if the loader is disabled \u2014 only ext-toggle's own UI is the single point of management. --- extensions/ext-toggle.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/extensions/ext-toggle.ts b/extensions/ext-toggle.ts index 3cc084d..0ffe385 100644 --- a/extensions/ext-toggle.ts +++ b/extensions/ext-toggle.ts @@ -58,6 +58,18 @@ const DISABLE_GUARDS: Record string | null> = { if (!hasSshFlag) return null; return "Active --ssh session — disabling would silently revert read/write/edit/bash to local. Exit pi and relaunch without --ssh."; }, + // ext-toggle owns the /ext slash command. Disabling it removes the + // only TUI surface for re-enabling itself: pi auto-discovers `*.ts` + // only, so once renamed to `.ts.off` the file is invisible to pi and + // the next /reload silently drops the command. The disabled state + // also persists — in containerized setups (opencode-devbox) the + // ~/.pi volume keeps the `.ts.off` rename across container recreate, + // so even nuking the container doesn't recover the surface. Recovery + // path is manual: shell into the container (or open a host shell), + // run `mv ~/.pi/agent/extensions/ext-toggle.ts.off \ + // ~/.pi/agent/extensions/ext-toggle.ts`, then /reload. + "ext-toggle": () => + "Disabling ext-toggle would remove the /ext command itself — only manual `mv ~/.pi/agent/extensions/ext-toggle.ts.off ~/.pi/agent/extensions/ext-toggle.ts` recovers it. Refusing.", }; // ── Filesystem helpers ────────────────────────────────────────────────────────