Skip to main content

anci

anci is a lightweight python package that automatically converts decorated, type-annotated functions into basic or hierarchical command-line interfaces.

Installation

anci can be installed using pip

pip install anci

Or, added to your pyproject.toml using uv

uv add anci

Usage

Basic example

from anci import Arg, base, cmd, main

@base("ops")
def ops():
    """Base command for 'ops'."""
    pass

@cmd("ops", "add")
def ops_add(
    x: Arg[int],                 # A flagged argument with no help text
    y: Arg[int, "Second."],      # A flagged argument with help text
    z: Arg[int, "Third."] = 100  # A flagged argument with help text and a default value
):
    """Print the sum of three numbers."""
    print(x + y + z)

if __name__ == "__main__":
    main("A CLI tool for basic math operations.")

This example demonstrates how to create a simple CLI using only decorators and type annotations:

  • @anci.base("ops") - Creates a base command group called ops that initializes a hierarchy.
  • @anci.cmd("ops", "add") - Registers subcommand add under ops with flagged arguments.
  • usage - Usage info for each command (e.g. ops --help) are extracted from function docstrings.
  • anci.Arg - Provides type hints and help text for each parameter.
  • anci.main() - Automatically generates the CLI with help text, argument parsing, and command routing.

On the command-line, the anci command-line program can then be called as

python3 main.py ops add --help 
... usage: A CLI tool for basic math operations. ops add [-h] [--x X] [--y Y] [--z Z]
... 
... Print the sum of three numbers.
...
... options:
...   -h, --help  show this help message and exit
...   --x X
...   --y Y       Second.
...   --z Z       Third (default: 100).

python3 main.py ops add --x 2 --y 4
... 116

python3 main.py ops add --x 2 --y 4 --z 4
... 10

Or, if integrated as part of your python CLI package, then

package ops add --x 5 --y 3 --z 10
... 118

Annotated example

anci currently provides support for various annotated_types, allowing automatic enforcement of range and boundary checks on integers, containers (such as lists, sets, and tuples), and strings.

from anci import Arg, cmd, main
from anci.typing import Annotated, Gt, MaxLen

@cmd("types")
def check_my_types(
    x: Arg[list[str], "A list of strings."],
    y: Arg[Annotated[int, Gt(10)], "An integer greater than 10"],
    z: Arg[Annotated[set[float], MaxLen(2)], "A set of floats with a max of 2 elements"],
):
    """Print the types of each argument."""
    print("type length")
    print(type(x), len(x))
    print(type(y), 1)
    print(type(z), len(z))

if __name__ == "__main__":
    main("A CLI for checking types.")

This example shows how anci uses type annotations to handle complex types and enforce runtime checks:

  • x: Arg[list[str], ...] - anci converts a sequence of letters into list of strings.
  • y: Arg[Annotated[int, Gt(10)], ...]: anci verifies input integer is greater than 10.
  • y: Arg[Annotated[set[float], MaxLen(2)], ...]: anci verifies set only has two elements.

When all arguments satisfy the runtime checks, the command runs without errors:

python main.py types --x a b c --y 11 --z 1
... type length
... <class 'list'> 3
... <class 'int'> 1
... <class 'set'> 1

However, since anci enforces range/length constraints directly from type annotations, the following produce errors:

python main.py types --x a b c --y 5 --z 1
... types: error: argument --y: y must be > 10, got 5

python main.py types --x a b c --y 11 --z 1 2 3
... types: error: argument --z: Expected at most 2 elements, got 3

Supported type annotations

anci currently supports the following type annotations:

  • Base types: int, str, float, bool, bytes, pathlib.Path
  • Container types: list[...], List[...], tuple[...], Tuple[...], set[...], Set[...]
  • annotated_types (typing.Annotated[...]): Gt, Ge, Lt, Le, Interval, MaxLen, MinLen, Len.

All annotated types, and pathlib.Path, can be directly imported/aliased from anci.typing if desired.

Adding custom type annotations

If you want to add your new/custom type annotations to anci, see src/anci/handlers for now or, alternatively, open an issue. Documentation on adding your own custom annotations will be added soon.

Other CLI frameworks

  • argparse - Base of anci and reliable for small scripts but very verbose otherwise.
  • click - Too. Many. Decorators. Not much else to say.
  • typer - Mature ecosystem, "type-aware" but doesn't fully take advantage of type annotations (for example, see typer's use of Annotated).

Metadata

Release files for anci 0.1.5

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

Source distribution (sdist)

Source distribution for anci 0.1.5
File Size Uploaded Provenance
anci-0.1.5.tar.gz 107.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for anci 0.1.5
File Interpreter ABI Platform
anci-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 127.7 kB

Release files / anci-0.1.5.tar.gz

Download URL anci-0.1.5.tar.gz
Size 107.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9bcf95c081ee0705e6b3a1eadc34082fed8d359a79aa3dd6928acbd1794b775a
BLAKE2b-256 checksum
How to use checksums
cfb5a57a46198cff01b914dfce80b8af0eca018333d51c9b8f947e30a0b2bd22
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.4

Release files / anci-0.1.5-py3-none-any.whl

Download URL anci-0.1.5-py3-none-any.whl
Size 19.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
72765f7b775337282f1bc969251bc2d69b00e78203a304e0fa6bde367d86929d
BLAKE2b-256 checksum
How to use checksums
fb00b4385c9d40015b1d9e832bd618acf239d8d82723bc586346aadc146e284d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.4

Security for anci 0.1.5

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