Counterpoint: Yes, parse don't validate, but CLIs should not be dealing with dependency management.
I love Python's argparse because:
- It's "Parse, don't validate" (even supports
FileTypeas a target) - It enforces or strongly encourages good CLI design
- Required arguments should in most situations be positional arguments, not flags. It's
curl <URL>notcurl --url <URL>. - Flags should not depend on each other. That usually indicates spaghetti CLI design. Don't do
server --serve --port 8080andserver --reloadwith rules for mix-and-matching those, doserver serve --port 8080andserver reloadwith two separate subparsers. - Mutually exclusive flags sometimes make sense but usually don't. Don't do
--xml --json, do-f [xml|json]. - This
or(pattern of yours IMO should always be replaced by a subparser (which can use inheritance!). As a user the options' data model should be immediately intuitive to me as I look at the--helpand having mutually exclusive flags forces the user to do the extra work of dependency management. Don't doserver --env prod --auth abc --ssl, doserver serve prod --auth abc --sslwhereprodis its own subparser inheriting fromAbstractServeParseror whatever.
- Required arguments should in most situations be positional arguments, not flags. It's
Thinking of CLI flags as a direct mapping to runtime variables is the fundamental mistake here I think. A CLI should be a mapping to the set(s) of behavior(s) of your application. A good CLI may have mandatory positional arguments but has 0 mandatory flags, 0 mutually exclusive flags, and if it implements multiple separate behaviors should be a tree of subparsers. Any mandatory or mutually exclusive flags should be an immediate warning that you're not being very UNIX-y in your CLI design.
