Nope, nobody believes that. Devs say that for text documents which is somethig else entirely -- and, with provisions, for terminal single command apps (like grep, cut, ls, and so on). Nobody said it for TUIs.
The Claude Code rendering UI is the first place where I realized the TUI is more like a DOS or Borland UI system rather than a command line interface.
I was poking about CLAUDE_CODE_NO_FLICKER=1 setting when I realized what exactly this TUI is, it is layers of stuff showing up on top of each other with terminal codes.
Ended up reading the Ink Terminal implementation of React
https://github.com/vadimdemedes/ink
Fascinating how it ends up looking Wordperfect or Wordstar from the past instead of pixel based graphics.
The usability for a vision impaired user is about the same, though I remember braille pads for DOS tools (80x25) which work better than all the screen readers which came later.
I get it that maybe the constraints of terminals force design of TUIs to be more focused on the purpose of the tool than polish, but it's not that compelling of a point to me.
But the UX? If you the goal is not to read a single line of the code churned by these agents, and perhaps that is the point, then they are fine - type the prompt and cross your fingers.
Anything else that requires reading and changing needs an IDE of sorts. I am not saying you cannot have your workflow works with TUIs - plenty of people do. It is just not as good and flexible as full desktop applications.
If developers want to experiment with various UI configs then let them but keep a CUA in the background that can be called upon by machines and humans alike. (Unfortunately, ergonomics has never been a strong point for developers.)
They’re attempts at pretending to have Windows (etc.) GUIs in a terminal.
Same stuff people made for DOS when Windows wasn’t common or good enough yet.
I’m not surprised they’re a disaster. Or built without understanding the abilities of the terminal they’re running on.
Ever used Emacs? Or Vim? Or Mutt? Or Borland's old IDEs?
The power of the terminal is also in ubiquitness, trivial connection to a remote system, and lack of mountains of GUI cruft, that a TUI app can as well have.
1. There's already a large-ish community of engineers who live in the terminal e.g. Vim/Neovim/tmux/zellij/etc users. Lots of engineering tasks are accomplished by running scripts in a terminal, so it makes sense for some people to just move as much of their work there as possible. This means there's a set of users you can address with dev tools that run in a terminal.
2. Cross-platform distribution among the platforms most of those people care about — macOS and Linux — is largely a solved problem via package managers. Distributing cross-platform native apps is fragmented at best.
3. Building modern TUIs has become a lot easier thanks to the demand+distribution wins above: there's a lot of appetite for building blocks, and so lots of good options have flourished like Ink for React, Bubble Tea for Go, etc.
4. General developer distaste for the most straightforward analogue to all of this for desktop GUIs: Electron. Deservedly or not it's associated with slow, bloated applications. And if you don't use Electron, doing cross-platform anything is going to be a much harder problem than just pushing out a quick TUI app.
Eventually successful products seem to eventually jump the gap, like Claude Code eventually spawning Claude Cowork and OpenCode adding OpenCode Web. But it's easier and faster to test product market fit for dev tools with a TUI. And plenty of your users will stay there, even after you launch something else.
2) Constraints imposed by the terminal make all the apps look and work approximately the same - in the outside world the standards developed for UX are ignored as a matter of routine just because they can be. TUIs are in an optimum of least surprise, so to speak.
I still today meet users missing those old workflows. But they express it as "old text interface" aka TUI. If you listen to them you realize they mean blazing fast and shortcut driven. When you work with data entry you care about speed - not animations.
Any beginner likes eye candy. The veteran has stopped caring.
That's what a terminal UI is, and has been since Emacs was a thing.
Actually, I think that is close to a good name for them: Terminal-based GUIs.
Some are pretty useful, for instance I like lazygit as a simple dashboard/panel for a small repo (or when making small changes to a larger one), some make me wonder what those who made them were smoking!
The less silly ones are handy when you are tinkering with a far away machine and want something a little more interactive than CLI commands and stuff connected by pipes and scripts but don't want to deal with the latency of GUI remoting. Some, though, are so badly thought out that they are slower than using a browser over long-distance X…
Back in the 90s when most SAP systems switched from AS/400 terminals to Windows NT, people reported massive losses in productivity.
I've never worked on SAP, my mother did. And basically, she went from a fully tabular, function-key based oriented workflow, to holding a mouse, moving around and clicking a lot (tabbing and F keys were lost for many functions).
She showed me how she could go from ESC ESC F4 F3 TAB TAB and she was across the whole system a super speed. And this was a terminal, not the actual system!
The short of the story is this
Windows based application work best for discoverability and new users
Terminal based applications work best for faster, memory based navigation and power users.
Seems a lot more viable than trying to get new standard escape codes and outputting those along with visual content that may be flickering erratically. Also probably gets too complex faster than those proposals with more intricate UIs, but IMO it's really hard to defend TUIs for anything but relatively simple programs as an in-between a CLI and a native application.
> It isn't fair to blame TUIs.
> The real problem is that pretty much the whole stack has a terrible AX story.
> First, most GPU-rendered terminal emulators don't engage in system-provided accessibility APIs AT ALL. Because text is GPU-rendered, AX tooling can't "read" it, it just shows up as an image. This applies to Kitty, Alacritty, WezTerm. My own terminal Ghostty is AX-readable (on macOS), and so are others like iTerm2 and Terminal.app (which admittedly do it better than me, we have gaps to fill).
> Second, there are no terminal sequences or initiatives at all for TUIs to communicate AX information to the emulator, so the emulator itself can't do much more than display a blob of text to AX tooling. We need the equivalent of ARIA-style annotations but for terminal cells, runs, and regions. No such initiative exists. Even if TUIs do great things with the cursor, this is going to bite a lot of use cases.
> As an example of combining the above, I've been working on something with Ghostty where we integrate semantic prompt (OSC133) and AX APIs so that we can present each shell prompt, input, and command as structurally significant to AX tooling (rather than simply a text box where the cursor is somewhere else). This shows the importance of the relationship between terminal specs (OSC133), TUIs (which must emit OSC133), and terminal emulators (which must both understand OSC133 AND communicate it to AX APIs).
> The whole stack is rotten. And no one is earnestly trying to fix it (including me, I have limited time and I do my best but this is a WHOLE TOPIC that requires a huge amount of time and politicking the ecosystem and I don't have it, sorry).
Bonus: a simultaneously awesome and horrible reality is that AI is really helping to improve AX here. A lot of AI tooling uses/abuses AX APIs to make things happen. How is OpenAI reading your list of windows, typing into them, etc? Accessibility frameworks! So a lot more apps are taking AX integration a lot more seriously since its table stacks for AI using it... Sad it requires that but the glass half full is more software is doing that.
I wish the terminal-wg was more active. There's a bunch of weird odd OSC's folks have tried to make for enhancing structure of the terminal, for various ways to emit more layout-coupled semantic info. Accessibility APIs are great but in most forms a huge chunk of their capabilities feel pretty disconnected from the actual drawing on the screen, are somewhat a parallel construct to what's on screen. Using OSC to layer in more information about what is being drawn feels righter.
Two examples, collapsible regions, semantic prompt regions, https://gitlab.freedesktop.org/terminal-wg/specifications/-/... https://gitlab.freedesktop.org/terminal-wg/specifications/-/...
But in general feels like, for all the TUI interest, not many folks are about and working together to actually figure out how to advance the terminal itself.
If you're going to "run command, edit command, run command", performing the edits from the terminal you're running the commands in seems reasonable/intuitive. (In contrast, for tools like VSCode, I think it's more common for terminals to take up a fraction of the screen space rather than switching it to full screen. And then developers will say they need a huge monitor).
It also seems to be that keyboard-driven programs are more commonly TUI than GUI. e.g. magit or lazygit. Or lazydocker. Or k9s.
- CLI by default
- if I need a GUI, but no access to the local system: web
- if I need a (restricted) GUI with access to the local system: TUI
- else: either start a local web server, or, if nothing else works, go for a GUI toolkit
- you can use em over ssh
- they’re typically made with keyboard usage in mind, which is often an afterthought in a typical browser based UI
- other GUI options are browser (sandboxes, obvi, not good for lil personal tools), native (not dead simple, compared to TUI/browser/electron), or something like electron (no way lmao)
I don’t seek out TUI’s instead of other solutions. But it’s so dang easy to pop open a new pane and run lazygit. And it makes you look really cool when people walk behind you
Yes it's gronky.
But so are VT100 escape codes.
We have a term for that, it's called a CLI. For example, ed and ex are the historical CLI counterparts to vi.
For example, I really dislike mouse support in TUIs. 100% of the times I used the mouse on a TUI, I wanted to copy a piece of text. If the TUI hijacks the mouse and does something different with it (e.g. vim switching into visual mode) that is just annoying.
Of course a11y is important. But it barely works on the web and we won't get perfect semantics on the terminal without a lot of work. I say the better option is to strip down the experience to the parts that work well.
My objection to TUI is I don’t think it’s clear enough for what’s happening here. I think you could easily argue that applies to most readline style stream CLI programs.
Would you call a fully 3D UI in VR, not a planar in the VR world but true 3D, a GUI? It is graphical by definition. But if you talked to someone about a GUI that’s not what they’d think you’re talking about without additional context.
That’s my objection. I think TUI implies way less than what these programs are doing. Yeah it can describe them but I don’t think it should be the word for them.
In fact, all successful applications for professionals/power users are built with fast paths in mind. Even Microsoft's ribbon which gets a lot of hate for some reason is an example of that, it's keyboard-driven, customizable, and discoverable at the same time.
The language of accessibility – Staffnet | ETH Zurich https://ethz.ch/staffnet/en/service/communication/digital-ac...
tmux is great for this. Just press Ctrl+[ and the cursor can select whatever text is in the window.
But the terminal is just fundamentally the wrong basic abstraction on which to build a structured GUI, it just happens to require few enough bits to be sent over the wire that it actually works reasonably well over SSH as opposed to pushing graphics.
I typically prefer CLI myself but having a TUI to manage torrents for instance was much more ergonomic.
A more textually oriented environment (like a normal Unix shell) is, in my experience, usually referred to as a CLI: Command Line Interface.
I did find an interesting hybrid in the Pi coding agent: it seems to leverage the normal terminal scrollback, while still enhancing it with things like transient input fields and status lines, so that it can display those without cluttering scrollback.
Like, okay, they are a big step back with accessibility, but they're flickering garbage because they were vibecoded in a weekend and the TS or Python library they're built on was similarly forced upon this world.
Edit: yikes, pressing M-w caused emacs-pgtk to crash with a Wayland protocol error, so it isn't trivial and requires some configuring I guess.
Edit 2: Apparently I have to install wl-clipboard and write a bunch of emacs lisp to work around this. I don't think I have the patience for that, and I fear that such problems will be even harder to solve for applications which are not as flexible and programmable as emacs. So far I'll conclude that remote Wayland is not ready and stick to TUI.
Edit 3: No, the problem is probably mismatched waypipe versions on client and server. Still not fun.
There is a persistent misconception among sighted developers: if an application runs in a terminal, it is inherently accessible. The logic assumes that because there are no graphics, no complex DOM, and no WebGL canvases, the content is just raw ASCII text that a screen reader can easily parse.
The reality is different. Most modern Text User Interfaces (TUIs) are often more hostile to accessibility than poorly coded graphical interfaces. The very tools designed to improve the Developer Experience (DX) in the terminal—frameworks like Ink (JS/React), Bubble Tea (Go), or tcell—are actively destroying the experience for blind users.
To understand the failure, we must distinguish between two distinct concepts often conflated under “terminal apps”: the CLI (Command Line Interface) and the TUI.
The CLI (The Stream): This operates on a standard input/output model (stdin/stdout). You type a command, the system appends the result below, and the cursor moves down. This is linear and chronological. For a screen reader, specifically kernel-level readers like Speakup, this is ideal.
The TUI (The Grid): This treats the terminal window not as a stream of text, but as a 2D grid of pixels, where every character cell is a pixel. It abandons the temporal flow for a spatial layout.
gemini-cli MadnessLet's look at a concrete example: gemini-cli, a tool written in Node.js using the Ink framework. On the surface, it looks like a simple chat interface. But underneath, Ink is trying to reconcile a React component tree into a terminal grid.
When you use this tool with Speakup (Linux) or NVDA (Windows), the application doesn't just fail; it actively spams you.
Because the framework treats the screen as a reactive canvas, every update triggers a redraw. When the AI is “thinking,” the tool updates a timer or a spinner. To do this, it moves the hardware cursor to the timer location, writes the new time, and moves it back.
For a sighted user, this happens instantly. For a screen reader user, this is what you hear: “Responding... Time elapsed 1s... Responding... Time elapsed 2s... [Fragment of chat history]... Responding...”
It drives the screen reader mad. The cursor is teleporting all over the screen to update status indicators, spinners, and history. Speakup tries to read whatever is under the cursor at that exact millisecond. You end up hearing random bits of conversation mixed with timer updates, making it impossible to focus on what you are actually typing.
Worse, lets pretend that you've somehow managed well with speakup so far, but that you want to do some work with nvda. Maybe paste an error you're getting on windows. So you open your terminal, ssh into your linux box, attach to your screen session and paste your text.
The result is an immediate crash of the screen reader (NVDA) or massive system instability. Why? Every time you type a character or paste text, the application triggers a state change. The framework decides it needs to re-render the interface. Because the conversation history is part of that state, the application attempts to redraw or re-calculate the layout for thousands of lines of text instantly. The more messages you have in a conversation, the more this will happen. And no, you can't just avoid this by using insert+5, the key combo supposed to avoid announcing dynamic change of content.
Furthermore, frameworks like Ink running on single-threaded environments (like Node.js) suffer from massive performance degradation when the history grows. If you paste a large block of text, the system has to calculate the diff for thousands of lines.
This causes input lag. You press a key, and you wait. You can wait up to 10 seconds for a single character to echo back. The system is too busy calculating how to redraw the screen to actually process your input.
Sighted developers often ask: “If TUIs are bad, why do you use nano, vim, or menuconfig?”
The answer is not that these tools handle the cursor perfectly by default. The answer is that they allow you to hide the cursor entirely.
nano, vim)In tools like nano or vim, usability depends on turning off features that track cursor position. If you run nano with options that show the cursor position (like --constantshow), or if you use vim without specific configuration, the experience is broken.
When the cursor is visible and tracking is active, Speakup prioritizes the cursor's location update over the character echo. Instead of hearing the letter “a” when you type it, you hear “Column 2”. You type “b”, and you hear “Column 3”.
These older tools succeed because they allow you to disable this noise. You can configure them to suppress the visual cursor or status bar updates, forcing the screen reader to rely on the character input stream rather than the noisy coordinate updates. Modern frameworks rarely offer a “no-cursor” or “headless” mode; they assume the visual cursor is essential.
menuconfig)Tools like the Linux kernel's menuconfig work because they enforce a strict, single-column focus. Even though there are borders and titles, the active area is a vertical list. The cursor stays pinned to that list. It doesn't jump to the bottom right to update a clock, then to the top left to update a title. The spatial complexity is kept low enough that the screen reader never gets “lost.”
Irssi is the gold standard for accessible chat, but not because of luck. Irssi was built over 20 years with a custom rendering engine that utilizes VT100 Scrolling Regions.
When a new message arrives in Irssi:
It tells the terminal driver: “Define a scrolling region from line 1 to 23.”
It sends a command: “Scroll up.” The terminal moves the bits up.
It draws the new text at the bottom of that region.
Crucially, it handles this in a way that minimizes interference with the input line. It relies on the terminal's hardware capabilities rather than rewriting every character on the screen manually. Modern frameworks ignore these hardware features in favor of “diffing” the screen state and rewriting characters, which is computationally heavier and hostile to accessibility.
Google and the maintainers of gemini-cli pretend to care about accessibility. “Pretend” is the operative word here. If you look at the repository, critical accessibility regressions like Issue #3435 and Issue #11305 have been left to rot. There is no discussion, no roadmap, and no fix. Even worse is the fate of Issue #1553, which was supposed to track these accessibility failures. It didn't get solved; it got silenced. It was closed automatically by a bot with this generic dismissal:
Hello! As part of our effort to keep our backlog manageable and focus on the most active issues, we are tidying up older reports. It looks like this > issue hasn't been active for a while, so we are closing it for now.”
This is unacceptable. Closing an accessibility report because the maintainers haven't touched it in months is not “tidying up”; it is hiding evidence. It effectively says that if a bug is ignored long enough, it ceases to exist. It boosts the project's “Closed Issues” metric while leaving the actual software unusable for blind users.
If you are building for the terminal and care about accessibility, stop using declarative UI frameworks that treat the terminal like a canvas.
The “modern” TUI stack has optimized for the developer's ability to write React-like code at the expense of the machine's ability to render text efficiently.
If you cannot guarantee that your application allows the user to hide the cursor, or if you rely on aggressive redrawing to show spinners and timers, you are building an inaccessible tool.
For the blind user, a dumb, linear CLI stream is infinitely superior to a “smart” TUI that lags, spams, and scatters the cursor across the screen.