api-claim-audit
Offline CLI that checks a Python project's documented public API against its
source on disk. Version 0.1.0 uses only the Python standard library (Python
3.11+). It never imports or executes project code, accesses the network, or
reads .env contents. Reports contain matched claims and rule names, never
unrelated file contents.
Usage
Install with pip install ., then run:
api-claim-audit .
api-claim-audit /path/to/project --json
api-claim-audit . --fail-on HIGH
api-claim-audit . --ignore documented-import-missing --verbose
api-claim-audit --version
python -m api_claim_audit .
The path defaults to .. --ignore RULE,... drops named rules entirely; for
example, ignore an import rule when documenting a symbol provided only by an
optional extra. Unknown rules and invalid arguments are usage errors.
For a package defining greet(name) and Config.__init__(name="x"), this
README example verifies an import and a call:
from pkg import greet, Config
greet(name="Ada")
Changing the call to greet(nam="Ada") reports an unknown keyword. Documenting
from pkg import missing_thing reports a missing import. Constructor keyword
arguments are checked against __init__; pkg.Config.run checks a class method.
Imports with aliases check the original name, and imported aliases resolve
function and constructor calls within the same fenced example.
Human output prints SEVERITY rule file:line message for each finding, then a
PASS/FAIL summary. Verified claims print only with --verbose. --json returns:
{"status":"PASS","findings":[],"verified_claims":[{"claim":"from pkg import greet","file":"README.md"}]}
Each finding has severity, rule, file, line, and message; findings sort
by (rule, file, line). Exit codes are 0 for PASS, 2 for FAIL, and 1
for usage/input errors. The default failure threshold is MEDIUM. With
--fail-on HIGH, MEDIUM findings still print but do not fail.
Full rule table
| Rule | Severity | Trigger |
|---|---|---|
documented-import-missing |
HIGH | from pkg[.sub] import Name names a symbol absent from an existing module. Includes the import line and missing symbol in the message. |
documented-module-missing |
HIGH | import pkg.sub or from pkg.sub import ... names a module absent on disk; a missing own top-level package uses this rule too. |
documented-symbol-missing |
HIGH | pkg[.sub].Name is absent, or pkg[.sub].Class.method names a missing method. One finding per missing reference. |
documented-kwarg-unknown |
MEDIUM | A resolved function or constructor call passes a keyword its signature does not accept, without a **kwargs catch-all. One finding per unknown keyword. Positional-only parameters are not keyword-passable. |
verified_claims |
Not a finding | Resolved imports, symbols, and calls appear as claim text plus doc file in JSON; human output shows them with --verbose. No claims means PASS with zero verified claims. |
Scan boundaries
Scans top-level *.md (including README.md) and recursive docs/**/*.md.
Imports are claims only inside Python (python, py) or bare backtick fences,
or inline code spans. Dotted references and calls are checked in fences only.
Malformed import syntax is skipped. Plain prose is not a claim.
Own names come from the normalized [project].name in pyproject.toml (lowercase,
dashes replaced by underscores), packages containing __init__.py under the
root or src/, and single Python modules there. Third-party names are ignored.
Module evidence comes from Python files and package initializers. Top-level
functions, classes, assignments, annotated assignments, and explicit
from ... import ... re-exports count as symbols. Class methods come from the
class body. Re-exports count in any module, including __init__.py.
Tests are never evidence: tests/, test_*.py, and *_test.py are excluded.
The scanner also skips .venv, __pycache__, dist, .git, node_modules,
and .egg-info directories. Symlinks are not followed. Unparseable Python
source produces an input error rather than a misleading missing-symbol report.
Differentiation
- readme-claim-audit audits install names, --flags, links, versions, make
targets, and
python -mpaths. This tool audits documented importable symbols, modules, and call signatures; there is no overlap in rules. - apimirage really imports code at runtime to check whether an API exists, including LLM-hallucinated APIs. This tool is static and offline, executes nothing, and checks a project's own docs against its own source.
- pyflakes/ruff check names used inside code. This checks names promised inside documentation.
- Sphinx autodoc generates docs from code and cannot drift in that generated surface. Hand-written README/docs examples can drift; this audits that drift.
- dep-claim-audit / privacy-claim-audit audit dependency and privacy prose. This audits API prose only, within the code formatting boundaries above.
Honest limitations
Static scanning misses dynamic symbols: importlib, module __getattr__ hooks,
exec/eval-defined names, and symbols added by decorators at runtime. A symbol
that exists but is not actually importable, for example behind a failing
top-level import, still counts as present.
Method checks cover only the Class.method dotted form. Instance calls such as
client.foo() cannot be resolved statically and are skipped. Inherited methods
and inherited constructor signatures are not inferred. Calls to functions
accepting **kwargs skip keyword checks entirely. Unresolved callees are skipped
by the keyword rule. Required arguments, argument values and types, positional
arity, and runtime behavior are not checked. Star re-exports are not expanded.
Claim detection is limited to fenced code blocks and inline code spans in docs; usage written as plain prose without code formatting is not checked. Inline spans support import claims only. Third-party imports are ignored by design. Examples are static evidence, not proof that code runs successfully.
Development
PYTHONPATH=src python3 -m unittest discover -s tests -v
python3 -m build
Builds produce an sdist and wheel. Tests use local temporary fixtures and no network. MIT licensed.
Metadata
Release files for api-claim-audit 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| api_claim_audit-0.1.0.tar.gz | 14.7 kB | Without provenance | Details for api_claim_audit-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| api_claim_audit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for api_claim_audit-0.1.0-py3-none-any.whl |
Total release size: 25.2 kB
Release files / api_claim_audit-0.1.0.tar.gz
| Download URL | api_claim_audit-0.1.0.tar.gz |
|---|---|
| Size | 14.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
320044322faa4c8a52e15227b644c7d152fbf55ec2404ba51e49971143343ab1
|
|
BLAKE2b-256 checksum How to use checksums |
4feedcfb41a9fc54536ce6e059608766b7f3e1af528195c4132f51881c147d31
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / api_claim_audit-0.1.0-py3-none-any.whl
| Download URL | api_claim_audit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 10.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6b8e2eda147b8666dd6a1ff2ae3208543b1dce2a49772adfa4df4f06799492d7
|
|
BLAKE2b-256 checksum How to use checksums |
24296eb8feea42ae476e7e3225e837de99fcde08b7202a9e24725e53182dfac1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for api-claim-audit 0.1.0
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.