Typer is a library for building CLI applications that users will love using and developers will love creating. Based on Python type hints.
It's also a command line tool to run scripts, automatically converting them to CLI applications.
The key features are:
Intuitive to write: Great editor support. Completion everywhere. Less time debugging. Designed to be easy to use and learn. Less time reading docs.
Easy to use: It's easy to use for the final users. Automatic help, and automatic completion for all shells.
Short: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
Start simple: The simplest example adds only 2 lines of code to your app: 1 import, 1 function call.
Grow large: Grow in complexity as much as you want, create arbitrarily complex trees of commands and groups of subcommands, with options and arguments.
Run scripts: Typer includes a typer command/program that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally.
fast →💬 Run your applicationtyper main.py run 💬 You get a nice error, you are missing NAMEUsage: typer [PATH_OR_MODULE] run [OPTIONS] NAME Try 'typer [PATH_OR_MODULE] run --help' for help. ╭─ Error ───────────────────────────────────────────╮ │ Missing argument 'NAME'. │ ╰───────────────────────────────────────────────────╯
💬 You get a --help for freetyper main.py run --help Usage: typer [PATH_OR_MODULE] run [OPTIONS] NAME
Run the provided Typer app.
╭─ Arguments ───────────────────────────────────────╮ │ * name TEXT [default: None] [required] | ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────╯
💬 Now pass the NAME argumenttyper main.py run Camila Hello Camila
fast →💬 Run your applicationpython main.py 💬 You get a nice error, you are missing NAMEUsage: main.py [OPTIONS] NAME Try 'main.py --help' for help. ╭─ Error ───────────────────────────────────────────╮ │ Missing argument 'NAME'. │ ╰───────────────────────────────────────────────────╯
💬 You get a --help for freepython main.py --help Usage: main.py [OPTIONS] NAME
╭─ Arguments ───────────────────────────────────────╮ │ * name TEXT [default: None] [required] | ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────╯
💬 Now pass the NAME argumentpython main.py Camila Hello Camila
Create a typer.Typer() app, and create two subcommands with their parameters.
importtyperapp=typer.Typer()@app.command()defhello(name:str):print(f"Hello {name}")@app.command()defgoodbye(name:str,formal:bool=False):ifformal:print(f"Goodbye Ms. {name}. Have a good day.")else:print(f"Bye {name}!")if__name__=="__main__":app()
And that will:
Explicitly create a typer.Typer app.
The previous typer.run actually creates one implicitly for you.
Add two subcommands with @app.command().
Execute the app() itself, as if it was a function (instead of typer.run).
fast →python main.py --help Usage: main.py [OPTIONS] COMMAND [ARGS]...
╭─ Options ─────────────────────────────────────────╮ │ --install-completion Install completion │ │ for the current │ │ shell. │ │ --show-completion Show completion for │ │ the current shell, │ │ to copy it or │ │ customize the │ │ installation. │ │ --help Show this message │ │ and exit. │ ╰───────────────────────────────────────────────────╯ ╭─ Commands ────────────────────────────────────────╮ │ goodbye │ │ hello │ ╰───────────────────────────────────────────────────╯
💬 When you create a package you get ✨ auto-completion ✨ for free, installed with --install-completion 💬 You have 2 subcommands (the 2 functions): goodbye and hello restart ↻
Now check the help for the hello command:
fast →python main.py hello --help Usage: main.py hello [OPTIONS] NAME
╭─ Arguments ───────────────────────────────────────╮ │ * name TEXT [default: None] [required] │ ╰───────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────╮ │ --help Show this message and exit. │ ╰───────────────────────────────────────────────────╯
In summary, you declare once the types of parameters (CLI arguments and CLI options) as function parameters.
You do that with standard modern Python types.
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
Just standard Python.
For example, for an int:
total:int
or for a bool flag:
force:bool
And similarly for files, paths, enums (choices), etc. And there are tools to create groups of subcommands, add metadata, extra validation, etc.
You get: great editor support, including completion and type checks everywhere.
Your users get: automatic --help, auto-completion in their terminal (Bash, Zsh, Fish, PowerShell) when they install your package or when using the typer command.