Skip to content

fix(terminal): rejoin user prompts the PTY wrapped with an indent - #672

Open
RonenMars wants to merge 1 commit into
mainfrom
fix/terminal-wrapped-prompt-collapse
Open

fix(terminal): rejoin user prompts the PTY wrapped with an indent#672
RonenMars wants to merge 1 commit into
mainfrom
fix/terminal-wrapped-prompt-collapse

Conversation

@RonenMars

Copy link
Copy Markdown
Owner

Problem

A long prompt renders in the terminal view as two unrelated transcript lines, split mid-sentence.

The split itself is not ours to remove: the streamer spawns the PTY at a fixed PTY_COLS = 120 with no resize protocol, so Claude Code word-wraps its own render at 120 columns and emits each wrapped row separately.
lib/collapseWrappedUserLines.ts exists precisely to stitch those rows back together using the user_message text the streamer sends as ground truth, and it silently failed to fire.

Verified state

Measured against the reported session on 2026-08-12: the first row is plus 116 characters = 118 columns, and continuing with the next word would need 122 — over 120, so the CLI wrapped and indented the continuation row.

Two whitespace holes stopped the rejoin, both reproduced before the fix:

  • collapseWrappedUserLines.ts:34 joined rows with ' ' + lines[j] untrimmed, but VirtualTerminal.getRawLines() only trimEnd()s — the continuation row's leading indent survived into the joined string and broke the exact-string comparison.
  • collapseWrappedUserLines.ts:23 matched the prefix against the untrimmed row, so any left padding on the prompt row stopped the collapse before it started. isUserLine in TerminalOutput.tsx:39 trims first, so the two disagreed about what a user row is.

Neither shape was covered — every fixture in the existing suite used unindented continuation rows.

Change

Compare joined rows against the ground truth on collapsed whitespace, and match the prompt prefix on the trimmed row.
The collapsed row now emits the ground-truth string verbatim instead of the space-joined reconstruction, which also restores prompts that were typed with newlines — broken before for the same reason.

Deliberately unchanged: PTY_COLS stays at 120, and wrapping of non-user output (tool results, trees, tables) is still left alone, since the rejoin only engages on an exact user_message match.

Tests

Three regression cases added — indented continuation row (using the reported prompt verbatim), left-padded prompt row, and a newline-bearing prompt.

npx jest --ci --runInBand __tests__/unit/lib/collapseWrappedUserLines.test.ts → 10 passed.
npx jest --ci --runInBand --testPathPattern "TerminalOutput|TerminalView" → 26 passed.
npx tsc --noEmit clean on the changed files, npx eslint clean.

The streamer spawns the PTY at a fixed 120 columns, so Claude Code word-wraps a long prompt across rows and indents each continuation row.
collapseWrappedUserLines joined those rows with a single space and compared the result to the user_message ground truth as an exact string, so the surviving indent made the match fail and the prompt rendered as two unrelated transcript lines.
Compare on collapsed whitespace instead, and match the prompt prefix on the trimmed row so left padding on the row carrying the chevron does not stop the collapse before it starts.
The collapsed row now emits the ground-truth string verbatim rather than the space-joined reconstruction, which also restores prompts that were typed with newlines.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant