Skip to main content

Replace your HTML templates with Python server-Side components

Project description

Proper CLI

Proper CLI is a Python library for creating composable, nestable, and ridiculously good looking command-line-user-interfaces from simple classes.

proper_cli output


  • Made for interfacing with humans.
  • Arbitrary nesting and composition of commands.
  • Automatic help page generation
  • No need to redeclare paramaters and options with decorators, just write Python methods
  • The help of a command is its docstring, why make it more complex?


Declare a class that inherits from proper_cli.Cli. Every method/attribute that does not starts with an underscore will be a command.

from proper_cli import Cli

class Manage(Cli):
    def first(self, arg1, arg2=3):

    def second(self):

    def _not_a_command(self):

Then, instance that class and call it.

cli = Manage()

if __name__ == "__main__":

The class dosctring will be printed at the beginning of the help page.

The arguments can be then passed by position:

python first foo bar

or by name:

python first -arg1 foo -arg2 bar

To pass a True use the name without a value, for a False, prepend the name of the argument with no-:

python first -arg1 -no-arg2


If an attribute is a subclass of proper_cli.Cli, it will be a subgroup:

from proper_cli import Cli

class DBSub(Cli):
    def migrate(self):

class Manage(Cli):
    # A subgroup
    db = DBSub  # NOT `DBSub()`


You can pass any named argument as context to be used by your commands. This will be stored at the _env attribute.


>>> cli = Manage(lorem="ipsum")
>>> print(cli._env)
{"lorem": "ipsum"}

An example

The image at the top was autogenerated by running this example:

from proper_cli import Cli

class DBCli(Cli):
    """Database-related commands

    def migrate(self, message):
        """Autogenerate a new revision file.

        This is an alias for "revision --autogenerate".


        - message: Revision message


    def branches(self):
        """Show all branches."""

class MyCli(Cli):
    """Welcome to Proper CLI 3

    def new(self, path, quiet=False):
        """Creates a new Proper application at `path`.


        - path: Where to create the new application.
        - quiet [False]: Supress all output.

    def hello(count, name):
        """Simple program that greets NAME for a total of COUNT times."""

    # A subgroup!
    db = DBCli

cli = MyCli()

if __name__ == "__main__":

Coloring the Output

Whenever you output text, you can surround the text with tags to color its output (thanks to This is automatically enabled for the docstrings, but you can also have it by using proper_cli.echo() as a drop-in replacement of print().

# green text

# black text on a cyan background

# bold text on a yellow background

Available foreground and background colors are: black, red, green, yellow, blue, magenta, cyan and white.

The available options are: bold, underscore, blink, reverse and conceal.

The closing tag can be replaced by </>, which revokes all formatting options established by the last opened tag.

Custom styles

These four styles are available by default:

# green text

# yellow text

# black text on a cyan background

# white text on a red background

It is possible to define your own styles using the proper_cli.add_style() method:

add_style("fire", fg="red", bg="yellow", options=["bold", "blink"])


Beyond the CLI builder, proper_cli also includes some commonly-used helper functions

confirm(question, default=False, yes_choices=YES_CHOICES, no_choices=NO_CHOICES)

Ask a yes/no question via and return their answer.

ask(question, default=None, alternatives=None)

Ask a question via input() and return their answer.


Why don't just use optparse or argparse?

I find it too verbose.

Why don't just use click?

Are you kidding? Because this looks better and is easier to use and understand.

Why don't just use...?

Because this library fits better my mental model. I hope it matches yours as well.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

proper_cli-1.4.1.tar.gz (12.9 kB view hashes)

Uploaded Source

Built Distribution

proper_cli-1.4.1-py3-none-any.whl (13.6 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page