From 5c0cc8e617159c21cfbf81a56ee02e27a45d73f2 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Tue, 11 Aug 2026 22:20:52 -0400 Subject: [PATCH] fix(tui): align running shell output (#41880) --- packages/tui/src/routes/session/index.tsx | 29 ++++++++++++++--------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx index a299458518..2f7ba5be6e 100644 --- a/packages/tui/src/routes/session/index.tsx +++ b/packages/tui/src/routes/session/index.tsx @@ -2826,10 +2826,15 @@ function Shell(props: ToolProps) { }) const maxLines = 10 const maxChars = createMemo(() => maxLines * Math.max(20, ctx.width - 6)) + const prompt = createMemo(() => (workdir() && workdir() !== "." ? `${workdir()}$` : "$")) const input = createMemo(() => { - if (!command()) return "" - const prompt = workdir() && workdir() !== "." ? `${workdir()}$ ` : isRunning() ? "" : "$ " - return `${prompt}${command()}` + const cmd = command() + if (!cmd) return "" + // While running, the workdir prompt shares the spinner's text column; when + // settled, the prompt renders as its own column so wrapped command lines + // keep a stable hanging indent instead of jumping to the card inset. + if (isRunning() && prompt() !== "$") return `${prompt()} ${cmd}` + return cmd }) const content = createMemo(() => [input(), output()].filter(Boolean).join("\n\n")) const collapsed = createMemo(() => collapseToolOutput(content(), maxLines, maxChars())) @@ -2837,6 +2842,8 @@ function Shell(props: ToolProps) { if (expanded() || !collapsed().overflow) return content() return collapsed().output }) + const limitedInput = createMemo(() => limited().slice(0, input().length)) + const limitedOutput = createMemo(() => limited().slice(Math.min(limited().length, input().length + 2))) const expandable = createMemo(() => Boolean(shellID()) || collapsed().overflow) const toggle = () => { const next = !expanded() @@ -2860,16 +2867,16 @@ function Shell(props: ToolProps) { - {limited().slice(0, input().length)} - {limited().slice(input().length)} - + + {prompt()} + {limitedInput()} + } > - - {limited().slice(0, input().length)} - {limited().slice(input().length)} - + {limitedInput()} + + + {limitedOutput()}