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.2

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.2
File Size Uploaded Provenance
argledger-0.1.2.tar.gz 52.6 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 95.3 kB

Release files / argledger-0.1.2.tar.gz

Download URL argledger-0.1.2.tar.gz
Size 52.6 kB
Tags Source
SHA-256 checksum
How to use checksums
8e2921ffc97c1bed9066063530bb7b9f4c6fa1875b9082388fd859b835f20b6f
BLAKE2b-256 checksum
How to use checksums
3837f422fd9d34267d53d822aeb28fdba4a2feadbf7c015716e6faf99085e863
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.2-py3-none-any.whl

Download URL argledger-0.1.2-py3-none-any.whl
Size 42.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f42b57a4624983b2555731ef85b5396f352563e370774d258090e5ff84ee1b35
BLAKE2b-256 checksum
How to use checksums
489cce72eb607d2c8bec9f2e327f0fe0a5ac58ab58060bb72fb141c23445ef2b
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.2

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.2 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