Zellij Incompatibility

Resolved 💬 21 comments Opened Jan 12, 2026 by anton-kalshi Closed Mar 27, 2026
💡 Likely answer: A maintainer (etraut-openai, contributor) responded on this thread — see the highlighted reply below.

What version of Codex is running?

codex-cli 0.81.0-alpha.1

What subscription do you have?

Pro

Which model were you using?

_No response_

What platform is your computer?

Darwin 24.6.0 arm64 arm

What issue are you seeing?

Using Alacritty 0.15.1.

Installed codex verison 0.81.0-alpha.1 as mentioned in this issue, but zellij incompatibility continues. Using zellij 0.43.1.

What steps can reproduce the bug?

Mostly just wanted to flag for @hjanuschka -- very possible this is user error on my side. Can produce screen recording of behavior using the versions I mentioned above if it would help.

What is the expected behavior?

_No response_

Additional information

_No response_

View original on GitHub ↗

21 Comments

SawyerHood · 6 months ago

I'm also getting this but with ghostty

etraut-openai contributor · 6 months ago

@SawyerHood, can you say more about what you're seeing?

SawyerHood · 6 months ago

Sorry! I'm getting the same old issue with codex scroll back not working in Zellij despite using v0.81 (which I think has the fix).

My env:

  • OpenAI Codex (v0.81.0)
  • Ghostty (1.2.3)
  • MacOS Tahoe 26.2
  • Zellij (0.43.1)

Here is a video, note that scroll back doesn't work even when passing no-alt-screen

https://github.com/user-attachments/assets/520b591c-113f-4575-bf32-d5982457179a

hjanuschka contributor · 6 months ago

i'll take a look

hjanuschka contributor · 6 months ago

Found the bug - the alt_screen_enabled flag was being set AFTER the resume/fork pickers ran, so those overlays would enter alternate screen regardless of the --no-alt-screen flag.

Fix: #9258

hezhexi2002 · 5 months ago
Sorry! I'm getting the same old issue with codex scroll back not working in Zellij despite using v0.81 (which I think has the fix). My env: OpenAI Codex (v0.81.0) Ghostty (1.2.3) MacOS Tahoe 26.2 Zellij (0.43.1) Here is a video, note that scroll back doesn't work even when passing no-alt-screen codex-zellij-issue.mp4

Hi @SawyerHood — sorry to bump, but your description matches my setup almost exactly.

Have you found any workaround / solution since your comment (e.g. any Codex/Zellij/Ghostty settings, or a newer Codex version that fixes it)?

I’m still seeing no trackpad/mouse-wheel scrolling in Codex when it’s running inside a Zellij pane, even with --no-alt-screen / tui.alternate_screen = "never".

My env:

  • codex-cli: 0.93.0 (Codex TUI)
  • Zellij: 0.40.1 (mouse_mode true)
  • Local: macOS Sequoia 15.7.3 + iTerm2 3.6.6
  • Remote over SSH: CentOS 7

Symptom: two-finger trackpad scroll does nothing while Codex is focused (other TUIs like opencode scroll fine).

If you did get it working, could you share what changed (terminal settings, disabling mouse reporting, Zellij mouse mode toggle, etc.)? Thanks a lot!

DamianPala · 5 months ago

I can reproduce the same Zellij scrollback issue on Linux with codex-cli 0.93.0 and zellij 0.43.1, even with alt-screen disabled.

Versions:

  • codex-cli 0.93.0
  • zellij 0.43.1
  • Linux, TERM=xterm-256color

Repro:

  • codex --no-alt-screen
  • also tested codex -c 'tui.alternate_screen="never"' --no-alt-screen
  • also tested ZELLIJ=1

Findings:

  • No alt-screen sequences (CSI ?1049h/?1047h/?47h not present)
  • No scrollback clear (CSI 3 J) and no terminal reset (ESC c)
  • Full-screen redraw patterns present (cursor addressing CSI row;col H, CSI J, CSI K, scroll regions CSI r, reverse index ESC M)
  • Synchronized output toggles (CSI ?2026 h/l) are present

This suggests --no-alt-screen keeps the full-screen renderer in the main buffer. Zellij doesn’t build scrollback from in-place redraws, so scrollback stays empty. A “true inline/line-based mode” (no cursor addressing / screen clears / scroll regions) would likely fix it.

quinncomendant · 5 months ago

Looks like the PR https://github.com/openai/codex/pull/9258 didn't work out.

mwurm293 · 5 months ago

Please fix this. Multiplexing is a common requirement. I have Claude and Codex. Prefer Codex, but switching to Claude until fixed.

paul-pro · 5 months ago
silverberrydesert · 5 months ago

Workaround until this issue is fixed:

Use Codex’s built-in transcript pager: press Ctrl+T, then use ↑/↓ to scroll, PgUp/PgDn to page, Home/End to jump; q or Ctrl+T to close.

Note: If you're using the default key bindings in Zellij, you'll need to press Ctrl + g before pressing Ctrl + T. This sends kb shortcuts to the Zellij pane instead of sending them to the multiplexer.

Alternatively, you can free up Ctrl + T in Zellij and use a different combination to cycle through tabs.

Hope this helps someone!

kanlanc · 5 months ago

Love Zellij but had to Tmux because of this, any updates on this issue at all?

Irvingouj · 4 months ago

what is the issue exactly here?

acgxv · 4 months ago

need higher priority

RainyPixel · 4 months ago

+1

