Sinclair Target

Why Use the Terminal?

Dec 06, 2024

One might have expected that the terminal, a computer interface dating from an era before the desktop and the mouse and the graphical display, would by now be almost irrelevant. Instead, in 2024, we are living through a terminal application renaissance.

To the venerable old set of Unix tools like cat and sed, we can add some new indispensables like jq and fzf. Many of the new tools have been built in modern languages like Go and Rust. This is remarkable: Software developers were given fancy languages with memory safety guarantees and improved concurrency models and all sorts of features above and beyond what C and C++ can offer, and they used them to build… command-line tools?

Why is the terminal still a thing? Using the terminal can be so hard! You have to remember several dozen commands with cryptic names like ls and awk in order to get anything done. Every command takes a battery of options you always have to look up. More complicated terminal applications like Vim are notorious for being difficult to learn. Why do people work in the terminal when there are perfectly good graphical IDEs they could use instead? Do they do it just to look clever?

I’ve come to love working in the terminal. I love it so much that I sometimes wish I could crawl inside the terminal and just do all of my computing there, dispensing with graphical applications altogether. Obviously that would make my life very hard. Graphical applications are useful and there are many things that would be unpleasant or impossible to do in the terminal, such as web browsing. But I’m curious about why my attachment to the terminal has grown so strong and why it has elicited a corresponding aversion to graphical software.

I’m not trying to make anyone who likes their GUI-based tools feel bad. I’d like to figure out for myself exactly what it is that software gives up by being GUI-based rather than terminal-based—and I’m increasingly convinced something important is given up—but that doesn’t mean the tradeoff is never worth it. I want to write about this because so many of the explanations I’ve seen for why you should work in the terminal seem to miss something critical that could help us better understand the relative merits of graphical and terminal software.

So let’s start there, with two reasons commonly given for why people use the terminal that I think are overrated.

Keyboards

The explanation I was given in college for why the command line is useful was based on speed and fluency. The argument was that typing commands at the command line, once you get good at it, can be faster than clicking through nested menus with a mouse. I remember our Introduction to Computer Science class being told to have patience, because even if the smallest task was a huge undertaking in the terminal now, that was only because we did not yet know all the basic commands and flags. Once we were over the hump in the learning curve, we’d prefer the command line because it would then be easier.

I didn’t buy this argument because the putative gains in speed seemed so minor next to the drawbacks of using the terminal. Does it really matter if you’re able to do things 10% faster, or even 25% faster? In a graphical environment, you can discover the functionality of the software you use as you go and you don’t have to commit everything to memory. Giving that up for a fractional gain in efficiency and ergonomics didn’t make sense to me.

Today, I understand better what those gains in efficiency and ergonomics feel like. I hate using my mouse for anything and love that I can do everything in the terminal from the comfort of my keyboard. But it’s not about speed. Perhaps if you timed me with a stopwatch you’d find that I can do some tasks faster at the command line than via a mouse and GUI, but speed isn’t really at the forefront of my mind when I’m thinking about how to accomplish a task at my computer. What it’s really about is laziness. Using the keyboard and command line to do something is like cutting a corner across the grass when the path I’m following doesn’t go where I want it to go. It’s not that I particularly care about getting where I’m going more quickly. I just can’t be bothered to walk all that extra way.

So, yes, once you have invested a lot of time and energy into learning how to use the terminal it can be hard to imagine going back. But that would be true of anything you spend a lot of time and energy on. You could spend a lot of time learning to efficiently navigate your favorite GUI software applications and you’d end up in a similar situation where the trails pressed into the grass involve menus and features in those applications rather than arcane command invocations in the terminal.

And that wouldn’t necessarily be slower. Just because something is a GUI application doesn’t mean it can’t have hotkeys and shortcuts. You could even use a GUI application without ever touching a mouse; Slack is not hard to use this way. People claim all the time that everyone should use Vim to edit text because of its amazing keybindings, but given that so many GUI editors have plugins providing Vim keybinding support or even an entire Vim emulation layer, that’s only an argument to use the keybindings and not an argument to use Vim itself.

So the keyboard ergonomics / speed explanation for why people use the terminal just doesn’t seem that good to me.

Servers

The other explanation I’ve often seen for why people prefer using the command line is that it’s necessary for working on remote servers. According to this explanation, if you need to SSH into remote servers anyway, then it pays to learn tools that you can use both locally and on the remote servers.

