NeuraLinux Bringing GenAI to the Linux desktop

Linux shells have terrible UX

The UNIX command-line was clearly designed by the hardened programmers fabled in The Night Watch, who worked with rudimentary tools like pointy sticks and teletypewriters. They laid the groundwork of their OS with their bare hands and wrote textbooks when things went wrong. However, today’s command-line users get to wear their non-functional scarfs and sip tea while executing ./run.sh because of the hard work of those systems programmers before us. But boy did they leave us some unresolved baggage while designing these systems.

Unix shells have the worst out-of-box user experience I’ve ever used, rivaled only by that of the original ed line editor and my school’s class registration portal. They are enigmatic and dumb programs that work the way I imagine Patrick Star thinks. Your command didn’t seem to do what you expected? Well then you’d better cross your fingers it didn’t have any side effects, or else you’ll be scratching your head pondering what happened to your disk image went after executing sudo dd if=/dev/sdb of=archlinux.iso.

Though shells are extremely pragmatic and efficient, they are interactive tools designed for humans at the end of the day. Why don’t we take a look at the evolution of UX features in influential shells?

  1. Multics shell, 1967. This was the OG command-line interpreter, distributed with the Multics operating system. Bet that surprised you. It started as the primitive program, RUNCOM, that executed commands in a script back to back (the “rc” from “.bashrc” is a remnant of this program) The subsequent shell attempted to use “commands somehow like a programming language” (remember this).
  2. Thompson shell, sh, 1971. A Bell Labs shell modeled after Multics shell and was distributed with UNIX 1-6. It introduced piping (ls | grep 'txt'), wildcards (ls *.c), and conditionals.
  3. Bourne shell, sh, 1977. Another Bell Labs shell which was distributed with UNIX 7. It introduced more of the basic features common to all Unix shells, like functions (x() { echo x }), asynchronous execution of commands (sleep 5 &), and a fresh environment for every subprocess.
  4. C shell, csh, 1978. At last, a shell with thought put into its interactive usage. It supports everything from Thompson shell + history, command substitution (echo $(date)), aliases (alias l='ls -al'), here documents (cat << EOF), condition testing ([[ -z $(ls) ]]), named variables (a=b), and iteration.
  5. Bourne again shell, bash, 1989. The first open source shell made for the GNU project, implementing all the features before it. Later versions added Perl-style regex and associative arrays.
  6. Z shell, zsh, 1990. Open source, based on C shell, and introduced extended globbing (ls **/*.c), spell check, and a whole lot more customizability.
  7. Fish shell, fish, 2005. Basically, a fully configured zsh with autosuggestions and syntax highlighting out of the box. Not widely adopted due to slow performance in scripting tasks.

The timeline of Unix shells

My point with all of this is that popular shells have not changed since the C shell in 1978. (Note: I read on IBM’s website that shells are like text editors where everyone has a favorite and tells you why you should switch. If a stranger tries to “convert” you to another Unix shell, please politely advice them to pursue more interesting things in life and walk away).

Now, I already hear those of you with grey beards that touch the ground thinking “this gen-Z kid does an awful lot of complaining, the shell is old and reliable.” But as I would say to someone who says the same about Subway, it doesn’t have to be this way. You don’t need to put up with their bland bread and mystery sauces in a world where pub subs exist. The truth is that an increasing number of CS students are being exposed to the shell and are freaking out because they have to learning a foreign language, one which has a vocabulary containing “chmod” and “lsmod” which sound similar but have absolutely nothing in common, one where they learn not from Duolingo but rather man pages where the key bindings of the pager are derived from a 1976 text editor (vi).

At least with math theorems, if you pick any Eastern European man’s name, you’re probably talking about something vaguely related. But in this realm, our vernacular comes from whatever the programmers were feeling, plus 3 bits of quirkiness entropy, XORed with whatever they had for lunch. For example, the command line tool ripgrep is a faster grep, which stands for “globally search a regular expression and print,” of course. Or less, which is actually a more feature-rich pager than the older more. Thanks, Multics shell, for the absense of a naming scheme. Program names are like coral growing on top of other, more dead coral.

alt text

Let’s talk theme. Take the default zsh prompt vs zsh with the powerlevel10k theme. In the former, all I’ve learned for free is that my name is Chinar… great.

alt text

In the latter, I get my current working directory, return status of the previous command (green vs red arrow), and the git branch and repo status when applicable.

The difference in the mental overhead of this small component is baffling. Hopefully, no-one uses the default shell theme for more than a one-off ssh session, but defaults are powerful, and users are required to either blindly copy and paste enigmatic incantations that for some reason care deeply about spaces, or take the time to learn shell scripting. In the latter case, many hairs will grey to the realization that dereferencing a pointer var in bash is ${!var} which makes sense, but in zsh it’s echo \$$var. sigh… I suppose our portable shell scripts can’t have nice things that were invented after Stephan Bourne.

Ideally, our computers would understand our English directly, and require less interaction to achieve whatever task we sought to do, correctly. The latter can be readily achieved with built-in shell primitives like the alias. And now that LLMs are extremely widespread, the former seems begging to be solved as well. I think the combination of the two would radically improve the users experience across all existing shells, with no fancy DSL or extensive configuration required.

I don’t need to write about the countless quirks of Unix programs; there’s a whole book about it. But despite some poorly aged user-facing design choices, I love the Unix philosophy and ecosystem. The fact the design principles are so pervasive to this day is sufficient proof it did something right. But for the unacquainted bunch, learning “the terminal” is an unnecessary source of anxiety, pushing them to the tantalizing evils of Microsoft 365 and Google Drive. If a few people from the containerization bunch or Red Hat rack their brains on what the average command-line user needed while still being practical as a default, I’m sure we would have shells that are more friendly and forgiving than Ebenezer Scrooge.