Skip to main content

typed-argparse

CI Python uv Ruff ty SemVer License

typed-argparse is a small annotation-driven CLI helper for people who want typed parser generation without adopting a large framework.

It is aimed at simple command-line tools, scripting utilities, and lightweight LLM-facing CLIs where you want a small API surface, explicit Python functions, and standard argparse behavior instead of a large abstraction layer.

The core package has no required third-party runtime dependencies. The main API is build_parser(), which converts a typed function signature into an argparse-compatible parser. The package also includes Argument, Option, unwrap(), call(), parse_and_call(), and build_subcommand_parser(), plus optional cmd2 integration through with_annotated().

Why use it:

  • small API surface
  • typed function signatures instead of command classes or decorators everywhere
  • easy argparse.Namespace -> kwargs conversion through unwrap()
  • a good fit for short-lived tools and simple LLM CLI wrappers
  • optional cmd2 integration when you want an interactive shell

Install

The package is published on PyPI as typed-argparse-gen and imported as typed_argparse.

uv add typed-argparse-gen

For cmd2 integration:

uv add "typed-argparse-gen[cmd2]"

Main feature: build_parser()

Use build_parser() when you want annotation-driven parser generation directly.

import argparse
from typing import Annotated

from typed_argparse import Argument, Option, build_parser


def greet(
    name: Annotated[str, Argument(help_text="Who to greet")],
    count: Annotated[int, Option("--count", "-c", help_text="Number of greetings")] = 1,
    loud: bool = False,
) -> None:
    pass


parser = build_parser(greet)
args = parser.parse_args(["Kelvin", "--count", "2", "--loud"])

assert isinstance(parser, argparse.ArgumentParser)
assert args.name == "Kelvin"
assert args.count == 2
assert args.loud is True

build_parser_from_function() is still available as an alias.

By default:

  • parameters without defaults become positional arguments
  • parameters with defaults become --option flags
  • bool = False becomes store_true
  • bool = True becomes store_false on --no-name
  • Annotated[..., Argument(...)] and Annotated[..., Option(...)] override the defaults

Unwrapping and calling

Use unwrap() to convert a parsed argparse.Namespace into plain values. Use call() and parse_and_call() for the common dispatch path.

from typed_argparse import build_parser, call, parse_and_call, unwrap

parser = build_parser(greet)
namespace = parser.parse_args(["Kelvin", "--count", "2"])

kwargs = unwrap(namespace)
values = unwrap(namespace, as_tuple=True)

assert kwargs == {"name": "Kelvin", "count": 2, "loud": False}
assert values == ("Kelvin", 2, False)

assert call(greet, namespace) == ["Hello Kelvin", "Hello Kelvin"]
assert parse_and_call(greet, ["Kelvin", "--loud"]) == ["HELLO KELVIN"]

Subcommands

Use build_subcommand_parser() or parse_and_call() with a mapping for small multi-command CLIs.

from typed_argparse import build_subcommand_parser, parse_and_call

commands = {"greet": greet, "tag": tag}

parser = build_subcommand_parser(commands)
namespace = parser.parse_args(["tag", "release", "--labels", "stable"])

result = parse_and_call(commands, ["tag", "release", "--labels", "stable"])

Optional cmd2 support

If you are using cmd2, you can use the same metadata model with with_annotated(). Install the optional cmd2 extra first.

For typed code, prefer direct imports:

import cmd2
from typing import Annotated

from typed_argparse import Argument, Option, with_annotated


class App(cmd2.Cmd):
    def sport_choices(self) -> list[str]:
        return ["football", "basketball", "tennis"]

    @with_annotated
    def do_play(
        self,
        sport: Annotated[str, Argument(choices_provider=sport_choices)],
        venue: Annotated[str, Option("--venue", "-v")] = "home",
    ) -> None:
        self.poutput(f"{sport=} {venue=}")

Development

uv sync --group dev
uv run ruff check .
uv run ty check
uv run pytest
uv build

Release flow

This repo is configured for semantic versioning with conventional commits.

  • Push conventional commits to main
  • GitHub Actions runs tests and lint with uv
  • python-semantic-release determines the next version, updates CHANGELOG.md, tags the release, and publishes to PyPI

Expected commit prefixes include feat:, fix:, and perf:. Breaking changes should use ! or a BREAKING CHANGE: footer.

Metadata

Release files for typed-argparse-gen 0.3.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-argparse-gen 0.3.0
File Size Uploaded Provenance Actions
typed_argparse_gen-0.3.0.tar.gz 27.5 kB With provenance Details for typed_argparse_gen-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for typed-argparse-gen 0.3.0
File Interpreter ABI Platform Actions
typed_argparse_gen-0.3.0-py3-none-any.whl Python 3 none any Details for typed_argparse_gen-0.3.0-py3-none-any.whl

Total release size: 47.4 kB

Release files / typed_argparse_gen-0.3.0.tar.gz

Download URL typed_argparse_gen-0.3.0.tar.gz
Size 27.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7afd0d5f428acbb5ba2ce7beb9dd19054f53c64fd99b68c303f9802c9fdf920d
BLAKE2b-256 checksum
How to use checksums
652410d07a7d802bff0beea00b16c23a2e0d4525a2ab5e753306fe2a27f3ded8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 1, 2026.

Transparency log

Release files / typed_argparse_gen-0.3.0-py3-none-any.whl

Download URL typed_argparse_gen-0.3.0-py3-none-any.whl
Size 19.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c4a16db44563e9a681d6a4d0c46661ebeba526226455e1023b20ab19d7a3dfcd
BLAKE2b-256 checksum
How to use checksums
86567467932ceca7629d63d58eaf32d4c9c9801fdc06b6ebd01daf63e26018ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 1, 2026.

Transparency log

Security for typed-argparse-gen 0.3.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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for typed_argparse_gen-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 1, 2026.

Transparency log

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