Repository navigation
Description
Confirmed present in v0.7.0-rc. Accepted for this release — cosmetic, and it self-corrects.
Symptom
On restore, the input line in a Claude pane is drawn about one character into the placeholder text, so the leading character of the placeholder survives (e.g. Thi there typed into Try "how do I log an error?"). Text elsewhere can also wrap oddly mid-line.
Resizing the window, or changing layout, fixes every pane immediately.
What we know
That resize detail is the clue. A resize fires the page's ResizeObserver → fitAddon.fit() → a new column count → term.onResize → the PTY is resized. So the correction is a column-count change, which means at startup xterm and the PTY disagree about the width. Claude wraps its placeholder at one column while xterm draws at another, and the offset follows.
What it is NOT — two theories already disproved
Recording these so nobody re-treads them:
- Font loading. fix(terminal): re-fit once the font has loaded, not on a timing guess #113 added a re-fit on
document.fonts.ready, on the theory that xterm measured the fallback font's advance width before Cascadia Code loaded. It was a no-op.document.fonts.readyresolves once at page load and stays resolved, so the callback ran immediately with the same metrics. document.fonts.load(). Also a no-op here: it only matches CSS-connectedFontFaceobjects, i.e.@font-facerules. There are none — the fonts in play are OS-installed — so it resolves having matched nothing.
The setTimeout(50) / setTimeout(250) fits in terminal-init.js are what currently correct the separate 0×0-container case, and they do not fix this.
Suggested next step: measure, don't theorise
Two guesses have already been wrong. The decisive probe is small — log both sides and compare:
- In
terminal-init.js, on everyfit()and everyterm.onResize, log the resultingcols/rows. - In
TerminalBridge, log thecols/rowsthe PTY is actually set to, with the session name.
If they diverge, the log shows exactly when and which side is stale. If they agree, the cause is elsewhere and both remaining theories die.
One specific thing worth checking in that data: term.onResize only fires when dimensions change. If the PTY is started from a stale TerminalSize and a later fit() happens to compute the same cols xterm already had, no resize message is sent and the PTY keeps the wrong width indefinitely — which would match "only an external resize fixes it".
Related
- fix(terminal): re-fit once the font has loaded, not on a timing guess #113 — the attempted fix, kept because it does no harm, but it does not address this.
- The
0x0container case that thesetTimeoutfits cover is a different problem with a similar symptom; don't conflate them.
Activity
AThraen commentedon Sep 6, 2026
Update: the attempted fix from #113 is gone from the code too
#115 replaced the
document.fonts.readyre-fit with arequestAnimationFrameone (Assets/terminal-init.js:114-124, comment preserved in place). So theory 1 in this issue is now disproved and removed — nobody reading the source will find a fonts-based fit and assume the case is handled.The current fit sites, for whoever picks this up:
terminal-init.js:33:79ResizeObserver:94-95focus/fitmessages:110-124setOptions, then again on the nextrequestAnimationFrame:270mousedown(the capture-phase activate handler):276-277setTimeout50ms / 250ms — these are what correct the separate 0×0-container case:294-296document.fonts.readyfit; harmless, and per the above it resolves immediatelyThe suggested next step in the issue body is unchanged and is still the right one: log
cols/rowson everyfit()and everyterm.onResize, and log whatTerminalBridgeactually sets the PTY to, with the session name. Two theories have now been wrong; the third guess should be a measurement.The specific hypothesis worth testing first remains the one about
onResizefiring only on change: if the PTY is started from a staleTerminalSizeand a laterfit()computes the samecolsxterm already had, no resize message is sent and the PTY keeps the wrong width indefinitely — which is exactly the shape of "only an external resize fixes it".Still present, still cosmetic, still self-correcting on any resize.
AThraen commentedon Sep 9, 2026
Related: #134 — a separate, coarser startup render bug (Claude panes garbled, rows colliding/duplicated, corrected by a repaint). Filed separately per this issue's own warning not to conflate the one-char offset with the similar-symptom 0×0 case.
The two do share one mechanism, and it's the trap named in this issue:
term.onResizefires only when dimensions change, so a latefit()that recomputes the same wrongcolsposts nothing and the PTY keeps its stale width. #134 argues that's the root pathology rather than a detail, and that the logging proposed here (both sides'cols/rows) should land first since it would confirm both issues at once.#134 also found that
FitTerminal()is only called on attach in theSinglelayout branch — every multi-pane branch attaches wrappers with no fit — which would explain why this reproduces on restore into a multi-pane layout.