Skip to content

Typer Support

Experimental

patch_typer() does not work with typer>=0.26.0. See Typer 0.26+ Support below.

Experimental

This feature is still experimental. Please report any bugs or issues you run into!

You don't need to use rich-click directly to get access to a lot of rich-click's great features.

If you are a fan of Typer and you'd like to use rich-click's themes, you can patch Typer to use rich-click and set the global config's THEME (and other config options) to whatever you want.

All you need to do is import patch_typer() from rich_click.patch. This does not need to be done at the top of the file, in fact you can do it right before calling app.run() or typer.run(...):

# /// script
# dependencies = ["rich-click>=1.9", "typer>=0.15"]
# ///
from enum import Enum
import typer
from typing_extensions import Annotated

class LogLevel(str, Enum):
    debug = "debug"
    info = "info"
    warn = "warn"
    error = "error"

def main(
        id: Annotated[int, typer.Argument(min=0, max=1000)],
        age: Annotated[int, typer.Option(min=18)] = 20,
        score: Annotated[float, typer.Option(max=100)] = 0,
        log_level: Annotated[LogLevel, typer.Option(rich_help_panel="Logging")] = LogLevel.info,
        color: Annotated[bool, typer.Option(rich_help_panel="Logging")] = True,
) -> None:
    print(f"id={id} age={age} score={score} log_level={log_level} color={color}")

if __name__ == "__main__":
    from rich_click.patch import patch_typer
    import rich_click.rich_click as rc

    patch_typer()
    rc.THEME = "star-slim"

    typer.run(main)
Output

Running the above Typer CLI works the same as you would otherwise expect, except now with a rich-click theme applied:

python typer_example.py --help

Patching Typer via the rich-click CLI

You can also patch Typer as an end-user of any Typer CLI via the rich-click CLI.

rich-click my-typer-cli --help

In addition to giving access to rich-click's themes, another benefit of this is being able to generate HTML and SVG help text easily. Although, do note that Typer and rich-click have some minor differences in how they render help text.

More information about usage of the rich-click CLI is in the rich-click CLI docs, or you can run rich-click --help to view the CLI.

Typer 0.26+ Support

Starting with typer==0.26.0, Typer vendors its own internal fork of Click (typer._click) instead of subclassing the click package directly. typer.core.TyperCommand, TyperGroup, TyperOption, and TyperArgument no longer derive from click.Command, click.Group, click.Option, or click.Argument. They derive from Typer's own private copies of those classes, built with a different metaclass (abc.ABCMeta).

patch_typer() works by building new classes that inherit from both Typer's classes and rich-click's own RichCommand / RichGroup / etc. (which are built on the real click classes). Since typer>=0.26, those two class hierarchies are unrelated and their metaclasses conflict, so building the patched subclass raises:

TypeError: metaclass conflict: the metaclass of a derived class must be a
(non-strict) subclass of the metaclasses of all its bases

patch_typer() catches this. It builds all four patched classes up front, inside a single try/except TypeError block (a metaclass conflict or an unresolvable MRO are the only ways this construction can fail), and only swaps them into Typer's internals once every one of them succeeds. When one fails, which is currently always the case on typer>=0.26, patch_typer() emits a short RuntimeWarning pointing back to this section, leaves Typer's own classes untouched, and returns without raising. Your program keeps running exactly as it would if patch_typer() had never been called.

This means:

  • Your Typer CLI keeps working normally on typer>=0.26.
  • You won't get rich-click's themes or panels from patch_typer(). Typer falls back to rendering help with its own (also Rich-based) formatter.
  • You'll see a RuntimeWarning at the point where patch_typer() is called, which you can silence with the standard warnings filters if it's expected in your environment.

If you need patch_typer() to actually apply rich-click's theming, pin typer<0.26 for now. Patching against Typer's private, vendored fork of Click would mean re-implementing this logic against internals that could change again with any future Typer release, so there is no fix planned at this time. Track issue #330 for updates.