
Ask HN: How should the CLI be designed today? - danfrost
I&#x27;ve long thought that the command line is just a bit rubbish, even if it is powerful.<p>If you were redesigning it today (2016), how would you lay it out and what it do?<p>E.g. collapse output. Keep more metadata on history. Built in error hints (e.g. google the error, harvest possibilities).<p>How should the CLI work across microservices and cloud services?<p>What should the graphical design be?<p>This is deliberately open. Looking for pet hates and ideas.
======
Udo
My primary complaint about Unix CLI is that the commands try to do two
disparate things simultaneously: outputting text for humans and generating
data for consumption by other commands. In a properly designed command line
ecosystem (it's far, far too late for that now), there would be good human
readable output in one mode, and tools would exchange structured, already
escaped data amongst themselves in another mode. Alternatively, the _shell_
would render the output for humans, and tools would just communicate in
machine format.

Consider for example executing a compression command on all jpg files in a
folder and below. Currently, the syntax goes something like this:

    
    
      find . -iname "*jpg" -exec gfxcompress {} \;
    

Naive Unix users would have expected this to be achievable by piping, but no!
In reality there is a special syntax of the _find_ command that does this, and
it's not completely clear how you would deal with file names further down the
line, or how you would achieve further chaining. This syntax is also
completely unique to the find command. You can't just plug in another data
source and perform the same operation. In a CLI where tools are _designed_ to
be chained, it would look something like this:

    
    
      find | match :name="*jpg" |> gfxcompress :name 
    

In this example I used an imaginary |> operator to indicate I want something
performed on every item, and I can refer to the "name" field of each directory
entry directly. If I wanted to filter by time, for example, I might use the
:time field instead, without any need for explicit support. If I wanted to
mutate the name somewhere in the chain, I could do it. If I wanted to chain
additional commands, it would be obvious how. And it would just work.

The same goes for error handling. Imagine a compiler spitting out structured
error information which you could use directly in other tools without having
to parse and interpret it first.

~~~
CWuestefeld
Windows PowerShell seems to offer exactly what you're looking for.

~~~
joelthelion
The problem with power shell is that it misses basics such as grep that
command line users take for granted.

~~~
ColinCochrane
Select-String is the PowerShell equivalent of grep.
[https://technet.microsoft.com/en-
us/library/hh849903.aspx](https://technet.microsoft.com/en-
us/library/hh849903.aspx)

~~~
ygra
Should even have grep as its default alias.

~~~
besselheim
It has "sls" as its alias, even easier to type.

------
viraptor
I'd basically like to have powershell. Potentially with a better introspection
and attributes so that you can build a more interactive CLI. For example
output size estimation + tagging local read-only commands to allow showing
some output preview as you combine the commands. On-a-side display of help for
arguments.

My pet hate is that commands themselves cannot tell you things about them in a
structured way. There's no reason why completion and --help are somehow
separate from the execution itself.

Love: context aware shell like zsh/oh-my-zsh provide. If I'm in a git project,
show me a good git summary for example. If I'm in python venv, tell me about
it. If I'm in some python project, extract its name from setup.py.

------
J_Darnley
People say Windows' Powershell using some sort of objects rather than a text
stream is good.

For me I want better control over how my shell records and stores history. I
want it to record more and probably not in a flat text file. I don't want it
to write commands that fail to disk but I do want them in my history so I can
correct my typo and run again.

I'd like lines to be rewrapped if I change terminal dimensions. I'd like more
automatic pagination (rather than forgetting to use less and nuking your
scrollback). I think is an issue with mintty/putty but I'd like its command
history to be printed correctly after changing the terminal width.

Pet hates: terminal bells that I didn't explicitly ask for; middle click
paste; the obscure terminfo file that sometimes controls the features a
program uses.

~~~
skykooler
Powershell is like the Java of shells: object-oriented, but needlessly
verbose.

~~~
ctolkien
Eh, I like the Powershell angle here. By default everything is named in
lengthy, self explaining names, but there's shorthand aliases for everything.

In reality, no one is using `get-childitem` instead of `ls` or `dir` (both of
which are simply aliases for `get-childitem`).

------
gue5t
Don't google errors. Don't network anything that isn't explicitly requested to
be networked. Don't give any built-in affordances for HTTP or other poorly-
designed, politically-imposed protocols. I don't even know what you're talking
about with microservices, as that notion only makes sense in the context of
implementation details of RPC services ("Cloud APIs" in 2016 parlance).

A modern shell would:

\- Never use text as the interchange format, but rather keep binary
representations in memory and link all commands in a given interaction into a
single computation, doing inlining and optimization across the boundaries of
what are currently separate processes communicating via pipes/IPC.

\- Know about the structure of valid invocations of commands (essentially,
their type signature and the algebraic type structure of their parameters),
preventing any "invalid invocation" error messages a priori. Only valid
options would be permissible for tab-completion, and un-tab-completable
options would give error feedback directly without executing the program.

\- Have a principled, data-race-free alternative to the filesystem for
persistent storage of data, which maintains type information without
preventing useful generic operations like bytewise encryption.

\- Support unicode as the only character set for text.

\- Encourage proportional fonts, so as to make box-drawing characters not work
properly. An associated UI system would permits applications to refer neither
to character cells nor pixels, but only to a graph of modifiable or immutable
values and a set of presentation hints. Platform-specific modules would
interpret these based on the capabilities of the local terminal. Full
graphical applications over SSH are trivial under this model--no more "I use a
shitty 1980's-era UI because that's the only thing I can export across the
network consistently".

\- Allow addressing both local and remote system resources (RAM, CPUs, I/O
devices) via a uniform interface, and allow dynamically attaching and
detaching these from running processes, both local and remote.

\- From a more traditional shell perspective, it seems important to support
"by" operations with good ergonomics. This is stuff like "sort all these files
_based on the output of applying this other file-accepting command to each_ "
or "filter out all paragraphs in a text file containing the string 'foo', but
only print the last seven characters of each one.".

These would be a start.

------
jhallenworld
History should be recorded in non-volatile storage immediately, not just on
clean exits (can do this in bash, but it needs to be the default).

You should be able to step though history for just arguments (can be done in
bash, but needs to be easier).

Take a look at TOPS-20: it had "question-mark help"\- any time you hit ?, it
told you what the next argument is for.

The terminal emulator should have inline graphical output- it should not be
text only. Someone should define a protocol so that you can have full
graphical programs running in the terminal emulator. When you exit the
program, the last view remains in the scroll-back history.

Some plan9 things are good: network access should be in the filesystem so that
you don't need special programs like wget: cp
/net/www.google.com/http/index.html foo

Same with local I/O: parameters for opening a serial port should be part of
the filename when you open, something like: cp foo /dev/ttyS0:9600n81

The filesystem should be extended to also be a database. SQL is ugly, but some
kind of relational algebra query language should be built in:

    
    
        cat /mydatabase/name="joe" is like 'select * from mydatabase where name="joe"'

~~~
tedmiston
My bash history file seems to get bonked when working in multiple tabs / panes
simultaneously. Is there a trick to getting history to be tracked or aggregate
all of them?

~~~
severine
[https://news.ycombinator.com/item?id=11806553](https://news.ycombinator.com/item?id=11806553)

------
bizzleDawg
As an aside, in terms of design and little helpers (e.g. git/virtualenv)
powerline shell really made my terminal much more friendly:
[https://github.com/banga/powerline-shell](https://github.com/banga/powerline-
shell)

Idea: proper graphics for data/image/video display.

I think it's an interesting idea that a terminal editor can have text only
input, but the ability to draw real high-res graphical output. e.g. a canvas
to draw your matplotlib diagram in the terminal output or a more graphical
version of htop (with time data graphs etc).

~~~
dozzie
> Idea: proper graphics for data/image/video display.

Too late. xterm already has it for a long time (I remember seeing it working
as long ago as in 2003 in rxvt, and it was nowhere new thing then). See the
screenshot of w3m, a lynx-like web browser:
[https://en.wikipedia.org/wiki/W3m](https://en.wikipedia.org/wiki/W3m)

My today's rxvt-unicode also supports this mode.

------
saynsedit
Would love something that showed you how the current command was going to be
parsed as an argument vector before actually submitting the command (pressing
return). Would help with spacing and quoting.

------
seanp2k2
Do this:
[https://www.gnu.org/prep/standards/html_node/Command_002dLin...](https://www.gnu.org/prep/standards/html_node/Command_002dLine-
Interfaces.html)

And this:
[http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_...](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html)

------
random_upvoter
In TCC/LE (a CMD replacement for Windows by JPSoft) there is one little
feature that I miss in Powershell because I got so used to it: if you just
enter the name of a folder (as if it's a command), you change dir to that
folder (so no need to type the 'cd').

In Powershell you just get an error that this thing is not executable. A waste
of semantic space, IMO.

------
nextweek2
My biggest pet hate is the single tasking. Which is more to the nature of
scripting languages. It would be great to have an event command queue.

<rant> Each time I do a npm, apt-get, brew command it irks me that all the
downloads happen then they unpack, then they process. Where really it should
be put on an event command queue. That way downloads can continue whilst
processing is happening.

I have the same bug bear about the GUI, if I want to transcode a set of videos
and move them to a NAS it's a linear process. I keep promising myself I should
write a small app to get it done properly. I just wish the operating system
was a little better at it. The main pain point is that if I send 10 files to
my NAS it will transfer them all at the same time and take forever because of
the seek time. What OS's should be doing is queuing up these things to make
the transfer quicker. </rant>

~~~
paulddraper
* `parallel` for scripting parallelism

* `make` for scripting parallelism with dependencies

------
alexkehayias
Easier inline editing of command args i.e accidentally executing the script
when trying to enter a newline.

~~~
pritambaral
Current best solution: set $EDITOR to your favourite editor and Ctrl-x,
Ctrl-e.

------
woodruffw
Hyperlinking is good, we should do more of that.

I have my urxvt configured to open http(s) URLs in my browser, but it would be
nice if I could open URLs of arbitrary protocols via handlers. Similarly,
being able to distinguish valid pathnames and open them in $EDITOR/$VISUAL (or
perhaps via special file-type handlers) would be a nice.

Overall, I'm not particularly dissatisfied with the state of the command line
in 2016. My experience has been that I make no more (or fewer) mistakes with
command-line interfaces than I do with graphical ones, and that spending a few
seconds thinking about what I actually want to do prevents me from using the
wrong approach (i.e., a graphical or console program) to a problem.

------
0x37
If we could start with having working ctrl-c ctrl-v that would be great :). (I
know Windows improved on this with 10 but Linux is still lacking)

Other than that I wouldn't mind some graphical features, such as being able to
display thumbnails of images for example.

~~~
tokenizerrr
On Linux I usually use Ctrl+Shift+C, Ctrl+Shift+V which seems to be bound by
default on most terminals. Ctrl+C of course terminates the running program,
usually.

~~~
skykooler
Why is ctrl-C the shortcut for "terminate", anyway? I would have expected it
to be something like ctrl-T.

~~~
jaredsohn
from wikipedia
([https://en.wikipedia.org/wiki/Control-C](https://en.wikipedia.org/wiki/Control-C)):

As many keyboards and computer terminals once directly generated ASCII code,
the choice of control-C overlapped with the ASCII end-of-text character. This
character has a numerical value of three, as "C" is the third letter of the
alphabet. It was chosen to cause an interrupt as it is otherwise unlikely to
be part of a program's interactive interface. Many other control codes, such
as control-D for the end-of-transmission character, do not generate signals
and are occasionally used to control a program.

Also see
[https://en.wikipedia.org/wiki/C0_and_C1_control_codes#STX](https://en.wikipedia.org/wiki/C0_and_C1_control_codes#STX)

------
majkinetor
It should look exactly like Powershell. Its simply a space ship compared to
any other shell.

Since it is comming to Linux you should start learning it now IMO.

Xiki also had promiss. Unfortunatelly, it doesnt look like it will become
mainstream.

------
dlitz
I'd like to see a good CLI design involving sandboxing-by-default, and
handling object-capabilities (e.g. file descriptors) as first-class objects.

Right now, "convert a.jpg b.png" passes the strings "a.jpg" and "b.png" to
ImageMagick's convert command, but that command is free to open whatever files
it wants, since there's no distinction between strings vs resources such as
filenames, network sockets, etc.

You can do this with pipes in simple cases, and bash has some support for
this, but it's very primitive and the syntax is cumbersome.

------
ubuntourist
Although, through a long career, I've become accustomed to a wide variety of
CLIs, I tend to agree: We've moved beyond 1999 a bit. The fact that a lot of
these systems have legacy and tradition isn't sufficient. Languages like COBOL
also have a long history. But now we have lots of other languages to choose
from.

First off, as much as possible, I'd eliminate non-words. I tutor a lot and
people think perhaps I have a speech impediment the first time I say "grep".
(Yes, I know, it's not technically part of the shell. But okay how about "fi"
and "esac"? Really? Why not "enod" then?)

I'd take command completion further: IDEs often have drop-downs and function
signature descriptions as you move along coding. In a hypertext world with
tooltips, etc, I think there's be a lot of room for those types of ideas.

I do think the philosophy of "do one thing and one thing only, but do it well"
is a good one. Piping stuff together is wonderful. I wonder if it would make
sense and be shorter to explain in plain English, if the "water flowed the
other way" instead. For example:

"sort the output of the find result" = sort | find

as opposed to:

"take the output of find and sort it" = find | sort

(That last bit was just a random thought of the moment, just trying to think a
wee bit outside of the box.)

~~~
saynsedit
It wouldn't be enod, it would be rof

------
kranner
I'd like to leave this cautionary tale against getting too clever from the
Jargon File:

Warren Teitelman originally wrote DWIM to fix his typos and spelling errors,
so it was somewhat idiosyncratic to his style, and would often make hash of
anyone else's typos if they were stylistically different. Some victims of DWIM
thus claimed that the acronym stood for ‘Damn Warren’s Infernal Machine!'.

In one notorious incident, Warren added a DWIM feature to the command
interpreter used at Xerox PARC. One day another hacker there typed delete _$
to free up some disk space. (The editor there named backup files by appending
$ to the original file name, so he was trying to delete any backup files left
over from old editing sessions.) It happened that there weren 't any editor
backup files, so DWIM helpfully reported _$ not found, assuming you meant
'delete _'. It then started to delete all the files on the disk! The hacker
managed to stop it with a Vulcan nerve pinch after only a half dozen or so
files were lost.

The disgruntled victim later said he had been sorely tempted to go to Warren's
office, tie Warren down in his chair in front of his workstation, and then
type delete _$ twice.

------
tedmiston
Autocomplete globally for every command and its subcommands

~~~
michaelmior
While this would be great, I doubt it will ever happen. I don't really see how
this possible without support from each command being completed. And not every
command is going to do this.

~~~
joelthelion
Maybe machine learning could help?

~~~
michaelmior
Going through man pages would certainly help. Otherwise you're analyzing the
source code of scripts or worse, binaries. I won't say it's impossible, but
I'm not convinced the effort is worth it. That said, I think it could be made
much easier to make completion scripts rather than all the shell-specific
stuff that exists now.

~~~
a3n
\--help would be a good thing to learn from too. But again, that assumes that
--help or even a man page was implemented.

------
myroon5
Default support for control-f searching output

~~~
jaredsohn
OSX Terminal does this (but with Command-f).

------
josh-wrale
I've tried using Elixir's iex as a login shell. It was an interesting
experience. The pipelining in Elixir actually makes it feel a lot like bash.
In Elixir, remote shell [1], autocomplete are built in. Strings are binary.
Structs help structure output for human vs machine use (e.g. see
HTTPoison.get("[http://example.org"](http://example.org")) vs.
HTTPoison.get!("[http://example.org"](http://example.org")). Processes are
cheap. Functions are compostable. Rock on!

[http://elixir-lang.org/docs/stable/iex/IEx.html#module-
remot...](http://elixir-lang.org/docs/stable/iex/IEx.html#module-remote-
shells)

------
modeless
A standard method for programs to provide help, examples, and tab completion
suggestions to the shell. Right now we have man, info, --help, -help, -?, etc,
and tab completion is part of the shell rather than the apps. If all of that
was standardized the tools could be much better.

------
lsiebert
You should have a separate output for humans, instead of having a flag for it,
and programs which are the last in a chained series should default to it, but
you could also redirect stuff to it in the middle of piping.

I'd love if the bash shell language was less clunky.

------
jonsg
A good CLI has to satisfy a number of conditions, IMHO:

* Human-friendly interaction:

\-- Command completion

\-- Help for all commands

\-- Doesn't need a load of APL-like runes in order to achieve anything

\-- Intuitively obvious, so far as possible

\-- Low bar for entry

* Not too verbose (something that requires the equivalent of COBOL's "ADD A TO B GIVING C" ain't gonna roll, sorry!)

* Sensible and consistent

* Embeds a full programming language - but you don't need that language to run straightforward commands

* Completely embraces parallelism without pain

\-- Including being able to spin off and manage daemon processes

\-- And having a painless way of managing (plumbing, in other words) inputs
and outputs of each stage - {Uni,Linu}x shells haven't really improved the way
they do this in over thirty years, and they didn't get it right the first
time!

* As much as possible of the operating system's capability should be exposed, to as deep a level as possible, through the CLI

* Not tied to one operating system - inherently capable of being applied to any (or at least any common one)

My preference would be that the CLI presents a genuinely object-oriented
representation of data and the programs that know how to interpret the data,
plus the operating system services as well.

Microsoft's PowerShell satisfies a lot of these requirements...however, it
falls way short of the "Low bar for entry" criterion, as anyone who's tried to
learn it casually will have discovered the hard way.

A Pythonic shell could also be made to work (yes, I've tried using Python as a
shell. No, it didn't go well), but would require a bit of nurdling to bring it
into compliance with most of the requirements above, particularly the human
interface ones.

A lot of questions here - a lot fewer answers, but I thought I'd throw out
these thoughts for the assembled masses to contemplate, be inspired by, or
tear to pieces.

------
abbasaamer
It'd have the features of fish shell
([https://fishshell.com](https://fishshell.com)) and would be able to pipe
structured objects between programs like Windows Power Shell.

------
y1426i
I find CLI a great interface. Its just stuck in pre web days! Here are some
thoughts on its design / UX -

\- contextual help. if i write a command incorrect, it should suggest
correction and link to more help.

\- cloud storage of all my command history

\- be more understanding. talk a bit in natural language. Eg. show my ip
address -> translated to the right shell command.

\- learn and grow automatically as the community builds more tools. Like, hey
used this command but check this one out!

It is not feasible to upgrade all existing scripts to adhere to this but a
wrapper shell that can provide this functionality should be very well
possible.

------
55555
Please build me an app that lets me search "prebuilt commands" from the
command line itself. I am always opening Chrome to google "how to grep
recursively only files of a certain type to find phone numbers"... why can't i
just search that from the command line itself and then select from the
outputted suggestions?

Other than that, some random ideas..:

Probable command completion.

Possible arguments should be displayed as I type.

Syntax highlighting and beautiful margins/padding

Collapsible threads

------
xwvvvvwx
Black Screen has some pretty interesting ideas:

[https://github.com/shockone/black-screen](https://github.com/shockone/black-
screen)

~~~
danfrost
Do you know what the roadmap is for this? It looks like they want to build a
terminal, but I can't see how it's significantly different from what we've got
at the moment.

------
z1mm32m4n
If you have a little sense of humor, Gary Bernhardt spoke at length about what
effect a better terminal environment could have on things like terminal based
editors:

[https://www.destroyallsoftware.com/talks/a-whole-new-
world](https://www.destroyallsoftware.com/talks/a-whole-new-world)

------
flukus
I'd add an easy way for cli apps to expose bindings to be used from other
apps. Working in a higher level language and having to rely on
executing/parsing cli programs isn't pleasant.

------
softEngg
Plan9?

~~~
spelufo
I used a port of the rc shell for linux as my login shell for a couple of
months. I switched back to zsh eventually because rc doesn't have job control
and autocompletion. The autocompletion wasn't that big an issue because it can
use readline for history completion, and it can be configured so that when you
type the start of a command and hit up arrow it will find the last command
that started with what you typed. This can be replicated for zsh and bash, and
it's arguably as good as autocompletion. I found no convinient work-around for
the lack of job control, other than starting a new terminal.

How is rc better than bash or zsh? I've read the bash man pages and I couldn't
figure out exactly how bash expands commands before executing them. Every time
the shell see's an unquoted variable name (e.g. $foo) it will do word
splitting, which is why you have to write "$foo" instead, or "${foo}bar" to
distinguish "$foo" from "$foobar", etc. Add history and filename expansion and
command substitution, weird syntax for control statements...

The best feature of rc is that word splitting and globbing happens once, and
it results in a list of strings. There is no longer a need to quote variables
all the time. No need to use filenames without spaces.

Here's what bash does:

    
    
        $ files=*; echo "$files"; echo $files
        *
        file1.txt file2.txt file3.txt
        $ # echo $files -> echo * -> file1.txt file2.txt file3.txt
    

Here's what rc does:

    
    
        $ files=*; echo $files
        file1.txt file2.txt file3.txt
        $ # files=(file1.txt file2.txt file3.txt)
        $ # echo $files -> echo file1.txt file2.txt file3.txt
    

It's similar to the situation for dynamic vs lexical scope.

[http://plan9.bell-labs.com/sys/doc/rc.html](http://plan9.bell-
labs.com/sys/doc/rc.html)

[https://github.com/rakitzis/rc](https://github.com/rakitzis/rc)

------
hellcat84

      int main(int argl, byte* argb)
    

For having just a byte* stream, not claiming this is a char, when I just have
a byte of a char, and without terminating NUL character.

------
Koshkin
Looks like IPython Notebook is almost an ideal way to interact with a computer
(as an information processing device, rather than, for example, a game
machine).

~~~
a3n
Agree. I think the plain ipython shell can go a long way now. It will pop up a
graphic, and you can access the surrounding shell. In theory you can just live
in ipython; I've tried it but I stumbled too much.

Next on the spectrum would be the QT version of ipython. And then of course
ipython notebook/jupyter.

What _really_ looks promising is the Jupyter Lab, currently in alpha.

[http://blog.jupyter.org/2016/07/14/jupyter-lab-
alpha/](http://blog.jupyter.org/2016/07/14/jupyter-lab-alpha/)

[https://pypi.python.org/pypi/jupyterlab](https://pypi.python.org/pypi/jupyterlab)

~~~
shabble
ipython shell is great for quick jobs, and is taking over a lot of what I used
to do with long pipelines of cut/grep/perl -n, etc.

Being able to grab some filenames/contents with

    
    
        foo = !ls
        bar = !cat *.txt # returns list of lines
    

is super handy. And the real shell is always just C-z away, if I need it.

------
vasili111
It should understand human language. Not commands, functions and etc, just
plain human language.

~~~
shabble
Down that road lies AppleScript...

trying to do even trivial things in it has forced me into the alternative hell
of 'scripting bridges' and using real languages, and ultimately giving up.

------
joelthelion
It should have a daemon to centralize things such as command history across
multiple terminals.

------
joelthelion
A modern protocol to communicate with the terminal would be nice.

