Skip to main content

CleanLibrary JavaScript SDK

@cleanstart/cleanlib-sdk is the JavaScript / TypeScript 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 Node.js or browser-side program.

1. What it does

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

  1. Is this version safe to install?client.fetchVerdict(...)
  2. What does my policy do with this package?client.policyPreview(...)
  3. Should I accept the risk on this finding?client.riskAccept(...)

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

npm install @cleanstart/cleanlib-sdk

pnpm / yarn users:

pnpm add @cleanstart/cleanlib-sdk
yarn add @cleanstart/cleanlib-sdk

The SDK ships as ESM + CJS dual-package and includes TypeScript types. It targets Node.js 18+ and modern browsers; it has no native dependencies.

3. Quickstart

import { HttpVerdictClient } from "@cleanstart/cleanlib-sdk";

const client = new HttpVerdictClient("https://cleanapp.clnstrt.dev", {
apiKey: process.env.CLEANLIB_API_KEY!,
});

const verdict = await client.fetchVerdict("npm", "lodash", "4.17.21");

console.log(`verdict_id: ${verdict.verdict_id}`);
console.log(`severity: ${verdict.severity}`);
console.log(`source: ${verdict.source}`);

Output:

verdict_id: <stable-identifier>
severity: NONE
source: ALLOWED_NO_FINDINGS

4. Configuration

The HttpVerdictClient constructor accepts an endpoint positional argument plus an options object:

OptionPurposeDefault
apiKeyBearer token (typically from CLEANLIB_API_KEY env var); alias: bearer(required)
apiVersionAPI version path segment"v1"
timeoutMsPer-request timeout in milliseconds30_000
fetchOptional fetch implementation override (for testing or custom transports)global fetch

The convention for production deployments is to read endpoint and apiKey from environment variables and let everything else default:

const client = new HttpVerdictClient(process.env.CLEANLIB_ENDPOINT!, {
apiKey: process.env.CLEANLIB_API_KEY!,
});

5. API reference

client.fetchVerdict(ecosystem, package, version) -> Promise<Verdict>

Returns a verdict for a single (ecosystem, package, version) tuple. The Verdict shape conforms to VerdictEnvelopeV1Schema and carries the verdict identifier, severity, source label, freshness fields, and remediation hints.

interface Verdict {
verdict_id: string; // stable identifier for this decision
source: string; // ALLOWED_NO_FINDINGS | VECTOR_VERDICT | DM_THRESHOLD_BLOCK | INSUFFICIENT_DATA
severity: string; // NONE | LOW | MEDIUM | HIGH | CRITICAL
composite_score: number; // 0-100 confidence in the decision
reasoning: string;
suggested_actions: string[];
// Plus freshness, similar_to, evidence_gaps, attestation, and rich-data fields
}

client.scan(packages) -> Promise<ScanResponse>

Scans a list of package references 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.policyPreview(policyYaml, packages) -> Promise<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.

client.riskAccept(verdictId, justification) -> Promise<RiskAcceptResponse>

Records a customer-side risk-acceptance against a specific verdict.

client.audit(window) -> Promise<AuditWindowResponse>

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

client.fetchBytes(ecosystem, package, version) -> Promise<Uint8Array>

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

deriveStatus(source, severity) -> Status

Helper function exposed at the top of the package that derives a renderable status from a verdict's source and severity fields — useful for clients that build their own UI without going through the underlying enrichment client.

5a. Other clients in the package

The package also exports specialized clients for the supporting surfaces:

import { HttpEnrichClient, HttpRemediationClient } from "@cleanstart/cleanlib-sdk";
  • HttpEnrichClient — vulnerability-intelligence and EPSS/KEV lookups for known CVEs
  • HttpRemediationClient — upgrade-path search for a vulnerable package

Use HttpVerdictClient for the verdict surface (most customers); the enrichment and remediation clients sit alongside it for richer flows.

6. Error handling

The SDK throws typed errors for known failure modes. Common error classes:

ClassWhen it throws
CleanlibErrorBase class for all SDK errors
HttpErrorNon-2xx HTTP response surfaced as a structured error
VerdictNotFoundErrorThe catalog has no verdict for this (ecosystem, package, version) yet
TransportErrorNetwork, DNS, or TLS failure — wraps the underlying fetch error

A verdict is not thrown — it's a successful response with a verdict-aware shape. Use the verdict's severity and source to drive flow control, not try / catch.

7. CI integration

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

// scripts/precheck.ts
import { HttpVerdictClient, VerdictNotFoundError } from "@cleanstart/cleanlib-sdk";

const client = new HttpVerdictClient(process.env.CLEANLIB_ENDPOINT!, {
apiKey: process.env.CLEANLIB_API_KEY!,
});

try {
const v = await client.fetchVerdict("npm", "lodash", "4.17.21");
if (v.source === "DM_THRESHOLD_BLOCK") {
console.error(`BLOCKED: npm/lodash@4.17.21 — ${v.reasoning}`);
process.exit(1);
}
} catch (e) {
if (e instanceof VerdictNotFoundError) {
console.error("BLOCKED: no verdict on file for this version yet");
process.exit(2);
}
throw e;
}

For multi-package scans, prefer client.scan(...) over a loop of client.fetchVerdict(...) 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.4 against the same backend without coordination.

v0.4.x envelopes are byte-identical with the Python, Go, 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 — Python — Python 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