Skip to main content

typed-args

PyPI version Python versions Python package Publish

A typed command-line argument parser for Python, inspired by Rust's clap. Define a pydantic model — its types drive the CLI, and parsing runs real runtime validation. Subcommands are discriminated unions you dispatch with match.

Requires Python 3.10+ and pydantic 2.

Installation

pip install typed-args

A first example

from typing import Annotated, List

import typed_args as ta
from pydantic import Field


class Args(ta.TypedArgs):
    model_config = ta.ParserConfig(description="Process some integers.")
    integers: Annotated[List[int], ta.Arg(metavar="N", nargs="+", help="an integer for the accumulator")]
    workers: Annotated[int, Field(gt=0, le=32), ta.Arg("-w", "--workers", help="worker count")] = 4


args = Args.parse_args()
print(args.integers, "max =", max(args.integers), "workers =", args.workers)
$ python prog.py 1 2 3 4 -w 8
[1, 2, 3, 4] max = 4 workers = 8

$ python prog.py 1 -w 99
workers
  Input should be less than or equal to 32 ...

The Field(gt=0, le=32) constraint is enforced at parse time — workers=99 raises a pydantic.ValidationError instead of silently producing a bad value.

How it works

  • Types drive structure. bool → --flag (store_true), Literal[...] → choices, list → nargs, Optional/defaults → optional args, required scalars → positionals.
  • Arg(...) is the argparse passthrough. Attach it via Annotated[T, Arg(...)] for option strings, help, metavar, action, nargs, const, ... It overlays argparse params on top of the type-derived defaults.
  • Docstrings become help automatically. A bare string literal on the line after a field is used as its help text (via pydantic's use_attribute_docstrings, on by default). Precedence: Arg(help=...) > Field(description=...) > attribute docstring.
  • Validation is real. pydantic coerces and validates the parsed namespace, so Field(...), field_validator, and structured error messages all work.
  • Parser config is model_config. Use ParserConfig(prog=..., description=...), which subclasses pydantic's ConfigDict and mixes freely with pydantic config (frozen, str_strip_whitespace, ...). For full control, pass your own argparse.ArgumentParser via Args.parse_args(parser=...).

Subcommands

Subcommands are a pydantic discriminated union; dispatch with match:

from typing import Annotated, Literal, Union

import typed_args as ta
from pydantic import Field


class GlobalArgs(ta.TypedArgs):
    verbose: Annotated[bool, ta.Arg("-v", "--verbose")] = False


class AddArgs(ta.TypedArgs):
    cmd: Literal["add"] = "add"
    file: Annotated[str, ta.Arg(help="file to add")]
    force: Annotated[bool, ta.Arg("--force")] = False


class RemoveArgs(ta.TypedArgs):
    cmd: Literal["remove"] = "remove"
    file: Annotated[str, ta.Arg(help="file to remove")]
    recursive: Annotated[bool, ta.Arg("-r", "--recursive")] = False


class Root(ta.TypedArgs):
    common: GlobalArgs
    subcommand: Annotated[Union[AddArgs, RemoveArgs], Field(discriminator="cmd")]


root = Root.parse_args()
match root.subcommand:
    case AddArgs(file=f, force=True):
        print("force-add", f)
    case AddArgs(file=f):
        print("add", f)
    case RemoveArgs(file=f, recursive=True):
        print("recursive remove", f)
    case RemoveArgs(file=f):
        print("remove", f)

Global flags (the common field) work before the subcommand (argparse behavior); after-subcommand globals are not supported.

API

  • TypedArgs — pydantic.BaseModel subclass adding parse_args(argv=None, *, parser=None) and parse_known_args(...) classmethods.
  • ParserConfig — ConfigDict subclass with argparse.ArgumentParser fields.
  • Arg(*option_strings, **kwargs) — argparse passthrough marker for a field.
  • parse(model, argv=None, *, parser=None) / parse_known_args(...) — free functions for users who don't subclass TypedArgs.
  • DefaultHelpFormatter — strips dotted dest prefixes from help output.

Feature support

Feature Status How / note
Args
Positional / optional ✓ Arg() / Arg("-f", "--foo")
action (store_true / store_const / append / count / custom) ✓ auto for bool; Arg(action=...)
nargs ✓ auto * for list; Arg(nargs=...)
const / default / type / choices / required / help / metavar ✓ Arg(...) passthrough
Custom Action ✓ via Arg(**kwargs)
dest override ✗ rejected — dest is the field-path link to the model
Types & validation
Type-driven structure (bool→flag, Literal→choices, list→nargs, required→positional) ✓
Field constraints (gt/le/…), field_validator, ValidationError ✓ pydantic at parse time
Help
Attribute docstring → help ✓ use_attribute_docstrings, on by default
help precedence: Arg(help=) > Field(description=) > docstring ✓
DefaultHelpFormatter (strips dotted dest) ✓
Parser config
prog / description / epilog / prefix_chars / fromfile_prefix_chars / argument_default / conflict_handler / add_help / allow_abbrev / exit_on_error / formatter_class ✓ ParserConfig in model_config
Custom ArgumentParser (escape hatch) ✓ parse_args(parser=...)
Subcommands
Discriminated union + match dispatch ✓
Optional subcommand (required=False) ✓ Optional[Union[...]] = None
Nested subcommands ✓ recursive
Subcommand help from class docstring / explicit config ✓ ParserConfig(subcommand_help=..., description=...)
Subparsers section title / description / prog / metavar ✓ Subparsers(...) marker
Subcommand aliases (add_parser(aliases=...)) ✗ not implemented
Other per-subparser config (prog / formatter_class) ✗ not implemented
Groups
Argument group (titled section) ✓ Group(...) marker
Mutually exclusive group ✓ Mutex(...) marker
Composition
Nested model as a field (library args as an attribute) ✓
Merge into a host argparse parser ✓ add_arguments / from_namespace
Global args before the subcommand ✓ nested model on the main parser
Global args after the subcommand (clap global=true) ✗ cut — put globals before the subcommand
Prefixing a nested model's flags (--lib-host) ✗ decided against
Parsing
parse_args / parse_known_args ✓
parse_intermixed_args ✗ not exposed

Metadata

Release files for typed-args 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for typed-args 0.9.0
File Size Uploaded Provenance
typed_args-0.9.0.tar.gz 13.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for typed-args 0.9.0
File Interpreter ABI Platform
typed_args-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.7 kB

Release files / typed_args-0.9.0.tar.gz

Download URL typed_args-0.9.0.tar.gz
Size 13.9 kB
Tags Source
SHA-256 checksum
How to use checksums
836e247556f1fea74672d732870957a199c8c5bc76955753f279db023b6bc371
BLAKE2b-256 checksum
How to use checksums
14d2d3064a840a1334414dd81f1cec3ed670ad8b3ae6470e653d556c7c0764b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / typed_args-0.9.0-py3-none-any.whl

Download URL typed_args-0.9.0-py3-none-any.whl
Size 16.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d79c169561df278f397d5b7dbbafec747500dbd3590154b89184106de64e856
BLAKE2b-256 checksum
How to use checksums
4f23d4ac3350bde285d5bc8d5ebfca509d8e499e88721d35711f68311e1dafea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.14.7

Security for typed-args 0.9.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page