Cleo 0.4 is now out. Commands have been largely improved and are now easier to use. Helpers have also been improved. Overall, Cleo is now more intuitive.
This version breaks the backward compatibility for the following parts:
- The 
DialogHelperhas been replaced by a more robustQuestionHelper - The 
ProgressHelperhas been removed and theProgressBarclass must be used - When using decorators or dictionaries, the signature of the callback has changed and accepts only a 
Commandinstance 
New Commands
The Command class has been improved, with a new way of describing it via docstring and several helper methods:
Command signature
The definition of a command can now be declared in the docstring:
class GreetCommand(Command):
    """
    Greets someone
    demo:greet
        {name? : Who do you want to greet?}
        {--y|yell : If set, the task will yell in uppercase letters}
    """The handle() method
The logic of the command now needs to be put in the handle() method:
class GreetCommand(Command):
    """
    Greets someone
    demo:greet
        {name? : Who do you want to greet?}
        {--y|yell : If set, the task will yell in uppercase letters}
    """
    def handle(self):
        name = self.argument('name')
        if name:
            text = 'Hello %s' % name
        else:
            text = 'Hello'
        if self.option('yell'):
            text = text.upper()
        self.line(text)Helper methods
Commands are now easier to use with new helper methods.
argument() and option()
These methods make it easier to access command's arguments and options.
name = self.argument('name')
yell = self.option('yell')line()
This methods writes a new line to the output:
self.line('New line')A style can also be passed as a second argument:
self.line('New line', 'comment')The native styles have their own helper methods:
self.info('foo')
self.comment('foo')
self.question('foo')
self.error('foo')call()
Calls another command:
return_code = self.call('demo:greet', [
    ('name', 'John'),
    ('--yell', True)
])If you want to suppress the output of the executed command,
you can use the call_silent() method instead.
confirm()
Confirm a question with the user.
confirmed = self.confirm('Continue with this action?', False)In this case, the user will be asked “Continue with this action?”. If the user answers with y it returns True or False if they answer with n. The second argument to confirm() is the default value to return if the user doesn’t enter any valid input. If the second argument is not provided, True is assumed.
ask()
Prompt the user for input.
name = self.ask('Please enter your name', 'John Doe')secret()
Prompt the user for input but hide the answer from the console.
password = self.secret('Enter the database password')choice()
Give the user a single choice from an list of answers.
def handle(self):
    color = self.choice(
        'Please select your favorite color (defaults to red)',
        ['red', 'blue', 'yellow'],
        0
    )
    self.line('You have just selected: %s' % color)render_table()
Format input to textual table.
def handle(self):
    headers = ['ISBN', 'Title', 'Author']
    rows = [
        ['99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'],
        ['9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'],
        ['960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'],
        ['80-902734-1-6', 'And Then There Were None', 'Agatha Christie']
    ]
    self.render_table(
        headers,
        rows   
    )You can also use the table() method to retrieve a Table instance.
progress_bar()
Creates a new progress bar.
def handle(self):
    # Create a new progress bar (50 units)
    progress = self.progress_bar(50)
    # Start and displays the progress bar
    for _ in range(50):
        # ... do some work
        # Advance the progress bar 1 unit
        progress.advance()
        # You can also advance the progress bar by more than 1 unit
        # progress.advance(3)
    # Ensure that the progress bar is at 100%
    progress.finish()set_style()
Sets a new formatting style.
def handle(self):
    self.set_style('fire', fg='red', bg='yellow', options=['bold', 'blink'])
    self.line('<fire>foo</fire>')Progress Bar
The ProgressHelper has been removed and the improved ProgressBar (or its helper method progress_bar())
must now be used instead: 
def handle(self):
    # Create a new progress bar (50 units)
    progress = self.progress_bar(50)
    # Start and displays the progress bar
    for _ in range(50):
        # ... do some work
        # Advance the progress bar 1 unit
        progress.advance()
        # You can also advance the progress bar by more than 1 unit
        # progress.advance(3)
    # Ensure that the progress bar is at 100%
    progress.finish()Table
The TableHelper has been deprecated and the improved Table (or its helper method table())
should now be used instead:
def handle(self):
    table = self.table()
    headers = ['ISBN', 'Title', 'Author']
    rows = [
        ['99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'],
        ['9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'],
        ['960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'],
        ['80-902734-1-6', 'And Then There Were None', 'Agatha Christie']
    ]
    table.set_headers(headers)
    table.set_rows(rows)
    table.render()Question Helper
The DialogHelper has been removed and the improved QuestionHelper (or one of its helper methods)
must now be used instead:
def handle(self):
    confirmed = self.confirm('Continue with this action?', False)
    name = self.ask('Please enter your name', 'John Doe')
    password = self.secret('Enter the database password')
    color = self.choice(
        'Please select your favorite color (defaults to red)',
        ['red', 'blue', 'yellow'],
        0
    )More verbosity
Two other levels of verbosity (-vv and -vvv) have been added.
Command description format
Commands description can now be output as json and markdown:
console help demo:greet --format json
console help demo:greet --format mdDecorators and dictionaries notation
When using decorators or dictionaries, the signature of the callback has changed and accepts only a Command instance:
def decorated(c):
    """
    :type c: Command
    """This is so that helper methods can be accessed inside code functions.
Autocompletion
Autocompletion has also been improved, and the old bash_completion.sh has been removed.
To activate support for autocompletion, pass a complete keyword when initializing
your application:
application = Application('My Application', '0.1', complete=True)Now, register completion for your application by running one of the following in a terminal,
replacing [program] with the command you use to run your application:
# BASH ~4.x, ZSH
source <([program] _completion --generate-hook)
# BASH ~3.x, ZSH
[program] _completion --generate-hook | source /dev/stdin
# BASH (any version)
eval $([program] _completion --generate-hook)By default this registers completion for the absolute path to you application,
which will work if the program is accessible on your PATH.
You can specify a program name to complete for instead using the -p\--program option,
which is required if you're using an alias to run the program.
If you want the completion to apply automatically for all new shell sessions,
add the command to your shell's profile (eg. ~/.bash_profile or ~/.zshrc)
Fixes
- Values are now properly cast by validators
 - Fixing "flag" not being set properly
 - Progress bar now behaves properly (Fixes #37)
 - The 
-n|--no-interactionoption behaves properly (Fixes #38 and #39) 
There is a lot more you can do with Cleo, you can just give a look at the documentation: http://cleo.readthedocs.org.