Improve copy/paste in the Rust TUI, or at least make the existing solution more discoverable

Resolved 💬 16 comments Opened Jun 6, 2025 by bolinfest Closed Aug 2, 2025
💡 Likely answer: A maintainer (bolinfest, collaborator) responded on this thread — see the highlighted reply below.

It's complicated.

Today, if you want to be able to drag to select text with the mouse to copy/paste, you have two not-so-great options:

  • In iTerm, hold down alt while you drag. (Other terminals may have a different keybinding.)
  • Use the [admittedly obscure] /toggle-mouse-mode command so that the TUI no longer processes mouse events itself. This will make text selection work "the normal way," but it also means that if you try to scroll the conversation area with your mouse, it won't work because the TUI is no longer receiving those scroll events. (You can use the keyboard shortcuts we provide to scroll, though.)

At this point, you are probably wondering: why does it work this way???

The TUI is built atop the Ratatui toolkit. By default, Ratatui encourages you to create full-screen TUIs. This means that if you want to have scrollback, you need to manage it yourself (as we do today).

Now that said, Ratatui does have an insert_before() API that would make it possible to "continuously append" to the TUI output like the TypeScript CLI does. The advantages of that scheme are:

  • the user can use their terminal's native scrollback
  • copy/paste "just works"

Though there are some downsides, which is that things like popping up menus is a bit weird:

https://github.com/openai/codex/issues/899

It is also more difficult to update content that is not "fully baked," such as a tool call with its own in-progress output or a spinner that appears above the input text box that needs to be continuously updated.

Nevertheless, it feels like, with enough effort, it should be possible to have the best of both worlds. That said, it seems that this issue needs to be solved to get there:

https://github.com/ratatui/ratatui/issues/984

From the discussion, it sounds like it is not a trivial fix, so someone would need to invest some time there.

Counterpoint: do we want to cede scrollback to the terminal?

While the copy/paste thing is frustrating, I don't think having Codex manage its own scrollback is "obviously wrong." Personally, there have been many times where it was helpful that I could navigate through the conversation history while still having the text input available so that I could author my next user message while looking at what had transpired thus far.

In managing our own scrollback, there are a number of things we could do, such as:

  • Support switching between multiple conversations/sessions.
  • Making events in the history expandable so you could, e.g., see the full tool call output if you wanted to.

If copy/paste is really the primary motivator, then perhaps the real fix is to improve how we handle mouse events to support text selection in the way users expect?

/cc @joshka

View original on GitHub ↗

16 Comments

nistath · 1 year ago

holding alt is fine!

But for copying multi line text, the border characters are really annoying. Would be nice if there were no vertical borders (and no scrollbar when not scrolling).
That way I can copy things almost normally!

joshka · 1 year ago
It's complicated.

Yep. :D

I haven't really seen a good pattern in any app for handling all these bits at once (scrolling + scrollbar + copy + mouse + interactive TUI). The best I've seen is in lnav, which allows you to press a button to write the current screen's output in a way that just lets the terminal wrap instead of handling it manually (and so then allows copy lines to work nice)

IceWreck · 1 year ago

Both current solutions are not very useful because of the border makes it impossible to properly copy things.

joshka · 1 year ago

Having used a few different ai cli tools, I think the most appropriate UI for Codex might be to let the user's terminal handle the scrollback instead of handing it in app. This sidesteps the issues of scroll borders causing issues with copying text.

Perhaps if the multi-session / conversation approach is necessary, add the ability to playback a conversation / session?

In an ideal world, there terminals would have a way to specify wrapping areas, but I don't think that's possible (and it certainly would not be universally supported if it was).

If you're looking for some inspiration for a TUI approach that handles mouse selection and copying in non full terminal width regions, take a quick look at the demos on textual (python framework).

pip install textual
python -m textual