RainyPixel · 4 months ago
what is the issue exactly here?

no scroll in zellij

hobodave · 4 months ago

Still reproducible for me on codex-cli 0.110.0 on macOS with Alacritty -> Zellij -> zsh.

Behavior:

  • When Codex history scrolls past the top of the visible window, normal mouse-wheel scrollback does not show prior Codex transcript.
  • Scrolling up shows pre-Codex shell content instead, which looks like alternate-screen behavior.

Notes:

  • ZELLIJ is present in the environment
  • No tui.alternate_screen override in ~/.codex/config.toml
  • codex --help includes --no-alt-screen
  • I also tested codex --no-alt-screen, and it had no effect
  • Claude Code in the same stack does not have this problem

Given #8555 and the docs, I’d expect either Zellij auto-detection or --no-alt-screen to preserve normal scrollback here, but neither appears to be happening.

thekoc · 4 months ago

Still reproducible on 0.114.0

mingerfan · 4 months ago
Still reproducible on 0.114.0

Same issue here. I have to use the plain terminal as a workaround (instead of Zellij)😔.

guysrd · 4 months ago

hi, i tried investigating this issue myself and the solution i found (with codex's help obv) requires a pretty big architecture change that codex isn't likely to implement. codex currently has two different transcript paths, one works with zellij and the other doesn't, codex chose this intentionally.

TL;DR : this breaks specifically inzZellij because the main codex transcript is not an app-owned scrollable view,
it is terminal scrollback. Zellij is a terminal multiplexer and manages pane scrollback separately from the application UI, so once Codex relies on terminal history as its transcript surface, scrolling behavior becomes dependent on Zellij’s pane/scroll mode semantics instead of Codex itself. opencode or claude code do not hit this class of bug if they render their transcript inside their own TUI/view layer and keep scroll state in the app, because then the multiplexer is just transporting input/output and not acting as the transcript browser.

note: i forked codex from commit 0334ddeccbef07995561de5b39334dd94ef9e33a

The likely fix is to keep App::transcript_cells as the source of truth, render committed transcript history inside the normal ratatui tree, and give the main view its own pager/scroll state, likely by
reusing or extracting the existing PagerView logic instead of keeping that capability only in TranscriptOverlay.

The ctrl+t transcript overlay is implemented by TranscriptOverlay which delegates scrolling to PagerView in [codex-rs/tui/src/pager_overlay.rs](/codex-rs/tui/src/pager_overlay.rs).
this path is a real in-app pager: PagerView owns scroll_offset, computes max_scroll, clamps during render, and handles both keyboard paging and mouse-wheel input. The overlay event path is literally:
TuiEvent::Mouse(mouse_event) => self.view.handle_mouse_event(tui, mouse_event),
and PagerView::apply_mouse_event updates scroll_offset for MouseEventKind::ScrollUp

the main chat view works differently, transcript data is kept in App::transcript_cells, but it is not rendered by ChatWidget as a scrollable ratatui surface. In [AppEvent::InsertHistoryCell in app.rs](codex/codex-rs/tui/src/app.rs:2327),
codex converts each committed HistoryCell into display lines and, when no overlay is open, does this:

  if self.overlay.is_some() {
      self.deferred_history_lines.extend(display_lines);
  } else {
      tui.insert_history_lines(display_lines);
  }

then Tui::insert_history_lines in codex-rs/tui/src/tui.rs:495 just queues those lines into pending_history_lines, and Tui::draw later flushes them into terminal scrollback:

  crate::insert_history::insert_history_lines(
      terminal,
      self.pending_history_lines.clone(),
  )?;

That is the key architectural difference: the overlay is a pager inside Codex (zellij not aware), while the main transcript is still terminal scrollback (zellij aware).

you can see the same split in the main render path. ChatWidget::as_renderable in codex-rs/tui/src/chatwidget.rs:8546 builds a FlexRenderable from only two things: the current active_cell and bottom_pane. There is no committed-transcript viewport there:

  flex.push(1, active_cell_renderable);
  flex.push(0, RenderableItem::Borrowed(&self.bottom_pane).inset(...));

That is also why ratatui itself does not solve this. ratatui only manages widgets the application actually renders. In the main view, committed history is not a ratatui widget with scroll state; it is emitted into terminal history. So this is not a missing ratatui flag or a bad Paragraph setting. The main transcript is simply outside the app-owned widget tree.
I tried to rule out terminal plumbing as the root cause: (in my own private branch):

  • TuiEvent::Mouse(MouseEvent) in tui.rs:239
  • Event::Mouse(mouse_event) => Some(TuiEvent::Mouse(mouse_event)) in tui/event_stream.rs:236
  • mouse handling in TranscriptOverlay::handle_event and StaticOverlay::handle_event
  • tui.set_mouse_capture_enabled(self.overlay.is_some() && !tui.is_alt_screen_active()) in App::handle_tui_event:2038
  • explicit debug logging showing that main-view mouse events are still dropped:
  • dropping mouse event in main view; inline transcript still relies on terminal scrollback

My experiments showed that the Ctrl+t overlay pager is real and can scroll in-app, while the main view still cannot because it never owns the transcript as a scrollable widget (this is the main issue).

edit:
i see this issue is also present in other terminal multiplexers as well, meh, i wonder if i commit a fix and change codex drastically they'll accept this change? this isn't likely though as it requires moving from the pager view to transcript view and has a few other consequences that require changes.

etraut-openai contributor · 3 months ago

Consolidating onto #2558.