quilt-sdk
v0.1.0
Published
Fully type-safe TypeScript SDK for Quilt HTTP APIs
Readme
quilt-sdk
Type-safe TypeScript SDK for Quilt production APIs.
quilt-sdk is the programmatic client for the live Quilt backend. It is intended to be the typed source of truth for production automation, not a thin convenience wrapper around ad hoc fetch calls.
Install
npm install quilt-sdkLocal package install exposes the SDK CLI through npx quilt and npx quilt-sdk.
or
bun add quilt-sdkGlobal install exposes the same CLI directly:
npm install -g quilt-sdk
quilt healthRequirements
- Node
>=20.10.0 - Quilt backend URL, usually
https://backend.quilt.sh - either
QUILT_API_KEYorQUILT_JWT
Local Development
The SDK repo builds standalone. Type generation and normal package validation use the bundled contract snapshot at contracts/API_CONTRACT.json; they do not require a sibling quilt-prod checkout.
Optional overrides:
QUILT_API_CONTRACT_PATHto generate from a different OpenAPI contract fileQUILT_BACKEND_REPOto run the stronger backend parity audit against a live backend repo checkout
Quick Start
import { QuiltClient } from "quilt-sdk";
const client = QuiltClient.connect({
baseUrl: process.env.QUILT_BASE_URL ?? "https://backend.quilt.sh",
apiKey: process.env.QUILT_API_KEY,
});
const health = await client.system.health();
const containers = await client.containers.list();
console.log(health.status);
console.log(containers.containers.length);Auth
QuiltClient.connect() accepts:
apiKeyforX-Api-Keytokenfor bearer authauthfor the explicit auth union when you need to control the transport directly
If both apiKey and token are provided, API key auth wins.
Core Client Shape
import { QuiltClient } from "quilt-sdk";
const client = QuiltClient.connect({
baseUrl: "https://backend.quilt.sh",
apiKey: process.env.QUILT_API_KEY,
});Primary SDK surfaces:
client.systemfor health, info, and activityclient.accountfor user profile, password, avatar, 2FA, and notification preferencesclient.billingfor plans, subscriptions, payment methods, invoices, checkout, portal, and usageclient.cleanupfor tenant and container cleanup status and task inspectionclient.containersfor container lifecycle, exec, logs, metrics, network, ICC, cleanup, and GUI URLsclient.dnsfor DNS entry lifecycleclient.k8sfor validate, diff, apply, status, resource, and export flowsclient.platformfor cross-cutting routes such as operations, env maps, archives, ICC, OCI, and helper control flowsclient.imagesfor OCI pull, inspect, history, remove, build-context upload, and OCI image buildsclient.servicesfor published service lifecycleclient.snapshotsfor snapshot lifecycle, lineage, pinning, and tenant-scoped readsclient.volumesfor volume lifecycle, browsing, and batch file flowsclient.clustersfor cluster, node, workload, placement, and join-token control-plane flowsclient.agentfor join-token and node-token authenticated agent callsclient.functionsfor serverless lifecycle, invoke, versions, source, simulation, invocations, graph, and pool statusclient.gpufor qgpu release download, GPU connection initialization/completion, and active connection statusclient.elasticityfor resize, pool targeting, and orchestrator-safe control actionsclient.monitorsfor monitor reads and system metricsclient.containerStreamsfor live non-PTY command output streaming over NDJSONclient.terminalandclient.terminalRealtimefor terminal session lifecycle and WebSocket attachclient.eventsfor SSE streamsclient.raw(...)for authenticated access to backend routes that are intentionally still exposed as raw contract calls
Docker-Compatible Images
Quilt supports Docker-compatible registry image ingress through the OCI image routes and normal container create.
That means:
- pull an image from Docker Hub or another OCI-compatible registry
- inspect or list the stored image metadata
- create a container from that pulled image with
oci: true
This is image compatibility, not Docker Engine API compatibility.
Registry pull:
const pulled = await client.platform.ociPull({
reference: "docker.io/library/alpine:3.20",
});Create from the pulled image:
const accepted = await client.containers.create(
{
name: "oci-demo",
image: "docker.io/library/alpine:3.20",
oci: true,
command: ["sleep", "60"],
},
"async",
);Build a local Docker context into Quilt's OCI store:
import { readFile } from "node:fs/promises";
import { QuiltClient } from "quilt-sdk";
const client = QuiltClient.connect({
baseUrl: process.env.QUILT_BASE_URL ?? "https://backend.quilt.sh",
apiKey: process.env.QUILT_API_KEY,
});
const upload = await client.images.uploadBuildContext(
(await readFile("./context.tar.gz")).toString("base64"),
);
const accepted = await client.images.build({
context_id: upload.context_id,
image_reference: "docker.io/acme/my-app:latest",
dockerfile_path: "Dockerfile",
});CLI
The npm package now ships a CLI backed by the same SDK client.
Examples:
npx quilt --api-key "$QUILT_API_KEY" health
npx quilt --api-key "$QUILT_API_KEY" gpu init
npx quilt --api-key "$QUILT_API_KEY" gpu connect --qgpu-path "$HOME/.local/bin/qgpu"
npx quilt --api-key "$QUILT_API_KEY" oci pull --reference docker.io/library/alpine:3.20
npx quilt --api-key "$QUILT_API_KEY" build --context . --dockerfile Dockerfile --tag docker.io/acme/my-app:latest
npx quilt --api-key "$QUILT_API_KEY" container create --image docker.io/acme/my-app:latest --oci --wait -- sleep 60
npx quilt --api-key "$QUILT_API_KEY" stream ctr_123 -- /bin/sh -lc 'echo hello && echo warn 1>&2'Public Types
The SDK ships declarations automatically through the package export.
Use the client-owned type surface when you need explicit types:
import { QuiltClient } from "quilt-sdk";
const options: QuiltClient.Options = {
baseUrl: "https://backend.quilt.sh",
apiKey: process.env.QUILT_API_KEY,
};
let invocation: QuiltClient.Functions.Invocation | null = null;
let resize: QuiltClient.Elasticity.ContainerResizeResponse | null = null;That keeps consumer imports simple while still exposing the production contract.
Execution Model
Use the SDK in the same execution style the backend expects:
- treat container lifecycle mutations as operation-driven when they return operation metadata
- treat exec as submit-and-track, not inline command execution
- treat
client.containerStreams.open(...)as the live non-PTY command output surface - use terminal attach and WebSocket flows for interactive sessions
- invoke a shell explicitly when shell parsing is required
- prefer typed module methods over
client.raw(...)
Recent contract-alignment details now reflected in the SDK:
client.containers.create()andcreateBatch()accept the full backend request shape, includinggpu_countandgpu_ids- snapshot responses include
source_container_namewhen the backend captured it at snapshot creation time client.platform.renameContainer(...)sends backend-correctnew_name- tenant-scoped snapshot and fork routes require
X-Tenant-Id; typed snapshot and fork helpers now accept explicit tenant headers - elasticity control mutation helpers require the full control header set:
X-Tenant-Id,Idempotency-Key, andX-Orch-Action-Id - workload function-binding control writes return an elasticity operation envelope; the current binding is under
result
Realtime
SSE
const source = client.events.openEventSource();
client.events.on(source, "container_update", (event) => {
console.log(event.data);
});WebSocket Terminal
const ws = client.terminalRealtime.connect({
container_identifier: "ctr_123",
cols: 120,
rows: 30,
});
ws.addEventListener("message", (msg) => {
if (typeof msg.data === "string") {
const parsed = client.terminalRealtime.parseServerMessage(msg.data);
console.log(parsed);
}
});Container Stream NDJSON
const frames = await client.containerStreams.open("ctr_123", {
command: ["/bin/sh", "-lc", "echo hello && echo warn 1>&2"],
timeout_ms: 30_000,
});
for await (const frame of frames) {
if (frame.type === "stdout") {
process.stdout.write(Buffer.from(frame.data_b64, "base64"));
}
if (frame.type === "stderr") {
process.stderr.write(Buffer.from(frame.data_b64, "base64"));
}
}Examples
The repository ships a production-validated example set in examples/.
Example files:
examples/containers-volumes-and-network.tsexamples/docker-and-oci-images.tsexamples/sdk-runtime-and-functions.tsexamples/clusters-nodes-workloads-and-k8s.tsexamples/terminal-and-icc.tsexamples/container-stream.tsexamples/elasticity-control.tsexamples/lifecycle-and-failures.ts
The example guide is in examples/README.md.
Run them from the repo root:
bun run example:containers
bun run example:images
bun run example:sdk
bun run example:clusters
bun run example:terminal
bun run example:stream
bun run example:elasticity
bun run example:lifecycle
bun run examples:allExpected environment variables:
QUILT_BASE_URL=https://backend.quilt.sh
QUILT_API_KEY=<api_key>Alternative auth:
QUILT_JWT=<jwt>Repository Validation
bun run lint
bun run typecheck
node ./scripts/check-backend-parity.mjs
fozzy validate tests/fozzy/sdk_backend_parity.guard.fozzy.json
fozzy run tests/fozzy/sdk_backend_parity.guard.fozzy.json --json --proc-backend host --http-backend host --fs-backend host
bun run examples:typecheck
bun run test
bun run build
bun run examples:allprepublishOnly runs:
bun run clean
bun run lint
bun run typecheck
bun run examples:typecheck
bun run test
bun run buildPackage Contents
The published npm package includes:
- compiled runtime in
dist/ - generated
.d.tsdeclarations README.mdLICENSE
The repository also includes the example app and validation setup used to verify the SDK against production.
License
MIT
