Skip to content

CLI reference

usage: torch-abi-audit [-h] [--version] [--env | --site-packages PATH]
                       [--json] [--all] [-v] [--check POLICY]
                       [TARGET ...]

Modes

The CLI selects exactly one inspection mode:

Mode Flag(s) What it inspects
Targets TARGET ... (positional) One or more import names or filesystem paths.
Active env --env Every package in the running interpreter's site-packages.
Specific env --site-packages PATH Every package under the given site-packages directory.

A TARGET can be:

  • An importable name like torchvision — resolved via importlib.util.find_spec.
  • A path to an installed package directory (recursive scan).
  • A path to a single .so / .pyd / .dylib / .dll file.

Output

By default the CLI prints a human-readable table.

  • --json switches to JSON. With multiple targets the output is wrapped in an EnvironmentReport-shaped envelope so the JSON shape is consistent.
  • --verbose (-v) shows the offending symbol list for unstable / non-compliant extensions.
  • --all makes env-scan output include packages with no torch use (hidden by default to keep the table focused on potentially-problematic packages).

Directory scans collect the library formats of the host: .so / .pyd / .dylib on Linux and macOS, .pyd / .dll on Windows. A file named directly on the command line is inspected whatever platform built it, so a Windows binary can be checked from Linux or macOS — that path uses the built-in PE parser and needs no external tools.

Package headers carry a Min torch: line, mirrored by the env-scan MIN-TORCH column: the lowest torch release that supplies every stable shim symbol the package references (see Minimum torch version). Each stable-ABI library row also gains a min-torch=<version> suffix, and --verbose lists the shim symbols that pin the floor.

Output examples

All samples below were captured against torch 2.14.0, torchaudio 2.11.0, and torchcodec 0.16.0 on Linux x86_64.

Default table -- multi-package

torch-abi-audit torchaudio torch torchcodec:

Package: torchaudio
  Root: <venv>/lib/python3.11/site-packages/torchaudio
  Torch ABI:   STABLE
  Min torch:   2.11.0
  CPython ABI: n/a
  Extensions:  0
  Bundled libs: 3
  -- bundled libs --
    [STABLE  ] [abi3-tagged-no-capi   ] lib/_torchaudio.abi3.so  (stable_shim=6, unstable=0)  min-torch=2.10.0
    [STABLE  ] [abi3-tagged-no-capi   ] lib/libtorchaudio.abi3.so  (stable_shim=80, unstable=0)  min-torch=2.11.0
    [STABLE  ] [abi3-tagged-no-capi   ] lib/torchaudio_prefixctc.abi3.so  (stable_shim=62, unstable=0)  min-torch=2.10.0

Package: torch
  Root: <venv>/lib/python3.11/site-packages/torch
  Torch ABI:   UNSTABLE
  Min torch:   n/a
  CPython ABI: no
  Extensions:  1
  Bundled libs: 11
  -- extensions --
    [NO-TORCH] [not-abi3              ] _C.cpython-311-x86_64-linux-gnu.so
  -- bundled libs --
    [NO-TORCH] [not-abi3              ] lib/libc10.so
    [UNSTABLE] [not-abi3              ] lib/libc10_cuda.so  (stable_shim=0, unstable=48)
    [NO-TORCH] [not-abi3              ] lib/libcaffe2_nvrtc.so
    [UNSTABLE] [not-abi3              ] lib/libshm.so  (stable_shim=0, unstable=9)
    [NO-TORCH] [not-abi3              ] lib/libtorch.so
    [UNSTABLE] [not-abi3              ] lib/libtorch_cpu.so  (stable_shim=0, unstable=343)
    [UNSTABLE] [not-abi3              ] lib/libtorch_cuda.so  (stable_shim=0, unstable=2569)
    [UNSTABLE] [not-abi3              ] lib/libtorch_cuda_linalg.so  (stable_shim=0, unstable=156)
    [NO-TORCH] [not-abi3              ] lib/libtorch_global_deps.so
    [UNSTABLE] [not-abi3              ] lib/libtorch_nvshmem.so  (stable_shim=0, unstable=74)
    [UNSTABLE] [uses-private-api      ] lib/libtorch_python.so  (stable_shim=0, unstable=5111)

