Skip to content

On resume, TUI repeatedly repaints terminal scrollback during paginated history refill #37635

Description

@astral303

What version of Codex CLI is running?

0.148.0-alpha.5

What subscription do you have?

Pro 20x

Which model were you using?

n/a, reproducible w/o any model interaction

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

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

Windows Terminal, Version: 1.24.11911.0

Codex doctor report

{
  "schemaVersion": 1,
  "generatedAt": "1786228035s since unix epoch",
  "overallStatus": "ok",
  "codexVersion": "0.148.0-alpha.5",
  "checks": {
    "app_server.status": {
      "id": "app_server.status",
      "category": "app-server",
      "status": "ok",
      "summary": "background server is not running",
      "details": {
        "control socket": "C:\\Users\\micro\\.codex\\app-server-control\\app-server-control.sock",
        "daemon state dir": "C:\\Users\\micro\\.codex\\app-server-daemon",
        "mode": "ephemeral",
        "pid file": "C:\\Users\\micro\\.codex\\app-server-daemon\\app-server.pid (missing)",
        "settings": "C:\\Users\\micro\\.codex\\app-server-daemon\\settings.json (missing)",
        "status": "not running",
        "update-loop pid file": "C:\\Users\\micro\\.codex\\app-server-daemon\\app-server-updater.pid (missing)"
      },
      "remediation": null,
      "durationMs": 0
    },
    "auth.credentials": {
      "id": "auth.credentials",
      "category": "auth",
      "status": "ok",
      "summary": "auth is configured",
      "details": {
        "auth file": "C:\\Users\\micro\\.codex\\auth.json",
        "auth storage mode": "File",
        "stored API key": "false",
        "stored ChatGPT tokens": "true",
        "stored agent identity": "false",
        "stored auth mode": "chatgpt"
      },
      "remediation": null,
      "durationMs": 0
    },
    "config.load": {
      "id": "config.load",
      "category": "config",
      "status": "ok",
      "summary": "config loaded",
      "details": {
        "CODEX_HOME": "C:\\Users\\micro\\.codex",
        "config.toml": "C:\\Users\\micro\\.codex\\config.toml",
        "config.toml parse": "ok",
        "cwd": "C:\\Users\\micro\\Documents\\projects\\subaru-ecu-research",
        "enabled feature flags": "<redacted>",
        "feature flag overrides": "none",
        "feature flags enabled": "39",
        "log dir": "C:\\Users\\micro\\.codex\\log",
        "mcp servers": "5",
        "model": "gpt-5.6-sol",
        "model provider": "openai",
        "sqlite home": "C:\\Users\\micro\\.codex"
      },
      "remediation": null,
      "durationMs": 0
    },
    "git.environment": {
      "id": "git.environment",
      "category": "git",
      "status": "ok",
      "summary": "git version 2.55.0.windows.2",
      "details": {
        ".git entry": "directory",
        "PATH git #1": "C:\\Program Files\\Git\\cmd\\git.exe",
        "PATH git entries": "1",
        "git branch": "main",
        "git build options": "git version 2.55.0.windows.2; cpu: x86_64; built from commit: c8dff95af823bd04181a583c03f3fbb954551c30; sizeof-long: 4; sizeof-size_t: 8; shell-path: D:/git-sdk-64-build-installers/usr/bin/sh; rust: disabled; feature: fsmonitor--daemon; gettext: enabled; libcurl: 8.21.0; OpenSSL: OpenSSL 3.5.7 9 Jun 2026; zlib: 1.3.2; SHA-1: SHA1_DC; SHA-256: SHA256_BLK; default-ref-format: files; default-hash: sha1",
        "git exec path": "C:/Program Files/Git/mingw64/libexec/git-core",
        "git version": "git version 2.55.0.windows.2",
        "repo detected": "true",
        "repo root": "C:\\Users\\micro\\Documents\\projects\\subaru-ecu-research",
        "selected git": "C:\\Program Files\\Git\\cmd\\git.exe"
      },
      "remediation": null,
      "durationMs": 82
    },
    "installation": {
      "id": "installation",
      "category": "install",
      "status": "ok",
      "summary": "installation looks consistent",
      "details": {
        "PATH codex #1": "C:\\Users\\micro\\AppData\\Local\\Programs\\OpenAI\\Codex\\bin\\codex.exe",
        "current executable": "C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\bin\\codex.exe",
        "install context": "other (package C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5, bin C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\bin, resources C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\codex-resources, path C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\codex-path)",
        "managed by bun": "false",
        "managed by npm": "false",
        "managed by pnpm": "false",
        "managed package root": "not set"
      },
      "remediation": null,
      "durationMs": 45
    },
    "mcp.config": {
      "id": "mcp.config",
      "category": "mcp",
      "status": "ok",
      "summary": "MCP configuration is locally consistent",
      "details": {
        "configured servers": "5",
        "disabled servers": "4",
        "stdio servers": "1",
        "streamable_http servers": "4"
      },
      "remediation": null,
      "durationMs": 38
    },
    "network.env": {
      "id": "network.env",
      "category": "network",
      "status": "ok",
      "summary": "network-related environment looks readable",
      "details": {
        "proxy env vars": "none"
      },
      "remediation": null,
      "durationMs": 0
    },
    "network.provider_reachability": {
      "id": "network.provider_reachability",
      "category": "reachability",
      "status": "ok",
      "summary": "active provider endpoints are reachable over HTTP",
      "details": {
        "ChatGPT base URL": "https://chatgpt.com/backend-api/ reachable (HTTP 403)",
        "reachability mode": "ChatGPT auth"
      },
      "remediation": null,
      "durationMs": 92
    },
    "network.websocket_reachability": {
      "id": "network.websocket_reachability",
      "category": "websocket",
      "status": "ok",
      "summary": "Responses WebSocket handshake succeeded",
      "details": {
        "DNS": "2 IPv4, 0 IPv6, first IPv4",
        "auth mode": "chatgpt",
        "connect timeout": "15000 ms",
        "endpoint": "wss://chatgpt.com/backend-api/<redacted>",
        "handshake result": "HTTP 101 Switching Protocols",
        "model provider": "openai",
        "models etag present": "true",
        "provider name": "OpenAI",
        "proxy env vars": "none",
        "reasoning header": "false",
        "server model present": "false",
        "supports websockets": "true",
        "wire API": "responses"
      },
      "remediation": null,
      "durationMs": 662
    },
    "runtime.provenance": {
      "id": "runtime.provenance",
      "category": "runtime",
      "status": "ok",
      "summary": "running local build on windows-x86_64",
      "details": {
        "commit": "unknown",
        "current executable": "C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\bin\\codex.exe",
        "install method": "other (package C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5, bin C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\bin, resources C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\codex-resources, path C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\codex-path)",
        "platform": "windows-x86_64",
        "version": "0.148.0-alpha.5"
      },
      "remediation": null,
      "durationMs": 0
    },
    "runtime.search": {
      "id": "runtime.search",
      "category": "search",
      "status": "ok",
      "summary": "search is OK (bundled)",
      "details": {
        "search command": "C:\\Users\\micro\\AppData\\Local\\Temp\\codex-official-0.148.0-alpha.5\\codex-path\\rg.exe",
        "search command readiness": "file exists",
        "search provider": "bundled"
      },
      "remediation": null,
      "durationMs": 0
    },
    "sandbox.helpers": {
      "id": "sandbox.helpers",
      "category": "sandbox",
      "status": "ok",
      "summary": "sandbox configuration is readable",
      "details": {
        "approval policy": "OnRequest",
        "codex-linux-sandbox helper": "none",
        "execve wrapper helper": "none",
        "filesystem sandbox": "restricted",
        "network sandbox": "restricted"
      },
      "remediation": null,
      "durationMs": 0
    },
    "state.paths": {
      "id": "state.paths",
      "category": "state",
      "status": "ok",
      "summary": "state paths and databases are inspectable",
      "details": {
        "CODEX_HOME": "C:\\Users\\micro\\.codex (dir)",
        "active rollout files": "309 files, 1408771752 total bytes, 4559131 average bytes",
        "archived rollout files": "0 files, 0 total bytes, 0 average bytes",
        "goals DB": "C:\\Users\\micro\\.codex\\goals_1.sqlite (file)",
        "goals DB integrity": "ok",
        "log DB": "C:\\Users\\micro\\.codex\\logs_2.sqlite (file)",
        "log DB integrity": "ok",
        "log dir": "C:\\Users\\micro\\.codex\\log (missing)",
        "memories DB": "C:\\Users\\micro\\.codex\\memories_1.sqlite (file)",
        "memories DB integrity": "ok",
        "queue DB": "C:\\Users\\micro\\.codex\\queue_1.sqlite (file)",
        "queue DB integrity": "ok",
        "sqlite home": "C:\\Users\\micro\\.codex (dir)",
        "state DB": "C:\\Users\\micro\\.codex\\state_5.sqlite (file)",
        "state DB integrity": "ok",
        "thread history DB": "C:\\Users\\micro\\.codex\\thread_history_1.sqlite (file)",
        "thread history DB integrity": "ok"
      },
      "remediation": null,
      "durationMs": 1164
    },
    "state.rollout_db_parity": {
      "id": "state.rollout_db_parity",
      "category": "threads",
      "status": "ok",
      "summary": "rollout files and state DB thread inventory agree",
      "details": {
        "default model provider": "openai",
        "rollout DB active files": "309",
        "rollout DB active rows": "309",
        "rollout DB archive mismatches": "0",
        "rollout DB archived files": "0",
        "rollout DB archived rows": "0",
        "rollout DB duplicate DB paths": "0",
        "rollout DB duplicate rollout thread ids": "0",
        "rollout DB malformed file names": "0",
        "rollout DB missing active rows": "0",
        "rollout DB missing archived rows": "0",
        "rollout DB model providers": "openai=309",
        "rollout DB rows": "309",
        "rollout DB scan cap reached": "false",
        "rollout DB scan errors": "0",
        "rollout DB sources": "subagent:thread_spawn=199, subagent:other=62, cli=47, unknown=1",
        "rollout DB stale rows": "0"
      },
      "remediation": null,
      "durationMs": 224
    },
    "system.environment": {
      "id": "system.environment",
      "category": "system",
      "status": "ok",
      "summary": "OS language en-US",
      "details": {
        "EDITOR": "set",
        "PAGER": "set",
        "VISUAL": "not set",
        "os": "Windows 10.0.26200 (Windows 11 Professional) [64-bit]",
        "os language": "en-US",
        "os type": "Windows",
        "os version": "10.0.26200"
      },
      "remediation": null,
      "durationMs": 0
    },
    "terminal.env": {
      "id": "terminal.env",
      "category": "terminal",
      "status": "ok",
      "summary": "terminal metadata was detected",
      "details": {
        "COLORTERM": "truecolor",
        "WT_SESSION": "present",
        "color output": "disabled (stdout is not a terminal)",
        "console input code page": "437",
        "console output code page": "437",
        "stderr console mode": "0x00000007 (VT processing: true)",
        "stderr is terminal": "true",
        "stdin is terminal": "true",
        "stdout console mode": "unavailable",
        "stdout is terminal": "false",
        "terminal": "Windows Terminal",
        "terminal size": "156x36"
      },
      "remediation": null,
      "durationMs": 0
    },
    "terminal.title": {
      "id": "terminal.title",
      "category": "title",
      "status": "ok",
      "summary": "terminal title default",
      "details": {
        "terminal title activity": "true",
        "terminal title items": "activity, project-name",
        "terminal title project source": "git repo root",
        "terminal title project value": "subaru-ecu-research",
        "terminal title source": "default"
      },
      "remediation": null,
      "durationMs": 0
    },
    "updates.status": {
      "id": "updates.status",
      "category": "updates",
      "status": "ok",
      "summary": "update configuration is locally consistent",
      "details": {
        "cached latest version": "0.147.0",
        "check for update on startup": "true",
        "last checked at": "2026-08-08T16:38:58.645428900Z",
        "latest version": "0.147.0",
        "latest version status": "current version is not older",
        "update action": "manual or unknown",
        "version cache": "C:\\Users\\micro\\.codex\\version.json"
      },
      "remediation": null,
      "durationMs": 356
    }
  }
}

