CLI tool
pallets/click avatar
pallets/click

click turns a function signature into the command line, help text included

Python composable command line interface toolkit

17,821 stars2,658 forksPythonBSD-3-Clause

At a glance

What is it?
Click derives a command line interface from decorated Python functions, generates the help page from those same decorators, and loads subcommands lazily. The tree on main is version 8.6.0.dev and requires Python 3.10 or newer.
Who is it for?
Click suits developers writing a CLI with subcommands, a generated help page or shell completion, who would rather define the interface once on the function than assemble a parser and a help string separately. It does not suit a team still on Python 3.9, since this tree requires 3.10 or newer, nor a reader who wants a feature list in the README, because the three points it states are the whole summary.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • pallets/click17,821 ★ · +65
Star history
Repository2026-09-212026-11-13
pallets/click17.8k17.8k

65 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The decorators carry the interface, and the docstring carries the help

Everything the tool does to your program is visible in the twelve lines of the README example:

python
import click

@click.command()
@click.option("--count", default=1, help="Number of greetings.")
@click.option("--name", prompt="Your name", help="The person to greet.")
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for _ in range(count):
        click.echo(f"Hello, {name}!")

if __name__ == '__main__':
    hello()

`@click.command()` turns the function below it into the entry point, and each `@click.option` declares a flag that is passed to the function as the matching parameter. The docstring is not decoration: it is the description the generated help page prints. The one non-obvious piece is `prompt="Your name"`, which turns a missing flag into a question, so the same program runs non-interactively with a flag and interactively without one.

code
$ python hello.py --count=3
Your name: Click
Hello, Click!
Hello, Click!
Hello, Click!

Running it with `--count=3` and no `--name` produces the prompt, then three lines. No argument parser object is constructed, no help string is written by hand, and `click.echo` handles the output.

Lazy subcommand loading moves the import error to invocation time

The README states its three points: arbitrary nesting of commands, automatic help page generation, and support for lazy loading of subcommands at runtime. The third is the one with a consequence worth planning for.

A lazy subcommand is a module imported when that subcommand is invoked rather than when the process starts, which is what lets a CLI with many commands start quickly without importing all of them. The cost lands in your debugging: an ImportError or a syntax error inside one subcommand module surfaces the first time somebody runs that subcommand, not at startup, and a smoke test that only runs `--help` on the top-level command will pass over a broken branch of the tree.

The first two points are cheaper to reason about. Nesting composes because each subcommand is itself a decorated function, and help generation is not a separate feature you switch on, it is a consequence of the decorators being the single source of the interface.

The README gives no install line, so pyproject.toml is the install spec

There is no pip command anywhere in this README, so the packaging metadata is where an adopter has to look. In pyproject.toml the distribution is named `click`, the version is `8.6.0.dev`, the licence is `BSD-3-Clause` with `LICENSE.txt` as the licence file, and `requires-python` is `>=3.10`. Classifiers cover Production/Stable, Intended Audience :: Developers, Operating System :: OS Independent and Typing :: Typed, and the maintainer is the Pallets organization.

Two details matter more than the rest. The `[project]` table declares no runtime dependencies, so nothing in the package list can be argued with or trimmed; every entry under `[dependency-groups]` is tooling, covering ruff and tox for development, pytest for tests, mypy and pyright for typing, and the Sphinx set for docs. And the build backend is `flit_core>=3.11,<4` with `[tool.flit.module]` naming `click`.

The version being `8.6.0.dev` means main sits ahead of the newest release. Documentation is at click.palletsprojects.com, and the `[project.urls]` table points at the docs, the changes page and the source.

A src/ layout whose sdist ships the tests and the docs

The repository root carries `.devcontainer/`, `.editorconfig`, `.github/`, `.gitignore`, `.pre-commit-config.yaml`, `.readthedocs.yaml`, `CHANGES.md`, `LICENSE.txt`, `README.md`, `docs/`, `examples/`, `pyproject.toml`, `src/`, `tests/` and `uv.lock`. The `src/` directory is where the package lives, which keeps the installed package separate from the checkout.

`[tool.flit.sdist]` says what leaves the repository in a source distribution: `docs/`, `tests/`, `CHANGES.md` and `uv.lock` are included, and `docs/_build/` is the only exclusion. That is an unusual choice worth noticing, because a downstream packager who mirrors the sdist ships the test suite and the documentation, which makes verification possible but grows the artifact. `uv.lock` travelling with the sdist has the same effect for anyone trying to reproduce the tool chain.

For someone reading the project rather than running it, the split tells you where to look: behaviour in `src/`, guarantees in `tests/`, user-facing text in `docs/`, and worked examples in `examples/`.

Warnings are errors and the race-condition suite is off by default

The pytest configuration is short and opinionated. `testpaths` is set to `tests`, `filterwarnings` is set to `error`, and a custom marker is declared for high-iteration stress tests for race conditions, with the note that they are deselected with `-m "not stress"`. `addopts` carries that deselection, so the default invocation skips them.

`filterwarnings = error` is the consequential line. A DeprecationWarning raised anywhere in the run, including one from a dependency, fails the suite instead of printing. That catches drift before it becomes a release note, and it also means a dependency bump can turn a green build red on a warning nobody wrote.

The stress marker describes the other half of the suite: high-iteration tests for race conditions. A separate `tests-random` dependency group adds `pytest-randomly` and `pytest-xdist` to plain pytest. A default green run therefore says nothing about concurrency behaviour.

The examples/ directories are the feature index the README omits

The README's summary is three points long, and it leaves out most of what the package does. The `examples/` directory is the wider list: `aliases/`, `colors/`, `completion/`, `complex/`, `imagepipe/`, `inout/`, `naval/`, `repo/`, `termui/` and `validation/`, with a `README` of its own.

Read the names against the summary and the gap is obvious. Shell completion, command aliases, terminal user interface behaviour, colour output, argument validation, composing several commands into one, piping image data, and a repository layout example appear nowhere in the three points, and the README does not say what any of these directories demonstrate. The directory names are the whole index, so anyone starting from a feature they need has to open the example and read the code.

That ordering is deliberate in a small way: a README of a couple of hundred words is a good front door, and a reader who needs colour handling or completion is expected to walk into `examples/` rather than read a feature list.

The docstring becomes the help page, which the standard library makes you assemble

The comparison that matters is the difference in approach against what Python already ships. The standard library's argparse expects you to build an argument parser object, and add arguments to it with explicit calls. Click inverts that: the function signature is the interface, the decorators are the declaration, and the docstring is the description, so the help page is generated from the same source that defines the command.

Nested command groups come from nesting decorated functions, and completion is a directory in `examples/` rather than a script you write, because the command tree is already described in one place.

The cost is the same inversion seen from the other side. The interface cannot be assembled dynamically in ways the decorators do not allow, and the help text is whatever the docstring says, so a badly written docstring becomes a badly written help page with no separate place to fix it.

Releases are frequent and the working tree is a dev version ahead

The last push to the repository was 2026-11-01. Recent releases came at 8.5.0 on 2026-08-27, 8.4.2 on 2026-06-26 and 8.4.1 on 2026-05-22, three releases across a little over three months, with the patch releases sitting between minor ones. The version in pyproject.toml is `8.6.0.dev`, so main is already working toward the next minor version.

Change history lives in `CHANGES.md` at the root, and the `[project.urls]` table points at the rendered changes page on the documentation site, so a reader can check what broke between two pinned versions before upgrading. Documentation builds are pinned in the tree through `.readthedocs.yaml` and the `docs` dependency group, which includes `myst-parser`, `pallets-sphinx-themes`, `sphinx`, `sphinx-tabs` and `sphinxcontrib-log-cabinet`.

The licence is BSD-3-Clause in `LICENSE.txt`, and the README asks for donations to the Pallets organization rather than describing any commercial tier, so there is no support contract to buy and no feature gated behind one.

Editorial conclusion

Click suits developers writing a CLI with subcommands, a generated help page or shell completion, who would rather define the interface once on the function than assemble a parser and a help string separately. It does not suit a team still on Python 3.9, since this tree requires 3.10 or newer, nor a reader who wants a feature list in the README, because the three points it states are the whole summary. Before adopting, install a released version rather than the 8.6.0.dev on main, then open the examples/ directory and read the one your CLI is shaped like.

Frequently asked questions

How do I install click for Python?

The README does not include an install command, and the packaging metadata in pyproject.toml is what an adopter has to work from: the distribution is named click and requires-python is >=3.10. Documentation and the change history are at click.palletsprojects.com.

What is click in Python?

Click is a Python package for creating command line interfaces in a composable way, described in the README as the Command Line Interface Creation Kit. Its three stated points are arbitrary nesting of commands, automatic help page generation, and support for lazy loading of subcommands at runtime.

Does click require any third-party packages at runtime?

The [project] table in pyproject.toml declares no runtime dependencies. Everything under [dependency-groups] is tooling for development, tests, typing and documentation, including ruff, tox, pytest, mypy and pyright.

Which Python versions does click support?

The tree on main sets requires-python to >=3.10, so Python 3.9 and older are outside its floor. The repository also classifies the package as Typing :: Typed and Operating System :: OS Independent.

Official sources

  1. License: BSD-3-Clause
  2. pallets/click on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pallets-click.svg)](https://hysenlabs.com/projects/pallets-click)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/pallets-click.svg)](https://hysenlabs.com/projects/pallets-click)

Was this useful?