In my experience, backend developers are more likely to use the command line and especially terminal text editors than frontend developers, so maybe there is something to this explanation.

But remote desktop software exists! It is more commonly used in the Windows world than it is in the Linux world, but on both operating systems, if you really want to, you can deploy your software by remoting into a server and then dragging and dropping some files and clicking a few buttons. Backend developers learn to use terminal text editors so they can edit configuration files on servers over SSH… but if they were to use remote desktop software, they could edit files in Notepad or VS Code or whatever they fancy.

Maybe this seems a pedantic thing to point out. In practice, most software organizations don’t use remote desktop software, so relying on the terminal is necessary for the software engineers employed by those organizations. But then one could ask, if it’s at least possible to deploy software using a graphical interface, why don’t more software organizations do that? The terminal might be necessary for SSH-ing into remote servers when you have them set up that way, but why not set them up differently?

So my problem with this explanation is not that it’s wrong but instead that it’s only a first-order explanation. It doesn’t get at why the terminal is still the vastly more popular interface for accessing and controlling servers.

Zen and the Art of Software Maintenance

I think the real reason that the terminal remains useful is that the terminal is simpler.

Command-line programs are more complicated to use, yes. But the programs themselves are simpler.

Command-line programs don’t have to worry about drawing menus to a frame buffer. Command-line programs don’t have to worry about system-specific APIs for creating windows or system-specific UI conventions. Command-line programs generally don’t have to worry about handling a mouse click at any time, and can consume their input only when they are ready to.

Why does it matter that the programs themselves are simpler? I’m going to try to explain why by taking a detour to discuss a book I loved but that many people find pretentious. Sorry. It will wind it’s way back to the terminal in the end, I promise.

I recently finished reading Zen and the Art of Motorcycle Maintenance. The book is ostensibly a novel about traveling across the United States on a motorcycle, but really the plot is there to motivate an extended reflection on the relationship between human beings and technology. I’m far from the first person to observe that the book offers lessons for software developers and not just motorcycle mechanics. There are so many ideas you could take away from that book and apply to software. I want to focus on how the book describes maintenance—what is actually involved in maintaining something—because it helped me clarify for myself why I think simplicity is so important for people who build software.

You might not think that software developers have much in common with motorcycle mechanics, but Zen and the Art of Motorcycle Maintenance makes a compelling case that maintaining software and maintaining motorcycles are the same activity. Motorcycle maintenance seems like a different thing because it involves a physical motorcycle with bolts that need to be tightened and fuel filters that need to be replaced (or whatever, I don’t know anything about motorcycles). You might, by working on a motorcycle, get your hands greasy. Software development obviously isn’t like that. But in reality what both the motorcycle mechanic and the software developer are maintaining is the system.

The system is not the physical thing, or even the digital thing, but the bundle of concepts and their relationships to each other that constitute the real design of the thing, the web of cause and effect that actually makes the thing work. With software, perhaps because there is so little to look at, we have an easier time recognizing that the bytes in any one copy of our program aren’t what matters. What matters is the design of the program and the way in which subcomponents of the program interact with each other to effect changes in the program’s environment. This design resides partly in the source code for our program but also partly just in the head of the last programmer to have worked on it, a problem we do our best to overcome with documentation. This underlying design of a program is what Zen and the Art of Motorcycle Maintenance calls the “system.” Other people have called it the “theory” of the program.

Motorcycles have a system too. You can divide them into subcomponents that interact with each other. Motorcycles can be divided, according to Zen and the Art of Motorcycle Maintenance, into a power assembly and a supporting assembly. The power assembly can be further divided into the engine and the power-delivery system. The supporting assembly can be divided into a frame, a steering assembly, front and rear shock absorbers, wheels, control levers and cables, lights, horn, and so on. It’s the relationship of these concepts to each other that make a motorcycle go, though the physical reality of a motorcycle might make that harder to appreciate:

That’s all a motorcycle is, a system of concepts worked out in steel. There’s no part in it, no shape in it, that is not out of someone’s mind… I’ve noticed that people who have never worked with steel have trouble seeing this—that the motorcycle is primarily a mental phenomenon. They associate metal with given shapes—pipes, rods, girders, tools, parts—all of them fixed and inviolable, and think of it as primarily physical. But a person who does machining or foundry work or forge work or welding sees “steel” as having no shape at all. Steel can be any shape you want if you are skilled enough, and any shape but the one you want if you are not. Shapes, like this tappet, are what you arrive at, what you give to the steel. Steel has no more shape than this old pile of dirt on the engine here. These shapes are all out of someone’s mind.

