šŸ› Mouse / scroll in zellij doesn’t let me view earlier TUI conversation (alt-screen interaction)

Resolved šŸ’¬ 8 comments Opened Aug 28, 2025 by vitatea2023 Closed Nov 18, 2025
šŸ’” Likely answer: A maintainer (oyiakoumis, contributor) responded on this thread — see the highlighted reply below.

name: "šŸ› Mouse / scroll in zellij doesn’t let me view earlier TUI conversation (alt-screen interaction)"
about: Report that codex TUI rendered in zellij cannot be scrolled to view earlier conversation because of alternate-screen / mouse handling.

Thank you for taking a look — I found a reproducible problem where the Codex TUI prevents using zellij’s pane scrolling / mouse wheel to view earlier conversation context. Below are reproduction steps, expected vs actual behavior, environment info, and a short technical analysis + suggested mitigations.

Version

  • codex-cli 0.25.0

Model

  • gpt-5 (TUI / terminal interaction bug)

Platform

  • Arch Linux; zellij version tested: zellij 0.43.1

Steps to reproduce

  1. Start zellij (or run inside an existing zellij session).
  2. Run the Codex TUI CLI (e.g. codex).
  3. Interact until you have a long conversation / transcript (enough output to exceed the pane height and require scrolling).
  4. Attempt to use the mouse wheel (or zellij’s normal pane scrollback) to view earlier lines of the conversation.
  5. Optionally try Shift + scroll or zellij’s Scroll/Copy mode (Ctrl+s or [ depending on config) as well.

Expected behavior

  • Mouse wheel or zellij pane-scrollback should show earlier conversation lines (i.e., allow you to scroll/inspect older parts of the transcript).
  • Alternatively, if mouse wheel events are captured by the app, there should be a smooth in-app scroll that reveals earlier lines.

Actual behavior

  • In zellij, mouse wheel does not show early conversation context; you cannot use the pane scrollback to see older transcript lines rendered by the TUI.
  • Keyboard navigation inside the TUI (arrow keys, page up/down in-app) still works to move the app’s internal cursor/viewport.
  • Behavior is different in a normal terminal (outside zellij): terminal scrollback / wheel behaves differently (depends on terminal emulator).

Relevant code pointers

  • The TUI explicitly enters alternate screen and toggles an ā€œalternate scrollā€ mode:
  • codex-rs/tui/src/tui.rs — enter_alt_screen() / leave_alt_screen() (calls EnterAlternateScreen and EnableAlternateScroll / DisableAlternateScroll).
  • codex-rs/tui/src/app.rs — call sites that call tui.enter_alt_screen() when showing transcript / diffs / overlays (e.g. transcript/diff/pager code).
  • The event handling doesn't appear to explicitly handle Event::Mouse for scrolling in event_stream / textarea code, so mouse wheel handling doesn’t translate to in-app scroll by default.

Technical analysis (why this causes the problem)

  • Entering the terminal’s alternate screen (alt-buffer) means the application’s output is rendered into a separate buffer that is not part of the terminal emulator’s main scrollback. Most terminal multiplexers / emulators treat the alt-buffer separately, so zellij’s pane scrollback typically does not include content written to alt-screen.
  • The code also enables a terminal mode related to alternate scroll behavior (CSI ?1007 h) which alters how wheel events are delivered/translated. Depending on terminal/emulator and whether the application requests mouse capture/reporting, the wheel events may be delivered to the app (and the app must handle them) rather than letting the multiplexer scroll the pane history.
  • Because codex enters alt-screen and (as far as I can see) doesn’t handle mouse wheel events to scroll its internal viewport, zellij cannot show that content in its pane scrollback and mouse wheel appears ineffective.

Workarounds

  • In zellij:
  • Try entering zellij’s Scroll/Copy mode (Ctrl+s or [), then use keys to navigate history. Note: whether this shows alt-buffer content depends on zellij’s capture behavior.
  • Try Shift + scroll or Shift + click (some terminals/tilers forward these to the terminal/tiler instead of the app).
  • From the Codex side:
  • Temporarily suspend the app (Ctrl+Z) — the code already has a suspend/resume path in some places — and then use the terminal/tiler’s scrollback. Not ideal but workable.
  • Run Codex outside zellij or avoid entering alt-screen (see suggested fixes below).

Possible fixes (options ranked by UX)

  1. Add a config option so Codex can render inline (not use alternate screen) for the main conversation UI:
  • Add e.g. tui.use_alternate_screen = false (TOML config) and conditionally skip enter_alt_screen() calls when set. This will allow zellij/terminal scrollback to include the conversation output.
  • Pros: users can use zellij’s scrollback naturally; no need for app to implement mouse handling.
  • Cons: some visual/UX differences: app won’t be able to rely on alt-screen semantics (clear / restore, dedicated buffer).
  1. Implement in-app mouse-wheel handling:
  • Enable mouse capture and explicitly handle Event::Mouse (ScrollUp / ScrollDown) in the TUI event loop and map them to the app’s internal scroll behavior.
  • Pros: consistent in-app mouse scrolling across multiplexers (if they forward mouse events).
  • Cons: when mouse is captured by app, multiplexer scrollback is not available; the app must maintain its own scrollback/history support.
  1. Provide a quick toggle / key to temporarily leave alt-screen (and then re-enter):
  • The code already handles suspension/resume (Ctrl+Z). Expose an explicit key to LeaveAlternateScreen so user can use zellij scrollback, and then restore alt-screen after.

Suggested change I can submit as a PR

  • Add use_alternate_screen under [tui] in ~/.codex/config.toml (default true), and wrap calls to tui.enter_alt_screen() with if config.tui.use_alternate_screen { ... }. This gives users configuration-based control (render inline when desired). The PR would:
  • Add the config field (Tui struct) with a default.
  • Update each enter_alt_screen() call site (app.rs, app_backtrack.rs, and other overlay points) to conditionally call it.
  • Optionally add a short config doc note describing tradeoffs.

Additional notes / diagnostics

  • I inspected the code on Arch Linux and cloned zellij sources to inspect behavior; zellij version used for inspection: zellij 0.43.1.
  • Key files where behavior is controlled:
  • codex-rs/tui/src/tui.rs — enter_alt_screen() / leave_alt_screen(), EnableAlternateScroll implementation.
  • codex-rs/tui/src/app.rs — multiple tui.enter_alt_screen() call sites used to open transcript/pager overlays.
  • codex-rs/tui/src/bottom_pane/textarea.rs — textarea rendering and keyboard-based scroll logic; no direct mouse-wheel handling observed.

If you'd like, I can prepare the config-based patch and open a PR with tests/formatting applied. Alternatively, I can implement mouse-wheel handling instead — let me know which route you prefer.

View original on GitHub ↗

8 Comments

just-kir Ā· 10 months ago

I reproduce the same behaviour on mac zellij.

vitatea2023 Ā· 10 months ago

You can refer to (or use as a reference) this project: https://github.com/sst/opencode.

oyiakoumis contributor Ā· 10 months ago
jiangying000 Ā· 10 months ago

Similar issues on iOS Termius and ISH app When I connect to remote server and run codex, I can see only the last about 30 lines of history. All the previous histories can't be scrolled back. I must use ctrl+t or tmux now to see more previous history.

dpolivaev Ā· 10 months ago

I see the same problem on macOS with iTerm2.
By default, when the Codex TUI is active, the mouse wheel is captured by the app and cycles through the prompt history, so I cannot use iTerm2’s scrollback.

As a workaround, I set Preferences → Profiles → Terminal → ā€œScroll wheel sends arrow keys in alternate screenā€ = No, which fixes the issue for me.

It would still help to have a config option in Codex to disable alternate screen / mouse reporting, so users can choose the behavior they prefer.

Yz-2 Ā· 9 months ago

This is the same problem with alacritty. Is there a workaround for alacritty?

gregkonush Ā· 8 months ago

would be nice to fix this

etraut-openai contributor Ā· 8 months ago

Closing in favor of #2558