Command line interfaces are reified UIs
expressionsofchange.org
expressionsofchange.org
If we have to search for an underlying reason, it's that most GUI interactions by most end users don't need reification and therefore, that code is not put in.
If the GUI has obvious needs for reification, the programmers account for it. Two examples that come to mind are computer chess games, and software audio workstations.
Many computer users who are comfortable with UNIX command line will nevertheless "move chess pieces" by clicking and dragging the piece from one square to another. However, virtually all chess programs still record the algebraic chessboard notation of each move and the players can see the tally of moves scrolling on the side of the board.
The other example has music producers mixing a song. They will adjust the sliders/faders of volume panning and the software will record their moves. It's known in the trade as "mix automation". When the song is played back, the software makes the sliders mimic the same moves. The automation in "reified" into a time graph[1] such that one can move the nodes around to fine tune the movements more precisely than the fingers did in real time.
As for other GUI applications like typical business data entry screens, etc... most GUI toolkits like C# Winforms, C++ Qt, HTML buttons, etc do not include a macro recorder in the default event loop. Therefore, to "reify" the GUI in the same fashion as chess programs or the audio software requires grafting data structures and programming extra code to "record" the button presses into a timeline. Programmers won't do this unless there's a customer need for it. (E.g. Photoshop lets you reify the GUI as "actions" for later playback")
[1] example yellow line graphs the fader or knob changes: http://cdm.link/app/uploads/2014/06/logicmixing-640x399.jpg
Hell, often it is useful to launch a X11 program via a terminal as they will dump useful messages that way.
And said output can also be captured in logs elsewhere.
One example of such would be SMPlayer. This is a Qt based media player that wrap MPlayer (and more recently the MPlayer fork MPV). But you can still access the MPlayer CLI output by either launching SMPlayer from a terminal, or going opening the log window from one of its menus.
Since this has been par for the course for for as long as I remember, I take it that's not what's discussed here...
A manager once asked for full undo in a GUI for a shared db. That's not possible...
My point was that if actions are dependent and undoable then they form a stack. If everything can be undone then all that you are affecting (including view state, config, ...) has simply become part of the document.
In the app I'm developing I'm distinguishing "actions" as being what a shortcut/button/menu item represents and "commands" as being document modifications.
Actions aren't necessarily undoable ("quit" is an example) but most actions end up as being commands, and those commands form the undo stack. Actions handle availability (enable/disable) etc. I think this is a fairly standard pattern for document based applications.
Other software like Houdini or Maya (or NR Shake) used DAG (acyclic graph) of operations to create an output scene/image. There the history isnt linear it's a bit of a multiverse, you can disconnect part of the graph, try new things, reconnect. Everything is there.
I don't think Paint.NET or GIMP do quite what you've described though. They show a history of action, but they don't show commands.
Here is a example: https://i.imgur.com/NNFruMx.jpg
Though as you mention, many developers nowadays don't see the need for history, and so are putting application/webpage state somewhere other than the router. This IMO is short-sighted, as it undermines the transparency of a user's actions on the web. And plays into the walled-garden effect many of these same developers will lament in the loss of the "open web".
There are several ways to capture that state, and the nice thing is that the browser allows sites to either opt in or out depending on their requirements.
See: Insights, FullStory, or any other event hooking library.
We can also play back those actions using the very nice WebDriver apis available in modern browsers.
There is zero reason to assume that we've lost reification simply because we've moved away from an approach that requires at least one RTT in latency before updating what the user sees.
It's not something most users do, so if your argument is "Reification is not on by default for all users" then sure.
But that's a meaningless statement. Most users don't want that ability, or aren't willing to spend the 10 minutes it takes to configure.
Otherwise, you absolutely can enter commands and output state: https://sites.google.com/a/chromium.org/chromedriver/downloa...
Further, there are a HOST of tools that make this process very easy, complete with replay solutions, detailed logging, real time monitoring and all sorts of other fantastic, modern tools.
Just because you choose not to use them doesn't mean they don't exist. Sorry your understanding of web dev is out of date...
* The interface is typically NOT optimized for keyboard.
Typing E4D5 is not optimized. You need to look at a square in the middle, then look which row it is, and which column it is. I've implemented a better one for a similar game (Jungle). You press a character key to highlight one of your pieces, and the game essentially highlights legal moves by displaying alphanumeric chars on tiles. Instead of 4 keypresses, you have 2. In Chess it could be like this: 1-8 selects a pawn, b/B one of bishops, r/R - rooks, k/K - knights, q - queen, i - king. Then another character depending on what shows up where you want to move. * People who play realtime chess (one example is Kung Fu Chess)do use keyboard
certainly those playing in tournaments.E4-D5 notation is optimized for recording games, not for playing.
depends on the type of player. Every serious hobby player can do it that way. They learned it.
But for casual players it is not the way to go, I agree.
In the MacOS System 7 days when Apple was still pushing AppleEvents/AppleScript heavily, a good portion of Mac software would let you record your actions in them through the AppleScript Script Editor (they would emit the AppleEvent equivalents of your GUI actions), generating an AppleScript which you could then edit. It was a fantastic system. It's still there in macOS X, but it's rarely supported/used now.
The real value of CLI tools is extensibility and scriptability. You don't have to rely on the application developer inserting UI hooks everywhere; you just write a shell script, and in the absolute worst-case scenario use Expect to automate interactive processes. And adding a new subcommand is relatively trivial. The code is typically easy to trace the user input down to the internal machinery. The UI is a very simple function dispatch and argument-passing mechanism. There are no widgets to worry about, no switches or boxes to position.
Therefore CLI tools will always be beloved by power users and feared by everyone else. If you know exactly what you're doing, they can really speed up your workflow and provide and interface for precise, expressive control and automation. Otherwise, all but the best-designed CLI tools are intimidating and difficult to master. Who can remember all those switches? Having a bunch of labeled buttons laid out in a UI leads to a much lower cognitive load.
IMO the real value is in CLI applications that can be embedded in a GUI, but are embedded transparently, in that the GUI can be scripted by simply scripting the underlying CLI. Git (Git GUI, GitHub, Tortoise, Tower, etc), Apt (Aptitude, others), TeX (Tex Live Manager, kinda), and others have good interfaces along these lines, but we're definitely in need of a good CLI interface for Rsync and Tar. Many CLI wrapper GUIs tend to be opaque and don't expose enough underlying functionality.
One standard for history-keeping is the following: If we start with a clean system, and replay all the commands from the history, will we end up with the same system?
This is how Lighttable, Photoshop, and other Adobe CS products work. Also the Vim "undo tree" to some extent. It's an excellent feature.
This is where your CLI application becomes a de-facto API and the wrapper has to anticipate and handle any output from the command. It's an astonishingly brittle system (have fun using any GUI around CVS) to the point that in many cases the GUI doesn't actually wrap a CLI application, but instead uses a library (e.g. most Git GUIs probably use libgit2 instead of calling the CLI). Libraries tend to have better designed interfaces for other programs, you don't have any problems with shell quoting and you don't try to shoehorn an interface for users into one for programs.
Bspwm[0], for instance, uses a client CLI program (bspc) to send commands to the daemon and alter its configuration at runtime.
In fact, it doesn't have a configuration file format at all, since it can be configured via a simple shell script that runs a sequence of bspc commands.
It also doesn't have any key binding functionality and offloads this to a separate program, sxhkd[1], whose only purpose is to interpret key presses and execute shell commands. Since this is bspwm's interface, the two work seamlessly together, even though they're not dependent on each other at all.
This is just brilliant design, and speaks volumes for the "do one thing and do it well" school of thought.
For the record, I've been using both programs without a single issue for the past 3 years at least, and it's been one of the most stable and least problematic systems I've ever used, and use to this day.
So just wanted to offer an opposing personal experience (anecdotal, to be sure) regarding your brittleness concerns with this interface.
[0]: https://github.com/baskerville/bspwm [1]: https://github.com/baskerville/sxhkd
And frankly i suspect that CLI gets a bad rep because MacOS never had a CLI to begin with (OSX got one via its unix internals, but i am unsure Apple knew to value it), and DOS was minimalist to put it mildly.
Sadly this has lead to unix UI devs to disparage the CLI when they should embrace it. That a X11 GUI tool is a wrapper around CLI tools is not a hindrance but a boon.
It means that if the CLI tool behaves correctly, the GUI tool will as well. And if the GUI tool behaves incorrectly, the user can try the same in the CLI to see where the problem originates.
It is really sad to see the push towards using dbus rather than CLI to communicate between GUI and daemon, as so much potential information is obscured in the protocol.
Macintosh didn't have a (built-in) command line for a long time, but it has supported scripting for a long time, starting with System 7 in 1993.
And prior to AppleScript, there were a few other CLIs on early Macs: Terminal programs like telnet, the CLI in MPW, and CLI / scripting in Applications like HyperCard and others IIRC.
I'd rather say that it was Windows which made the CLI look bad. They made people think that CLI means old fashion technology. Amiga like OS X had a window system and CLI from the beginning and so users did not view CLIs as old fashion technology but rather as one of several alternatives.
My experience from the time was that it was mainly PC Windows users who talked down CLIs because they viewed DOS as a antiquated. In some ways it makes sense as the DOS CLI has been horrible for decades and MS never put any effort into making it nice.
I'd say OS X could be thanked for resurrecting the CLI. I still encounter Windows developers who almost don't know about the CLI and who never uses it. I don't think you find and OS X developers in the same position.
Other problem: man pages are too long to read because modern CLI tools are cluttered with lots of rarely used options. I wish developers followed Unix way [1], but trend goes in the opposite direction.
I'd consider the front panel of physical buttons, switches, knobs and dials of early, pre-teletype computers to be much more like a GUI than a CLI. We circled back around to buttons and sliders, with state display laid out in 2D in ways our brains enjoy.
But we can gain some knowledge from the game nonethless. Control panels do have some great benefits, because the human vision system is so powerful, and because there is the possibility of direct manipulation.
But the CLI has the great advantage that you are just telling the machine what to do, instead of having to point and grunt. But it's not good for ordinary users because the language is baroque while also requiring you to talk very precisely.
We missed a lot by being slow to develop "fuzzy CLIs" where people can talk more lazily. The "press the windows key to search" feature from Win7 onwards is a good start in this direction.
Not surprisingly the following transitions happened in many industrial applications, complex vehicles, not to mention weapons (e.g. submarines):
"few knobs and dials" -> "airplane cockpit" -> airplane cockpit + keyboard and a simple CLI -> full scripting
For me the key thing about CLI's is the same as the benefit of plain text in the traditional unix style of thinking.
When your interface to any functionality is plain text you have the advantage that you can use any number of generic tools to manipulate that interface.
One example is how visual programming languages are mostly failures. It doesn't take long before the inherent problems of composing a program in a GUI is made clear. Text is easily malleable.
You see this on many levels. You might be in an IDE and need to change a value of multiple settings or duplicate some setting several times, except there is no tool in your IDE to actually do a substitution of values in arbitrary settings or do duplication.
However when settings are represented as just plain text, this becomes a trivial matter to solve.
One of the reasons I love macOS so much is that from the very beginning of OSX Apple made the interaction between GUI and CLI very smooth. They both have strengths and I am no fundamentalist, and so they should work well together. You see that in how Apple early supported things such as dragging and dropping objects from the GUI into the terminal.app or the "open" command which allowed you to invoke the appropriate GUI tool for a given file type from the CLI.
The Plan9 guys probably went furthest in this. They seemed to have woven GUI and CLI thinking tightly together.
Thus one gets a history of commands, which also can be reused, even from mouse gestures. Selecting a command from a menu or direct manipulation usually will lead to a recorded commnand in the interactor. The interactor runs a command loop.
Or, in other words, "|" in the shell is "." in Haskell (with operands reversed).
Well for real power you also throw partial application and arbitrary sub-lambdas / case-switches / let-binders into this mix and now that basic 'pluggable' composability truly shines =)
http://www.osnews.com/story/6282/The-Command-Line--The-Best-...
It basically talk about teaching older people to use computers by way of the unix CLI.
Economy:
Graphical protocols like X or web standards are much heavier over the wire than text, and are often not suitable for many use cases. There is also economy of movement, moving the hand back and forth from keyboard to mouse or up to the screen to tap.
Consistency:
Text is a relatively simple data format supported everywhere. Cutting and pasting data with images and formatting, for example, is often a mess or doesn't work.
Precision:
Mouse (and touch) input is imprecise and frustrating analog experience. Clicking on a specific point requires moving to it and not missing it. Grabbing an edge of a window is the least elegant gesture ever created. Text entry is precise and digital.
Yes! But only because they made it 1px wide, and do not auto increase the border once you get close ... really stupid and inconviniend.
re·i·fy
make (something abstract) more concrete or real. "these instincts are, in humans, reified as verbal constructs"
In addition to creative authoring tools such as Photoshop which others have mentioned, I want to praise Microsoft's SSMS (SQL Server Management Studio). Some years ago, I had spent some time DBA'ing MS SQL Server and really enjoyed that tool. It's an extremely discoverable GUI for managing this very complex DBMS, and before every operation you perform through one of its wizards it would show you the T-SQL command it generated to perform that action, so you could review and/or script it.
I wish more sysadmin tools were like that.
We can take as our model of a simple UI the "dialog box", in which a user can prepare some inputs, and then submit. The "dialog box" corresponds to a function with arguments, and the sumbmission is a function call. So of course, in an underlying programming language, the equivalent can be reified as a first class function.
Even a relatively unsophisticated textual CLI can "reify" that at least by turning the concept of a "command" into a string value: there can be a variable that can hold a command, which can be passed around, dynamically calculated and altered, and executed.
The UI usually has no straightforward equivalent of "generate 100 instances of this dialog box invocation, feeding successive values from this list into the ID field ...". That sort of "reification" can occur with tools that automate the generation of events into the windowing system.
Graphical frameworks in which you can make "actor" objects and hook them up are kind of a reification of the GUI.
Pain points for me are discoverability and ease of making dangerous mistakes. I can't remember the command for every useful utility and it's very easy to accidentally break lots of things. Great power comes with great responsibility and all that.
What tools do you use for auto-complete-ish features on the command line? or anything to generally make using it easier.
I think the real usability issue of CLI is that their potential is handicapped if you don't know how to compose these programs, etc. In other words, if you don't know your way around a Unix command line, you're not going to be able to make use of the tool that assume that knowledge.
I think this is different than what you're saying, but maybe I'm just repackaging your points?
I personally prefer working on a command line because it's _more_ discoverable to me than most gui's. This did take some getting used to though. The approach is different.
The worry over making dangerous mistakes is understandable. That said I have made very few big ones after a bit of learning, and it has also helped me _avoid_ making dangerous mistakes by facilitating the automation of otherwise delicate or involved tasks which would be unpleasant to click and type through.
That kind of system would have been very hard to make with object oriented programming. But thanks to the recent advances in programming languages supporting asynchronism and composability, we'll see more of them.
Of course, this interaction with the command interface - that of selecting the previous command, copying it, then pasting it - is not 'reified'. It is executed through the - we may have to admit it - graphical interface through which you are interacting with the command line interface. It's not a purely textual interface, after all, since it includes graphical elements like a cursor.
As an experiment, consider that a voice assistant like Alexa or Siri is also effectively a command line interpreter, but that in those cases 'copy paste' is not available so easily. 'Siri, repeat back the last command I gave'?
So maybe the interface that is being praised here isn't the command line but rather the graphical interface in which a command-reifying interface is hosted...
I didn't say anything about using a mouse to interact with the CLI - copying and pasting don't require a mouse, but they do require a UI through which you can see what you're selecting and copying, even if it's just cursor key driven. And it's the original article which suggests copy/pasting commands from web pages or docs into your CLI, as well.
One supremely nice thing about *nix-style systems is that most programs will barf a number of complaints along the way to failure, while Mac/Windows counterparts typically fail silently or log errors to a mysterious per-app location.
We've already had a half-assed version for decades, part of nearly every GUI ever (though they're falling out of fashion these days): "status bars." And most OSes also already have a "scripting" mechanism that requires applications to expose a specific "scriptable API" (WSScript requiring ActiveX components on Windows, Automator requiring Apple Events on macOS.)
So just combine the two! The OS could have a "status-bar control" that you'd stick onto your main window of your app, which would start as a regular status bar, but have a little disclosure arrow—that would turn it into a full historical log of every previous "status", plus a REPL for entering script (probably with a dropdown to select which of the OS's available "scriptable languages" you're writing in.)
If you don't want to muck up your GUI, you could simply detect whether your GUI app has been launched from an interactive terminal (i.e. whether stdin is a PTY) and then provide a regular REPL-like interface on the terminal. A lot of GUI apps already log to stdout in the expectation that developers will be running them from the terminal; why not just add some more interactivity the same way?
---
I should also mention a third, much less obvious route: Plan9's Acme editor, which isn't so much a "GUI editor" in the normal sense as it is a text buffer with a configurable space of API commands hanging off of it.
In Acme, the menu system (and its associated keyboard accelerators) are effectively just another text file that you can tab into and edit. Each thing you write into the menu is just a literal API call. Hitting that menu item will then call that API, passing the selection or the current buffer as necessary. [It's actually even more universal—in Acme, left-click selects and middle-click activates. You can write a command anywhere and then middle-click it. The menu just provides a convenient holding place for middle-click-able text.]
Acme has its own internal commands—sort of like Windows PowerShell—but it also allows you to just write regular shell commands into the menu as well. Activating a `wc -l` menu-command will literally just dump the output of `wc -l` into the status bar. Activating `tr A-Z a-z` will literally just tr(1) your selection/buffer into lowercase. Etc.
And I fudged a bit: the commands that are "internal" to Acme are just shell commands too. Since we're talking about Plan9, every process has its own environment, so Acme has a set of internal binaries that end up in its own /bin. These little "command" programs just use RPC to send commands to the current Acme instance. So the "scripting environment" here is literally the shell itself! (And you can "script" Acme from outside it, too, by mounting its command-binaries from wherever it keeps them, into your process's /bin dir.)
Now you can do a GUI-less Windows server install, as manage it completely over the CLI.
Never mind that with Windows 10 there is no damned way to tell Windows to request a new address from DHCP if the initial attempt failed. The only way to do so is via the CLI and ipconfig.
In Unix, "everything is a file", and what is not a file, is a program that can be configured or a CLI with arguments that can be passed in programatically.
A button might kick off a set of tasks and aggregate the output into a final success message. If it doesn't work there's almost no way to dig into what's going on or even attempt to get the program to an acceptable state with whatever data you're working with.
A CLI might have an analogous command that also kicks off a set of tasks but if it breaks/doesn't work and assuming the CLI is following a unixy model, you can run through specific commands diagnosing the issue or at the very least get to an acceptable state in your workflow that leaves you with a few options to work with.
Any GUI, in my opinion, should just be a visual abstraction from a set of executable tasks that can be run individually. Take something like Github's Desktop client. In yester-years, when it first came out, it was pretty bad at handling git rebasing operations. But because of the way git was built and used most of the time, the Desktop client actually just called into the gitlib API or even just straight up wrapped git commands. If something broke, just like rebasing, I could actually take to the command line, inspect the state of the repository, and continue with rebasing via the vanilla git commands. And even then, when a git command doesn't act right, it might actually just be a wrapper around other more internal commands that you can execute yourself (i.e., git pull is actually analogous to git fetch; git merge origin/*). Compare this to a TFS error I've been getting for a few months on a legacy repository, with little to no information across application and system logs, and almost no information via google: "Provided parameter is not valid." Neat.
I wish the described "composable application" if you will was just a standard across every application. Even in web applications I build I make sure there are "steps" in data processing instead of just monolithic operations. I take care to make sure steps can be kicked off individually with sane output. It seems like we lost this philosophy along the way across every level of application development and the linux ecosystem hasn't been immune from this in my experience. Windows has never really stepped foot in those waters until recently with PS. But most of the time, in my experience, we get GUI's with no recourse. If it breaks you just might be out of luck until a patch comes in or you can interact with the data yourself.
Maybe one day if a program (even a web app!) doesn't provide a set of clean commands to run we'd look at it like we do a badly designed GUI, with disdain and disgust.
Against better judgment, I will bite.
The author makes a valid point. Consider command line history, and command line editing via vi or emacs bindings. I use sh like a REPL all day, every day. I make constant use of searching prior tasks with Ctrl-[ + / or fc -l. I also have hundreds of short, saved scripts.
I do not use a mouse or X11, no vim. I do not use a "clipboard", other than tmux buffers. Everything happens through editors/pagers like sed, vi and less. There is constant iteration. What is the GUI equivalent? Keyboard macros?
The ultimate aim is to make tasks non-interactive. To script away the interactive work. Automation. This is in direct opposition to the philosophy of the GUI: that work must be interactive, and to make interaction more pleasant.
But there are so many differences and similarities between CLI and GUI. What really separates them and makes me choose one over the other? If I can pick just one point of differentiation: Most times, CLI is more reliable. What does reliable mean here? It means robust. Less likely to fail.
Assume that for comparison we can have both GUI and CLI versions of the same applications. And that the GUI is more than just a "skin" over the CLI.
Show me a GUI application that is more reliable than the CLI version. I will take notice.
But to get me to switch away from CLI usage, one must show me many GUI applications, all more reliable than their CLI versions.
An entire system of fast, robust GUI applications, all more reliable than CLI alternatives.
This might be possible. But it is not available as of today AFAIK. And I have to go with what works. Today.
FWIW, I am an end user not a developer.
Well now I'm really curious about your actual software use-cases here. Because regardless of whatever "end user not dev" use-case I can think of, out of the many multiple dozens that instantly spring to mind, I cannot name a single one that has not had for 1-2 decades multiple well-known, widely-used-daily, best-in-class apps or suites on the market that are fully GUI-no-CLI and are at the very least evidently "reliable enough". Whatever GUI app I have used in the past 10 years, we can talk GIMP/Paint/VS/Sublime/VLC/Photoshop/Lighttable/LuminanceHDR/Blender/Unity/Unreal/VScode/Thunderbird/Firefox/Chromium/archival-tools/file-explorers/countless-others --- not only have they been utterly reliable and predictably delivered as was demandedd, their CLI alternatives hovered between non-existent and underfeatured.
So "end user not a dev" to me sounds like you must be a sys-admin or maybe, "author of man pages" ;)
All of the software you mention has had, over the versions, introductions of major bugs, regressions, UI elements changing for the sake of it, features available in a previous version being removed in a subsequent version (sometimes to be reintroduced later)...
Is that your definition of utterly reliable and predictable?
The various dialog boxes and widgets in apps like Gimp and Inkscape always seem fussy and annoying to me, especially when I know exactly what I want. If I could talk to the app, I would say "put margins 2cm from the page edge" or "position object X halfway between objects Y and Z", etc.
Blender has a Python console, and it's even somewhat discoverable because you can find out how to script an action you do in the UI, but the Python API is too verbose and ugly to be an actual daily mode of operation, I think.
Oh, you don't?
There is an enormous number of GUIs whose purpose is to make things quick and discoverable for transient use cases. In those cases the user may only need the application to perform their task one time ever. In those cases the learning curve for a more expressive system is too high a price to pay.
I've given light thought to the possibility of writing some kind of hybrid which acts as a general purpose terminal, but can somehow provide more information in a graphical manner-even something like directory traversal would be drastically simpler, IMO. Of course, this is not a trivial problem.
Are there any existing shells which hybridize GUI and CLI?
This gets worse with applications. For instance there is a web server control panel called 'Cpanel' that people buy into because they don't want to do the command line. This one really is a 'sea of icons' and I have no idea how you are supposed to work like that. But to people who don't appreciate that on a server you probably want to just run a few things (all available in the history file), the 'sea of icons' provides a lot of help.
Those of us that use the command line are 'having a conversation' with our computers and 'teaching' these machines to do stuff. Meanwhile, the GUI folks are true 'users', there is no 'conversation', it is a fundamentally different relationship.