← Back to context

Comment by dwb

4 days ago

I think TUIs-that-want-to-be-GUIs (as opposed to terminal commands just outputting plain text) are sad. Mainly because they’re largely inaccessible. They flatten the structure of a UI under a character stream. You’re forced to use it exactly the way it was designed and no different. Modern GUIs, even web pages too, expose enough structure to the OS to let you use it more freely. I get why people build TUIs, but it’s a sorry state of affairs.

I disagree, I think TUIs are a great fit in some problem domains.

Think for instance the Debian package configuration dialogs -- they're far more comfortable than the same questions without a TUI, and still work over a serial console if you have to use one.

For tools like various kinds of "top", there's many potential tools you can use to the same end and intentionally using one that draws CPU graphs over one that just displays a number. Graphs are much easier to interpret than a column of numbers.

In many cases they're the optimal choice given some constraint -- like the desire to have minimal dependencies, working over SSH, and being usable without breaking the flow. Yeah, you could make a tunnel to a tool that runs a local webserver and delivers graphs by HTTP, but the ergonomics of that are terrible.

  • Sure, I said I understand why people build them. I’ve used a lot of them. And yes with the tools we have you’re right, but I’m more lamenting the wonky, kind of archaic, unintegrated, only-semi-composable toolset that we have. No fundamental reason why you couldn’t deliver more structured UIs directly over SSH or a serial console, it’s just that in this timeline that didn’t happen yet (apart from X forwarding, which isn’t quite what I’m on about).

    • I found this which is by far the closet to what I’m on about. Imagine this but with inline UI controls too (keyboard-controllable, natch), probably based on Nushell (I like Nushell), and maybe an “alternate display mode” type thing for UIs that want to take over more and not act as a transcript. And, no offence, but more visually appealing and implemented with a common-denominator subset of native UI controls where possible. Clearly the issue is not building it, but adoption. I don’t have an answer for that.

      https://github.com/unconed/TermKit

  • The difference there, in Debian's case at least, is that there is a distinction between the frontend and the configuration backend; you're probably most familiar with the `newt` frontend, but there's also `text` (for textual entry without using curses or anything), `noninteractive` (for just use the defaults), gnome, kde, teletype, or even 'web' which does not seem to work effectively but is a neat idea regardless.

    TUIs which are just TUI views of data you can get otherwise are fine; TUIs which are the only way to interact with something... less so.

    • I like TUIs, but if given the choice between a TUI or a CLI program, I'd take the latter. You can always create your own interface from it. Better if it's backed by a library.

Here's why I use them: many modern graphical applications are extremely wasteful. TUIs are typically small, low footprint applications that don't come bundled with a browser or webview. I don't need yet another electron app for every little thing.

  • I’m definitely not advocating more little electron apps, and I’m totally with you on TUI’s benefits. I’m bemoaning the lack of imagination that has ended us up here and not in a situation where we can have, say, a small, low-footprint application that can deliver a more structured UI with minimal dependencies. It’s not an impossibility, it’s not even that difficult to imagine, we just don’t have the exact technology.

    • I'm with you.

      The thing is Windows 98 let you throw up a HTML window with almost zero overhead (the OS used the same libraries) and javascript could get data easily from another process via COM etc.

      Now like 25 years later, apparently our choices are shipping bespoke copies of Chrome and Node, OR making shit work on an emulated 1981 DEC terminal. Lack of vision is exactly right.

    • I think for the time being, there's no way to get around writing native UIs to get a native experience. Any sufficiently high level APIs will have to give up something. TUIs for me fill that niche because across any POSIX-compatible interface they will generally work the same, and modern high level languages make cross-compiling to terminals a breeze. Now to write a native UI across Windows, MacOS, Wayland and X11, that's a different story.

      1 reply →

    • We do. We are only stubborn. Cross platform and low-footprint:

        .net core => avalonia ui
        Java => JavaFX

  • > TUIs are typically small, low footprint applications

    That ship has sailed. These days, TUIs are often Node.js / React monstrosities. Claude Code is a case in point.

