TUI resume main view shows partial transcript when `terminal_resize_reflow_max_rows` is capped

Open 💬 6 comments Opened May 8, 2026 by BHSDuncan

What version of Codex CLI is running?

0.129.0

What subscription do you have?

Pro

Which model were you using?

gpt-5.5

What platform is your computer?

Darwin 23.6.0 arm64 arm

What terminal emulator and version are you using (if applicable)?

zsh/oh-my-zsh

What issue are you seeing?

When resuming a long TUI session, the main resumed view can show only a partial transcript, making it look like most of the session history was lost.

In my case, thread/resume returns the full session history and Ctrl+T opens the full transcript, so the data is loaded correctly; however, the normal main TUI view after codex resume only shows the first prompt/partial history.

The issue appears tied to tui.terminal_resize_reflow_max_rows. Setting tui.terminal_resize_reflow_max_rows=0 makes the full transcript appear in the main resumed view.

What steps can reproduce the bug?

  1. Have a long Codex session with more transcript rows than the resize-reflow row cap.
  2. Resume it with default TUI settings.
  3. Main TUI view shows only an early/partial portion of the transcript, making history appear missing.
  4. Press Ctrl+T and the full transcript is present.
  5. Resume with -c tui.terminal_resize_reflow_max_rows=0 and the full transcript appears in the main view.

What is the expected behavior?

After codex resume, the main TUI view should not make the transcript appear lost or truncated when the full transcript is available.

If row-capping is applied during initial replay, the UI should either show the most useful recent tail of the transcript, clearly indicate that older transcript rows were omitted from the main terminal scrollback buffer, or otherwise keep the main view consistent with the full transcript available through Ctrl+T.

Additional information

  • thread/resume returns all turns for the session, so persistence/resume loading is correct.
  • The issue appears isolated to initial history replay / resize-reflow row cap in the main TUI scrollback.

View original on GitHub ↗

6 Comments

oxysoft · 3 months ago

Related: #21945 traces the root cause of why the reflow cap exists in the first place — the transcript overlay and reflow path have O(n) rendering that scales linearly with session length (full markdown re-parse per cell, no height caching, no virtualization). The partial transcript you're seeing when the cap is active is the band-aid; the underlying issue is that uncapped reflow walks and re-renders every cell from scratch.

Necmttn · 2 months ago

The main resumed view should expose the render cap as a display state.

If thread/resume loaded the full transcript but terminal_resize_reflow_max_rows limits visible rows, show a small status like full transcript loaded, main view capped at N rows with a jump/open-full-transcript action. That avoids confusing a performance guard with missing history.

---

_Generated with ax._

Josephur · 12 days ago

I reproduced the same visible-transcript/model-context split on Linux with codex-cli 0.147.0.

Environment:

  • Ubuntu 26.04 LTS, Linux 7.0.0-29-generic, x86_64
  • SSH terminal, TERM=xterm-256color
  • No explicit tui.terminal_resize_reflow_max_rows setting (therefore the default applies)
  • Long, heavily compacted session

Trigger:

  1. Continue a long session through several recent user/assistant turns.
  2. Reboot the host while/after Codex initiates the requested reboot.
  3. Relaunch Codex and resume the same session.

Observed:

  • The main TUI transcript replay ends at older conversation content rather than showing the actual newest turns before reboot.
  • The resumed agent nevertheless retains the omitted turns: when asked what it last remembered, it accurately described the NVIDIA driver update, restored nvtop/python NVML packages, and reboot request that were absent from the displayed replay.
  • No resume error or warning is shown.

This strongly suggests the rollout/model context is intact while the initial human-facing TUI replay is selecting or rendering the wrong/older slice. The useful invariant here is that the newest model-visible turn and newest TUI-visible turn diverge. Expected: even when replay is row-capped, the main view should include the newest completed tail, never only an older slice.

shleder · 11 days ago

This is a useful healthy-persistence control for codex-rescue: thread/resume has the full history and the model retains the omitted turns, while only the main TUI replay looks truncated. Rescue should therefore avoid diagnosing session corruption from the human-facing display symptom.

