Skip to main content

confargs

⚠️ Early development. APIs may change.

confargs is a small, declarative CLI argument parser for Python 3.10+ that merges configuration from three sources into one result:

  1. Command line arguments (--log out.html, -l NONE)
  2. Environment variables (per-option or auto-generated)
  3. TOML config files (discovered by walking up from the current directory, pyproject.toml-style)

You describe options as methods on a class. Each method receives the raw value from whichever source supplied it, performs any parsing/validation you like, and returns the final value. confargs handles discovery, precedence and basic type coercion; your code owns the domain logic.

import confargs
from confargs import ArgConfig


class MyArgs(ArgConfig):
    """My CLI tool.

    Longer description shown in --help.
    """

    name = "mytool"

    @confargs.option
    def log(self, value: str | None = "log.html") -> str | None:
        """HTML log file. Disable with the special value 'NONE'."""
        if value == "NONE":
            return None
        return value

    @confargs.option(names="--console/-c")
    def console(self, value: str = "verbose") -> str:
        choices = ["verbose", "dotted", "quiet", "none"]
        if value not in choices:
            raise confargs.OptionValueError(f"console must be one of {choices}")
        return value


config = confargs.ConfigurationProcessor(MyArgs).process()
print(config.log, config.console)

Precedence

Highest wins: CLI > environment variables > nearest TOML > user-directory TOML > option default.

Configuration sources

TOML files

Config is read from a table named after your tool. By default that is [tool.<name>] (e.g. [tool.mytool]); override it with default_config_section = "tool.custom". The file names searched are set with config_names (default ["pyproject.toml"]). Both dashed-keys and snake_case_keys are accepted.

[tool.mytool]
log = "results.html"
console = "dotted"
tags = ["ci", "nightly"]

Discovery walks up from the current directory looking for those files and stops at the project root (a directory containing .git). If nothing is found, a per-user config directory is consulted (%APPDATA%\<name> on Windows, $XDG_CONFIG_HOME/<name> otherwise). Discovery is controlled by built-in, CLI-only options:

  • --config PATH — use only this file, skip discovery.
  • --no-config — ignore config files entirely.
  • --ignore-git — keep searching above the .git project root.

By default (strict_config = True) unknown keys — and any cli_only option — found in the config section raise an error, which catches typos early. Set strict_config = False on your class to silently ignore them instead.

Environment variables

Set a name per option with @option(envvar="MYTOOL_LOG"), or enable auto_env_vars = True on the class to expose every non-cli_only option as <NAME>_<OPTION> (e.g. MYTOOL_CONSOLE).

CLI-only options

Options marked @option(cli_only=True) are never read from TOML or the environment — use this for switches that control the tool run itself (the built-in discovery options above are defined this way).

Options in depth

  • Long names come from the method name (dry_run--dry-run); a short name is derived from the first letter when it is still free. Override with names="--console/-c".
  • The value type is taken from the value parameter annotation. bool becomes a flag; list[...] becomes a repeatable option; int/float/str are coerced from strings. Your method receives the coerced value and returns the final one — raise confargs.OptionValueError to reject it.
  • Boolean options can be negated on the command line: --verbose sets it to True, --no-verbose sets it to False.

Eager options and argument files

Mark an option is_eager=True to resolve it before every other source, directly against argv. The method's return value — an iterable of tokens or None — replaces the option's own arguments, so it can inject more options. This is how an --argumentfile option expands a file (Robot Framework style) into extra arguments, including nested argument files:

from confargs import ArgConfig, option, read_argument_file


class Args(ArgConfig):
    @option(names="--argumentfile/-A", cli_only=True, is_eager=True)
    def argumentfile(self, value: str | None = None) -> list[str] | None:
        return read_argument_file(value) if value else None

ConfigurationProcessor(Args, argv=[...]) accepts an explicit argument list; when omitted it falls back to sys.argv[1:].

Example

A complete, self-contained example lives in examples/demo.py (with a sample examples/example.args and examples/README.md). It's a single copy-pasteable file showing value options, --no- flag negation, environment variables and an eager --argumentfile. Run it from a checkout without installing anything:

uv run python examples/demo.py --who Ada --repeat 3
uv run python examples/demo.py -A examples/example.args
uv run python examples/demo.py --help

Separately, the packaged confargs.demo module is installed as the confargs-demo console script via [project.scripts]:

uv run confargs-demo --console quiet --retries 5
uv run confargs-demo --help

To ship your own tool, point a console script at a main() that runs the processor, for example in pyproject.toml:

[project.scripts]
mytool = "mytool.cli:main"

Development

This project uses uv.

uv sync                 # create the environment
uv run pytest           # run the tests
uv run ruff check       # lint
uv run ruff format      # format
uv run mypy             # type-check
pre-commit install      # enable git hooks

Publishing

Releases are published to PyPI by .github/workflows/publish.yml when a GitHub Release is published. It uses PyPI Trusted Publishing (OIDC), so no API token is stored in the repository — configure the project as a trusted publisher on PyPI (workflow publish.yml, environment pypi) once.

Versioning

confargs follows Semantic Versioning. The version is single-sourced from __version__ in src/confargs/__init__.py (hatchling reads it at build time). While the project is 0.x.y the API is still stabilising, so minor releases may include breaking changes. Notable changes are recorded in CHANGELOG.md.

Releases are automated with release-please: merging Conventional Commits to main keeps an open release PR that bumps __version__, updates the changelog and, once merged, tags the release and publishes to PyPI. Pre-1.0, breaking changes bump the minor version (bump-minor-pre-major).

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

confargs-0.2.0.tar.gz (90.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

confargs-0.2.0-py3-none-any.whl (24.9 kB view details)

Uploaded Python 3

File details

Details for the file confargs-0.2.0.tar.gz.

File metadata

  • Download URL: confargs-0.2.0.tar.gz
  • Upload date:
  • Size: 90.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for confargs-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c61a4c5a1a23bb02dd8264c0057b1fdf5b22391ed74d76dd283f499b8915f24f
MD5 88a1e08e9c7a68d867f3730f9a870bde
BLAKE2b-256 648d214e15471c4def881a2004a58cbf02e3982fbed6fd063557bc1865cc3c1f

See more details on using hashes here.

Provenance

The following attestation bundles were made for confargs-0.2.0.tar.gz:

Publisher: release-please.yml on MarketSquare/confargs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file confargs-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: confargs-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 24.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for confargs-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ed24df1a13532c277dca6d9cd12f0d095d409abb74dedfbd66e4316bdcbce2c8
MD5 f2641caa9657d550e7f9f9bc5595922d
BLAKE2b-256 c259b62f2b231093dfe934772770f12e4eea00691f8e095c4c6a58330ba838eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for confargs-0.2.0-py3-none-any.whl:

Publisher: release-please.yml on MarketSquare/confargs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

This release

0.2.0 This release

2 files

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