What issue are you seeing?

Resuming a sufficiently long paginated thread causes the normal inline TUI to clear and repaint terminal scrollback several times while older history pages load in the background. Each repaint becomes progressively slower as the retained history grows.

In one recording, a long thread produced about eight visible repaint cycles; a shorter thread produced four. The Ctrl+T transcript view is not involved.

Image

What steps can reproduce the bug?

  1. Use a saved thread whose history exceeds the initial bounded resume hydration.
  2. Use the default terminal_resize_reflow.max_rows = "auto" setting, or another nontrivial terminal scrollback row budget.
  3. Exit Codex, so you can start a new Codex process.
  4. Resume the thread with codex resume <thread-id> or through the resume picker.
  5. Keep the TUI in its normal inline view while older history loads.
  6. Bug: Observe repeated clear-and-repaint cycles, with later cycles taking longer.

Thread used for the recording: 019fde95-870b-7c33-86cf-c5c7bbf07c1c

What is the expected behavior?

  1. The initial history should appear promptly. While older history loads in the background, the TUI should not repeatedly clear and repaint terminal scrollback. It should perform one final repaint after the background refill finishes.

Additional information

Measurements

With terminal_resize_reflow.max_rows set to its default/Auto value, the detected row budget was 9,001 rows.

The recorded repaint sizes grew through approximately:

  • 3,376 rows
  • 4,014 rows
  • 5,726 rows
  • 6,323 rows
  • 8,739 rows
  • about 9,001 rows

