Why Cyclopts for Python CLIs

python
tool
develop
Python isn’t natively designed to build command line interfaces (CLIs), so we need to choose a package to help us build them. In this post, we describe why we chose Cyclopts.
Published

January 26, 2026

Context and problem statement

We want to build command line interfaces (CLIs) for some of our Python tools, but Python doesn’t natively support building CLIs, nor was it designed initially to do that. However, there are many packages available, including some built-in standard libraries, for exposing a Python package as a CLI application. So the question is:

Which package should we use to build command line interfaces (CLIs) for our Python tools?

Decision drivers

Aside from our design principles that we generally follow when using or choosing software, the package needs to:

  • Be well maintained and actively developed.
  • Integrate easily into our current development workflow and style.
  • Be ergonomic and easy to use, so we can develop CLIs quickly and easily.
  • Have excellent documentation that is easy to follow.

Considered options

Based on the Awesome Python: Command-Line Interface Development list, we considered these packages, since they were still actively maintained and developed at the time of this post:

There are a few others that almost matched our criteria, but didn’t in one way or another:

  • cement: It isn’t that actively maintained, but importantly, it seems to be more of an advanced framework for building CLIs (e.g. with Dockerfiles), which is more complex than what we need.
  • prompt_toolkit: It is designed more for building “full screen” terminal applications, which is more complex than what we need.
  • cliff: It isn’t regularly updated. The documentation was last updated in 2021.

Argparse

Argparse is a part of the standard library in Python for building CLIs.

Benefits

  • Comes built-in with Python, so no extra dependencies.

Drawbacks

  • Not very ergonomic and requires a lot of code to set up.
  • The documentation (like a lot of Python standard library documentation) is not easy to follow or read.
  • Needs to duplicate a lot of code and information between the function/class signatures and the argument parsing code.
  • Lacks a lot of features (hence requires the duplicate code mentioned above) that they openly state in the documentation, and even refers to click and Typer as alternatives, stating that e.g., Typer integrates with type hints.

Python Fire

There isn’t as much information (blogs, tutorials, etc) about Python Fire, including their own documentation, so we can’t really describe it that well. Based on their tag line, it is:

[…] a library for automatically generating command line interfaces (CLIs) from absolutely any Python object.

Benefits

  • A Google built library (though not an official product).
  • A lot of GitHub stars, so it seems to be popular.

Drawbacks

  • The documentation is sparse, disorganised, and not very beginner friendly.
  • Given the documentation, it’s very difficult to assess it well enough to make an informed decision.

Click

A widely used, very popular library for building CLIs in Python.

Benefits

  • Because of its popularity, there are a lot of resources available online to learn from.
  • Has a lot of features and is very flexible and powerful.

Drawbacks

  • Requires a lot of decorators, one for each CLI argument/option, for each function that would be a CLI command.
  • Because it was developed before Python had type hints, it doesn’t use them, so there is a lot of duplicated information between the function signatures and the decorators.
  • It is an older package, so it was designed before some of the more modern Python features were available (e.g. type hints and docstring parsing).

Typer

A newer library for building CLIs in Python that is built on top of Click, but designed to take advantage of modern Python features like type hints.

Benefits

  • Documentation is very well written, easy to follow, and beginner friendly.
  • Like Click, it is very widely used and popular, so there are a lot of resources available to learn from.
  • Of the previous options, this is the newest and most well-designed.
  • While only “owned” by one person, it has a core team of maintainers.

Drawbacks

  • Because it was built on top of Click, it inherits some of its drawbacks.
  • Still needs some level of boilerplate and duplication of code (e.g. CLI help text needs to be written in both the function docstring and the argument/option declaration via Annotated Python code).

Cyclopts

A package specifically designed to resolve some of Typer’s limitations.

Benefits

  • Rather than build on top of previous packages, it is designed from the ground up to take advantage of modern Python features like type hints and docstring parsing.
  • Very ergonomic and requires little to no boilerplate code.
  • Includes features like parsing docstrings for help texts, including the argument/option help text.
  • Can check input values against a set of allowed values, for both string and number types.
  • Supports Union types, which also means it can support Optional types natively.
  • Multiple input values to an argument/option are supported.

Drawbacks

  • It is a newer package with a smaller user base, so there are fewer resources available online.
  • Because it is newer, it might have more undiscovered bugs or missing features.
  • Since it is still in active development, there might be breaking changes in future releases.
  • Seems to be developed by only one person, so long-term maintenance is uncertain.

Decision outcome

We decided on Cyclopts because of its modern design, ergonomics, and features that interact nicely with how we develop. In particular, it addresses some of Typer’s limitations (which would have been our second choice) as these design decisions would make our code leaner and easier to develop and maintain.

Consequences

  • Because it is a much newer package, there might be some issues that come up that lead to breaking changes that we’d have to resolve.
  • Long term maintenance is uncertain, so if the package is abandoned, we might have to switch to another package in the future.

Resources used for this post