Why another task-running/subprocess-spawning Python library? As usual, the
short answer is “there were already great 80-90% solutions out there, but none
that fit our needs 100%.” Specifically:

Multiple tasks at once - almost no other Python command-line oriented
libraries allow for invocations like:

runner--core-optstask1--task1-optstask2--task2-opts

and the few that do have half-baked implementations of the feature or are
lacking in other ways.

Ability to mirror and capture subprocess output simultaneously (in
addition to everything flowing from that, like the ability to transparently
auto-respond) - the standard library’s subprocess can’t do this and most
other tools choose one or the other, or have other tradeoffs such as not
supporting (or only supporting!) pseudoterminals.

Simplicity - tools that try to do many things often suffer for it due to
lack of focus. We wanted to build something clean and simple that just did
one thing (ok…two things) well.

Customizability/control - Invoke was designed to work well with (and be a
foundation for) other tools such as Fabric’s second
version, and we felt that the work needed to adapt existing tools towards
this goal would impede progress.

Some of the pre-existing solutions in this space in the Python world include:

Argh: One of the more
appealing options, but being built on argparse it doesn’t support the
multi-task invocation we needed. Also has its own “prior art” list which is
worth your time.

Argparse: The modern gold
standard for CLI parsing (albeit without command execution). Unfortunately,
we were unable to get multiple tasks working despite lots of experimentation.
Multiple tasks with their own potentially overlapping argument names, simply
doesn’t mesh with how argparse thinks about the command line.

Click: is actually not pre-existing
(Invoke’s first public releases predate Click by a number of years) but it
deserves mention anyway, as it’s become popular in this particular niche.