Skip to main content

CleanLibrary Rust SDK

cleanlib-client is the Rust 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 Rust program — a service, a CLI tool, a CI gate, or an admission controller.

1. What it does

The Rust SDK answers the same package-manager-layer questions as the CLI, but from inside a Rust program rather than from a shell:

  1. Is this version safe to install?client.fetch_verdict(...)
  2. What does my policy do with this package?client.policy_preview(...)
  3. Fetch the verified upstream bytesclient.fetch_artifact(...)

The wire contract is identical to every other CleanLibrary client. A verdict returned by the Rust 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

cargo add cleanlib-client

Or in your Cargo.toml:

[dependencies]
cleanlib-client = "0.1"
tokio = { version = "1", features = ["full"] }

The SDK targets Rust 1.75+ and uses tokio + reqwest for transport. cleanlib-client is the same library that powers cleanlib-cli; using it directly gives you the same wire contract without the binary.

3. Quickstart

v0.1.1+ re-exports the canonical types at the crate root — Client, Verdict, and PolicyDecision are all available via use cleanlib_client::{Client, Verdict, PolicyDecision}; directly.

use cleanlib_client::{Client, Verdict};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(
"https://cleanapp.clnstrt.dev",
Some(std::env::var("CLEANLIB_API_KEY")?),
)?;

let verdict: Verdict = client
.fetch_verdict("npm", "lodash", "4.17.21")
.await?;

println!("verdict_id: {}", verdict.verdict_id);
println!("severity: {:?}", verdict.severity);
println!("source: {}", verdict.source);

Ok(())
}

Output:

verdict_id: <stable-identifier>
severity: Some("NONE")
source: ALLOWED_NO_FINDINGS

4. Configuration

Client::new takes the endpoint and an optional api_key. For richer configuration use Client::from_config(&Config).

FieldPurposeDefault
endpoint (positional)Base URL of the CleanLibrary backend(required)
api_key (positional Option<String>)Bearer token (typically from CLEANLIB_API_KEY env var)None
Config { api_version, timeout, http_client, .. }Richer-knob configuration via Client::from_configsensible defaults

The convention for production deployments is to read endpoint and API key from environment variables:

let client = Client::new(
&std::env::var("CLEANLIB_ENDPOINT")?,
Some(std::env::var("CLEANLIB_API_KEY")?),
)?;

5. API reference

Client::fetch_verdict(ecosystem, package, version) -> Result<Verdict>

Returns a verdict for a single (ecosystem, package, version) tuple.

pub struct Verdict {
pub verdict_id: String, // stable identifier for this decision
pub verdict: String, // ALLOWED_NO_FINDINGS | VECTOR_VERDICT | DM_THRESHOLD_BLOCK | INSUFFICIENT_DATA
pub source: String, // mirrors `verdict` on v0.4.x
pub confidence: f64,
pub composite_score: u8, // 0-100 confidence in the decision
pub severity: Option<String>, // NONE | LOW | MEDIUM | HIGH | CRITICAL
pub reasoning: String,
pub suggested_actions: Vec<String>,
pub data_freshness_at: Option<String>,
// Plus similar_to, evidence_gaps, computed_at, attestation, and rich-data fields
}

Client::policy_preview(...)

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.

Client::fetch_artifact(ecosystem, package, version) -> Result<Bytes>

Returns the verified upstream bytes for an (ecosystem, package, version) tuple.

Client::fetch_artifact_stream(ecosystem, package, version, writer) -> Result<()>

Streams the upstream bytes to a writer — useful for large artifacts where buffering the full byte vector is undesirable.

Client::audit(...)

Returns the customer-side audit log for a time window.

derive_status(source, severity) -> DerivedStatus

Helper function that computes a renderable DerivedStatus from a verdict's source and severity fields. Available via use cleanlib_client::derive_status;.

6. Error handling

The SDK returns Result<T, CleanLibraryError>. Common error variants:

VariantWhen it surfaces
CleanLibraryError::Authentication { .. }Missing, malformed, or rejected api_key
CleanLibraryError::PackageNotFound { .. }The catalog has no verdict for this (ecosystem, package, version) yet
CleanLibraryError::PolicyDeny { .. }A 403 with a verdict-attached policy-deny envelope
CleanLibraryError::RiskAcceptanceRequired { .. }A 403 indicating the customer must record risk-acceptance
CleanLibraryError::RateLimit { retry_after }A 429 with Retry-After set
CleanLibraryError::Transport(...)Network, DNS, or TLS failure — wraps the underlying reqwest::Error

A Verdict is not an error — it's a successful response with a verdict-aware shape. Use the verdict's source and severity to drive flow control, not ?.

7. CI integration

Drop the SDK into a build step and exit non-zero on a denied verdict:

// build/precheck/src/main.rs
use cleanlib_client::Client;

#[tokio::main]
async fn main() {
let client = Client::new(
&std::env::var("CLEANLIB_ENDPOINT").unwrap(),
Some(std::env::var("CLEANLIB_API_KEY").unwrap()),
).unwrap();

let v = client.fetch_verdict("npm", "lodash", "4.17.21").await.unwrap();

if v.source == "DM_THRESHOLD_BLOCK" {
eprintln!("BLOCKED: npm/lodash@4.17.21 — {}", v.reasoning);
std::process::exit(1);
}
}

8. Versioning

The SDK follows Semantic Versioning. The verdict envelope wire contract is stable across the v0.1 series — clients can mix v0.1.0 and v0.1.1 against the same backend without coordination.

v0.1.x envelopes are byte-identical with the Python, Go, and JavaScript SDKs against the same backend version — verdicts produced by each SDK derive the same status for the same (ecosystem, package, version) tuple. cleanlib-client shares its codebase with cleanlib-cli, so the binary and the library always agree.

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 — Python — Python programmatic access
  • SDK — JavaScript — JavaScript / TypeScript programmatic access
  • Integration Surfaces — the full integration matrix (admission, CI, IDE, agent)
  • Architecture — how CleanLibrary's verdict-and-enrichment surface composes end to end