CleanLibrary Python SDK
cleanlib-sdk is the Python client library for CleanLibrary. It wraps the same HTTP surface that powers the CLI, the MCP server, and the VS Code extension behind a small, typed API you can drop into any Python program — a service, a CLI tool, a CI gate, or a serverless function.
1. What it does
The Python SDK answers the same package-manager-layer questions as the CLI, but from inside a Python program rather than from a shell:
- Is this version safe to install? —
client.fetch_verdict(...) - What does my policy do with this package? —
client.policy_preview(...) - Should I accept the risk on this finding? —
client.risk_accept(...)
The wire contract is identical to every other CleanLibrary client. A verdict returned by the Python SDK has the same shape as a verdict returned by the CLI or the MCP server, so you can mix-and-match clients within one workflow.
2. Install
pip install cleanlib-sdk
uv users:
uv pip install cleanlib-sdk
Virtualenv:
python -m venv .venv && source .venv/bin/activate
pip install cleanlib-sdk
The SDK targets Python 3.9+ and depends only on httpx and the standard library.
3. Quickstart
import os
from cleanlib_sdk import Client
client = Client(
endpoint="https://cleanapp.clnstrt.dev",
api_key=os.environ["CLEANLIB_API_KEY"],
)
verdict = client.fetch_verdict("npm", "lodash", "4.17.21")
print(f"verdict_id: {verdict.verdict_id}")
print(f"severity: {verdict.severity}")
print(f"source: {verdict.source}")
Output:
verdict_id: <stable-identifier>
severity: NONE
source: ALLOWED_NO_FINDINGS
4. Configuration
The Client constructor accepts these positional and keyword arguments:
| Argument | Purpose | Default |
|---|---|---|
endpoint | Base URL of the CleanLibrary backend | (required) |
api_key | Bearer token (typically from CLEANLIB_API_KEY env var) | None |
api_version | API version path segment | "v1" |
timeout_secs | Per-request timeout in seconds | 30.0 |
The convention for production deployments is to read endpoint and api_key from environment variables and let everything else default:
client = Client(
endpoint=os.environ["CLEANLIB_ENDPOINT"],
api_key=os.environ["CLEANLIB_API_KEY"],
)
5. API reference
client.fetch_verdict(ecosystem, package, version) -> Verdict
Returns a verdict for a single (ecosystem, package, version) tuple. The Verdict carries the verdict identifier, severity, source label, freshness fields, and remediation hints.
class Verdict:
verdict_id: str # stable identifier for this decision
source: str # ALLOWED_NO_FINDINGS | VECTOR_VERDICT | DM_THRESHOLD_BLOCK | INSUFFICIENT_DATA
severity: str # NONE | LOW | MEDIUM | HIGH | CRITICAL
composite_score: int # 0-100 confidence in the decision
reasoning: str
suggested_actions: list[str]
# Plus freshness, similar_to, evidence_gaps, attestation, and rich-data fields
client.scan(packages) -> ScanResponse
Scans a list of PackageRef entries in one round-trip and returns a ScanResponse containing a verdict per package. Suitable for CI pipelines or admission controllers that need a single round-trip.
client.policy_preview(policy_yaml, packages) -> PolicyPreviewResponse
Returns what your candidate policy would decide for the given packages, with the matching policy rule attached. Useful for "if I add this rule, will it break my CI?" checks before deploying the policy.
client.risk_accept(verdict_id, justification) -> RiskAcceptResponse
Records a customer-side risk-acceptance against a specific verdict. The justification is stored alongside the verdict for audit purposes.
client.audit(window) -> AuditWindowResponse
Returns the customer-side audit log for a time window — verdicts fetched, policies previewed, risk-acceptances recorded.
client.fetch_bytes(ecosystem, package, version) -> bytes
Returns the verified upstream bytes for an (ecosystem, package, version) tuple — useful when you want CleanLibrary to fetch the artifact for policy evaluation or attestation signing.
6. Error handling
The SDK raises typed exceptions for known failure modes. Common exception types:
| Exception | When it raises |
|---|---|
AuthenticationError | Missing, malformed, or rejected api_key |
InsufficientDataError | The catalog has no verdict for this (ecosystem, package, version) yet |
IntegrityFailureError | An attestation or signature check failed |
CleanLibraryError | Base class for all SDK errors |
A verdict is not raised — it's a successful response with a verdict-aware shape. Use the verdict's severity and source to drive flow control, not exception handling.
7. CI integration
Drop the SDK into a build step and exit non-zero on a denied verdict:
# build/precheck.py
import sys, os
from cleanlib_sdk import Client, AuthenticationError
client = Client(
endpoint=os.environ["CLEANLIB_ENDPOINT"],
api_key=os.environ["CLEANLIB_API_KEY"],
)
try:
v = client.fetch_verdict("npm", "lodash", "4.17.21")
except AuthenticationError:
print("BLOCKED: invalid API key", file=sys.stderr)
sys.exit(2)
if v.source == "DM_THRESHOLD_BLOCK":
print(f"BLOCKED: npm/lodash@4.17.21 — {v.reasoning}", file=sys.stderr)
sys.exit(1)
For multi-package scans, prefer client.scan(...) over a loop of client.fetch_verdict(...) calls — one round-trip is cheaper than N.
8. Versioning
The SDK follows Semantic Versioning. The verdict envelope wire contract is stable across the v0.4 series — clients can mix v0.4.0 and v0.4.3 against the same backend without coordination.
v0.4.x envelopes are byte-identical with the Go, JavaScript, and Rust SDKs against the same backend version — verdicts produced by each SDK derive the same status for the same (ecosystem, package, version) tuple.
9. Where to go next
- CLI — the same verdicts and remediation surface from the terminal, for ad-hoc queries and CI gates
- MCP Server — surface CleanLibrary inside any MCP-compatible AI coding agent
- SDK — Go — Go programmatic access to the same verdict surface
- SDK — JavaScript — JavaScript / TypeScript programmatic access
- SDK — Rust — Rust programmatic access
- Integration Surfaces — the full integration matrix (admission, CI, IDE, agent)
- Architecture — how CleanLibrary's verdict-and-enrichment surface composes end to end