Skip to content

fix(terminal): sync PTY dimensions after restore to prevent autocomplete issues#909

Merged
Kitenite merged 1 commit into
mainfrom
terminal-bug-3
Jan 23, 2026
Merged

fix(terminal): sync PTY dimensions after restore to prevent autocomplete issues#909
Kitenite merged 1 commit into
mainfrom
terminal-bug-3

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Jan 22, 2026

Problem

Terminal autocomplete from zsh was overwriting lines and there were positioning issues when reattaching terminals.

Root Cause

When a terminal was attached/restored, createOrAttach was called with dimensions from an initial fitAddon.fit() that ran before the container was fully laid out by CSS. This resulted in wrong dimensions (e.g., 70 cols) being sent to the PTY.

After the terminal rendered, the ResizeObserver would eventually send the correct dimensions (e.g., 74 cols), but there was a ~140ms window where the PTY had incorrect dimensions. During this window, shell operations (prompts, autocomplete) would use wrong column counts, causing line wrapping issues.

Fix

Added an immediate resize call in scheduleFitAndScroll (in useTerminalRestore.ts) that sends the correct dimensions to the PTY right after fitAddon.fit() completes during restore. This ensures the PTY dimensions are synced with xterm.js dimensions before any user interaction can occur.

Changes

  • Add onResize callback parameter to the useTerminalRestore hook
  • Call onResize after fitAddon.fit() in scheduleFitAndScroll

Summary by CodeRabbit

  • Bug Fixes
    • Improved terminal restoration to synchronize terminal dimensions during session restore, preventing size/layout mismatches.
    • Maintains user scroll position for reattached sessions while ensuring new sessions scroll to the bottom after restoration.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 22, 2026

📝 Walkthrough

Walkthrough

This change adds an onResize callback into the terminal restoration flow and wires it so that after the terminal fits, the hook/component invokes the callback with updated columns and rows; the Terminal component forwards those dimensions (with paneId) to resizeRef.current.

Changes

Cohort / File(s) Summary
Terminal restore hook
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalRestore.ts
Added onResize(cols: number, rows: number) to UseTerminalRestoreOptions; stored in a ref and invoked after fit() to surface updated xterm dimensions during restoration.
Terminal component wiring
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
Forwarded restore-time dimensions to resizeRef.current as { paneId, cols, rows } using the new onResize callback path.

Sequence Diagram(s)

sequenceDiagram
  participant Terminal as Terminal Component
  participant Hook as useTerminalRestore
  participant Xterm as xterm (fit)
  participant Resizer as resizeRef / PTY

  Terminal->>Hook: initiate restore
  Hook->>Xterm: call fit()
  Xterm-->>Hook: updated cols, rows
  Hook->>Terminal: invoke onResize(cols, rows)
  Terminal->>Resizer: resizeRef.current({ paneId, cols, rows })
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • AviPeltz

Poem

🐰 A tiny hop, a gentle nudge—
Cols and rows line up in a trudge.
Restore completes, the sizes chime,
PTY and xterm now in time.
Rejoice, the terminal's snug! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: fixing PTY dimension synchronization after terminal restore to prevent autocomplete issues.
Description check ✅ Passed The description is well-structured with clear Problem, Root Cause, and Fix sections, but is missing required template sections like Related Issues and Type of Change.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…ete issues

When a terminal is attached/restored, createOrAttach was called with
dimensions from an initial fitAddon.fit() that ran before the container
was fully laid out by CSS. This caused a ~140ms window where the PTY had
incorrect dimensions, leading to:
- zsh autocomplete overwriting lines
- Weird positioning when reattaching terminals

The fix sends a resize to the PTY immediately after fit() completes in
scheduleFitAndScroll, ensuring dimensions are synced before any user
interaction.

Also fixes scroll-to-bottom timing by ensuring all pending xterm writes
are processed before scrolling. xterm.write() is async and buffers writes,
so scrollToBottom() called immediately might not see all content.

Also fixes unexpected scroll-to-bottom when switching tabs - now only
scrolls to bottom for new sessions, not reattached ones, preserving the
user's scroll position.