Repairing something, whether that something is a motorcycle or a computer program, involves identifying where the system and the specific embodiment of the system (in steel or in code) have diverged. You do that by forming hypotheses and testing them. Testing a hypothesis might involve some labor—you might have to remove parts from your motorcycle, or set up your program to run in some different environment—but the hardest and central task of maintenance is understanding the system of the machine and using that to form hypotheses about what might have gone wrong:

An untrained observer will see only physical labor and often get the idea that physical labor is mainly what the mechanic does. Actually the physical labor is the smallest and easiest part of what the mechanic does. By far the greater part of his work is careful observation and precise thinking. That is why mechanics sometimes seem so taciturn and withdrawn when performing tests. They don’t like it when you talk to them because they are concentrating on mental images, hierarchies, and not really looking at you or the physical motorcycle at all. They are using the experiment as part of a program to expand their hierarchy of knowledge of the faulty motorcycle and compare it to the correct hierarchy in their mind. They are looking at underlying form.

The part about not liking it when people interrupt you should feel familiar to any programmer. You’re busy trying to hold the system in your head.

I’ve found this to be true of other kinds of technology as well. My fiancée and I recently came home to discover that our furnace wasn’t heating our apartment to the temperature we’d set on our thermostat. We know very little about HVAC, so our chief hurdle in troubleshooting the problem was our ignorance of the system. We had to remind ourselves first of very basic things like whether our furnace burns gas to make heat so we could figure out whether it’d be worth checking the gas intake to our home. Eventually we found a manual that told us how to interpret a flashing light on the front panel of our furnace. All we had to do was flip a switch off and on to fix the issue. The actual fix itself was trivial. What was hard was understanding the system.

Okay, so why does this similarity between software maintenance and other kinds of maintenance mean we should write and use software built for the terminal?

What Zen and the Art of Motorcycle Maintenance helped me better understand is what I mean when I say that software written for the terminal is simpler than graphical software. What I mean is that terminal software has a simpler underlying form. The terminal, as an application platform, has plenty of complicated quirks and idiosyncrasies. But if you were to diagram out the subcomponents and interrelationships of a command-line program, there would be fewer boxes and arrows in that diagram than there would be in an equivalent diagram for a graphical program. You wouldn’t need to draw a box for “event handling” or “text rendering” or “layout.” The terminal, because its rules are simpler—just write text to stdout, or if you’re being fancy, write text and escape codes to stdout—enables simpler programs.

This matters when you want to fix or change programs. If you never want to do that, than it doesn’t matter if you use a complicated program or not. But then you’re like the main character’s friend in Zen and the Art of Motorcycle Maintenance, who buys an expensive BMW motorcycle in the hope that it never breaks and he will never have to maintain it, but who is constantly in danger of being stopped in his tracks by minor issues with his bike. If you want to be able to tweak or maintain a program, you need to be able to form hypotheses about why it isn’t doing what you want it to do. A simple underlying form makes that easier.

If you click on a menu item in a graphical program and nothing happens, is that because something went wrong with the action you were trying to perform or because something went wrong with registering the click? Wait, are you positive you clicked on what you thought you clicked on and not actually two pixels to the left of it? You see why a command-line program might be easier to reason about, even if it’s harder to use.

So ultimately I think the terminal is still a thing today not because it’s somehow more ergonomic or because it’s the only way to access servers. The terminal is still a thing because command-line software is easier to write, modify, and maintain. Engineers SSH into servers rather than remote desktop-ing into them because then they can create deploy scripts and update them over time and these things are easier to do when we don’t have to think about icons or menus or somehow scripting a bunch of button clicks. If terminal text editors offer improved ergonomics then I believe that’s mostly down to how configurable they are. They’re configurable in a way that graphical IDEs are not because there’s less there there that you have to worry about when writing a plugin.

Again, this doesn’t matter for end users of software and maybe not even for software developers that have found graphical tools that work for them and never break. But if you want to work in an environment you can tweak and change and fix—if you want to ride a motorcycle you can maintain—then that’s what the terminal is for.