Ask HN: What are the best and worst command-line interfaces you have used?
Best: probably that of Docker. <a href="https:&#x2F;&#x2F;github.com&#x2F;docker&#x2F;cli" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;docker&#x2F;cli</a><p>Why: it didn&#x27;t force you to read man pages or look up documentation, but instead allowed every command to explain what it does to you, either when you&#x27;d run it with --help, or just no parameters (in case it expects any). Furthermore, invocations of these commands weren&#x27;t just a long string of arguments, but rather commands that are logically grouped and can essentially be navigated as a tree. All of that made it extremely useful and pleasant, at least in my eyes.<p>It just feels like it&#x27;s made to actually be used by developers and to help them as much as possible. Whether you agree with me on that or not, i suggest that you have a look at this excellent talk by Dylan Beattie, &quot;Life, Liberty and the Pursuit of APIness: The Secret to Happy Code&quot;, which talked more about the discoverability of systems and the developer experience: <a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=lFRKrHE8oPo" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=lFRKrHE8oPo</a><p>Nowadays, you can actually use something like Typer for Python to create similarly useful interfaces, which i strongly advise you to have a brief look at: <a href="https:&#x2F;&#x2F;typer.tiangolo.com&#x2F;" rel="nofollow">https:&#x2F;&#x2F;typer.tiangolo.com&#x2F;</a><p>Example:<p><pre><code>  $ docker
  
  Usage:  docker [OPTIONS] COMMAND
  
  A self-sufficient runtime for containers
  
  Options:
    ... (a list of items)
    -v, --version            Print version information and quit
  
  Management Commands:
    ... (a list of items)
    image       Manage images
  
  Commands:
    ... (a list of items)
  
  Run &#x27;docker COMMAND --help&#x27; for more information on a command.
  
  To get more help with docker, check out our guides at https:&#x2F;&#x2F;docs.docker.com&#x2F;go&#x2F;guides&#x2F;
  
  
  $ docker image
  
  Usage:  docker image COMMAND
  
  Manage images
  
  Commands:
    ... (a list of items)
    ls          List images
    ... (a list of items)
    pull        Pull an image or a repository from a registry
  
  Run &#x27;docker image COMMAND --help&#x27; for more information on a command.
  
  
  $ docker image pull
  
  &quot;docker image pull&quot; requires exactly 1 argument.
  See &#x27;docker image pull --help&#x27;.
  
  Usage:  docker image pull [OPTIONS] NAME[:TAG|@DIGEST]
  
  Pull an image or a repository from a registry
  

  $ docker image pull alpine:3.15
  
  3.15: Pulling from library&#x2F;alpine
  59bf1c3509f3: Pull complete
  Digest: sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300
  Status: Downloaded newer image for alpine:3.15
  docker.io&#x2F;library&#x2F;alpine:3.15
  

  $ docker image ls
  
  REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
  alpine       3.15      c059bfaa849c   11 hours ago   5.59MB
</code></pre>
The worst: tar<p>Why: <a href="https:&#x2F;&#x2F;xkcd.com&#x2F;1168&#x2F;" rel="nofollow">https:&#x2F;&#x2F;xkcd.com&#x2F;1168&#x2F;</a><p>In short, it&#x27;s the exact opposite of the previous example. Frankly, without memorizing the flags, i still have no idea how to work with archives with it. Say, i want to create a compressed archive with it.<p>Example:<p><pre><code>  $ tar
  
  tar: You must specify one of the &#x27;-Acdtrux&#x27;, &#x27;--delete&#x27; or &#x27;--test-label&#x27; options
  Try &#x27;tar --help&#x27; or &#x27;tar --usage&#x27; for more information.
  

  $ tar --usage
  
  Usage: tar [-AcdrtuxGnSkUWOmpsMBiajJzZhPlRvwo?] [-g FILE] [-C DIR] [-T FILE]
              [-X FILE] [-f ARCHIVE] [-F NAME] [-L NUMBER] [-b BLOCKS]
              [-H FORMAT] [-V TEXT] [-I PROG] [-K MEMBER-NAME] [-N DATE-OR-FILE]
              ... (a really long list of items)
  

  $ tar --help
  
  Usage: tar [OPTION...] [FILE]...
  GNU &#x27;tar&#x27; saves many files together into a single tape or disk archive, and can
  restore individual files from the archive.
  
  Examples:
    tar -cf archive.tar foo bar  # Create archive.tar from files foo and bar.
    tar -tvf archive.tar         # List all files in archive.tar verbosely.
    tar -xf archive.tar          # Extract all files from archive.tar.
  
   Main operation mode:
    ... (a list of items)
    -c, --create               create a new archive
  
   Operation modifiers:
    ... (a list of items)
  
   Local file name selection:
    ... (a list of items)
    
   File name matching options (affect both exclude and include patterns):
    ... (a list of items)
  
   Overwrite control:
    ... (a list of items)
  
   Select output stream:
    ... (a list of items)
  
   Handling of file attributes:
    ... (a list of items)
  
   Handling of extended file attributes:
    ... (a list of items)
  
   Device selection and switching:
    ... (a list of items)
    -f, --file=ARCHIVE         use archive file or device ARCHIVE
  
   Device blocking:
    ... (a list of items)
  
   Archive format selection:
    ... (a list of items)
  
   FORMAT is one of the following:
    ... (a list of items)
  
   Compression options:
    ... (a list of items)
    -z, --gzip, --gunzip, --ungzip   filter the archive through gzip
  
   Local file selection:
    ... (a list of items)
  
   File name transformations:
    ... (a list of items)
  
   Informative output:
    ... (a list of items)
    -v, --verbose              verbosely list files processed
  
   Compatibility options:
    ... (a list of items)
  
   Other options:
    ... (a list of items)
  
  Mandatory or optional arguments to long options are also mandatory or optional
  for any corresponding short options.
  
  The backup suffix is &#x27;~&#x27;, unless set with --suffix or SIMPLE_BACKUP_SUFFIX.
  The version control may be set with --backup or VERSION_CONTROL, values are:
  
    ... (a list of items)
  
  Valid arguments for the --quoting-style option are:
  
    ... (a list of items)
  
  *This* tar defaults to:
  --format=gnu -f- -b20 --quoting-style=escape --rmt-command=&#x2F;usr&#x2F;lib&#x2F;tar&#x2F;rmt.exe
  --rsh-command=&#x2F;usr&#x2F;bin&#x2F;rsh
  

  $ # Copied from the Internet, because the documentation is overwhelming
  $ tar -vczf new-archive.tar.gz .&#x2F;files-i-want-to-archive
  
  .&#x2F;files-i-want-to-archive&#x2F;
  .&#x2F;files-i-want-to-archive&#x2F;test1.txt
  .&#x2F;files-i-want-to-archive&#x2F;test2.txt
  .&#x2F;files-i-want-to-archive&#x2F;test3.txt
  

  $ # Consider the full format instead, maybe we should actually use the full parameters more often?
  $ tar --verbose --create --gzip --file=new-archive.tar.gz .&#x2F;files-i-want-to-archive
</code></pre>
In short, using tar does not inspire joy and it feels overcomplicated, no matter how you look at it, possibly either because creating archives is a complicated domain (though the zip tool might not necessarily support that claim), or because the tool has grown over time and no longer does just one thing and does it well.