Yes, but this kind of dashboard was never going to be accessible anyway. It's a dense visual representation of vast system state with constant real-time fluctuation. Even in a browser, it would be hell to navigate the constantly changing state with a screen reader. And visually increasing the scale and contrast defeats the purpose of the density of the original display.

If you need to support screen readers, your UI would have to be totally different: You should allow the user to snapshot the system state and navigate it. Generate succinct summary text to impart the same sense that a dashboard would to a visual user. "Normal: All systems OK" "Critical: Boeing RPA servers down since 2:17PM PDT and 54 others". Once you've done this work, a CLI tool could expose this just as screen-readable:

    $ cli status
      all systems OK, last outage resolved 2:27 PDT

    $ cli topjob cpu
      117 Boeing RPA, 78% CPU
      434 SAIC PDM, 43% CPU

    $ cli downtime today 117
      Boeing RPA down 10 minutes today, resolved now

  • I’m not just talking about screen readers, though they are important. I mean “accessible” more generally. Yes you could build a specific UI for each kind of user, but that seems far less likely to cover as many uses as building one UI that is structured, programmatically navigable, etc.

>I think TUIs-that-want-to-be-GUIs (as opposed to terminal commands just outputting plain text) are sad.

You'd think that, but you'd be wrong. Case in point from Emacs/Vim and the Borland IDEs to Claude, plus all kinds of handy utils from mc and htop to mutt.

>They flatten the structure of a UI under a character stream. You’re forced to use it exactly the way it was designed and no different. Modern GUIs, even web pages too, expose enough structure to the OS to let you use it more freely

That's not necessarily bad. Not everything has to be open ended.

  • Funnily, Emacs is getting closer to what I’m after (it’s my main editor).

    > That's not necessarily bad. Not everything has to be open ended.

    I think it is necessarily bad and everything should be open ended. Bad in the sense of low quality, but if we’re talking about critical accessibility (someone is unable to use your application at all), morally bad too.

  • How many developers are using VSCode? How does that number compare with Emacs/Vim?

    In many ways, GUI was developed as the natural evolution of TUI. X server, with its client-server architecture, is meant to allow you to interact with remote sessions via "casted" GUI rather than a terminal.

    Countless engineers spent many man-hours to develop theories and frameworks for creating GUI for a reason.

    TUI just got the nostalgia "coolness".

    • >How many developers are using VSCode? How does that number compare with Emacs/Vim?

      How many people eat microwave meals? How many eat gourmet Michelin star dishes?

      I don't care "how many use VSCode". My argument Emacs/Vim have great, well loved TUIs. And they are used by a huge number of the most respected coders in the industry. Whether a million React jockeys use VSCode doesn't negate this.

      >Countless engineers spent many man-hours to develop theories and frameworks for creating GUI for a reason.

      Yes, it sells to the masses. Countless food industry scientists aspend many man-hours to develop detrimental ultra-processed crap for a reason too.

      6 replies →

    • > How many developers are using VSCode? How does that number compare with Emacs/Vim?

      Perhaps I'm in some sort of "TUI bubble", but I'd bet good money that Emacs/Vim users outnumber VSCode users by an order of magnitude. But maybe I'm just surrounded by *nix devs.

      7 replies →

    • I agree except about the TUI coolness factor. There really is a lot that’s appealing about TUIs, I agree on that with the other commenters here. I want a better synthesis than what we have.

What is great about them is the constraints they impose on the UI designer. I spend so much time finding actions in apps like Zed, Obsidian or Slack because menus and rows of buttons are not cool anymore.

