cliff Command Line Interface Formulation Framework
cliff (Command Line Interface Formulation Framework) is a Python library for building structured command-line applications, commonly used for OpenStack clients and other complex CLIs. It provides base classes for application structure, command registration, argument parsing, and consistent output formatting. The current version is 4.13.3, and it maintains a regular release cadence with active development.
Warnings
- breaking Python 3.10+ is now required. Additionally, build system dependencies shifted from 'pbr' to 'setuptools-scm' or direct 'setuptools' for project setup.
- breaking The `log_file` option for `App.run()` and related logging configuration methods have been removed.
- gotcha Commands are discovered via Setuptools entry points (e.g., `[cliff.commands]` or custom groups like `[mycli_entrypoints]` in `setup.cfg` or `pyproject.toml`). Misconfiguring or omitting these entry points will prevent your commands from being found by the CLI application.
- gotcha `Lister` and `ShowOne` command types expect specific return value structures. `Lister` expects `(column_names, data_rows)` and `ShowOne` expects `(column_names, data_item)` where `data_rows` is a list of tuples/lists and `data_item` is a single tuple/list.
Install
-
pip install cliff
Imports
- App
from cliff.app import App
- Command
from cliff.command import Command
- Lister
from cliff.lister import Lister
- ShowOne
from cliff.showone import ShowOne
Quickstart
import sys
from cliff.app import App
from cliff.command import Command
from cliff.commandmanager import CommandManager
class MyCommand(Command):
"""A simple example command."""
def get_parser(self, prog_name):
parser = super().get_parser(prog_name)
parser.add_argument(
'--name',
dest='name',
default='World',
help='Name to greet'
)
return parser
def take_action(self, parsed_args):
print(f"Hello, {parsed_args.name}!")
class MyCLIApp(App):
def __init__(self):
super().__init__(
description='My simple cliff-based CLI',
version='1.0',
command_manager=CommandManager('mycli_entrypoints'),
deferred_help=True,
)
def initialize_app(self, argv):
self.LOG.debug('initialize_app')
def prepare_to_run(self, argv):
self.LOG.debug('prepare_to_run')
def clean_up(self, cmd, result, err):
self.LOG.debug('clean_up')
if err:
self.LOG.debug(f'An error occurred: {err}')
def main(argv=sys.argv[1:]):
# For a real app, commands are typically registered via setup.cfg or pyproject.toml entry points.
# Example: In pyproject.toml, under [project.entry-points."mycli_entrypoints"]
# 'mycommand = my_module:MyCommand'
# And under [project.scripts]
# 'mycli = my_module:main'
# For this quickstart, we manually register the command:
app = MyCLIApp()
app.command_manager.add_command('mycommand', MyCommand)
return app.run(argv)
if __name__ == '__main__':
# Simulate running 'mycli mycommand --name Registry' from the command line
sys.exit(main(['mycommand', '--name', 'Registry']))