Skip to main content

argledger

Reusable, class-based command registry that turns validated JSON specs into real argparse parsers — with reproducible default resolution and automatic execution history.

argledger gives you one source of truth for every command:

  • parser construction (argparse.ArgumentParser)
  • default resolution CLI > env > config file > spec default with source tracking
  • deterministic default argv / shell rendering
  • automatic ExecutionContext recording (timestamps, duration, resolved args, provenance, git, outputs, metrics, success/failure)
  • JSONL + SQLite history, query, and replay
  • guide generation & shell completion hooks

No domain coupling. Your specs live with your project via Registry(user_root=...).

Installation

pip install argledger

Requires Python ≥3.11. No mandatory dependencies.

pip install argledger  # from PyPI
# or for development
pip install -e ".[dev]"

Quick start

1. Define a spec (my_project/specs/demo/greet.json):

{
  "name": "demo.greet",
  "description": "Greet someone a number of times.",
  "version": "1.0.0",
  "groups": ["common"],
  "arguments": {
    "name": { "type": "str", "default": "world", "help": "Name to greet." },
    "count": { "type": "int", "default": 1, "minimum": 1, "maximum": 10 },
    "excited": { "action": "store_true", "default": false }
  }
}

2. Use it:

from pathlib import Path
from argledger import Registry, History, ExecutionContext

registry = Registry(user_root=Path("my_project"))  # loads specs/my_project via importlib.resources + user_root
command = registry.load("demo.greet")

# resolves CLI > env > config > default, tracks source for each arg
resolved = command.parse_args(["--name", "Alice", "--count", "2"])
print(resolved.values)   # {'name': 'Alice', 'count': 2, 'excited': False, ...}
print(resolved.sources)  # {'name': 'cli', 'count': 'cli', ...}
print(resolved.namespace)  # argparse.Namespace

history = History(jsonl=Path(".run-registry/history.jsonl"), sqlite=Path(".run-registry/history.db"))

with ExecutionContext(command, resolved, history=history) as ctx:
    for _ in range(resolved.values["count"]):
        print(f"Hello, {resolved.values['name']}!")

    ctx.add_output(Path("out.txt"))
    ctx.set_metric("greetings", resolved.values["count"])
    ctx.set_data_version("my-data-v1")

Normal code stays simple:

args = command.parser().parse_args()

also works (legacy, source=unknown).

CLI

# list/show/defaults (pure package – no builtins – so pass where your specs live)
python -m argledger list --user-root my_project
python -m argledger show demo.greet --user-root my_project
python -m argledger defaults demo.greet --user-root my_project

# history query / replay
python -m argledger query --command demo.greet --success --limit 5
python -m argledger replay <execution-id>               # exact argv
python -m argledger replay <execution-id> --expanded     # fully expanded, reproducible argv

# guide generation (marker-based, never overwrites hand-written docs)
python -m argledger guide --output docs/COMMAND_GUIDE.md --user-root my_project

# shell completion
python -m argledger completion --shell bash

Features

  • Validated models Argument / Command – reject malformed names, unknown types/actions, minimum>maximum, invalid pattern, default not in choices, etc. (see Argument.from_spec)
  • Field-level group merge – groups listed in order, then spec overrides field-by-field ({**group, **spec}), e.g. a spec can override only "default" while keeping group's type/help/env.
  • Precedence CLI > env > config (TOML) > spec default. TOML layout:
    [groups.common]
    workers = 1
    [commands."demo.greet"]
    count = 5
    
    Configure via Registry(config_path=Path("argledger.toml")) or RUN_REGISTRY_CONFIG env.
  • Default argv Command.default_argv() / default_argument_string() – deterministic, shlex.join'd, respects include_in_default_argv/include_empty/include_false_flags. All docs delegate to this.
  • History – JSONL is canonical, SQLite is mirror. Queries by command/since/until/success/tags/limit; fallback to JSONL scan if SQLite disabled. Sensitive args stored as "<redacted>", expanded replay raises ReplayUnavailableError.
  • Provenance – UTC timestamps, monotonic duration, hostname/pid/cwd/python/platform/cpu_count, git commit/branch/dirty (never crashes outside a repo), optional peak RSS.
  • Compatibility argledger.compat.parser_from_spec(__file__, "demo/greet.json", user_root=...) wraps Registry().load(...).parser() with deprecation warning.

See examples/ for runnable demos (demo.greet, demo.counter, demo.file_processor) and tests/fixtures/ for the minimal spec used in 74 core tests.

Why

Research and product CLIs usually duplicate: arg definitions vs. parser vs. docs vs. history append vs. replay. argledger collapses them to one validated spec, so your script stays

command = registry.load(NAME)
resolved = command.parse_args()
with ExecutionContext(command, resolved, history=history) as run:
    result = do_the_actual_work(resolved.namespace)
    run.add_output(result.path)

— everything else (parser, defaults, env/config, docs, timing, history, replay, provenance) belongs to the framework.

Publishing / Development

pip install -e ".[dev]"
pytest -q
python -m build
twine check dist/*

Metadata

Release files for argledger 0.1.1

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

Source distribution (sdist)

Source distribution for argledger 0.1.1
File Size Uploaded Provenance
argledger-0.1.1.tar.gz 41.4 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 80.5 kB

Release files / argledger-0.1.1.tar.gz

Download URL argledger-0.1.1.tar.gz
Size 41.4 kB
Tags Source
SHA-256 checksum
How to use checksums
9d7ae6d32dc13062610e342ac9a9b80e377e1590d59ff86d2b6a322549c93d90
BLAKE2b-256 checksum
How to use checksums
fa413311338f04210e43e562e171932943a260d53992bdcd58f4f097857054ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release files / argledger-0.1.1-py3-none-any.whl

Download URL argledger-0.1.1-py3-none-any.whl
Size 39.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
21c994c872a4c327bef01c0140507bd8a1e1985ce73f6a9e0fe83d70570e50dc
BLAKE2b-256 checksum
How to use checksums
774542734e1c05e568946b4cd72402460a96ec8cdb7f7ac7f3c96e32fa42143e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Security for argledger 0.1.1

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.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

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