Then highlight some text and press ctrl+c (yes even if you're on a mac) to copy.
This should give an idea of how viable it is to attack the problem that way.
It works nicely, but only for specific text elements that support it rather than the entire app.

joshka · 1 year ago

Another novel approach to this that could be worth an exploration is to treat the log and the interactive parts of the app as two separate things. Keep the log as wrapped immutable text append only on the main screen without a scrollbar, and then make any interactive parts (aside from the main user input) be rendered on the alternate screen (https://ratatui.rs/concepts/backends/alternate-screen/).

There's some recent discussion about how we should be handling inline mode in Ratatui over on https://github.com/ratatui/ratatui/pull/1964#issuecomment-3047855001. There's some reference to how claude code works with its inline approach to displaying information longer than the current page, that are later removed. It seems it achieves this by clearing and rewriting the entire scrollback. Claude Code uses ink, and the behavior of how this part of ink works is documented a bit in https://github.com/vadimdemedes/ink/issues/382

There's a possibility that the redraw the entire conversation approach could also work here, or maybe some hybrid of approaches that allows flipping between sessions and redrawing the entire session.

crw2998 · 1 year ago

Among other things, copy/paste is critical for:

  • searching or sharing an error in the output
  • killing the CLI and starting a new invocation with the same prompt again

For me, having a nice border, spinners, and non-shifty output isn't worth giving up actual functionality. Plus, I didn't know about /toggle-mouse-mode until I found this issue.

Personally, there have been many times where it was helpful that I could navigate through the conversation history while still having the text input available so that I could author my next user message while looking at what had transpired thus far.

Copy/paste would make this specific activity much more useful.

joshka · 1 year ago
For me, having a nice border, spinners, and non-shifty output isn't worth giving up actual functionality. Plus, I didn't know about /toggle-mouse-mode until I found this issue.

I don't think anyone here is saying that copy-paste should not be usable in codex. This issue is really about the technical tradeoffs that are inherently part of rendering large amounts of text to the terminal while having a degree of interactivity inherent in a TUI app.

The crux of the problem is that when interacting with a terminal, you can either:

  • write to specific areas of a screen by moving the cursor to that location and then writing text
  • append lines to areas of the screen that appear in the scroll buffer

You cannot (at least without future changes to terminal emulators to support):

  • write to or replace specific areas of the scroll buffer
  • un-append lines from the scroll buffer
bcanvural · 1 year ago

I had this problem too, using tmux was not a problem before. My workflow was ctrl+b [ followed by a few ctrl+Us to get to where i need to be, then shift+v + j/k to highlight required area and then Y to copy. Now doing this copies a lot of white space and some chars. Would love a workaround for tmux users

bolinfest collaborator · 1 year ago

FWIW, we've been discussing this on our side and are considering moving to the TypeScript UX just to avoid the existing issues with copy/paste and also https://github.com/openai/codex/issues/1502.

crw2998 · 1 year ago
I don't think anyone here is saying that copy-paste should not be usable in codex.
This issue is really about the technical tradeoffs that are inherently part of rendering large amounts of text to the terminal while having a degree of interactivity inherent in a TUI app.

Yeah, agreed. Sorry I wasn't clear. I think in your terms, what I'm trying to say is that this tradeoff isn't worth it for me. If you ask if I would prefer clean copy/paste vs the interactivity and nice formatting of the TUI app, I would prefer the clean copy/paste. But I'm sure other people use/enjoy the TUI aspects more than me.

bentito · 11 months ago

For other MacOS users reading this and wondering what alt key might mean. It's the option key and it works, but super annoyingly does get the vertical side bars in the copy. FWIW: k9s gets around this by offering a full screen toggle.

nmurrell07 · 11 months ago

Option key does not appear to work in Mac any longer. Cursor turns into a crosshair and does not change behavior when interacting with text inside the terminal.

domenkozar · 11 months ago
From the discussion, it sounds like it is not a trivial fix, so someone would need to invest some time there.

We're in the same spot between a few projects, maybe we can work this out? It looks like a feasible long-term investment to get this DX nailed.

domenkozar · 11 months ago
easong-openai contributor · 11 months ago

We're letting the terminal handle scrollback and text selection. Give the latest release a shot! :)

simonw contributor · 11 months ago

Just tried this - I had to run brew upgrade codex (codex --upgrade doesn't work if you installed it from Homebrew) and it's the exact fix I needed. Thanks for this!