Ask HN: Why is there no specification for Command Line Interfaces?
Similar to specifications like OpenAPI, etc. it seems like having something similar for CLIs would be cool. Why isn't there one already? How do you approach stubbing a CLI to interface with one or more APIs?
Edit: I forgot to mention the closest thing I've found is: https://clig.dev/ which is the most comprehensive "guide" I've seen to date.
18 comments
[ 3.5 ms ] story [ 55.3 ms ] threadBy "CLI" do you mean "shell interpreter/environment"?
Or do you mean "command-line interface for a given tool"
- GNU: https://www.gnu.org/prep/standards/html_node/Command_002dLin...
- POSIX: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1...
An OpenAPI specification describes an HTTP interface, and I see it as useful because it makes it easier to write code in language-of-choice to generate HTTP requests (by generating client libraries from the OpenAPI spec).
For a CLI, the interface is the command-line. Usually people type these commands, or they end up in bash scripts, or sometimes they get called from programming language of choice by shelling out to the CLI. So I could see a use case for a CLI spec, which would make it easier to generate client libraries (which would shell out to the CLI)... but it seems a little niche.
Or maybe, as input to a documentation tool (like Swagger docs). I would imagine if you're using a CLI library like Python's Click, most of that data is already there. Click Parameters documentation: https://click.palletsprojects.com/en/8.1.x/parameters/
Or maybe, you could start from the spec and then generate code which enforces it. So any changes pass through the spec, which would make it easy to write code (server and client-side) / documentation / changelogs. Some projects like this: Guardrail (Scala) https://github.com/guardrail-dev/guardrail , and Connexion (Python) https://github.com/spec-first/connexion .
But without this ecosystem of tooling, documenting your CLI in a specification didn't really seem worth the effort. Of course, that's a bootstrapping problem.
I also recently saw Microsoft take a higher level approach with CADL/Typespec: https://microsoft.github.io/typespec/ which could be cool if it reaches wide adoption.
Especially in the DevOps space, I find one CLI’s “update” will be another’s “apply”, one “delete” will be another “remove“, add/create, etc. It adds excessive cognitive load.
More broadly, an enterprise might define how CLIs are created including handling of authentication through such a specification.
Google ended up using gflags which automatically adds command line arguments to a program as a side effect of code being imported. In this way, using the same library as someone else automatically creates some consistent command line behavior.
My take is gflags not only creates side effects but abuses global scope and therefore encourages bad architecture.
Specification is too strict in this case, so it's less useful than "best practices" which's adapt to a context.
Command line arguments are an array of null-terminated strings, as is the environment (at least there we have the convention "<key>=<value>").
It might be neat to define a schema language together with a validator that takes a schema and a "style" and then validates an array of strings. e.g. "validate gnu myschema.ext -- subcommand --flag -etc --thing=value arg arg".
- https://cs.github.com/?scopeName=All+repos&scope=&q=github.c...
[0]: https://github.com/spf13/cobra
As an example, for a C program you have
From there, it is just conventions on what the arguments mean.There are trends, and patterns, and conventions in both GUI and CLI design but it's always going to be about the UX, the use case, the target audience, etc.