If you still have an affected long session, could you run:

pipx install codex-rescue
codex-rescue sessions
codex-rescue doctor --latest

A healthy/no-damage result is the expected useful outcome. I’m also interested in whether sessions identifies the correct latest durable thread despite the TUI showing an older slice. No salvage is needed for this control case.

Please share sanitized output, versions and exit codes only—no raw rollouts/SQLite, prompts, credentials, or private paths. Repo: https://github.com/shleder/codex-rescue

Loong0x00 · 3 days ago

I reproduced a stronger variant of this on Linux with a long paginated thread: the capped main view did not merely omit older history; it settled inside an older oversized tool output and hid the actual newest semantic tail.

Environment

  • Arch Linux x86_64
  • Terminal size: 307x68
  • Codex CLI: 0.149.0, built from the exact rust-v0.149.0 tag with one scoped local change in the rollout ordinal decoder; the TUI/history hydration code is unchanged from the tag
  • Thread history mode: paginated

Observed behavior

After codex resume <thread-id>, the TUI reached Ready, but the visible main transcript consisted of an interior fragment of an older package-manager command output. That persisted command output is about 1.16 MB and belongs to an interrupted turn several turns before the true tail.

The latest user/assistant turns were not visible in the main view. This made the resumed thread look as if it had reopened at an old operation, even though the backend had loaded the current history.

Healthy-persistence controls

Read-only checks showed no rollout or projection loss:

  • the current rollout contained 2,002/2,002 valid JSONL records;
  • SQLite PRAGMA quick_check returned ok;
  • thread/read(includeTurns: true) reconstructed 99 turns in chronological order;
  • default thread/resume also returned all 99 compatibility turns;
  • the newest two returned turns were the actual newest persisted turns;
  • a descending initialTurnsPage likewise returned the newest turns first;
  • the rollout SHA-256 and mtime were unchanged by the inspection.

So this is a human-facing initial replay/materialization error, not stale durable history and not model-context loss.

Boundary evidence

The 0.149 TUI uses bounded paginated hydration and a terminal-dependent initial replay row budget (1,000 rows in this environment). The first descending item page contained the current tail. The next page reached the older 1.16 MB commandExecution output; that single cell was sufficient to exhaust the row budget. The resulting main-view replay landed inside that tool output rather than preserving the newer semantic tail below it.

This appears to be the same family as #40345, but with a large tool-output cell rather than one long user-message cell. It is also distinct from durable projection failures: both app-server resume/read paths returned the correct latest turns here.

Expected behavior

When initial replay is capped:

  1. The newest user/assistant tail must always remain visible.
  2. The cap should be applied at atomic transcript-cell or turn boundaries, never inside one tool-output cell.
  3. A single oversized tool output should be collapsed to an explicit placeholder in the main view rather than consuming the entire replay budget.
  4. The UI should state that the main view is capped while the full transcript remains available.

No thread IDs, transcript text, local paths, account data, or raw rollout contents are included here.

Loong0x00 · 1 day ago

Fresh recurrence after a machine reboot, with a tighter control for wrong-thread selection:

  • Codex CLI 0.149.0 on Arch Linux, paginated history.
  • The TUI issued thread/resume for the intended newest thread ID. App-server logs tie that exact ID to the resume request.
  • The raw rollout was 16,786,181 bytes and its final semantic message was the expected latest assistant message.
  • The projection cursor exactly matched rollout EOF (next_rollout_byte_offset = 16,786,181, next_rollout_ordinal = 20,161), with 966 projected items and 21 turns; both state and history databases passed PRAGMA quick_check.
  • Nevertheless, the reopened main view appeared to the user at older transcript content rather than the latest tail.

This rules out both a stale projection and accidentally resuming a parent/older thread in this recurrence. It is specifically: correct thread ID + correct durable EOF + incorrect initial visible transcript after resume/reboot.

The local build still differs from the 0.149.0 tag only in a scoped rollout-ordinal decoder fix; TUI pagination/reflow code is unchanged.