lupe
Reference

SDK reference

Embed lupe in your own tools with the Promise-returning @gigadrive/lupe-sdk facade.

@gigadrive/lupe-sdk lets you run a lupe review from your own code β€” a build script, a bot, a custom CI step β€” and get back typed findings, a summary, and a cost breakdown. The surface is a plain Promise-based facade: you pass an options object and await a result.

Install

pnpm add @gigadrive/lupe-sdk

The package ships two functions:

  • reviewDiff(options) β€” review a raw unified diff string or a local git range.
  • reviewPullRequest(options) β€” fetch a GitHub PR diff, review it, and optionally post the review back.

Both return a ReviewResult (reviewPullRequest adds a posted flag).

The AI config

Every review needs an ai object describing which provider and models to use. This mirrors the ai section of .lupe.yaml.

FieldTypeNotes
provider'anthropic' | 'openai' | 'google' | 'bedrock' | 'openai-compatible' | 'gateway'Required.
apiKeystringFalls back to the provider's conventional env var when omitted.
baseURLstringRequired for openai-compatible; otherwise overrides a provider endpoint.
headersRecord<string, string>Extra request headers.
modelsPartial<Record<'triage' | 'review' | 'verify' | 'deep', string>>Per-task model id overrides. Only Anthropic ships built-in defaults; other providers must set the models they use.
regionstringAWS region for bedrock.
namestringDisplay name for openai-compatible.
disableToolsbooleanTurn off the agent's read-only repo tools (readFile/listDir/grep) for untrusted checkouts.

See providers and models for the full provider matrix.

reviewDiff(options)

Review a diff you already have, or a range in a local checkout.

OptionTypeNotes
aiLupeAiConfigRequired. See above.
rootDirstringWorking tree used for the agent's read-only tools. Default process.cwd().
diffstringA raw unified diff to review…
basestring…or the base ref of a local git range to diff.
headstringThe head ref of a local git range.
targetPartial<ReviewTarget>Extra target metadata (title, body, SHAs) merged into the review context.

Provide either diff (a raw unified diff string) or a base/head range against rootDir. All of the shared tuning knobs are also accepted.

reviewPullRequest(options)

Fetch a pull request's diff over the GitHub API, review it, and β€” when you opt in β€” post the result as one batched review with inline comments and a sticky summary.

In addition to ai, rootDir, and the shared tuning knobs:

OptionTypeNotes
github{ owner, repo, number, token, baseUrl? }Required. baseUrl targets GitHub Enterprise.
headShastringThe commit the review comments anchor to. Required for posting.
postbooleanPost the review back to the PR. Default false (review only).

Posting requires both post: true and a headSha. With either missing, the review runs but nothing is written to GitHub, and posted is false.

reviewPullRequest returns a ReviewResult extended with a posted: boolean.

ReviewResult

Both functions resolve to this shape:

FieldTypeNotes
findingsreadonly Finding[]The published findings after the grounding verifier and filter chain.
summaryMarkdownstringThe rendered review summary (Markdown).
costCostSummaryToken usage and USD cost, broken down byModel.
sarif()() => SarifLogRender the findings as a SARIF 2.1.0 log on demand.

Each Finding carries ruleId, title, path, startLine/endLine, side, severity, category, message, an optional suggestion, a confidence score, and grounding evidence. See findings and output for the full model and the SARIF shape.

cost reports { usage, costUsd, byModel }, where usage breaks down into inputTokens, outputTokens, cacheReadTokens, and cacheCreationTokens.

When the (compressed) diff has no reviewable files, the review short-circuits before any model call β€” so an empty diff is offline and free, returning zero findings and zero cost.

ReviewTuning

These knobs are shared by both functions and mirror the keys in .lupe.yaml. All are optional.

KnobTypeNotes
profile'chill' | 'assertive'Overall reviewer disposition.
maxFilesnumberCap the number of changed files reviewed.
maxFindingsnumberCap the number of published findings (most severe + confident first).
confidenceThresholdnumberGlobal confidence floor (0..1). Default 0.5.
categoryThresholdsPartial<Record<Category, { minConfidence?, minSeverity? }>>Per-category confidence/severity gates that override the global floor.
pathThresholds{ glob, minConfidence?, minSeverity? }[]Per-path-glob gates (highest precedence; last matching rule wins).
suppressAdvisorybooleanDrop advisory (style/maintainability/docs/test) findings entirely.
codingStandardsstringRepo conventions injected into the review prompt.
minSeverityToCommentSeverityPR posting only: less-severe findings stay summary-only.
verifybooleanRun the grounding verifier. Default true.
thoroughbooleanUse the strongest model and extra passes.
pathFiltersreadonly string[]Include/exclude globs applied to the diff.
maxChunkTokensnumberMax serialised-diff tokens per review pass (large-PR map-reduce). Default 120000.
maxChunksnumberHard ceiling on review passes; overflow is reported on the result, not dropped silently.
reviewConcurrencynumberBounded concurrency for the fan-out chunk passes. Default 3.
maxCostUsdnumberHard USD ceiling; over-budget runs reject before or mid the model calls.
modelPricesRecord<string, ModelPrice>Per-model price overrides (keyed by exact model id) for accurate cost on BYO endpoints.

Severity is one of critical, high, medium, low, info. Category is one of correctness, security, performance, concurrency, error-handling, resource-leak, api-misuse, data-loss, maintainability, style, test, docs. See cost and budget for how maxCostUsd and modelPrices interact.

Examples

Review a raw diff string

import { readFileSync } from 'node:fs';
import { reviewDiff } from '@gigadrive/lupe-sdk';

const diff = readFileSync('changes.diff', 'utf8');

const result = await reviewDiff({
  ai: {
    provider: 'anthropic',
    apiKey: process.env.ANTHROPIC_API_KEY,
  },
  diff,
  confidenceThreshold: 0.6,
  maxCostUsd: 1.5,
});

for (const finding of result.findings) {
  console.log(`[${finding.severity}] ${finding.path}:${finding.startLine} β€” ${finding.title}`);
}

console.log(`\n${result.findings.length} findings Β· $${result.cost.costUsd.toFixed(4)}`);

Review a pull request and post the result

import { reviewPullRequest } from '@gigadrive/lupe-sdk';

const result = await reviewPullRequest({
  ai: {
    provider: 'anthropic',
    apiKey: process.env.ANTHROPIC_API_KEY,
  },
  github: {
    owner: 'gigadrive',
    repo: 'lupe',
    number: 42,
    token: process.env.GITHUB_TOKEN!,
  },
  headSha: process.env.HEAD_SHA!,
  post: true,
  minSeverityToComment: 'medium',
});

console.log(`Posted: ${result.posted} Β· ${result.findings.length} findings`);
Posting is gated on both post: true and a headSha β€” the comments anchor to that commit. Omit either and the review still runs, but nothing is written to GitHub.

On this page