Of course! Setting up a Python CLI with the click library is a fantastic choice. It's powerful, easy to learn, and produces a great user experience.

Here is a comprehensive, step-by-step guide to setting up a click project, from installation to advanced features.
Step 1: Installation
First, you need to install the click library. It's best practice to do this in a Python virtual environment.
# 1. Create and activate a virtual environment (optional but recommended) python -m venv my_cli_project source my_cli_project/bin/activate # On Windows: my_cli_project\Scripts\activate # 2. Install click pip install click
Step 2: Your First "Hello, World!" CLI
Let's create a simple command that prints "Hello, World!".
- Create a new file named
hello.py. - Add the following code:
# hello.py
import click
@click.command()
def hello():
"""This script prints Hello, World!"""
click.echo("Hello, World!")
if __name__ == '__main__':
hello()
Explanation:

import click: Imports the library.@click.command(): This is a decorator. It tellsclickthat thehellofunction is a command-line interface. It automatically handles parsing arguments and running the function.click.echo(...): This is the preferred way to print output inclick. It's similar toprint(), but it handles some terminal complexities better (like colors and encoding).if __name__ == '__main__':: This standard Python construct allows the script to be run directly.
How to run it:
Save the file and run it from your terminal:
python hello.py
Output:
Hello, World!
click automatically generates a helpful help message. Try running:
python hello.py --help
Output:
Usage: hello.py [OPTIONS]
This script prints Hello, World!
Options:
--help Show this message and exit.
This is the foundation of every click application.
Step 3: Adding Arguments and Options
Commands become useful when they can accept input. click has two main types of inputs:
- Arguments: Positional values (required). Think of them like function arguments.
- Options: Named flags with values (can be optional or required). Think of them like
--verboseor--count.
Example with Arguments
Let's modify hello.py to greet a specific person.
# hello.py
import click
@click.command()
@click.argument('name') # This is a required positional argument
def hello(name):
"""Greets someone by their name."""
click.echo(f"Hello, {name}!")
if __name__ == '__main__':
hello()
How to run it:
Now you must provide a name:
python hello.py Alice
Output:
Hello, Alice!
The help message is also updated:
python hello.py --help
Output:
Usage: hello.py [OPTIONS] NAME
Greets someone by their name.
Options:
--help Show this message and exit.
Example with Options
Let's add an option to control the greeting's excitement level.
# hello.py
import click
@click.command()
@click.argument('name')
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--verbose', is_flag=True, help='Enables verbose mode.')
def hello(name, count, verbose):
"""Simple program that greets NAME for a total of COUNT times."""
for _ in range(count):
if verbose:
click.echo(f"Verbose mode is on. Greeting {name}...")
else:
click.echo(f"Hello, {name}!")
if __name__ == '__main__':
hello()
Explanation of new decorators:
@click.option('--count', default=1, ...): Defines an option named--count.--count: The command-line flag the user will type.default=1: If the user doesn't provide--count, it defaults to1.help='...': The description shown in the--helpmessage.
@click.option('--verbose', is_flag=True, ...): This is a common pattern for boolean flags.is_flag=True: Tellsclickthat this option is a boolean flag. The user will either include--verbose(makingverboseTrue) or not include it (makingverboseFalse).
How to run it:
# Basic usage python hello.py Bob # Use the count option python hello.py Bob --count 3 # Use the verbose flag python hello.py Bob --count 2 --verbose
Output for the last command:
Verbose mode is on. Greeting Bob...
Verbose mode is on. Greeting Bob...
Step 4: Organizing with Groups
For larger applications, you'll want to group related commands. click makes this easy with click.Group.
Let's create a main CLI group called mycli with two sub-commands: hello and goodbye.
- Create a file named
mycli.py.
# mycli.py
import click
@click.group()
def cli():
"""A simple CLI application with a group of commands."""
pass
# A sub-command of the 'cli' group
@cli.command()
@click.argument('name')
def hello(name):
"""Prints a greeting to NAME."""
click.echo(f"Hello, {name}!")
# Another sub-command
@cli.command()
@click.argument('name')
def goodbye(name):
"""Prints a farewell to NAME."""
click.echo(f"Goodbye, {name}!")
if __name__ == '__main__':
cli() # This runs the group, which then dispatches to the correct sub-command
Explanation:
@click.group(): This decorator creates a specialclick.Commandthat can hold other commands.@cli.command(): This decorator registers a function as a sub-command of thecligroup.cli(): We call thecligroup at the end, which acts as the main entry point.
How to run it:
# Run the main group's help python mycli.py --help
Output:
Usage: mycli.py [OPTIONS] COMMAND [ARGS]...
A simple CLI application with a group of commands.
Options:
--help Show this message and exit.
Commands:
goodbye Prints a farewell to NAME.
hello Prints a greeting to NAME.
# Run a specific sub-command python mycli.py hello Charlie
Output:
Hello, Charlie!
# Run another sub-command python mycli.py goodbye David
Output:
Goodbye, David!
Step 5: Packaging Your CLI (Making it Installable)
To make your CLI available system-wide (like pip or git), you need to package it using setuptools.
-
Project Structure: Organize your files like this:
my_cli_project/ ├── mycli/ │ ├── __init__.py # Can be empty │ └── cli.py # Your click code ├── setup.py └── README.md -
mycli/cli.py: Move your code frommycli.pyinto this file.# mycli/cli.py import click @click.group() def cli(): """A simple CLI application.""" pass @cli.command() def hello(): """Prints a greeting.""" click.echo("Hello from the packaged CLI!") if __name__ == '__main__': cli() -
setup.py: This is the most important file for packaging.# setup.py from setuptools import setup, find_packages setup( name='my-cli-app', version='0.1.0', packages=find_packages(), include_package_data=True, install_requires=[ 'Click>=7.0', # Specify your dependencies ], entry_points={ 'console_scripts': [ 'my-cli=mycli.cli:cli', # This is the magic line! ], }, )Explanation of
entry_points:'console_scripts': This tellssetuptoolsto create a command-line script.'my-cli=mycli.cli:cli': This is the mapping.my-cli: The name of the command you'll type in your terminal.mycli.cli: The Python module where your code is (mycli/cli.py).cli: The function to call inside that module.
-
Install your package in "editable" mode:
From the root of your project (
my_cli_project/), run:pip install -e .
- The
-eflag stands for "editable." This means any changes you make to your source code will be immediately reflected without needing to reinstall. This is perfect for development.
- The
-
Run your new command!
Now you can run your CLI from anywhere in your terminal, no need for
python:my-cli --help
Output:
Usage: my-cli [OPTIONS] COMMAND [ARGS]... A simple CLI application. Options: --help Show this message and exit. Commands: hello Prints a greeting.my-cli hello
Output:
Hello from the packaged CLI!
You have now successfully set up a well-structured, installable CLI application using Python and click. From here, you can explore more advanced features like context (@click.pass_context), callbacks, and custom parameter types.