Package: torchcodec
  Root: <venv>/lib/python3.11/site-packages/torchcodec
  Torch ABI:   STABLE
  Min torch:   2.11.0
  CPython ABI: no
  Extensions:  1
  Bundled libs: 14
  -- extensions --
    [NO-TORCH] [uses-private-api      ] libtorchcodec_pybind_ops.so
  -- bundled libs --
    [STABLE  ] [not-abi3              ] libtorchcodec_core4.so  (stable_shim=67, unstable=0)  min-torch=2.11.0
    [STABLE  ] [not-abi3              ] libtorchcodec_core5.so  (stable_shim=67, unstable=0)  min-torch=2.11.0
    [STABLE  ] [not-abi3              ] libtorchcodec_core6.so  (stable_shim=67, unstable=0)  min-torch=2.11.0
    [STABLE  ] [not-abi3              ] libtorchcodec_core7.so  (stable_shim=67, unstable=0)  min-torch=2.11.0
    [STABLE  ] [not-abi3              ] libtorchcodec_core8.so  (stable_shim=67, unstable=0)  min-torch=2.11.0
    [STABLE  ] [not-abi3              ] libtorchcodec_core9.so  (stable_shim=67, unstable=0)  min-torch=2.11.0
    [STABLE  ] [uses-private-api      ] libtorchcodec_custom_ops4.so  (stable_shim=65, unstable=0)  min-torch=2.11.0
    [STABLE  ] [uses-private-api      ] libtorchcodec_custom_ops5.so  (stable_shim=65, unstable=0)  min-torch=2.11.0
    [STABLE  ] [uses-private-api      ] libtorchcodec_custom_ops6.so  (stable_shim=65, unstable=0)  min-torch=2.11.0
    [STABLE  ] [uses-private-api      ] libtorchcodec_custom_ops7.so  (stable_shim=65, unstable=0)  min-torch=2.11.0
    [STABLE  ] [uses-private-api      ] libtorchcodec_custom_ops8.so  (stable_shim=65, unstable=0)  min-torch=2.11.0
    [STABLE  ] [uses-private-api      ] libtorchcodec_custom_ops9.so  (stable_shim=65, unstable=0)  min-torch=2.11.0
    [STABLE  ] [not-abi3              ] libtorchcodec_heic.so  (stable_shim=60, unstable=0)  min-torch=2.11.0
    [STABLE  ] [not-abi3              ] libtorchcodec_image.so  (stable_shim=72, unstable=0)  min-torch=2.11.0

The per-row labels:

Torch CPython Meaning
STABLE / UNSTABLE / NO-TORCH — Per-library torch verdict.
— abi3-ok Filename tagged abi3 and every Py* symbol is in the limited API.
— abi3-tagged-violations Filename tagged abi3 but the file references private CPython symbols.
— abi3-tagged-no-capi Filename tagged abi3, file has no CPython API references at all (e.g. a STABLE_TORCH_LIBRARY plugin).
— uses-private-api Not abi3-tagged, references private CPython symbols.
— not-abi3 Not abi3-tagged, no Py* references.

Verbose excerpt -- --verbose surfaces offending symbols

torch-abi-audit torch -v (first 28 lines):

