Skip to content

VSCode terminals: TUI render artifacts on first open — initial Pseudoterminal dimensions are ignored #737

@amrmelsayed

Description

@amrmelsayed

Symptom

When opening an architect or builder terminal in VSCode (Codev extension), Claude Code's TUI renders with overlapping content: the streaming response and the input box's cursor occupy the same screen region, producing artifacts like a cursor block (`▌`) appearing in the middle of transcript text.

The artifact disappears immediately if the user resizes the VSCode terminal panel by even one pixel.

Reproduction

  1. Open VSCode in a Codev workspace
  2. Open the architect terminal (sidebar click, command palette, or keybinding)
  3. Have Claude Code stream a response longer than ~24 lines
  4. Observe: streaming content and input-box cursor render on top of each other

Resizing the panel after the artifact appears clears it.

Root cause

`packages/vscode/src/terminal-adapter.ts:37-44` — the `open()` callback receives `initialDimensions` from VSCode but discards them (parameter is prefixed `_`):

```ts
open(_initialDimensions: vscode.TerminalDimensions | undefined): void {
this.writeEmitter.fire('');
this.connect();
}
```

Consequence:

  1. Tower spawns the PTY at `node-pty`'s default (80×24)
  2. VSCode renders the terminal at the real panel size (e.g. 200×60)
  3. Claude Code queries PTY size → gets 80×24
  4. Claude Code anchors its input box at row 24
  5. Streaming transcript flows past row 24
  6. In the real 60-row xterm viewport, input box and transcript collide

`setDimensions()` only fires on subsequent resizes, not on initial open — so the desync persists until the user manually nudges the panel.

Fix sketch

In `open()`, store `initialDimensions`. In `ws.on('open')` after auth is sent, call `sendResize(cols, rows)` if initial dimensions are set. Keep the existing `replaying` guard so resume-from-replay still defers correctly.

~10 LOC change in `packages/vscode/src/terminal-adapter.ts`.

Test

Unit: assert that `sendResize` is invoked once on WebSocket open when `open()` was called with non-null dimensions.

Manual: open a fresh terminal at a non-default panel size, stream >24 lines of content, confirm no overlap without resizing.

Scope

AIR — single-file bugfix, no spec/plan needed.

References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions