Cleo
raw JSON → 2.1.0 verified Tue May 12 auth: no python install: verified quickstart: verified
Cleo is a Python library designed to help developers create beautiful and testable command-line interfaces. It draws significant inspiration from the Symfony Console Component, providing a robust and familiar structure for building CLI applications. The library is actively maintained, with a release cadence that includes support for new Python versions and essential bug fixes, as demonstrated by the recent 2.1.0 update.
pip install cleo Common errors
error ModuleNotFoundError: No module named 'cleo' ↓
cause The 'cleo' library is not installed in the current Python environment or is not accessible to the Python interpreter being used.
fix
Install the library using pip:
pip install cleo error Not enough arguments (missing: "<argument_name>") ↓
cause When programmatically calling a command using `self.call()` from within another Cleo command, the arguments for the target command were not passed or parsed in the expected string format, leading to missing required arguments.
fix
Ensure arguments for the called command are passed as a single string to
self.call(), often including the command name itself as the first part of the argument string, e.g., self.call("target_command_name", "target_command_name arg_value --option"). error The command "<command_name>" does not exist. ↓
cause The command you are trying to execute or get help for has not been registered with the Cleo `Application` instance, or there's an issue with how nested commands are identified.
fix
Verify that your command class is properly added to the
Application using application.add(YourCommand()). For nested commands, ensure the full command name (e.g., namespace:command) is correctly passed. error No such option: --<option_name> ↓
cause An option was provided on the command line that has not been defined in the command's signature, or there is a typo in the option name.
fix
Define the expected option in the command's docstring using the
{--option_name} or {--option_name=default} syntax, or correct any typos in the option name being passed. Warnings
breaking Cleo versions 1.0.0 and 2.0.0 removed the `clikit` dependency, signifying a major internal refactoring. Code relying on `clikit` directly or specific `clikit`-based behaviors within Cleo will break. ↓
fix Review your code for direct or indirect `clikit` usage. Adapt to Cleo's native implementations for input/output handling, command definition, and other CLI functionalities. The library is now self-contained in this regard.
breaking The `Terminal` class was removed and replaced with `shutil.get_terminal_size()` from Python's standard library. Direct calls to `cleo.terminal.Terminal` will fail. ↓
fix Replace usages of `cleo.terminal.Terminal` with `shutil.get_terminal_size()` for terminal dimension retrieval.
breaking The exception hierarchy changed in versions 1.0.0 / 2.0.0. Specifically, `CleoException` was renamed or replaced by `CleoError`. ↓
fix Update exception handling blocks to catch `CleoError` instead of `CleoException` and adjust for any other related exception class changes.
breaking Doc comment-based command configuration (where arguments and options were defined in the command's docstring) was removed in versions 1.0.0 / 2.0.0. ↓
fix Migrate command argument and option definitions to use the `arguments` and `options` class variables with `cleo.helpers.argument` and `cleo.helpers.option` decorators. Refer to the quickstart example for the new syntax.
gotcha Cleo version 1.0.0 was yanked shortly after its release due to compatibility issues with other projects (e.g., Poetry) that depended on its pre-release versions. Version 2.0.0 was released immediately after with no source code changes to effectively replace 1.0.0. ↓
fix Avoid using `cleo==1.0.0`. If targeting the feature set introduced in `1.0.0`, ensure you use `cleo>=2.0.0` (e.g., `pip install 'cleo>=2.0.0,<3.0.0'`).
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.16s 34.7M
3.10 alpine (musl) - - 0.14s 34.7M
3.10 slim (glibc) wheel 2.9s 0.14s 31M
3.10 slim (glibc) - - 0.14s 31M
3.11 alpine (musl) wheel - 0.20s 36.7M
3.11 alpine (musl) - - 0.22s 36.7M
3.11 slim (glibc) wheel 2.5s 0.18s 33M
3.11 slim (glibc) - - 0.16s 33M
3.12 alpine (musl) wheel - 0.17s 28.5M
3.12 alpine (musl) - - 0.18s 28.5M
3.12 slim (glibc) wheel 2.2s 0.17s 25M
3.12 slim (glibc) - - 0.17s 25M
3.13 alpine (musl) wheel - 0.15s 28.3M
3.13 alpine (musl) - - 0.17s 28.2M
3.13 slim (glibc) wheel 2.3s 0.17s 25M
3.13 slim (glibc) - - 0.16s 25M
3.9 alpine (musl) wheel - 0.10s 34.4M
3.9 alpine (musl) - - 0.11s 34.4M
3.9 slim (glibc) wheel 3.4s 0.11s 30M
3.9 slim (glibc) - - 0.10s 30M
Imports
- Application wrong
from cleo import Applicationcorrectfrom cleo.application import Application - Command wrong
from cleo import Commandcorrectfrom cleo.commands.command import Command - argument wrong
from cleo import InputArgumentcorrectfrom cleo.helpers import argument - option wrong
from cleo import InputOptioncorrectfrom cleo.helpers import option - CleoError wrong
from cleo.exceptions import CleoExceptioncorrectfrom cleo.exceptions import CleoError
Quickstart verified last tested: 2026-04-24
import os
from cleo.application import Application
from cleo.commands.command import Command
from cleo.helpers import argument, option
class GreetCommand(Command):
name = "greet"
description = "Greets someone"
arguments = [
argument("name", description="Who do you want to greet?", optional=True)
]
options = [
option("yell", "y", description="If set, the task will yell in uppercase letters", flag=True)
]
def handle(self):
name = self.argument("name")
if name:
text = f"Hello {name}"
else:
text = "Hello"
if self.option("yell"):
text = text.upper()
self.line(text)
application = Application("My CLI App", "1.0.0")
application.add(GreetCommand())
if __name__ == "__main__":
# Example of how to run, in a real app this would be called via command line
# e.g., `python your_script.py greet John --yell`
# For quickstart, we'll simulate it for programmatic execution and testing
try:
# Simulate a command-line call for demonstration
# In a real scenario, this would be invoked via sys.argv
from cleo.io.buffered_io import BufferedIO
from cleo.io.inputs.string_input import StringInput
from cleo.io.outputs.buffered_output import BufferedOutput
# Example: running 'greet John --yell'
input_stream = StringInput('greet John --yell')
output_stream = BufferedOutput()
error_stream = BufferedOutput()
io = BufferedIO(input_stream, output_stream, error_stream)
application.run(io)
print("\n--- Output ---")
print(output_stream.fetch())
print("--- Error ---")
print(error_stream.fetch())
print("--------------")
# Example: running 'greet'
input_stream_no_args = StringInput('greet')
output_stream_no_args = BufferedOutput()
error_stream_no_args = BufferedOutput()
io_no_args = BufferedIO(input_stream_no_args, output_stream_no_args, error_stream_no_args)
application.run(io_no_args)
print("\n--- Output (No Args) ---")
print(output_stream_no_args.fetch())
print("--- Error (No Args) ---")
print(error_stream_no_args.fetch())
print("------------------------")
except Exception as e:
print(f"An error occurred: {e}")