@patchlight/sdk
v0.4.0
Published
Patchlight SDK + CLI — trigger AI code reviews and security scans from any CI/CD pipeline and retrieve findings.
Maintainers
Readme
@patchlight/sdk
Trigger Patchlight AI code reviews and security scans from any CI/CD pipeline — GitLab, Bitbucket, Azure Repos, self-hosted git, or a custom script — and retrieve the findings. The GitHub App reviews pull requests automatically; this package covers everything else.
It ships two things in one package:
- a TypeScript SDK (
createClient) for programmatic use, and - a CLI (
patchlight) built for CI: it collects the git diff, submits it, waits for the result, prints findings, and can fail the pipeline when severe issues are found.
Node.js 18.17+ · zero runtime dependencies.
Install
npm install --save-dev @patchlight/sdk
# or run the CLI without installing:
npx @patchlight/sdk --helpAuthenticate
Create an API key in the dashboard under App → API Keys. The SDK reads it from the apiKey
option; the CLI reads the PATCHLIGHT_API_KEY environment variable. Store it as a masked secret
in your CI provider.
Working at a terminal rather than in CI? Install
@patchlight/cliand runpatchlight login— a browser sign-in that stores a token in~/.patchlight/, so no secret ever passes through your shell history. This package's commands read that token too. API keys stay the right credential for CI, which has an environment variable and no browser.
CLI quickstart
From any git checkout:
export PATCHLIGHT_API_KEY=pl_sk_...
npx @patchlight/sdk review --wait --fail-on highThe CLI auto-detects the base branch (from CI environment variables when available), runs
git diff, uploads changed-file contents as context, prints the findings, and exits non-zero
when findings at or above the --fail-on severity exist.
| Exit code | Meaning |
|-----------|---------|
| 0 | Clean, or nothing at/above --fail-on |
| 1 | Findings at or above the threshold |
| 2 | Review or scan failed, timed out, or was skipped |
| 3 | Usage/authentication error |
| 4 | Transient (workspace busy, platform briefly unavailable) — safe to retry |
Commands
| Command | Description |
|---------|-------------|
| patchlight review | Submit the current git diff for review |
| patchlight status <reviewId> | Status, summary and findings of a review |
| patchlight scan <repo> | Start a security scan of a connected GitHub repo |
| patchlight scan-status <scanId> | Status, cost and findings of a scan |
| patchlight finding <id> --status <s> | Triage a finding: open/resolved/dismissed |
| patchlight repos / reviews / findings / balance | Workspace listings |
| patchlight whoami | Which credential is in use, and its balance |
| patchlight logout | Forget a stored patchlight login |
Security scans read a whole repository rather than a diff, so they require a repository connected through the GitHub App:
patchlight scan acme/checkout-service --wait --fail-on highTo scan the code on your disk right now — including uncommitted work, in a repo
that need not be connected to anything — use @patchlight/cli, which uploads a
bounded snapshot instead of asking the server to clone:
npx @patchlight/cli scan --diffExample: GitLab CI
code-review:
image: node:20
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
variables:
GIT_DEPTH: "0" # full history so git merge-base works
script:
- npx @patchlight/sdk review --wait --fail-on highSnippets for Bitbucket Pipelines, Azure Pipelines, GitHub Actions, and plain shell are in the CI/CD docs.
SDK quickstart
import { createClient } from "@patchlight/sdk";
const client = createClient({ apiKey: process.env.PATCHLIGHT_API_KEY! });
const { id } = await client.createReview({
repo: "acme/checkout-service",
diff: myUnifiedDiff,
files: { "src/payment.ts": paymentSource }, // optional context
});
const review = await client.waitForReview(id); // throws on failure/timeout
const { findings } = await client.getReviewFindings(id);Methods
| Method | Description |
|--------|-------------|
| createReview(input, options?) | Submit a diff for review → { id, status } |
| getReview(id) | Status, summary, error, timestamps |
| getReviewFindings(id) | { status, findings } |
| waitForReview(id, options?) | Poll until done; throws on failure/skip/timeout |
| startScan(repoId) | Start a security scan → { id, status } |
| getScan(id) / getScanFindings(id) | Scan status and vulnerabilities |
| waitForScan(id, options?) | Poll until done; throws on failure/timeout |
| updateFinding(id, status) | Triage: "open" / "resolved" / "dismissed" |
| getBalance() / listRepos() / listReviews() / listFindings() | Read helpers |
All failures throw PatchlightError with a .code and .status, plus .retryAfterSeconds on
429. GET requests are retried on network errors and 5xx; createReview is retried only when an
idempotencyKey makes the replay safe, and startScan is never retried (the API dedupes
concurrent scans with already_running).
Timestamps are ISO-8601 strings, not epoch numbers — parse with
new Date(value). Versions before 0.2.0 typed them asnumber, which did not match what the API returned.
Configuration
| | Option | Environment variable |
|-|--------|----------------------|
| API key | apiKey | PATCHLIGHT_API_KEY (CLI) |
| API origin | baseUrl | PATCHLIGHT_BASE_URL |
Documentation
Full guides and API reference: https://patchlight.dev/docs/sdk
License
MIT
