Skip to content

TypeScript SDK

One package, promigence, the CLI and the SDK together, with two surfaces: a native client, and a compatibility Sandbox class with the familiar sandbox calls, so most existing code keeps working after a one-line import change.

Terminal
npm i ./promigence-<version>.tgz   # the file we sent you; not on npm yet
Language: bash

The native client

Three calls cover a run: quote, fan out, read the report.

Quote, run, report
TypeScript
import { PromigenceClient } from "promigence";

const client = new PromigenceClient(); // reads PROMIGENCE_API_KEY, or the key signup stored

// 1, know the ceiling first (the snapshot from the quickstart)
const quote = await client.runs.quote({ snapshot: "myapp", count: 20 });
console.log(quote.max_cost); // 0.828: 20 small sandboxes for their whole 15 minutes

// 2, fan out under a hard cap
const run = await client.runs.start({
  snapshot: "myapp",
  count: 20,
  spendCap: 1,
  verifyEach: true,
  exec: { sh: "cd /work/repo && npm test" },
});

// 3, the number about your environments
await client.runs.waitDone(run.run_id);
const report = await client.runs.report(run.run_id);
console.log(report.totals.env_verified);
console.log(report.totals.env_failed);   // ← ours
console.log(report.totals.task_failed);  // ← yours
console.log(report.cost?.charged);       // what was billed, never more than the cap
Language: typescript

Drop-in compatibility

Reimplemented from published typings. No third-party source, nothing proxied: migrating should be an import change, not a project.

Existing sandbox call sites
TypeScript
// Familiar sandbox calls keep working: create, commands.run, files and kill
// behave as you expect, so a migration is one import line and an API key,
// not a rewrite.
import { Sandbox } from "promigence";

// A snapshot, not a template: the environment was built and verified once, and
// this is that exact filesystem. `spendCap` sets the ceiling; without it your
// organisation's default applies.
const sandbox = await Sandbox.create("myapp", { spendCap: 1 });

await sandbox.files.write("/tmp/patch.diff", patch);
const res = await sandbox.commands.run("cd /work/repo && git apply /tmp/patch.diff && npm test");

console.log(res.exitCode, res.stdout);

// Still verified? The same integrity probe we use to decide whether a failure
// was ours or yours, asked before you spend the episode, not after.
const { ok, first_bad_path } = await sandbox.probe();

await sandbox.kill();   // the clock stops here: billing is per second
Language: typescript

Where a method would hand you an unverified box, the SDK throws and names the alternative rather than quietly doing something else.

Errors carry a fix

Every error has a stable code, an HTTP status, an exit code and a fix string. An error an agent cannot act on becomes a retry loop.

Structured failure
TypeScript
import { PromigenceError } from "promigence";

try {
  await client.runs.start({ snapshot: "myapp", count: 20, spendCap: 0.5 });
} catch (e) {
  if (e instanceof PromigenceError) {
    console.error(e.code);     // "cap_exceeded"
    console.error(e.message);  // "quote $0.83 exceeds remaining spend cap $0.50"
    console.error(e.fix);      // every error carries a fix, it is not optional
    console.error(e.exitCode); // 5
  }
}
Language: typescript

Join the waitlist

Promigence is in private beta. Leave your work email and we will send an invite as places open.