Package: torch
  Root: <venv>/lib/python3.11/site-packages/torch
  Torch ABI:   UNSTABLE
  Min torch:   n/a
  CPython ABI: no
  Extensions:  1
  Bundled libs: 11
  -- extensions --
    [NO-TORCH] [not-abi3              ] _C.cpython-311-x86_64-linux-gnu.so
  -- bundled libs --
    [NO-TORCH] [not-abi3              ] lib/libc10.so
    [UNSTABLE] [not-abi3              ] lib/libc10_cuda.so  (stable_shim=0, unstable=48)
        torch unstable: c10::ValueError::ValueError(c10::SourceLocation, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
        torch unstable: c10::SetAllocator(c10::DeviceType, c10::Allocator*, unsigned char)
        torch unstable: c10::WarningUtils::get_warnAlways()
        torch unstable: c10::MessageLogger::stream[abi:cxx11]()
        torch unstable: c10::MessageLogger::MessageLogger(c10::SourceLocation, int, bool)
        torch unstable: c10::MessageLogger::~MessageLogger()
        torch unstable: c10::DeviceAllocator::DeviceAllocator()
        torch unstable: c10::DeviceAllocator::~DeviceAllocator()
        torch unstable: c10::SmallVectorBase<unsigned int>::grow_pod(void const*, unsigned long, unsigned long)
        torch unstable: c10::CachingAllocator::AcceleratorAllocatorConfig::getMutableKeys[abi:cxx11]()
        torch unstable: c10::CachingAllocator::AcceleratorAllocatorConfig::getConfigParserHook[abi:cxx11]()
        torch unstable: c10::CachingAllocator::AcceleratorAllocatorConfig::roundup_power2_divisions(unsigned long)
        torch unstable: c10::CachingAllocator::AcceleratorAllocatorConfig::getKeys[abi:cxx11]()
        torch unstable: c10::CachingAllocator::AcceleratorAllocatorConfig::instance()
        torch unstable: c10::OutOfMemoryError::OutOfMemoryError(c10::SourceLocation, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
        ... 33 more

The first 15 unstable symbols per library are listed inline; anything past that becomes a ... N more summary so the table doesn't blow up.

JSON shape — --json

torch-abi-audit torchaudio --json:

{
  "name": "torchaudio",
  "root": "<venv>/lib/python3.11/site-packages/torchaudio",
  "extensions": [],
  "bundled_libs": [
    {
      "path": "<venv>/.../torchaudio/lib/_torchaudio.abi3.so",
      "cpython": { "intent": true, "compliant": false, "violations": [] },
      "torch": {
        "uses_torch": true,
        "stable": true,
        "unstable_symbols": [],
        "stable_shim_count": 6,
        "min_torch_version": "2.10.0",
        "version_defining_symbols": ["torch_library_impl"],
        "unknown_shim_symbols": []
      },
      "error": null
    },
    { "path": "<venv>/.../torchaudio/lib/libtorchaudio.abi3.so", "...": "..." },
    { "path": "<venv>/.../torchaudio/lib/torchaudio_prefixctc.abi3.so", "...": "..." }
  ],
  "error": null
}

The verdict roll-ups (torch_verdict, cpython_verdict) are @property on PackageReport, so they're computed on access and don't appear in the JSON dump. Compute them yourself by looking at the extensions and bundled_libs lists, or use the Python API.

Minimum torch version

Every stable shim entry point was introduced in some torch release. The tool maps each one to its introducing version (via a vendored copy of PyTorch's shim_function_versions.txt) and reports the highest such version a library needs, its minimum torch version floor. Shim symbols from the 2.9.0 baseline (when the stable ABI shipped) count as 2.9.0. A shim symbol newer than the vendored data is reported separately (unknown_shim_symbols, shown under --verbose) and turns the floor into a lower bound, displayed as min-torch=>=<version>; regenerate the data files to resolve it.

With --verbose, each stable library's floor is followed by the shim symbols that pin it (torchaudio -v, captured against torchaudio 2.11.0):

Package: torchaudio
  Root: <venv>/lib/python3.11/site-packages/torchaudio
  Torch ABI:   STABLE
  Min torch:   2.11.0
  CPython ABI: n/a
  Extensions:  0
  Bundled libs: 3
  -- bundled libs --
    [STABLE  ] [abi3-tagged-no-capi   ] lib/_torchaudio.abi3.so  (stable_shim=6, unstable=0)  min-torch=2.10.0
        requires torch 2.10.0: torch_library_impl
    [STABLE  ] [abi3-tagged-no-capi   ] lib/libtorchaudio.abi3.so  (stable_shim=80, unstable=0)  min-torch=2.11.0
        requires torch 2.11.0: torch_dtype_float4_e2m1fn_x2, torch_dtype_float8_e8m0fnu
    [STABLE  ] [abi3-tagged-no-capi   ] lib/torchaudio_prefixctc.abi3.so  (stable_shim=62, unstable=0)  min-torch=2.10.0
        requires torch 2.10.0: torch_call_dispatcher, torch_delete_list, torch_get_mutable_data_ptr, torch_library_impl, torch_list_push_back, +1 more

In the env-scan table the same floor appears as the MIN-TORCH column (- when a package uses no stable shims):

  PACKAGE           TORCH     MIN-TORCH  CPYTHON   EXTS  BUNDLED
  ----------------  --------  ---------  --------  ----  -------
  torch             UNSTABLE  -          no           1       11
  torchaudio        STABLE    2.11.0     n/a          0        3
  torchcodec        STABLE    2.11.0     no           1       14

Refresh the vendored version table from pytorch/pytorch with:

python scripts/update_shim_versions.py          # rewrite the vendored copy
python scripts/update_shim_versions.py --check  # CI: fail if it's stale

CI gating -- --check

--check POLICY turns a verdict into a non-zero exit code so a build fails when a package isn't on the stable ABI. Without it, the CLI only reports and exits 0 (see Exit codes).

Policy Fails when
torch any inspected package uses libtorch without the stable ABI (UNSTABLE).
abi3 any torch-using package isn't CPython abi3-compliant.
both either of the above.

The abi3 policy is scoped to torch-using packages, so an arbitrary non-torch package failing the limited API doesn't break an --env gate. It also only judges packages that ship a Python extension module (PyInit_*). A torch package made up entirely of bundled libraries loaded via STABLE_TORCH_LIBRARY (e.g. torchaudio) has no CPython ABI verdict, so abi3 / both never flag it -- the CPython limited API applies only to modules loaded by Python's importer, not to dlopen-ed shared libraries.

On Windows the check also requires the module to link python3.dll, the version-agnostic stable ABI forwarder. A module that links python314.dll (and friends) is tied to one interpreter version even when every symbol it uses is stable, so it fails abi3.

torch-abi-audit mypkg --check torch          # gate one package
torch-abi-audit --env --check both           # gate the whole environment

Violations print a FAIL: summary to stderr and exit 1. An operational error (below) still exits 2 and takes precedence over the policy code.

Exit codes

The CLI reports verdicts via stdout / JSON; it returns:

  • 0 on inspection success with no --check policy violation.
  • 1 when --check is given and a policy violation is found.
  • 2 on operational errors (missing nm, unknown import name, unreadable path, or a library that fails to parse) -- whether the failure is raised or recorded in a report's error field. A partly readable library counts: the verdict is computed from the symbols that were recovered and reported as normal, but the run still exits 2, because an audit that could not see every symbol must not report success.

Without --check, the tool is safe to run interactively without set -e surprises: it only exits non-zero on operational errors. As an alternative to --check, parse the JSON output and act on the torch/cpython fields yourself.