CLI¶
nab exposes three subcommands: lock, download, and config. The
first two read project shape from [tool.nab] in the project’s
pyproject.toml or a project-directory nab.toml; the CLI carries
runtime knobs and can override a project key for one run with a
--project-<key> flag. config inspects the layered configuration.
Synopsis¶
nab [--version | -V]
nab lock [PATH] [RUNTIME OPTIONS] [--output PATH] [--format pylock|requirements|requirements-without-hashes]
nab download [PATH] [RUNTIME OPTIONS] [--output DIR] [--max-concurrency N]
nab config {list | get <key> | explain <key>} [--path PATH]
PATH is positional and defaults to pyproject.toml in the
current directory. Run nab lock --help (or -h) for the full
per-command flag list. Boolean flags render as a --flag /
--no-flag pair (for example --cache / --no-cache). --offline
is layered, so an explicit --offline True / --offline False
overrides the config layers; bare --offline / --no-offline are
shorthands for those two values.
nab lock¶
Resolve and emit a lockfile or pin list. Three formats:
--format pylock(default) writes a PEP 751pylock.toml.--format requirementswrites a pip-compatiblerequirements.txtwith one--hash=<algo>:<digest>line per recorded digest.--format requirements-without-hasheswrites a sortedname==versionlist with no hashes.
Dependency-group selection (PEP 735):
--groups foo barfolds the named groups from the project’s[dependency-groups]table into the resolve. The selected group names land in the lockfile’s top-leveldependency-groupsarray. The separatedefault-groupsarray records the[tool.nab].default-groupsproject setting, not this run’s selection.--all-groupsselects every group defined in the project.
Extras selection:
--extras foo barfolds entries from the project’s own[project.optional-dependencies]table into the resolve. The selected extra names land in the lockfile’s top-levelextrasarray.--all-extrasselects every declared extra.
Both --groups and --extras produce a single union resolve. A
package that only a selected extra or group reaches is emitted with
a 'X' in extras or 'X' in dependency_groups marker, so an
installer given neither leaves it out; see
Lockfiles.
Workspace flags (see Lock a workspace):
--workspace-discovery(default) walks upward from the locked project for a[tool.nab.workspace]root and prefers its in-tree members over PyPI.--no-workspace-discoveryskips that search, so the run resolves the named project alone.--no-emit-workspacedrops the workspace members’ own[[packages]]entries from the emitted lockfile, along with the dependency edges and membership gates that reference them; the resolver still uses the members during the resolve. Default off (--no-no-emit-workspace). Use it when the lockfile is consumed by pip’s PEP 751 install or--require-hashes, which reject the directory entry a member pin emits because it cannot be hashed; pair it withpip install --no-deps -e <member>.
--output defaults to pylock.toml for pylock and
requirements.txt for the two requirements formats. Pass
--output - to write to stdout instead. A matrix has no default
requirements file: no one file can carry every tuple’s pins (see
below), so the requirements formats print to stdout unless --output
names a template.
A requirements --output template writes one file per tuple. The
variables are {python_version}, {platform_id}, and {selection},
which names the conflict fork a tuple belongs to (extra-cpu,
group-black22.group-isort5, empty when the resolve did not fork):
$ nab lock --format requirements-without-hashes --extras cpu gpu \
--output 'req-{python_version}-{selection}.txt'
Wrote req-3.12-extra-cpu.txt (12 packages, tuple py312-linux_x86_64-extra-cpu)
Wrote req-3.12-extra-gpu.txt (14 packages, tuple py312-linux_x86_64-extra-gpu)
A template that maps two tuples onto one path is rejected, naming the variable that would separate them.
Exits non-zero on resolution failure; the message starts with
Resolution failed: followed by a derivation tree, and any
captured diagnostics are appended under a Diagnostics: section.
Universal mode ([tool.nab].mode = "universal") is supported for
all three formats:
pylockproduces one PEP 751 file with per-tuplePackageentries gated by markers (python_version,sys_platform,platform_machine, plusimplementation_namewhen the matrix declares a non-CPython implementation or more than one). Versions agreed across every tuple appear once without a marker; divergent versions appear once per(version, source)group with the matching tuples disjoined.requirementsandrequirements-without-hashesemit a sequence of# labelcomment blocks, one per(python, platform, implementation)tuple, followed by that tuple’s pins. Pip’s hash-checking mode cannot install a single requirements.txt across multiple tuples, so the per-tuple block format is for inspection or for tools that consume one block at a time.
Failed tuples render as # {label}: FAILED followed by the
indented error and exit 1.
--python X.Y resolves for that Python on this machine instead of the
running interpreter, like pip’s --python-version; it moves only the
python axis, so a declared [tool.nab.environment].platform stays. It is
rejected in universal mode, where the matrix declares the Python axis.
A project option can be overridden for one run with a --project-<key>
flag: --project-resolution, --project-mode, --project-requires-python,
--project-uploaded-prior-to, --project-dist-policy,
--project-build-policy, and the repeatable --project-constraint and
--project-default-group. Each changes the resolved set, so passing one
prints a reproducibility notice on stderr and records the override in the
lockfile’s [tool.nab] block, since the lock no longer derives from the
committed files alone. --project-resolution was previously named
--resolution.
--locked re-resolves and checks that the committed pylock.toml is
already up to date, writing nothing. It exits non-zero if the lock would
change or is missing, so CI can assert the lock is current. It covers
pylock output to a file in single-environment mode.
--upgrade re-anchors the P<n>D resolve window to the current time
instead of reusing the timestamp recorded in an existing lockfile, and
prints a notice naming the cutoff it dropped.
nab download¶
Resolve and download every wheel, sdist, and direct-URL archive into a local directory. The download is idempotent: files whose recorded sha256 matches a local file are left alone. Local and VCS pins are skipped.
Universal mode ([tool.nab].mode = "universal") re-resolves
across the matrix and downloads the union of every tuple’s
artefacts into the same directory, deduplicated by URL so a
wheel shared across tuples is fetched once.
--outputdefaults towheels/.--max-concurrencycontrols parallel HTTP fetches (default8, minimum1). Layered, so it can also be set in annab.tomlorNAB_MAX_CONCURRENCY.--workspace-discovery(default) mirrorsnab lock: it finds a[tool.nab.workspace]root and resolves against the in-tree members.--no-workspace-discoveryturns that off. See Lock a workspace.
--offline, --cache-dir, --http-backend, --max-concurrency and the
--project-* overrides flow through the same layered config sources nab lock uses, so a NAB_* variable or a system/user/project nab.toml is
read for nab download as for nab lock.
A summary of how many files were written and how many were already present is printed to stderr.
nab config¶
Inspect the effective layered configuration (read-only). Three actions:
nab config listprints every option with its value, scope, and the source it came from.nab config get <key>prints one effective value.nab config explain <key>prints the full source stack for one key, the winning source marked with a>. Array options concatenate every layer instead of one winning, so each source is shown as a contribution and the merged effective value is printed on a trailing= effective:line. Add--include-rejectedto also list sources that tried to set the key but were rejected by the category gate.
The same per-option override flags the run commands accept (the
--project-* overrides and the user knobs --offline, --cache-dir,
--http-backend, --max-concurrency) layer a CLI value on top, so the
inspector reflects the same effective values a run would see.
See Configuration for the source ladder and the
NAB_* environment variables.
Runtime flags¶
Both subcommands accept the same runtime knobs:
Flag |
Default |
Effect |
|---|---|---|
|
|
Override the on-disk cache root. |
|
off |
Disable cache for this run. Combine with |
|
unset |
Use cache only, never hit the network. Layered: |
|
|
Pick the async transport for fetches. Layered, so it can also be set in an |
urllib3 is the only backend pulled in by the base install. The
others surface a helpful ImportError if selected without the
matching extra.
Global flags¶
Flag |
Effect |
|---|---|
|
Print |
|
Standard argparse-style help. Per-subcommand help works too: |
Environment variables¶
Variable |
Effect |
|---|---|
|
If set, |
Exit codes¶
Code |
Meaning |
|---|---|
|
Success. |
|
Resolution failed, lockfile cannot be written (missing hash), download failed, missing |
|
Interrupted with Ctrl-C. |