- Add onResize callback to useTerminalRestore hook
- Call onResize after fitAddon.fit() in scheduleFitAndScroll
- Use xterm.write('', callback) to flush writes before scrolling
- Only scroll to bottom for new sessions (result.isNew)
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalRestore.ts`:
- Around line 24-25: The onResize callback currently uses positional parameters
(cols: number, rows: number); change its signature to accept a single params
object { cols: number; rows: number } and update all call sites accordingly:
update the type/definition in useTerminalRestore.ts (onResize), change the
invocation inside useTerminalRestore (where onResize(...) is called) to pass an
object { cols, rows }, update the provider callback prop passed from
Terminal.tsx (where you supply onResize) to accept and forward an object, and
update the helper in helpers.ts (both its function signature and any internal
calls) to use and propagate { cols, rows } instead of positional args so all
usages conform to the object-params guideline.

Comment on lines +24 to +25
/** Callback to send resize to PTY after fit() - ensures PTY dimensions match xterm */
onResize: (cols: number, rows: number) => void;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and examine its content
cat -n apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalRestore.ts

Repository: superset-sh/superset

Length of output: 10639


🏁 Script executed:

# Search for all onResize usages across the codebase
rg -n 'onResize' --type ts --type tsx -B 2 -A 2

Repository: superset-sh/superset

Length of output: 91


🏁 Script executed:

# Search for all onResize usages with corrected rg syntax
rg 'onResize' --type ts -B 2 -A 2

Repository: superset-sh/superset

Length of output: 10561


🏁 Script executed:

# Search for useTerminalRestore usage to find where onResize callback is provided
rg 'useTerminalRestore' --type ts -B 2 -A 5

Repository: superset-sh/superset

Length of output: 4728


🏁 Script executed:

# Get context around Terminal.tsx onResize usage to see full implementation
rg -n 'onResize:' apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx -B 5 -A 1

Repository: superset-sh/superset

Length of output: 436


🏁 Script executed:

# Get helpers.ts function signature for onResize to understand full context
cat apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts | head -50

Repository: superset-sh/superset

Length of output: 2235


Use a params object for onResize to follow the object-params guideline.

The callback uses positional parameters (cols: number, rows: number) which conflicts with the coding guideline requiring object parameters for functions with 2+ parameters. Refactor to use { cols, rows } for clarity and consistency.

This requires coordinated updates across the Terminal module:

  • Interface definition in useTerminalRestore.ts (line 25)
  • Invocation in useTerminalRestore.ts (line 130)
  • Provider callback in Terminal.tsx (line 192)
  • Function signature and call site in helpers.ts
♻️ Proposed refactor
-	onResize: (cols: number, rows: number) => void;
+	onResize: (params: { cols: number; rows: number }) => void;
-	onResizeRef.current(xterm.cols, xterm.rows);
+	onResizeRef.current({ cols: xterm.cols, rows: xterm.rows });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/** Callback to send resize to PTY after fit() - ensures PTY dimensions match xterm */
onResize: (cols: number, rows: number) => void;
/** Callback to send resize to PTY after fit() - ensures PTY dimensions match xterm */
onResize: (params: { cols: number; rows: number }) => void;
🤖 Prompt for AI Agents
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalRestore.ts`
around lines 24 - 25, The onResize callback currently uses positional parameters
(cols: number, rows: number); change its signature to accept a single params
object { cols: number; rows: number } and update all call sites accordingly:
update the type/definition in useTerminalRestore.ts (onResize), change the
invocation inside useTerminalRestore (where onResize(...) is called) to pass an
object { cols, rows }, update the provider callback prop passed from
Terminal.tsx (where you supply onResize) to accept and forward an object, and
update the helper in helpers.ts (both its function signature and any internal
calls) to use and propagate { cols, rows } instead of positional args so all
usages conform to the object-params guideline.

@Kitenite Kitenite merged commit 7f5473d into main Jan 23, 2026
5 checks passed
@Kitenite Kitenite deleted the terminal-bug-3 branch January 23, 2026 06:30
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

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