I'd really want explicit UIs from 2000, but in the mean time TUIs feel like an improvement.

  • I don't quite agree with this. Feature discovery is much easier in GUI when most commonly used features are either in the first layer of menu or in standard hotkeys. In the worst case, you would do a search in GUIs that provide them. In CLI / TUI, no such function is present and you would basically have to man and scroll through all possible commands to find it, though I guess grep helps.

    • You accept search in GUI, but don't in man pages? Scrolling through actions in a tree-like menu structure is ok, but through a tree-like structure in the --help output is not? Feels inconsistent.

      The whole benefit of text-based interface is that search, filter and transformation is always available and completely independent of the running program.

      I can see the visual discoverability aspect for GUIs, but for the visual layout GUIs and TUIs are on par, the difference is rather in the rendering mechanism: pixel vs. character-based.

      1 reply →

  • I agree about the constraints. My ideal solution would also impose harsh constraints, but would also add just enough structure. I’m also frustrated by each app reinventing the same thing slightly differently.

  • > because menus and rows of buttons are not cool anymore.

    They are, which is why most desktop applications use them.

    (And please help remind the GNOME people of this fact.)

They are GUIs --- just minecraft GUIs. One day, we will rediscover why GUI toolkits exist. The only real advantage TUIs have over GUIs is easy remoting, TBH. Maybe that's enough for people. Otherwise? They're just hair shirts.

  • I've use Claude to make myself a number of little tools and weird apps that only I would want lately. They need to be cross-platform between Linux and Mac and sometimes Windows. The best approaches I've found are Tauri (+Svelte for making layout easier) for lightweight GUIs but for anything more complex I prefer a TUI. The Ratatui framework works very well. A TUI feels like a "real" app as opposed to a glorified webpage. For actually serious software I'd want a native GUI on each platform.

    • There are so many options for what you describe. E.g. the whole point of Tcl/Tk is to allow easy creation of small little tools and apps. And you can use Tk with Python as well.

    • > A TUI feels like a "real" app as opposed to a glorified webpage.

      Huh? "Feels"? Plenty of Electron/Tauri apps feel perfectly normal. Like I've been saying, the TUI craze is just a fad.

      3 replies →

I like that they are integrated into the terminal and stay in the terminal. For most things my terminal multiplexer is essentially my tiling window manager and everything that breaks out of that via its own window is very unergonomic and breaks the structured logic of my workflow. Technically just having a full GUI inside the boundaries of a terminal would be fine for a lot of things. But it's also one of these things where constraints make a lot of things better. Many GUIs are just really bloated and bad. TUIs just do not allow a lot of the sins of modern GUIs.

I agree that they can get very clunky for non text based tasks or anything where you actually need custom text formating.

  • Yeah, I sympathise. This is another angle on the sorry state of affairs we find ourselves in.

I think I see your point. I've had it in the back of my head too.

Guess it's like the separation between backend and front-end. When the logic is neatly wrapped in a nice API you can potentially get a lot of reusability from that since the API can be integrated into other things with other use cases.

But a TUI probably doesn't naturally come with a separate backend. However, if a cli is built in a non TUI way it is about as flexible as a backend. Output can be streamed into pipes etc.

I can't stream k9s output into a pipe or variable but I can with kubectl.

Would be nice if we could have the cake and eat it here. Can TUI frameworks encourage having it both ways?

> They flatten the structure of a UI under a character stream

Isn't this ... everything though? Even the browser which you mention as better in the next paragraph.

  • No. The browser structures the page in both a DOM tree and an accessibility tree.

    • What.. no, its text.. I've seen it in view source..

      You're talking about yet another 'presented' data stream, which is different than the character stream.

      One can rebuild these at will, im sure.

      1 reply →

> You’re forced to use it exactly the way it was designed and no different

So ... Like all Apple products?

  • Not even close. Apple UIs - despite recent graphical howlers - have excellent accessibility APIs and are regularly praised by people that track such things. I’ve recently been building a macOS app and the UI testing is also based off it. There are apps that allow full keyboard navigation using it. I do agree that the window management side is much less customisable, though, and that does frustrate me.

Maybe we just need to go all the way: How about a WASM core with a React GUI that runs inside a custom Electron renderer which outputs the TUI? 100% CPU guaranteed. And you'll never find that important piece of information in an all-monochrome wall of text with no icons. Why use a low-level print() when you could improve your productivity with a high-level framework? /s

  • Did you reply to the correct post? Can’t see how it follows from mine.