Skip to content

fix(terminal): clean profile/terminal startup under oh-my-posh#37

Open
kevmtt wants to merge 1 commit into
amirlehmam:masterfrom
kevmtt:fix/terminal-profile-rendering
Open

fix(terminal): clean profile/terminal startup under oh-my-posh#37
kevmtt wants to merge 1 commit into
amirlehmam:masterfrom
kevmtt:fix/terminal-profile-rendering

Conversation

@kevmtt

@kevmtt kevmtt commented Jun 17, 2026

Copy link
Copy Markdown

Fixes broken terminal/profile startup under oh-my-posh (PowerShell + PSReadLine): garbled prompt characters, a doubled prompt, and a slow first prompt.

Closes #36

Root causes & fixes

Symptom Root cause Fix
[?62;4;9;22c junk echoed on the prompt xterm image addon's DA1 reply does a slow renderer↔main round-trip and lands after the prompt → PSReadLine echoes it as input Answer DA1 in-process in PtyManager (instant); suppress xterm's own DA1 reply in useTerminal so there's no slow duplicate
Doubled prompt React StrictMode double-mount + async pty.has()pty.create() fired twice → two shells under one surfaceId PtyManager.create() is idempotent per surfaceId; IPC handler skips re-wiring a reused PTY
Doubled prompt (2nd cause) PTY spawned at 80×24 then resized → shell redraws prompt Spawn PTY at the measured size; drop redundant same-size resizes
Slow first prompt PR-polling Start-Job (spins a child runspace) ran during shell init Defer it to the shell's first idle
Quick-launch startup commands racing init queries startup commands injected as keystrokes after a fixed delay Bake them into shell init for PowerShell
xterm reading 'dimensions' crash async callbacks ran after terminal.dispose() (StrictMode) Guard callbacks with a disposed flag + cancel pending rAFs

Files

  • src/main/pty-manager.ts — in-process DA1 reply, idempotent create, spawn-at-size, same-size resize drop
  • src/main/ipc-handlers.ts — skip re-wiring reused PTYs
  • src/preload/index.tscols/rows in create options
  • src/renderer/hooks/useTerminal.ts — DA1 suppression, dispose guards, spawn-at-measured-size
  • src/shell-integration/wmux-powershell-integration.ps1 — deferred Start-Job, baked startup commands

Test plan

  • npm run build:main + tsc (main & renderer) clean; eslint 0 errors on changed files
  • Open a quick-launch profile under oh-my-posh → single clean prompt, no [?62;4;9;22c, no stall (verified via PTY trace: one shell-init sequence, one prompt render)
  • DA1 answered in-process (trace showed instant reply)
  • Sanity: normal tabs, split panes, tab switching, agent-spawned terminals still attach correctly

Notes

All temporary diagnostic instrumentation has been removed; only the fixes remain, each with an explanatory comment.

…t, stall

Opening a terminal (notably quick-launch profiles) under oh-my-posh showed
garbled text on the prompt, a slow/stalled first prompt, and a doubled prompt.
Root causes and fixes:

- DA1 query leak: the xterm image addon answers Device Attributes with
  \x1b[?62;4;9;22c through a slow renderer<->main round-trip, so the reply
  landed on the prompt and PSReadLine echoed it as typed input. It is now
  answered in-process in PtyManager (effectively instant), and xterm's own DA1
  reply is suppressed in useTerminal so there is no slow duplicate.

- Doubled prompt: React StrictMode double-mounts the terminal; the async
  pty.has() check let pty.create() fire twice for one surfaceId, spawning a
  second shell that also streamed to the renderer (and leaked an orphan).
  PtyManager.create() is now idempotent per surfaceId and the IPC handler skips
  re-wiring a reused PTY.

- Startup resize redraw: PTYs spawned at 80x24 then got resized, making the
  shell redraw its prompt. PTYs now spawn at the measured terminal size and
  redundant same-size resizes are dropped.

- Slow first prompt: the PR-polling Start-Job (spins up a child runspace) ran
  during shell init. It is now deferred to the shell's first idle.

- Quick-launch startup commands are baked into the shell's init for PowerShell
  instead of injected as keystrokes after a delay, avoiding a race with the
  shell's init-time terminal queries.

- Guard async terminal callbacks against use-after-dispose (StrictMode),
  fixing an xterm "reading 'dimensions'" crash from Viewport.syncScrollArea.
@kevmtt

kevmtt commented Jun 17, 2026

Copy link
Copy Markdown
Author

I'm honest here.. Many things I don't understood here, so I let AI add comments for me to understand. I left them in case they might be usefull.

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.

Terminal/profile startup glitches with oh-my-posh: DA escape leak, doubled prompt, slow first prompt

1 participant