Or: Why does writing command line apps still require so much work?
My answer to the first question would probably be: TAB. (Especially since I switched to zsh ~2 years ago.)
But more about that later. This is simply one of the reasons I started this project.
When you start a command line tool you probably add Getopt::* as soon as you need options. Maybe Getopt::Long::Descriptive, so you can get a usage output.
There's also App::Cmd, MooseX::App, MooseX::App::Cmd, MouseX::App::Cmd, MooX::Cmd and possibly more. Some can't do nested subcommands; they all look and work a bit different. Shell completion just exists for some and would have to be implemented for every single module.
And in the end you have to know about all, since you might work on projects from somebody else.
What they all do is create a commandline app from a specification, but the way you describe it is very different, although the basic concepts have a lot in common.
To get the specification of a tool, you have to run it. So the code for creating completion or usage, for example, has to be written for each of them. And the same for tools written in other languages.
A possible solution or just another reinvention of the wheel?
When I was working on an app which had subcommands and options generated automatically from another source, I had the option of generating a bunch of MooseX::App classes, which would still be lacking things I wanted. Better parameter validation, better completion, ...
So I thought of creating an intermediate format, a specification in text form. This resulted in Just Another Command Line Framwork, which I gave the boring but short name:
App::Spec is the class for representing the specification in perl, App::Spec::Run is the class you should inherit from which runs the actual app.