typer
Typer, build great CLIs. Easy to code. Based on Python type hints.
Description
Documentation: <a href="https://typer.tiangolo.com" target="_blank">https://typer.tiangolo.com</a>
Source Code: <a href="https://github.com/fastapi/typer" target="_blank">https://github.com/fastapi/typer</a>
Typer is a library for building <abbr title="command line interface, programs executed from a terminal">CLI</abbr> 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. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> 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
typercommand/program that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally.
2026 February - Typer developer survey
Help us define Typer's future by filling the <a href="https://forms.gle/nYvutPrVkmBQZLas7" class="external-link" target="_blank">Typer developer survey</a>. ✨
FastAPI of CLIs
Typer is <a href="https://fastapi.tiangolo.com" class="external-link" target="_blank">FastAPI</a>'s little sibling, it's the FastAPI of CLIs.
Installation
Create and activate a <a href="https://typer.tiangolo.com/virtual-environments/" class="external-link" target="_blank">virtual environment</a> and then install Typer:
<div class="termy">$ pip install typer
---> 100%
Successfully installed typer rich shellingham
</div>
Example
The absolute minimum
- Create a file
main.pywith:
def main(name: str):
print(f"Hello {name}")
This script doesn't even use Typer internally. But you can use the typer command to run it as a CLI application.
Run it
Run your application with the typer command:
// Run your application
$ typer main.py run
// You get a nice error, you are missing NAME
Usage: 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 free
$ typer 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 argument
$ typer main.py run Camila
Hello Camila
// It works! 🎉
</div>
This is the simplest use case, not even using Typer internally, but it can already be quite useful for simple scripts.
Note: auto-completion works when you create a Python package and run it with --install-completion or when you use the typer command.
Use Typer in your code
Now let's start using Typer in your own code, update main.py with:
import typer
def main(name: str):
print(f"Hello {name}")
if __name__ == "__main__":
typer.run(main)
Now you could run it with Python directly:
<div class="termy">// Run your application
$ python main.py
// You get a nice error, you are missing NAME
Usage: main.py [OPTIONS] NAME
Try 'main.py --help' for help.
╭─ Error ───────────────────────────────────────────╮
│ Missing argument 'NAME'. │
╰───────────────────────────────────────────────────╯
// You get a --help for free
$ python 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 argument
$ python main.py Camila
Hello Camila
// It works! 🎉
</div>
Note: you can also call this same script with the typer command, but you don't need to.
Example upgrade
This was the simplest example possible.
Now let's see one a bit more complex.
An example with two subcommands
Modify the file main.py.
Create a typer.Typer() app, and create two subcommands with their parameters.
import typer
app = typer.Typer()
@app.command()
def hello(name: str):
print(f"Hello {name}")
@app.command()
def goodbye(name: str, formal: bool = False):
if formal:
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.Typerapp.- The previous
typer.runactually creates one implicitly for you.
- The previous
- Add two subcommands with
@app.command(). - Execute the
app()itself, as if it was a function (instead oftyper.run).
Run the upgraded example
Check the new help:
<div class="termy">$ 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
</div>
Now check the help for the hello command:
$ python main.py hello --help
Usage: main.py hello [OPTIONS] NAME
╭─ Arguments ───────────────────────────────────────╮
│ * name TEXT [default: None] [required] │
╰───────────────────────────────────────────────────╯
╭─ Options ─────────────────────────────────────────╮
│ --help Show this message and exit. │
╰───────────────────────────────────────────────────╯
</div>
And now check the help for the goodbye command:
$ python main.py goodbye --help
Usage: main.py goodbye [OPTIONS] NAME
╭─ Arguments ───────────────────────────────────────╮
│ * name TEXT [default: None] [required] │
╰───────────────────────────────────────────────────╯
╭─ Options ─────────────────────────────────────────╮
│ --formal --no-formal [default: no-formal] │
│ --help Show this message │
│ and exit. │
╰───────────────────────────────────────────────────╯
// Automatic --formal and --no-formal for the bool option 🎉
</div>
Now you can try out the new command line application:
<div class="termy">// Use it with the hello command
$ python main.py hello Camila
Hello Camila
// And with the goodbye command
$ python main.py goodbye Camila
Bye Camila!
// And with --formal
$ python main.py goodbye --formal Camila
Goodbye Ms. Camila. Have a good day.
</div>
Note: If your app only has one command, by default the command name is omitted in usage: python main.py Camila. However, when there are multiple commands, you must explicitly include the command name: python main.py hello Camila. See One or Multiple Commands for more details.
Recap
In summary, you declare once the types of parameters (CLI arguments and *CLI optio