No individual repaint exceeded the configured cap, but the repeated repaints emitted roughly 37,000 terminal rows cumulatively, in addition to the initial display.

The complete conversation was not loaded into terminal scrollback. The delay came from repeatedly repainting the growing retained tail.

Relevant change history

The pagination infrastructure was developed across 8bfa49e, 3b8d22e, and dbcd837.

The repeated repaint regression itself was introduced by 449f099. That change extended older-page loading to normal terminal scrollback and scheduled an immediate resize reflow before checking whether another page needed to be loaded.

For a multi-page background refill, this ordering causes one cumulative terminal repaint per page. The proposed change preserves the earlier pagination behavior and defers that repaint until the refill chain completes.

Root cause

In the non-overlay older-page handler, each successful page currently:

  1. prepends its cells to transcript source;
  2. renders the source to measure its current row count;
  3. schedules an immediate terminal reflow;
  4. requests another page when the row budget remains underfilled.

This causes one destructive terminal repaint per loaded page.

Proposed approach

While scrollback remains underfilled and another older-page request can start:

  • retain the newly loaded cells;
  • defer the terminal reflow;
  • continue the bounded page chain.

Schedule one reflow when the row budget is reached, no older page remains, another page cannot be requested, or a later page fails after earlier pages were accumulated.

The Ctrl+T transcript-overlay path remains unchanged.

Regression coverage

I have a generic cross-platform TUI regression test extending the underfilled-scrollback test introduced by 449f099.

It forces two older-page responses and verifies:

  • both pages are requested;
  • all 120 expected outputs are loaded;
  • the transcript overlay remains closed;
  • no reflow is pending after the intermediate page;
  • one final reflow is pending when the chain completes;
  • the original 32-row rendering cap remains enforced.

A focused local patch and regression test are available. Following the repository’s contribution policy, I am opening this issue first and would be happy to submit the patch if invited.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLITUIIssues related to the terminal user interface: text input, menus and dialogs, and terminal displaybugSomething isn't workingperformancesessionIssues involving session (thread) management, resuming, forking, naming, archivingwindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions