Feud has a rich typing system based on Pydantic, allowing for CLIs that support Python standard library types, as well as complex types such as emails, IP addresses, file/directory paths, database connection strings and more.

All of the below types are made easily accessible through the feud.typing module.


It is recommended to import the feud.typing module with an alias such as t for convenient short-hand use, e.g.

from feud import typing as t


Feud relies on type hints to determine the type for command-line argument/option input values.


Suppose we want a command for serving local files on a HTTP server with:

  • Arguments:
    • PORT: Port to start the server on.

  • Options:
    • --watch/--no-watch: Whether or not restart the server if source code changes.

    • --env: Envionment mode to launch the server in (either dev or prod).

By default we should watch for changes and use the development environment.

# serve.py

import feud
from feud import typing as t

def serve(port: t.PositiveInt, *, watch: bool = True, env: t.Literal["dev", "prod"] = "dev"):
    """Start a local HTTP server.

        Server port.
        Watch source code for changes.
        Environment mode.
    print(f"{port=!r} ({type(port)})")
    print(f"{watch=!r} ({type(watch)})")
    print(f"{env=!r} ({type(env)})")

if __name__ == "__main__":
$ python serve.py --help
serve.py help screen
Valid input
$ python serve.py 8080 --no-watch --env prod
port=8080 (<class 'int'>)
watch=False (<class 'bool'>)
env='prod' (<class 'str'>)
Invalid input
$ python serve.py 8080 --env test
serve.py error