iTerm2 viewport jumps to top when a long rich-output response completes
What version of Codex CLI is running?
codex-cli 0.147.0
What subscription do you have?
API key authentication through a custom Responses-compatible provider.
Which model were you using?
gpt-5.6-sol
What platform is your computer?
Darwin 25.5.0 arm64 arm
macOS 26.5.2 (Build 25F84)
What terminal emulator and version are you using?
iTerm2 3.6.11
TERM=xterm-256color
Terminal size during codex doctor: 80x24
No tmux, screen, or zellij
The following iTerm2 settings are already enabled:
- Save lines to scrollback in alternate screen mode
- Save lines to scrollback when an app status bar is present
Codex doctor report
Relevant redacted fields from codex doctor --json:
{
"overallStatus": "warning",
"codexVersion": "0.147.0",
"runtime": {
"platform": "macos-aarch64",
"installMethod": "npm"
},
"terminal": {
"name": "iTerm2",
"version": "3.6.11",
"term": "xterm-256color",
"size": "80x24"
},
"config": {
"terminal_resize_reflow": "enabled",
"raw_output_mode": false
},
"auth": {
"mode": "api_key",
"provider": "custom Responses-compatible provider"
}
}
The full report contained local filesystem paths and provider details, so those fields were redacted.
What issue are you seeing?
While a long assistant response is streaming, I scroll upward in iTerm2 to inspect earlier output. When the response finishes, the terminal viewport jumps to the top of the replayed transcript instead of preserving the position I was reading.
This is reproducible in rich output mode. It still happens when the response contains no Markdown pipe table and no Markdown hard-break trailing spaces.
The same workflow did not jump in my /raw on test.
Observed A/B results:
- Rich output with a long Markdown pipe table: viewport jumped upward or to the top.
- Rich output without any pipe table: viewport still jumped to the top.
/raw on: no viewport jump in the same manual scrolling workflow.
Thread ID: 019fe996-b190-79f0-9d87-c88516253b3c
What steps can reproduce the bug?
- Start Codex CLI in iTerm2 with the default rich output mode. Confirm
/raw off. - Ask Codex to produce a long Markdown response containing headings, blockquotes, lists, fenced code blocks, and enough lines to exceed the terminal height. Do not include a Markdown pipe table.
- While the response is still streaming, scroll upward and remain above the latest output.
- Wait for the response to finish.
- Observe that iTerm2 jumps to the top of the replayed transcript.
- Run
/raw onand repeat with another long response. - Observe that the viewport remains where the user was reading in the raw-mode test.
What is the expected behavior?
Completing an assistant response should preserve the user's current scrollback viewport anchor. Codex should not force the viewport to the beginning or latest output when the user has manually scrolled away from the live tail.
If transcript consolidation requires replaying rendered history, it should avoid purging terminal scrollback or should explicitly restore the previous viewport anchor afterward.
Additional information
This appears related to #22936, but that report is for WSL and Windows Terminal. This report reproduces the same symptom on macOS and iTerm2 and adds a rich-mode versus raw-mode comparison.
The rust-v0.147.0 source has two completion-time paths that can require transcript reflow:
chatwidget/streaming.rs:26-43selectsConsolidationScrollbackReflow::Requiredwhenhad_live_tailorcompleted_message_differsis true.resize_reflow.rs:267-277clears the visible screen and, outside the alternate screen, clears scrollback before resettingviewport_area.yto zero.resize_reflow.rs:469-479clears pending history, clears the terminal, and then re-inserts reflowed transcript lines.
Raw mode only forces the Markdown table tail budget to zero in streaming/controller.rs:392-404. It does not disable the completed_message_differs reflow path. Therefore, the successful raw-mode test is useful evidence but does not yet isolate whether the rich-mode reproduction came from a completion difference or a resize reflow that ran during streaming.
A useful regression test would simulate a user-scrolled viewport, finalize a long rich-output stream, and assert that transcript consolidation does not emit destructive scrollback clearing or reset the user's viewport anchor.
2 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
This is the completion-time transcript reflow family, seen from the scroll-position angle. On finalize, rich mode may replace the streamed cells with the final Markdown cell and — whenever the streamed source doesn't byte-match the completed message — force a full scrollback rebuild that starts with
CSI 2J/3J(purge scrollback + clear screen). A scrollback purge unavoidably destroys the terminal's scroll position, so iTerm2 lands you at the top of the replayed transcript./raw onnever takes the consolidation path, which is why it doesn't jump — your A/B matches exactly.Two adjacent analyses cover the mechanics and fixes:
Worth stating plainly for this issue: scroll position cannot be preserved across a
3Jpurge — no repaint strategy fixes that. The only real fix is not running the destructive reflow when the rendered transcript didn't change, i.e. the rendered-lines comparison proposed in #37759. Your no-table/no-hard-break reproduction is useful evidence that the byte-compare mismatches on even more content shapes than documented there.