From da8ff4a7b3a149172aa016c4fbca53ca94738526 Mon Sep 17 00:00:00 2001 From: Kan <25264536+kanlac@users.noreply.github.com> Date: Thu, 7 May 2026 02:24:52 +0800 Subject: [PATCH 1/2] fix(tmux): enforce sidebar width after pane close When a pane is killed, tmux redistributes window space and can shrink or grow the sidebar pane. The pane-exited handler already ran to clean up orphaned sidebars, but did not re-enforce the stored sidebar width. Call scheduleClientResizeSync() after the orphan cleanup so the sidebar is snapped back to its configured width, same as on a terminal resize. --- packages/runtime/src/server/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/runtime/src/server/index.ts b/packages/runtime/src/server/index.ts index 7718c8d..4e01287 100644 --- a/packages/runtime/src/server/index.ts +++ b/packages/runtime/src/server/index.ts @@ -2285,13 +2285,15 @@ export function startServer(mux: MuxProvider, extraProviders?: MuxProvider[], wa return new Response("ok", { status: 200 }); } - // pane-exited hook: a pane closed — kill orphaned sidebar panes + // pane-exited hook: a pane closed — kill orphaned sidebar panes and + // re-enforce sidebar width (tmux redistributes space when panes close) if (req.method === "POST" && url.pathname === "/pane-exited") { if (isSidebarVisible()) { invalidateSidebarPaneCache(); for (const { provider } of listSidebarPanesByProvider()) { provider.killOrphanedSidebarPanes(); } + scheduleClientResizeSync(); } return new Response("ok", { status: 200 }); } From c63932551b154a565f4a1594f2fb7d032df1d1c6 Mon Sep 17 00:00:00 2001 From: Kan <25264536+kanlac@users.noreply.github.com> Date: Thu, 7 May 2026 02:35:48 +0800 Subject: [PATCH 2/2] fix(tmux): replace pane-exited with after-kill-pane hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pane-exited is silently ignored by tmux 3.4+ — set-hook accepts it without error but show-hooks never lists it and it never fires. As a result, orphaned sidebar cleanup and post-kill width enforcement have never worked on modern tmux. Replace with after-kill-pane, which fires reliably after kill-pane. Also add after-kill-pane to HOOK_NAMES in tmux-sdk so the type is correct and cleanupHooks can unset it on shutdown. --- packages/mux/providers/tmux/src/provider.ts | 7 ++++--- packages/mux/tmux-sdk/src/index.ts | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/mux/providers/tmux/src/provider.ts b/packages/mux/providers/tmux/src/provider.ts index 55b2d3d..870404e 100644 --- a/packages/mux/providers/tmux/src/provider.ts +++ b/packages/mux/providers/tmux/src/provider.ts @@ -106,9 +106,10 @@ export class TmuxProvider implements MuxProviderV1, WindowCapable, SidebarCapabl tmux.setGlobalHook("after-new-window", ensureCmd); // client-resized: terminal window changed size — enforce stored width back tmux.setGlobalHook("client-resized", clientResizedCmd); - // pane-exited: a pane closed — kill orphaned sidebar panes (only pane left in window) + // after-kill-pane: a pane was killed — clean up orphaned sidebars and + // re-enforce width (pane-exited is not recognised by tmux 3.4+) const paneExitedCmd = hookPost("/pane-exited"); - tmux.setGlobalHook("pane-exited", paneExitedCmd); + tmux.setGlobalHook("after-kill-pane", paneExitedCmd); } cleanupHooks(): void { @@ -118,7 +119,7 @@ export class TmuxProvider implements MuxProviderV1, WindowCapable, SidebarCapabl tmux.unsetGlobalHook("after-select-window"); tmux.unsetGlobalHook("after-new-window"); tmux.unsetGlobalHook("client-resized"); - tmux.unsetGlobalHook("pane-exited"); + tmux.unsetGlobalHook("after-kill-pane"); } getAllPaneCounts(): Map { diff --git a/packages/mux/tmux-sdk/src/index.ts b/packages/mux/tmux-sdk/src/index.ts index 238a50b..d80988e 100644 --- a/packages/mux/tmux-sdk/src/index.ts +++ b/packages/mux/tmux-sdk/src/index.ts @@ -102,6 +102,7 @@ export const HOOK_NAMES = [ "window-layout-changed", "after-select-window", "after-new-window", + "after-kill-pane", "after-resize-pane", "pane-died", "pane-exited",