[HN Gopher] Command line interface guidelines (2021)
       ___________________________________________________________________
        
       Command line interface guidelines (2021)
        
       Author : petercooper
       Score  : 293 points
       Date   : 2024-02-06 13:25 UTC (9 hours ago)
        
 (HTM) web link (clig.dev)
 (TXT) w3m dump (clig.dev)
        
       | ho_schi wrote:
       | If you wonder about command-line argument parsing with C and C++,
       | _getopt()_ is built-in:
       | https://www.gnu.org/software/libc/manual/html_node/Getopt.html
       | 
       | That said. I think CLI programs are user friendly for
       | professionals. Because they support _input-process-output_. Where
       | input is STDOUT read by human, process is thinking by human and
       | output is keyboard input to STDIN by human.
       | 
       | UIs for the general audience? TUIs! TUIs are easily to parse,
       | succinct in organization and fast input - all for humans. Humans
       | can parse TUIs. And they can make up a mental modal.
       | 
       | GUIs fail often with a lack of organization, information overflow
       | and distractions by weird metaphors. The Windows 95 _desktop_
       | metaphor is an example. It doesn't make sense. Same for Windows
       | 11 and its file-browser which makes it hard to recognize the
       | filesystem or even just the home-directory. Now open Nautilus on
       | Linux, it opens by default your home-directory (in most cases the
       | place to be).
       | 
       | I like the CLI but TUIs are my love. GUIs are okay if are like a
       | TUI.
        
         | unwind wrote:
         | That is only true in some environments, since it's not in fact
         | part of the language specification.
         | 
         | See the manual page's [1] "STANDARDS" section, which reads:
         | getopt()             POSIX.1-2008.              getopt_long()
         | getopt_long_only()             GNU.                  The use of
         | '+' and '-' in optstring is a GNU extension.
         | 
         | [1]: https://www.man7.org/linux/man-pages/man3/getopt.3.html
        
           | ho_schi wrote:
           | Correct.
           | 
           | It is probably a feature which isn't necessary for the
           | languages itself but Linux/POSIX.
        
         | kergonath wrote:
         | > UIs for the general audience? TUIs! TUIs are easily to parse,
         | succinct in organization and fast input - all for humans.
         | Humans can parse TUIs. And they can make up a mental modal.
         | 
         | TUIs have the same drawbacks as GUIs and then some. Their big
         | advantage is to work seamlessly over SSH but that's pretty much
         | it. They are not more discoverable and they are not more
         | efficient than GUIs. There is nothing preventing you from
         | having a decent GUI along the same lines as Midnight Commander
         | to have a file manager without the metaphors you dislike, for
         | example (as a matter of fact, there are several).
        
           | Linux-Fan wrote:
           | Working over SSH is not the only TUI advantage: IMHO one of
           | the greatest benefits of TUIs is the usage of characters to
           | display the UI. This way, the font size is always equal (no
           | unreadably small fonts).
           | 
           | When designing TUIs I found this to be limiting in a creative
           | sense -- I have to really think about how I arrange the TUI
           | elements and information because I cannot put as many
           | elements as I can on a GUI in the same screen space.
           | 
           | Also, TUIs seem to be mostely unaffected by the trend to make
           | every GUI element "touch-friendly" large which is an
           | advantage for me as a Desktop user.
           | 
           | Full rant here: <https://masysma.net/37/why_terminal.xhtml>
        
         | IshKebab wrote:
         | getopt is not built in.
        
         | indymike wrote:
         | > UIs for the general audience? TUIs!
         | 
         | TUIs are ideal (sometimes) where a command needs to be
         | interactive. Many commands lend themselves well to batch
         | processing or require no interactivity at all. In many cases, a
         | script piped into a text editor (which is a TUI) is all that is
         | needed, sparing apps from having to embed a text editor and
         | deal with all of the design choices. Other times GUI will work
         | a lot better.
        
       | enriquto wrote:
       | > Most people today don't know what the command line is, much
       | less why they would want to bother with it.
       | 
       | This is true today, and it was true as well "in the 1980s", to
       | use the same time frame as TFA. The difference is that today
       | there are _more_ _people_ _than_ _ever_ who know what the command
       | line is, and who can use it. At least an order of magnitude more
       | people; maybe two. We can certainly say that we live in the CLI
       | golden age!
        
         | nerdponx wrote:
         | Was that true as a % of _computer users_ in the 80s?
        
           | enriquto wrote:
           | I guess not, but why does it matter? Let people enjoy other
           | things.
        
         | atoav wrote:
         | Absolute vs relative numbers.
         | 
         | If you want to judge the shift in quality in a thing that grew
         | in quantity, then you should look at percentages -- otherwise
         | you end up creating statements that are true, but don't say
         | anything meaningful.
         | 
         | E.g. there are probably more _absolute_ listeners of Jazz music
         | today than back at the height of the cultural bloom of the
         | genre. But that isn 't because Jazz is more popular today than
         | it once was, but because there are more absolute listeners of
         | any kind of music. Would you say that Jazz in the US is now
         | more important, influential etc. than it was at its peak?
        
           | hiAndrewQuinn wrote:
           | No, but there's so much great jazz these days that wouldn't
           | have existed without those absolute numbers. Quantity
           | (aggregate supply) is a quality (increases specialization of
           | labor) all its own!
        
         | hinkley wrote:
         | I've been writing command lines for parts of our app to help
         | split up the monolith. Global state and dependencies thwart
         | reasoning and thus debugging and performance optimization.
         | Splitting out 500, 1000, 5,000, 10,000 or sometimes 50k lines
         | of code to work separately can clarify a lot of things.
         | 
         | If done right it can also encourage Functional Core, Imperative
         | Shell, because a sensible Unix-philosophy command line needs
         | lots of actions without side effects and a few with. You can
         | write a little command that generates and dumps out the system
         | state just before a (bad) decision is made, and do so against
         | production systems with virtual impunity. And that means you
         | can hand these tools to someone who you need to become part of
         | a bus number, even if they are otherwise hesitant to do so.
        
         | mvdtnz wrote:
         | If you substitute "people" with "computer users" (which is
         | obviously implied, despite your pedantry) then the author's
         | jist is correct. What a villager in a remote undiscovered
         | Amazonian civilisation thinks of the terminal is not relevant.
        
       | bluetomcat wrote:
       | > Traditionally, UNIX commands were written under the assumption
       | they were going to be used primarily by other programs. They had
       | more in common with functions in a programming language than with
       | graphical applications.
       | 
       | Not quite. They were primarily intended for interactive use
       | within a login shell. There are the programs which generate
       | output on stdout (ls, cat, find, tty, who, date), and there are
       | the "silent" text filters (tr, grep, cut, uniq, sort, wc). A one-
       | liner would enable you to do basic computing tasks in that era.
       | Any complex program would be written in C. After the appearance
       | of DSLs like sed and AWK, certain string-heavy programs were
       | offloaded to the shell.
       | 
       | The shell is not a sane programming environment and was never
       | intended as such.
        
         | rollcat wrote:
         | > The shell is not a sane programming environment and was never
         | intended as such.
         | 
         | There are 10kloc C programs that could be 10 lines of shell and
         | there are 1kloc shell programs that could've been 100 lines of
         | C.
         | 
         | Both kinds are nowadays probably better done in Python or Lua,
         | but the shell and C are what's most universally available.
        
           | bluetomcat wrote:
           | > There are 10kloc C programs that could be 10 lines of shell
           | 
           | Only when the shell calls other external C programs. Ten
           | lines of calling ffmpeg or curl is not shell programming.
           | 
           | > there are 1kloc shell programs that could've been 100 lines
           | of C
           | 
           | The 1kloc shell programs are fragile spaghetti that breaks in
           | weird ways. Any invocation of an external program can fail
           | for a variety of reasons, and the shell doesn't provide
           | adequate mechanisms for dealing with it, apart from exit
           | codes and filtering error text output.
        
             | shadowgovt wrote:
             | > Ten lines of calling ffmpeg or curl is not shell
             | programming
             | 
             | Ten lines of calling ffmpeg or curl is shell programming in
             | precisely the same sense that 100 lines of C that `#include
             | <sys/socket.h>` are C programming.
             | 
             | If your code isn't standing on the shoulders of giants,
             | you're probably wasting everyone's time.
        
             | fargle wrote:
             | > Only when the shell calls other external C programs. _Ten
             | lines of calling ffmpeg or curl is not shell programming._
             | 
             |  _100% wrong_. this is what the shell was designed to do
             | and where it is at it 's best.
             | 
             | often shell "scripts" are used like "macros" or power-
             | tools, shortcuts to save off a complex invocation or
             | workflow. error handling isn't as important in a one-off
             | and "adequate" is whatever gets the job done for the user,
             | which it does.
             | 
             | it's rare that 1kloc shell script is the best engineering
             | choice vs. (in the ancient days) Perl or (today) Python.
             | e.g. "real" programming languages. you mostly should not
             | write large programs in shell. and you _really_ should not
             | glue together pipelines of external programs using, for
             | example, Python or C, which is onerous.
             | 
             | ah, the HN crowd: where everything is either black or
             | white, great or terrible. how about "each to his own" and
             | "use the right tool for the job"
        
               | bongodongobob wrote:
               | It's not rare at all. In every corporate environment I've
               | worked in, my choices were PowerShell or 3 months of red
               | tape, meetings, and security audits.
               | 
               | I get that in a dev shop that's not the case, but most
               | businesses employ 0 devs. So people end up being forced
               | into shell scripting because it's the only approved
               | option.
        
               | int_19h wrote:
               | At least PowerShell gives you access to the entirety of
               | .NET, even if syntax is not ideal for non-interactive use
               | in many cases.
        
               | bongodongobob wrote:
               | Yup. My "scripts" end up with a lot of .NET stuff in
               | there. I'd rather use Python, but being forced to use PS
               | for years, I've come to like it.
        
         | samatman wrote:
         | Sane or not, shells are programming languages, and in early
         | Unix this was quite a bit more prominent and obvious, the
         | fanout into sh, bash, ksh, and csh being exemplary.
         | 
         | To me it makes total sense to think of the standard POSIX
         | toolkit as the standard library of the various shell languages,
         | that seems basically correct in fact.
        
       | EasyMark wrote:
       | This document is far to large for "guidelines".
        
         | shrikant wrote:
         | Whart's this based on? If anything, this is among the more
         | concise set of interface guidelines I've come across. Design
         | guidelines typically run into hundreds of pages long when
         | PDF'ed -- this page is just about thirty on default "Save as
         | PDF" settings...
        
         | tester457 wrote:
         | I thought so too until I ignored the philosophy section.
        
       | ttyprintk wrote:
       | not much has changed since the prior comments:
       | 
       | https://news.ycombinator.com/item?id=25304257
        
         | scbrg wrote:
         | Seems they took a small step back from their previous "don't
         | bother with man pages" stance. Now it's "Consider providing man
         | pages."
         | 
         | I still find it a rather shocking order of priority, honestly.
         | 
         | https://clig.dev/#documentation
        
       | jansan wrote:
       | What I find super irritating is that some terminals will
       | automatically execute a command if you paste it from the
       | clipboard and there is a newline char at the end. IMO command
       | line interfaces should not do this.
        
         | bloopernova wrote:
         | On macOS, iTerm asks if you try to paste a string with a
         | newline. You can disable it if you find it annoying.
        
         | riddley wrote:
         | You might try a clipboard manager. Most of these that I've used
         | have an option to strip new lines from anything in the
         | clipboard.
        
           | eviks wrote:
           | that would break multi-line commands, so not a good option
        
             | riddley wrote:
             | It just strips off the final one.
        
         | crlfcrlf wrote:
         | You find it irritating that terminals execute commands when
         | they receive a newline, which is indistinguishable from
         | pressing the enter key? The program is doing exactly as it
         | should. Consider not copying newline characters, and you will
         | solve the problem.
        
         | marcosdumay wrote:
         | You want to use C-x C-e.
        
         | avgcorrection wrote:
         | Bash                   bind 'set enable-bracketed-paste on'
        
         | aequitas wrote:
         | Fish shell by default does the expected behaviour of inserting
         | in and allowing you to edit the command (multiline if needed)
         | before executing it with [enter]. I've found Fish shell to have
         | a lot of sane defaults and have yet to find a thing I would
         | like to customize except for the prompt.
        
       | BobBagwill wrote:
       | The command line is dead. Too late to clean up, standardize,
       | organize. The non-wimpy future is chat.
        
         | Cockbrand wrote:
         | I was going to comment in protest - "but the CLI has always
         | been there, and it'll always be..."
         | 
         | But then I realized that you're probably right. I'm kinda
         | looking forward to looking back with bewilderment on those
         | decades of doing CLI stuff with remembering all those commands
         | and shell intricacies and whatnot.
        
           | kjs3 wrote:
           | In my vision of the future I see one of my descendants 100
           | years from now cussing furiously that his AI avatar is
           | borking up his request, and one of the local neckbeards walks
           | up, does an obscure incantation that pops up a command
           | window, types a few lines of text and fixes the problem right
           | up. "Newbs...geeze" he says as he walks away.
           | 
           | Maybe the proles will one day be permanently denied the CLI,
           | but even if only as a lowest common denominator
           | administration tool of last resort, I predict there will be a
           | CLI somewhere.
        
         | marcosdumay wrote:
         | Wake me up when chat becomes deterministic.
         | 
         | There is a lot of value on understanding the context and trying
         | to parse what you meant in a mangled command. For the
         | foreseeable future, that value will fall entirely on
         | documentation and search procedures, and chat will keep a
         | steady negative value for actual interaction.
        
           | BobBagwill wrote:
           | The current shells aren't deterministic either. Everything
           | depends on history, context, environment.
           | 
           | Early AI shells will ask for confirmation like "ansible
           | --check" or "terraform plan". Running commands in a
           | disposable virtual environment will inspire confidence. When
           | they are trusted enough, direct execution.
           | 
           | Soon after you're able to say "Set up a k8s cluster for me!"
           | you'll decide you don't need k8s anymore, you'll just
           | introduce your AI model to your data-lake and be done. The
           | days of thinking about how many nodes do I need, which
           | immutable linux distro, t5g vs m4.xlarge are almost gone.
           | 
           | Read the lyrics to Graham Nash's "Teach Your Children",
           | substituting "model" for "children" as necessary. :-)
        
             | int_19h wrote:
             | I'm not saying that what you describe is impossible, but
             | we're clearly far from the point where AI can be trusted to
             | do something like that unsupervised (which is a necessity
             | for any kind of scripting). So declaring that "command line
             | _is_ dead " is rather premature.
        
         | layer8 wrote:
         | Chats aren't a formal language. You need a formal language to
         | do anything reliably and reproducibly.
        
       | ceving wrote:
       | The current Unix command line situation is on the one hand
       | "incredible useful" and on the other hand "broken by design".
       | 
       | Why is it incredible useful?
       | 
       | Just imagine how long it would take to write the following in C
       | or Rust:                   curl -sS
       | https://go.dev/doc/devel/release |           html2text |
       | grep -o -P '\bgo\d+\.\d+\.\d+\b' |           sort -V |
       | uniq |           tail -1
       | 
       | Why is it broken by design?
       | 
       | Read this: https://news.ycombinator.com/item?id=29747034
       | 
       | The problem: a command line interface must be human readable and
       | machine readable at the same time. There is no canonical way to
       | solve this problem.
        
         | shadowgovt wrote:
         | > Why is it broken by design?
         | 
         | I think your example self-explains why it's broken by design.
         | It's a good example.
         | 
         | > a command line interface must be human readable and machine
         | readable at the same time. There is no canonical way to solve
         | this problem.
         | 
         | And you know, there could be one. Apple has Human Interface
         | Guidelines to reify the meaning of the visual abstractions in
         | its desktop UI. The problem is that the command line didn't
         | come from people who think like Apple designers; it came from
         | people who think "How can I express what I want using the least
         | code possible, because laziness, impatience, and hubris are
         | virtues?" And they weren't wrong for the time (especially
         | because every byte matters), but the design decisions they made
         | got baked into tooling that can't now be moved.
         | 
         | I think at this point we'd have to punt the POSIX toolchain to
         | get something better; it's hard for me to imagine how we'd
         | build discoverable, conceptually-consistent UX atop what we
         | currently have.
        
           | ceving wrote:
           | I think graphical user interfaces are no high standard. They
           | do not compose. How would you express a loop or a recursion
           | in a graphical user interface?
        
             | shadowgovt wrote:
             | They are a challenge for composition, often.
             | 
             | Great for discoverability though, and that doesn't require
             | graphics, just context.
             | 
             | There should be a button I can push in my shell that lets
             | me ask "what does the token at cursor mean," and a button
             | that lets me type a plain language search string that wires
             | down to a contextual search (i.e. I'm in the middle of
             | typing out "grep" I should be able to ask "how do I search
             | folders?").
             | 
             | We didn't have the tools to build this when grep was
             | invented; we have them now.
        
             | samatman wrote:
             | I'm genuinely unsure how to translate your question into,
             | hmm. Anything actually.
             | 
             | The snarky answer is "By writing it in source code, in a
             | GUI text editor", a thing I do frequently. But the problem
             | is that I have no idea what you're getting at in the first
             | place, so that's just an attempt to recover some meaning
             | from what you wrote.
        
               | shadowgovt wrote:
               | Shells allow one to pipe around the data flowing from
               | called process to called process in a very smooth and
               | transparent fashion.
               | 
               | By and large, GUIs do not. There is no such thing as a
               | universal shell for GUIs, and attempts to layer
               | automation atop the GUI abstraction are generally spotty
               | and unreliable (certainly when compared to CLI and
               | shells). This is both for technical reasons (i.e. it's
               | much easier to clearly delineate the two ends of a pipe
               | than to clearly delineate "I want to click on the red
               | square inside the 'diagram' window inside the drawing
               | app") and for ecosystem reasons (since GUIs aren't
               | thought of as automatable, GUI designers are free to move
               | pieces around version-to-version of software, making it
               | extremely challenging to describe a GUI structurally).
               | 
               | I've seen some neat attempts at GUI automation (Sikuli is
               | my favorite) but it's never been a core feature like it
               | is in the CLIs-glued-together-by-shells world.
        
               | samatman wrote:
               | CLIs are in the modern world a subset of GUI programs
               | which run inside a text-oriented window, and plenty of
               | more sophisticated GUI programs can be directed
               | textually, with macros or short scripts, and/or have a
               | command-line component for doing that sort of pipe or
               | batch-oriented work.
               | 
               | Yeah, sometimes there's functionality stuck behind a
               | button or menu select which I want exposed in a more
               | textual way, in macOS that's when you break out
               | Automator, Alfred, or Hammerspoon (the only one I've ever
               | used fwiw), Linux and Windows have their own equivalents.
               | 
               | I don't think the distinction you're pointing to is
               | nearly so stark or clear-cut as it's often made out to
               | be. Ecosystems converge towards the tasks which are
               | amenable to batching and pipelining being equipped to do
               | so.
        
               | shadowgovt wrote:
               | But in general, batching and pipelining are done via a
               | text-based interface. Extremely rare is the teachable GUI
               | interaface where there's a point-and-click way to
               | describe the concept "See these five items I clicked? Do
               | that twenty-eight more times with this radio button
               | family swizzled via a linear sweep."
        
               | samatman wrote:
               | My point being, I don't see why there ever should be. A
               | text window is a valid and frequently-included part of
               | GUI programs (I happen to be using one this instant, in
               | fact), so there isn't a lot of advantage in replacing
               | something like Lua scripting with a bunch of buttons and
               | whizbangs. It's been tried for normal programming, and no
               | one likes it.
               | 
               | The specific kind of task you described is frequently
               | exposed as macros in programs complex enough to deserve
               | it.
        
           | rascul wrote:
           | > I think at this point we'd have to punt the POSIX toolchain
           | to get something better; it's hard for me to imagine how we'd
           | build discoverable, conceptually-consistent UX atop what we
           | currently have.
           | 
           | Posix could potentially do this. It already has a bit about
           | conventions and could be expanded. Problem is getting things
           | to adhere to it, plus I doubt the posix authors could be
           | convinced to add a lot more to it.
           | 
           | https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1.
           | ..
        
         | ta8645 wrote:
         | > The problem: a command line interface must be human readable
         | and machine readable at the same time.
         | 
         | Since the computer is there to serve us, ultimately the
         | solution must be for the machine to read as well as humans.
        
           | oblio wrote:
           | What if the ultimate solution is only achieved after our
           | lifetimes?
        
             | ta8645 wrote:
             | I don't really understand the question. Nobody got to fly
             | until we figured out how to build airplanes, people before
             | that lived on the ground. Likewise, we'll live with
             | iterations on the current command line, until AI is fully
             | integrated with it.
        
           | ceving wrote:
           | Never ever. Humans are idiots. If you build machines like
           | humans you will get idiotic machines. Machines need to do
           | things exactly right and not almost right or mostly right.
           | Current AI trends will not create better machines, just more
           | idiotic machines. Those idiotic machines will be sufficient
           | to impress idiots, but they will not help to do things
           | exactly right. Automated theorem proving is the only way to
           | build better machines.
        
             | ta8645 wrote:
             | > Automated theorem proving is the only way to build better
             | machines.
             | 
             | Sure, but that will just be one aspect of an integrated and
             | wholistic AI, which can configure the parameters input to
             | the automated theorem proving component, and act on the
             | results.
        
             | samatman wrote:
             | Automated theorem proving will only ever be an arrow in the
             | quiver, because even in theory, the space of useful
             | computer programs is a vast superset of those which may
             | have all their properties formally verified. In practice,
             | it's a much larger superset than theory allows. Growing the
             | space of formally verifiable subprograms is a worthy
             | endeavor, sure, but so is good old-fashioned engineering.
        
         | friendzis wrote:
         | > The problem: a command line interface must be human readable
         | and machine readable at the same time. There is no canonical
         | way to solve this problem.
         | 
         | * Powershell has entered the chat
        
           | riddley wrote:
           | Powershell has some cool things, but it's a disaster when it
           | comes to usability.
        
             | adamrezich wrote:
             | how so?
        
         | PurpleRamen wrote:
         | > The problem: a command line interface must be human readable
         | and machine readable at the same time. There is no canonical
         | way to solve this problem.
         | 
         | It's not really the "same time". Usually, human and machine use
         | the same command, but at different times. And there are many
         | ways to enable different outputs, even at the same time. But
         | this all depends on having some standard which everyone
         | follows. And that's where it becomes complicated.
        
         | avgcorrection wrote:
         | The article covers this. Special machine-readable output modes
         | like `--json`.
        
         | BlueTemplar wrote:
         | Your example not only doesn't prove that it's broken by design
         | (only broken most of the time ?), it even seems to give a
         | (relatively ?) easy way to fix it ?
         | 
         | > Since very few implementations of ls allow you to terminate
         | filenames with NUL characters instead of newlines
         | 
         | In fact the solution to this issue seems to be so obvious that
         | I might be missing something ? (Rejection by shell interfaces
         | for some reason ??)
        
       | pmig wrote:
       | We recently chose cobra[1] to create a cli application. It comes
       | with so many best practices already packaged like
       | autocompletions, help texts etc. etc.
       | 
       | [1]: https://github.com/spf13/cobra
        
       | candiddevmike wrote:
       | I get that some CLIs are absolutely huge and require nesting
       | (like aws), but it really drives me nuts traversing nested CLIs.
       | I'd rather most apps spit out all their options in the help and
       | let me use less to find what I need instead of going into each
       | level and running help.
        
         | frontalier wrote:
         | isn't that what man(ual) is for?
        
           | otteromkram wrote:
           | You mean manpage? Yes.
        
         | wjdp wrote:
         | I find it depends on the number of subcommands and if those
         | subcommands are clear. It's rather useful to have the options
         | whittled down to just the ones you need if you know which
         | subcommand you need but otherwise can be painful.
         | 
         | Grepping through a large list of options is also painful, seems
         | ther needs to be a balance here.
        
           | candiddevmike wrote:
           | No need to grep, just use less and vi commands like forward
           | slash to search through things/move about a long list.
        
             | hk__2 wrote:
             | It's the task of searching in a long list that's painful,
             | not the tool to do it.
        
               | cellularmitosis wrote:
               | But we are comparing the pain of searching vs the pain of
               | having to re-run the help command for each possible
               | subcommand, and parsing through all of that. Much easier
               | to just have one command invocation and search through
               | it.
               | 
               | There is a web analogy for this in how people organize
               | FAQs. Some have a list of section links, and you have to
               | click on a section to get the FAQs for that topic. Others
               | just put everything on one giant page.
               | 
               | Here's the problem scenario with splitting things up into
               | section pages: You think you see the appropriate section,
               | but then you don't see your concern answered. There are
               | two possibilities: either the organization was counter-
               | intuitive and your concern was answered in one of the
               | other sections, or your concern wasn't answered anywhere.
               | And what's the only way to be sure? Visit every single
               | section page and search through all of them.
               | 
               | Much, much less painful to just have it all on one page
               | and search it.
        
         | epage wrote:
         | Something that can help is flattening subcommands' `--help`
         | into their parent
         | 
         | e.g. `git stash <sub> --help` just reports `git stash --help`
         | which includes each `<sub>`
        
         | swozey wrote:
         | I've spoken about this previously, I write a huge number of TUI
         | apps. I write every single app the have a nice TUI frontend for
         | people who are less technical (like QA) that is purely the
         | UI/UX IF you want to use it. What that does, in all of my apps,
         | is pass the settings chosen in the TUI to some sort of separate
         | generator file or function that can always be called by it's
         | own on the terminal with all options/help that are used in the
         | TUI.
         | 
         | So it's scriptable and useful by multiple levels of skill.
        
       | shadowgovt wrote:
       | Of all the challenges with using CLIs, the one that bites me
       | consistently is capitalization of flags. Really wish we'd
       | standardized on being capital-agnostic (or even demanding
       | lowercase only).
       | 
       | ... but we didn't, so now you have to memorize whether recursion
       | is capital or lowercase R, restart is capital or lowercase R,
       | poweroff is capital or lowercase P, etc.
        
         | thworp wrote:
         | Most utilities I use daily have --long-flags for all of these.
         | Using completion (prferrably https://github.com/unixorn/fzf-
         | zsh-plugin) you can complete them pretty quickly and without
         | knowing the precise name.
        
       | flykespice wrote:
       | POSIX standard had its own command line interface guide already,
       | didn't it?
        
         | 0cf8612b2e1e wrote:
         | Doesn't POSIX comment more on what programs did vs what they
         | should do? More a manual of backwards compatibility.
         | 
         | Like, why does tar get to be so special that it takes command
         | line flags with or without leading dashes?
        
           | Sprocklem wrote:
           | tar isn't a POSIX command, and retains its argument format
           | from before the POSIX CLI guidelines were standardized (as
           | does the POSIX ar command). pax, the POSIX-specified (but
           | rarely implemented/used) equivalent of tar does follow the
           | POSIX CLI guidelines.
        
         | rascul wrote:
         | Yes.
         | 
         | https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1...
        
       | xixixao wrote:
       | These are great. Most frustrating to me is that the basic
       | commands: rm, mv, cp, touch, mkdir do not follow some of the
       | basic guidelines, such as "ask before destructive action". I have
       | been reimplemting them in Rust for myself to fix this (although a
       | wrapper would have been perhaps better, it's hard to write it and
       | have the program work in any shell).
        
         | stephenr wrote:
         | It's pretty easy to have shell aliases for commands like rm,
         | cp, etc to use the "safe" mode (the `-i` option) by default.
         | 
         | Writing a replacement utility seems a bit like overkill.
        
       | pimlottc wrote:
       | Please also consider a --dry-run option that gives a preview of
       | what actions would be taken without actually making any changes.
       | This is really helpful for learning a tool and making sure you
       | got complex options and fileglobs correct before committing to
       | potentially irreversible changes.
        
         | samstave wrote:
         | dry-run should be a pipable | function for any command;
         | 
         |  _> do_thing.py | dry-run_
         | 
         | --
         | 
         | Think of it as " _explain your work, step by step_ " as one
         | would prompt...
         | 
         | also, its a food-for-thought you muppets.
         | 
         | ---
         | 
         | @jasonjmcghee ; ( $ ) . ( $ ) great justice.
        
           | jasonjmcghee wrote:
           | How could that work? The script on the left executes first,
           | piping its output to another command won't prevent that
        
             | saghm wrote:
             | I think there are ways to detect if stdout is a pipe and
             | operate differently (e.g. by using different defaults for
             | coloring output), but I'm not sure if there are ways to
             | detect what the other side of the pipe is, much less what
             | `dry-run` would actually be expected to be in this case
        
               | jasonjmcghee wrote:
               | Maybe I'm misunderstanding but sounds like you're
               | proposing the modifying the command on the left to detect
               | whether it's piping it's output (curious how you do that
               | btw sounds pretty cool / useful)
               | 
               | But at that point you could just handle --dry-run
               | directly
        
               | kergonath wrote:
               | > Maybe I'm misunderstanding but sounds like you're
               | proposing the modifying the command on the left to detect
               | whether it's piping it's output (curious how you do that
               | btw sounds pretty cool / useful)
               | 
               | You can do that. Possibly not from all languages but for
               | anything that can call functions in the c standard
               | library, that's what isatty() is for (among other uses).
               | It takes a file descriptor and returns whether it is a
               | terminal or not. If you do this with stdout, this tells
               | you whether it goes to a terminal or whether it is
               | redirected in a way.
               | 
               | As the parent suspects, though, this won't tell you
               | anything about what is on the other side of the
               | redirection.
        
               | jasonjmcghee wrote:
               | Very cool function - thank you!
        
               | kjs3 wrote:
               | If it operated differently based on what it was
               | outputting to, that kinda defeats the point of 'dry run',
               | which is to see exactly what's going to happen based on
               | what's on the other side of the pipe when I run it for
               | real. "Did this blow up because it's a bad command, or
               | because there's a bug in the 'only kinda real dry run'
               | code?".
        
               | samstave wrote:
               | +++
               | 
               | -
               | 
               | What if there wasa 'deep-pipe' '||' which would be based
               | on a set env/docker/blah - which would launch an env and
               | execute your '||'d code in it, and output some
               | log/metrics/whatever?
        
               | gpderetta wrote:
               | on the other hand you could have 'dry-run <command>' that
               | via .so interposition tricks could intercept and list all
               | destructive changes done by an arbitrary <command>, as a
               | form of sandboxing.
        
               | sokoloff wrote:
               | I often pipe output to tee and would be pretty annoyed if
               | that changed the behavior of the original command to not
               | do anything because stdout was a pipe.
        
               | indymike wrote:
               | > I often pipe output to tee and would be pretty annoyed
               | if that changed the behavior of the original command
               | 
               | The output sent to tee is usually not the same as the
               | output from the command to the terminal, so you are
               | getting something different than most human users expect
               | from original command... the reason is that terminal
               | escape codes and other formatting for humans may need to
               | be omitted from output to a pipe. You do this by asking
               | the OS, "is this thing a terminal?".
               | 
               | Python example
               | 
               | "terminal" if sys.stdout.isatty() else "something else"
               | 
               | C is very similar:
               | 
               | if (isatty (1)) fprintf (stdout, "Terminal."); else
               | fprintf (stdout, "Not Terminal.");
               | 
               | (printf works, too).
        
               | sokoloff wrote:
               | Sure; the output _format_ changes, but the
               | _functionality_ doesn 't.
               | 
               | Even ls outputs a tabular format by default when it's on
               | a terminal and a list one file/dir per line when it's not
               | on a terminal (if it's piped to cat for example or why ls
               | | wc -l correctly counts the entries).
               | 
               | But the (essential) behavior of the command remains the
               | same. ls still _lists files /dirs_... scp still copies
               | files, etc.
        
             | int_19h wrote:
             | Here's a possibly more interesting take on this: instead of
             | do-thing.py, imagine if there was thing.py, which processed
             | all that complex CLI options, and as output produced a
             | linear shell script, with each line invoking some atomic
             | operation, and a comment explaining which options
             | contributed to that particular line.
        
               | eichin wrote:
               | Yeah, that's a pattern I use for occasional sysadmin
               | tools - the command itself generates the actual commands,
               | I review them, then "<up arrow> | sh -xeu". (Yes, there's
               | no guarantee that the output is the same, so I don't use
               | the pattern when that's a risk; it's also rarely if ever
               | used for things I expect other people to run, just bulk
               | operations that are saving _me_ repetition.)
        
           | koolba wrote:
           | Having it be a shell function would work. It could create a
           | copy-on-write file system or override the syscalls for file
           | system access.
        
             | agos wrote:
             | not all the destructive actions are on file system
        
           | jasonjmcghee wrote:
           | Wasn't trying to be a prick- i was commenting "here's what
           | I'm seeing with your proposal and the presented obstacles,
           | how would you overcome them?"
           | 
           | One approach could be something like "set -x" after setting a
           | confirmation with "trap" command.
           | confirm_execution() {             echo -n "Execute
           | $BASH_COMMAND? [y/N] "             read response
           | if [[ $response != [yY] ]]; then                 echo
           | "Skipped."                 return 1             fi         }
           | trap 'confirm_execution' DEBUG         set -x
           | user_command         set +x
           | 
           | But that's a wrapper script
        
             | samstave wrote:
             | confirm_execution() { echo -n "Execute $BASH_COMMAND? [y/N]
             | " read response if [[ $response != [yY] ]]; then echo
             | "Skipped." return 1 fi }
             | 
             | draw_heart() { cat << EOF <svg
             | xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
             | width="100" height="100"> <path fill="red" d="M12
             | 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5
             | 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3
             | 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
             | </svg> EOF }
             | 
             | trap 'confirm_execution' DEBUG set -x draw_heart set +x
        
           | foobarqux wrote:
           | "try" is not a prefix (like watch, nice, etc) uses an
           | overlayfs in order to be able to see and accept or reject
           | changes to your filesystem from a command
           | 
           | https://github.com/binpash/try
        
         | epage wrote:
         | Or if the command can't be undone and with significant side
         | effects, be `--dry-run` by default and have an `--execute` flag
        
           | BD103 wrote:
           | Exactly. This is implemented by the Javascript code formatter
           | Prettier [1] where you have to pass `--write` in order to
           | overwrite an unformatted file.
           | 
           | [1]: https://prettier.io
        
         | bongodongobob wrote:
         | Whatif is one of my favorite things about powershell. Don't
         | know what I'd do without it. Has saved me many times from
         | completely destroying things.
        
           | ojintoad wrote:
           | Agree!
           | 
           | I'll go further. PowerShell covers a lot of the concerns in
           | the OP out of the box. It is extremely well thought out and
           | is one of my favorite cli models to buy into.
        
             | bigstrat2003 wrote:
             | Powershell is just plain a great shell. Blows all the *sh
             | variants out of the water. I'd love for it to gain traction
             | in Linux (so that, for example I could use it as my shell
             | on my desktop) but I don't really see that happening.
        
           | snuxoll wrote:
           | WhatIf in Powershell also remains completely broken; not that
           | it doesn't work, but it is not properly passed down the call
           | stack like it's supposed to from cmdlets or functions written
           | in PowerShell (as opposed to those loaded from .net
           | assemblies).
        
             | jcotton42 wrote:
             | Where have you seen this? If the function does it properly
             | (SupportsShouldProcess) then it should pass down
             | automatically.
        
         | danstewart_ wrote:
         | I tend to go the opposite way and have the default behaviour
         | not actually make any changes and require passing `--commit` to
         | actually do something.
         | 
         | I feel it's safer for scripts that have irreversible (or
         | difficult to reverse) actions.
        
           | enriquto wrote:
           | Even safer: your program does _never_ perform any actual
           | deed. It just prints commands that you can run afterwards,
           | using an external program, ideally a shell. This has the
           | advantage of allowing the user to edit all the actions one by
           | one.
           | 
           | Instead of                   myprog           # see what
           | would happen         myprog --commit  # alright, do it
           | 
           | You do                   myprog           # see what would
           | happen         myprog | sh      # alright, do it
           | 
           | But if you want to change something:                   myprog
           | > x         vi x         cat x | sh
           | 
           | And if you just want to run everything in parallel:
           | myprog | parallel -j 16
        
         | azemetre wrote:
         | Do you have an example of a CLT that has a dry run flag? I am
         | very confused on how to design one for some CLTs I'm making.
         | 
         | If you call an API to retrieve data, how can that be a dry run?
         | Are you suppose to give fake examples with fake output?
        
       | tester457 wrote:
       | > Do not read secrets from environment variables
       | 
       | > Secrets should only be accepted via credential files, pipes,
       | AF_UNIX sockets, secret management services, or another IPC
       | mechanism.
       | 
       | Which one of these is the most convenient and portable to use?
       | 
       | Do you use secret management services for work only, or do you
       | use them in your personal projects too?
        
         | AlwaysNewb23 wrote:
         | A secrets management service would be most convenient.
         | Documentation makes them easy to set up without having to build
         | anything extra yourself. A secrets manager like Doppler
         | (https://Doppler.com) or AWS Secrets Manager
         | (https://aws.amazon.com/secrets-manager/) has the advantage of
         | protecting your secrets in a secure place and the advantage of
         | minimizing exposure of those secrets - even to your own
         | developers. That way, you don't end up with a data breach that
         | could have easily been avoided. These types of leaks can cost
         | companies everything and are becoming way more common.
        
         | flgstnd wrote:
         | I like it when programs have a way to specify a command to
         | retrieve secrets. mbsync
         | (https://isync.sourceforge.io/mbsync.html) e.g. has afaik 3
         | options to provide a password for IMAP authentication: If you
         | don't configure a password, you'll be prompted on execution.
         | You can also put the plain text password in the configuration
         | (impractical if you want to share your configuration). But
         | there is also a configuration option to provide a command to
         | retrieve the password. That way you can delegate the password
         | handling to another program, e.g. a password manager like
         | pass(1) (https://www.passwordstore.org/) or some interactive
         | graphical prompt.
        
         | tashian wrote:
         | Hi, I'm one of the authors of CLI Guidelines.
         | 
         | See my post https://smallstep.com/blog/command-line-secrets/
         | for a bit more of a deep dive about using secrets on the
         | command line.
         | 
         | Credential files are a good, simple, portable option. Files
         | have permissions already. They don't depend on an external
         | service or a proprietary API.
         | 
         | And, if your program accepts a credential file, it will be
         | compatible with systemd credentials. systemd credentials offer
         | more security than an unencrypted credential file. They are
         | encrypted and can be TPM-bound, but they don't require the
         | software using the credential to have native TPM support.
        
           | cbm-vic-20 wrote:
           | It's probably a good idea to check the permissions of that
           | file, too, and emit a warning or exit with an error if the
           | they're too permissive.
        
             | indymike wrote:
             | A good example that all of us have seen is ssh. It does not
             | run if permissions on certs are incorrect.
        
       | avgcorrection wrote:
       | The worst part about terminal programs is that they can't be
       | deprecated. Or I don't know of a way to do it. Because once you
       | release something someone might immediately put it into a script
       | somewhere instead of running it interactively. Now what do you
       | do? Display a "hint" about the deprecation? Well no one's gonna
       | read that because it's a script which is run non-interactively.
       | 
       | So you just have to design the UI perfectly on the first try.
       | That's possible for small tools but what about larger ones? Past
       | a certain point it becomes a truism that do-it-once perfectly
       | without iteration is impossible.
        
         | fleischhauf wrote:
         | how is this different from some library somewhere?
        
           | avgcorrection wrote:
           | How is it similar? I get deprecation warnings if I update the
           | library. I can pin the version of the library. A library is
           | something I work with, unlike a terminal program which might
           | be written and forgotten.
           | 
           | Then those terminal programs get upgraded on the next system
           | update because hey, you're supposed to the get latest version
           | right?
           | 
           | Terminal programs can do the same (`-v1`) in principle. Few
           | do.
        
             | samatman wrote:
             | A terminal program is quite easy to pin, though, just do
             | this:                   - $package-manager install $program
             | - which $program         - cp $program ~/my/own/directories
             | - $package-manager uninstall $program
             | 
             | done. It won't ever change by accident.
        
               | avgcorrection wrote:
               | Nice. Then I will not hesitate to break the UI in my
               | upcoming terminal program releases. (... they are quite
               | well designed in my head.)
        
               | 10000truths wrote:
               | Not quite that simple. You can't just pin the program
               | itself, you also have to pin its dependencies. Which
               | means you have to run ldd to get the libraries it loads
               | (whether directly or transitively), and copy those too,
               | and then you patch the program and its dependencies to
               | set the rpath to $ORIGIN/my/own/directories, then you
               | have to examine all the other more subtle application-
               | level gotchas (e.g. path search order for config files,
               | hard-coded absolute paths, etc.) and port those too. Once
               | you're done, congratulations! You've done 50% of the work
               | of a package manager.
        
               | samatman wrote:
               | Yeah, I wish this kind of thing[0] were a core POSIX tool
               | which worked reliably on all systems and binaries. Bit of
               | an oversight, that.
               | 
               | [0]: https://github.com/greenpau/statifier
        
           | Viliam1234 wrote:
           | Other programs can use a later version of the library.
           | 
           | This would be analogical, if commands always included their
           | version. For example:                   rm-2.44.287-SNAPSHOT
           | -r /
        
       | arrakeen wrote:
       | > Use symbols and emoji where it makes things clearer.
       | 
       | for the love of god please don't. the yubikey-agent example
       | provided exemplifies everything i dislike about github READMEs
       | and whimsical user interfaces.
       | 
       | on the technical side, symbols and emojis can render
       | inconsistently among terminals, leading to potentially confusing
       | messaging. on the artistic side, personal tolerances towards
       | whimsy and playfulness vary wildly and should only be used very
       | sparingly and ONLY if you know what you're doing (if you have to
       | ask, you probably don't)
        
         | nerdponx wrote:
         | I like it as an optional feature. Some people enjoy it, some
         | people don't. Turn it off by default, but let users choose.
        
           | kevindamm wrote:
           | like a --verbosity=cute level, perhaps
        
         | Linux-Fan wrote:
         | Strongly resonates. The first time I saw the CLI Guidelines I
         | even stopped reading them upon reaching that section. This time
         | I read through the remainder and found it quite OK.
        
         | samatman wrote:
         | I like it. I like colored terminal output, and emoji are
         | colorful, which helps me rapidly form a gestalt of what's going
         | on. I like syntax highlighting too, and find code quite a bit
         | more difficult to read without it.
         | 
         | Not everyone is like that, and that's ok. I don't expect my
         | whims to be catered to, and you shouldn't either.
        
       | wang_li wrote:
       | If your program detects -? and tells the user to use -h or --help
       | or --long-help or --full-help you should be kicked in the crotch.
       | Just show me the help.
        
         | rascul wrote:
         | I often show help if an unknown option was given but in the
         | cases I don't I am not going through a list of special cases
         | that I don't even know of to try and determine that someone
         | wants the help text. I've never even seen -? before that I can
         | recall.
        
         | SAI_Peregrinus wrote:
         | I'd say -h and --help should return 0 & print help to stdout.
         | Any unknown option should return EINVAL and output an error
         | message and help text to stderr.
        
       | eterps wrote:
       | The most comprehensive CLI guidelines in the past have been in
       | this book by Eric Raymond:
       | 
       | https://www.goodreads.com/book/show/104745.The_Art_of_UNIX_P...
       | 
       | https://www.catb.org/esr/writings/taoup/
       | 
       | It has been a while since I read that book, but after skimming
       | through clig.dev I gather opinions have changed over time quite a
       | bit.
        
         | hiAndrewQuinn wrote:
         | I thought much the same thing when I read CLIG. I'm a big fan
         | of the 17 Unix rules he puts down, though, and I think a lot of
         | really good equilibria exist on the spectrum between the two.
        
       | nmz wrote:
       | There's something I wish command lines would not adopt that is
       | should not be as a CLI flag, and that's --json or --csv. Instead
       | this should be offered as an environment variable that runs
       | through all the commands like IOFORMAT=JSON { cmd1|cmd2|cmd3 } if
       | they support the environment variable, they can all read input in
       | a safe way and behave appropriately, if they don't, then they
       | just print as normal
        
         | gumby wrote:
         | (BTW sometimes ENV vars are bug removers and sometimes a
         | terrible source of mysterious bugs as well as a possible
         | injection vector.)
         | 
         | A good option package should support long options being _both_
         | command line flags and environment variables. The really good
         | ones support them in init files as well (I 'm partial to the
         | JSON-ish HOCON format, though .INI works too).
         | 
         | I always spec (later overrides previous settings):
         | - system default   (/etc/foo.conf)         - user defaults
         | (~/.foo.conf)         - local defaults   (${CWD}/foo.conf)
         | - user-specified init file (overrides local default)         -
         | environment vars (FOO_OUTPUT=JSON)         - command line var
         | (--output=json)
         | 
         | As well as --no-init and --no-env
        
       | klodolph wrote:
       | If you have -r / --recursive, I would rather just have -recursive
       | work as the others. POSIX be damned, the double hyphen is just an
       | opportunity to make more mistakes, and the combined -rptgo
       | single-hyphen flags are more opportunities to make mistakes.
       | 
       | Let some legacy programs like ls and sync keep their single-
       | hyphen combinations. Most new programs should just accept
       | separate flags, and allow either single or double hyphens.
       | 
       | Edit: Yeah, this opinion collects downvotes, doesn't it? Y'all
       | love it when you accidentally type -recursive instead of
       | --recursive, and it turns out that it means the same thing as -r
       | -e -c -u -s -i -v? That never made any sense to me, for the vast
       | majority of tools out there. It sucks, to be honest.
        
         | OJFord wrote:
         | I don't like combined single-hyphens for a different reason:
         | sometimes they accept arguments, and it seems strange to me
         | that `-a0` can variously mean `-a 0` and `-a -0`. (I think some
         | insist that argument-having options are long, and short options
         | can only be flags, which sort of solves it, except for the
         | existence of the others which makes it still confusing.) That
         | said, in a script, which is the main time I'd have to read the
         | way someone else has written it anyway, I favour everything
         | being --long --anyway --to-make-it=really-clear. (Though there
         | are a few that are so common I won't insist on, `cut -dX -fY`
         | say.)
         | 
         | You must like `find`.
        
       | gumby wrote:
       | > It is assumed that command-line interfaces are the opposite of
       | this--that you have to remember how to do everything. The
       | original Macintosh Human Interface Guidelines, published in 1987,
       | recommend "See-and-point (instead of remember-and-type)," as if
       | you could only choose one or the other.
       | 
       | I find that guis have _worse_ discoverability and cli better. It
       | 's pretty hard to search for a gui affordance. Plus they are
       | essentially unscriptable.
        
       | OJFord wrote:
       | > If stdout is not an interactive terminal, don't display any
       | animations. This will stop progress bars turning into Christmas
       | trees in CI log output
       | 
       |  _Never_ display animations in std _out_! I quite liked TFA in
       | general, but I was skimming around looking for where they were
       | going to advise on the difference between stderr  & stdout until
       | I saw that and realised they weren't.
       | 
       | stderr should be _all_ (not just  'errors') of your logging,
       | informational type stuff, the bits that maybe you might animate
       | (and some people will hate) if tty, etc.
       | 
       | stdout should be the useful output - which you may or may not
       | have - regardless of whether tty or not, primarily because an
       | inconsistency like that is just confusing.
       | 
       | e.g.                   echo foo | mysed 's/oo/aa/' | cat
       | # mysed should:         # stdout: faa         # stderr: mysed
       | version 1 here hello\nfound oo\nprinting aa (or whatever)
       | 
       | I don't want to have to fight your tool with grep to get the
       | 'actual' output lines. And I don't want to struggle to debug it
       | because if I remove `| cat` above (as a silly example) it behaves
       | differently than with it.
        
         | samatman wrote:
         | That's a good rule, pity about the name.
         | 
         | If we could go back in time and make it stdin, stdout, and
         | stdext (because UNIX so six letters, but standard_extra, or
         | standard_extended), we might have a prayer of getting people to
         | follow that convention.
         | 
         | But it's called stderr, so devs think, quite reasonably, that
         | it should be used for error reporting, and conversely, if it
         | isn't an error, it goes in stdout.
         | 
         | But I agree with you that this is the better way to structure a
         | program. You might confuse more people with it, but they'll be
         | able to do more useful things with its output, so that's a win.
        
           | OJFord wrote:
           | I think if I could go back in time, my fix would be to make
           | stderr the default. i.e. everything written 'out' goes to
           | stderr until you explicitly write it as an output to stdout
           | (or another descriptor/file), the inverse of the current
           | situation.
           | 
           | (Ok, sure, I'd probably change the name too!)
        
         | eikenberry wrote:
         | > stdout should be the useful output
         | 
         | To add a small tweak to this rule... "stdout should be what you
         | ask for". If I ask for --help, that should go to stdout. If I
         | ask for logs, they should go to stdout. If I don't ask for it,
         | stderr.
        
           | OJFord wrote:
           | Yup, absolutely, that is what I meant - the useful output
           | from the command, the thing you were looking for, that it's
           | actually doing/retrieving.
        
       | dang wrote:
       | Related:
       | 
       |  _Command Line Interface Guidelines_ -
       | https://news.ycombinator.com/item?id=38053692 - Oct 2023 (1
       | comment)
       | 
       |  _Command Line Interface Guidelines_ -
       | https://news.ycombinator.com/item?id=31651161 - June 2022 (1
       | comment)
       | 
       |  _Command Line Interface Guidelines_ -
       | https://news.ycombinator.com/item?id=25492119 - Dec 2020 (5
       | comments)
        
       | MichaelMoser123 wrote:
       | whatever happened to "Make each program do one thing well. To do
       | a new job, build afresh rather than complicate old programs by
       | adding new 'features'"?
       | 
       | now we got lots of mega-cli programs, each one with its own
       | distinct option language.
       | 
       | Examples: kubectl, docker, openssl, git - (git got two command
       | line languages: plumbing and porcelain)
       | 
       | https://danluu.com/cli-complexity/
       | 
       | ... ls had 11 command line options in 1979, in 2017 it got 58.
        
       | hiAndrewQuinn wrote:
       | I know it goes without saying for most of us here, but actually
       | being a heavy terminal user yourself is one of the most important
       | things to understand how to design CLIs. It helps a ton to
       | understand the ecosystem you live in, not just your own organism.
       | 
       | Example: Something I did a few months back ago for a tiny
       | personal project @ https://github.com/hiAndrewQuinn/finstem was
       | implement `--format CSV`, `TSV` and `JSON` flags. I haven't had
       | need for any of these myself, but they exist so any future people
       | who want to use `csvkit`, `awk` and `jq` respectively to wrap
       | around my program have easy ways to do so. That's not stuff I
       | would have had the instincts to do if I wasn't myself a user of
       | all 3 of those programs.
        
         | hollerith wrote:
         | >being a heavy terminal user . . . is one of the most important
         | things
         | 
         | I wish people wouldn't conflate CLIs with terminals. I run
         | (shell) command lines all day, but try hard to avoid terminals
         | / apps that emulate terminals.
         | 
         | (To run command lines, I use Emacs, which I never run inside a
         | terminal.)
        
       | egberts1 wrote:
       | systemd fails badly with the CLI guideline.
       | 
       | My biggest beef is total lack of CLI exit code.
       | 
       | Makes it useless for bash programming with systemd utils.
        
       ___________________________________________________________________
       (page generated 2024-02-06 23:01 UTC)