TypeScript SDK

TypeScript SDK for the FastVM microVM platform. Launch, snapshot, restore, and run commands on microVMs over a multiplexed HTTP/2 connection.

Installation

shell
npm install @fastvm/sdk

Quick Start

Set your API key, then create a client:

typescript
import { FastVM } from "@fastvm/sdk";

const client = new FastVM({ apiKey: "your-key" });
await client.warmup();

const vm = await client.launch({ machine: "c1m2" });
const snapshot = await client.snapshot(vm, { name: "my-snap" });
const restored = await client.restore(snapshot);
const result = await client.run(restored, "echo hello");

console.log(result.stdout); // hello

client.close();

launch, restore, and snapshot all block until the resource is ready. The client pre-establishes an HTTP/2 connection on warmup() so that all subsequent calls reuse a single multiplexed TLS session with zero additional handshake cost. If name is omitted, a UUID is generated automatically.

Configuration

The SDK reads environment variables when constructor options are not provided:

VariableRequiredDefaultDescription
FASTVM_API_KEYYesAPI key for authentication
FASTVM_BASE_URLNohttps://api.fastvm.orgAPI base URL

You can also pass credentials explicitly:

typescript
const client = new FastVM({ apiKey: "your-key", baseUrl: "https://api.fastvm.org" });

new FastVM()

new FastVM(opts?: {
  apiKey?: string;
  baseUrl?: string;
  timeout?: number; // milliseconds, default 300_000
})

Creates a new SDK client. Uses HTTP/2 for multiplexed connections. Call warmup() to pre-establish the connection, and close() when done:

typescript
const client = new FastVM();
await client.warmup();
// ... use the client ...
client.close();

VM Management

client.launch()

async launch(opts?: {
  machine?: MachineType; // default "c1m2"
  name?: string;
  diskGib?: number;
  firewall?: FirewallPolicy;
  timeout?: number;
}): Promise<VM>

Description

Launch a new microVM and wait until it is ready.

Parameters

ParamTypeDefaultDescription
machineMachineType"c1m2"Machine type — c{vCPUs}m{GiB RAM}. Options: "c1m2", "c2m4", "c4m8", "c8m16"
namestringundefinedVM name. Auto-generates UUID if omitted
diskGibnumberundefinedDisk size in GiB
firewallFirewallPolicyundefinedPublic IPv6 ingress firewall policy
timeoutnumber300_000Milliseconds to wait for 'running' status

Returns

Promise<VM>
FieldTypeDescription
idstringUnique VM identifier
namestringVM name
orgIdstringOrganization ID
machineNamestringMachine type name
cpunumberNumber of vCPUs
memoryMibnumberMemory in MiB
diskGibnumberDisk in GiB
statusVMStatusCurrent status ("provisioning", "running", "stopped", "deleting", "error")
createdAtstringISO 8601 creation timestamp
sourceNamestring | undefinedSource snapshot or image name
publicIpv6string | undefinedPublic IPv6 address if assigned
firewallFirewallPolicy | undefinedFirewall policy if configured
deletedAtstring | undefinedDeletion timestamp

Example

typescript
const vm = await client.launch({ machine: "c2m4", name: "my-vm", diskGib: 20 });

client.restore()

async restore(
  snapshot: string | Snapshot,
  opts?: {
    name?: string;
    firewall?: FirewallPolicy;
    timeout?: number;
  },
): Promise<VM>

Description

Restore a VM from a snapshot and wait until it is ready.

Parameters

ParamTypeDefaultDescription
snapshotstring | SnapshotSnapshot ID or Snapshot object
namestringundefinedVM name. Auto-generates UUID if omitted
firewallFirewallPolicyundefinedOverride the snapshot's firewall policy
timeoutnumber300_000Milliseconds to wait

Returns

Promise<VM>
FieldTypeDescription
idstringUnique VM identifier
namestringVM name
orgIdstringOrganization ID
machineNamestringMachine type name
cpunumberNumber of vCPUs
memoryMibnumberMemory in MiB
diskGibnumberDisk in GiB
statusVMStatusCurrent status ("provisioning", "running", "stopped", "deleting", "error")
createdAtstringISO 8601 creation timestamp
sourceNamestring | undefinedSource snapshot or image name
publicIpv6string | undefinedPublic IPv6 address if assigned
firewallFirewallPolicy | undefinedFirewall policy if configured
deletedAtstring | undefinedDeletion timestamp

Example

typescript
const restored = await client.restore(snapshot, { name: "worker-01" });

client.get()

async get(vm: string | VM): Promise<VM>

Description

Fetch the current state of a VM.

Parameters

ParamTypeDefaultDescription
vmstring | VMVM ID or VM object

Returns

Promise<VM>
FieldTypeDescription
idstringUnique VM identifier
namestringVM name
orgIdstringOrganization ID
machineNamestringMachine type name
cpunumberNumber of vCPUs
memoryMibnumberMemory in MiB
diskGibnumberDisk in GiB
statusVMStatusCurrent status ("provisioning", "running", "stopped", "deleting", "error")
createdAtstringISO 8601 creation timestamp
sourceNamestring | undefinedSource snapshot or image name
publicIpv6string | undefinedPublic IPv6 address if assigned
firewallFirewallPolicy | undefinedFirewall policy if configured
deletedAtstring | undefinedDeletion timestamp

client.list()

async list(): Promise<VM[]>

Description

List all VMs in the organization.

Returns

Promise<VM[]>
FieldTypeDescription
idstringUnique VM identifier
namestringVM name
orgIdstringOrganization ID
machineNamestringMachine type name
cpunumberNumber of vCPUs
memoryMibnumberMemory in MiB
diskGibnumberDisk in GiB
statusVMStatusCurrent status ("provisioning", "running", "stopped", "deleting", "error")
createdAtstringISO 8601 creation timestamp
sourceNamestring | undefinedSource snapshot or image name
publicIpv6string | undefinedPublic IPv6 address if assigned
firewallFirewallPolicy | undefinedFirewall policy if configured
deletedAtstring | undefinedDeletion timestamp

client.remove()

async remove(vm: string | VM): Promise<void>

Description

Delete a VM.

Parameters

ParamTypeDefaultDescription
vmstring | VMVM ID or VM object

client.rename()

async rename(vm: string | VM, name: string): Promise<VM>

Description

Rename a VM.

Parameters

ParamTypeDefaultDescription
vmstring | VMVM ID or VM object
namestringNew name for the VM

Returns

Promise<VM>
FieldTypeDescription
idstringUnique VM identifier
namestringVM name
orgIdstringOrganization ID
machineNamestringMachine type name
cpunumberNumber of vCPUs
memoryMibnumberMemory in MiB
diskGibnumberDisk in GiB
statusVMStatusCurrent status ("provisioning", "running", "stopped", "deleting", "error")
createdAtstringISO 8601 creation timestamp
sourceNamestring | undefinedSource snapshot or image name
publicIpv6string | undefinedPublic IPv6 address if assigned
firewallFirewallPolicy | undefinedFirewall policy if configured
deletedAtstring | undefinedDeletion timestamp

Example

typescript
const vm = await client.rename(vm, "new-name");

client.setFirewall()

async setFirewall(vm: string | VM, policy: FirewallPolicy): Promise<VM>

Description

Replace the VM's public IPv6 ingress firewall policy.

Parameters

ParamTypeDefaultDescription
vmstring | VMVM ID or VM object
policyFirewallPolicyNew firewall policy

Returns

Promise<VM>
FieldTypeDescription
idstringUnique VM identifier
namestringVM name
orgIdstringOrganization ID
machineNamestringMachine type name
cpunumberNumber of vCPUs
memoryMibnumberMemory in MiB
diskGibnumberDisk in GiB
statusVMStatusCurrent status ("provisioning", "running", "stopped", "deleting", "error")
createdAtstringISO 8601 creation timestamp
sourceNamestring | undefinedSource snapshot or image name
publicIpv6string | undefinedPublic IPv6 address if assigned
firewallFirewallPolicy | undefinedFirewall policy if configured
deletedAtstring | undefinedDeletion timestamp

Example

typescript
const vm = await client.setFirewall(vm, { mode: "open" });

client.patchFirewall()

async patchFirewall(vm: string | VM, patch: PatchFirewallPolicy): Promise<VM>

Description

Partially update the VM's firewall. Only the provided fields are changed.

Parameters

ParamTypeDefaultDescription
vmstring | VMVM ID or VM object
patchPatchFirewallPolicyPartial firewall update (mode and/or ingress rules)

Returns

Promise<VM>
FieldTypeDescription
idstringUnique VM identifier
namestringVM name
orgIdstringOrganization ID
machineNamestringMachine type name
cpunumberNumber of vCPUs
memoryMibnumberMemory in MiB
diskGibnumberDisk in GiB
statusVMStatusCurrent status ("provisioning", "running", "stopped", "deleting", "error")
createdAtstringISO 8601 creation timestamp
sourceNamestring | undefinedSource snapshot or image name
publicIpv6string | undefinedPublic IPv6 address if assigned
firewallFirewallPolicy | undefinedFirewall policy if configured
deletedAtstring | undefinedDeletion timestamp

Example

typescript
const vm = await client.patchFirewall(vm, { mode: "restricted" });

Command Execution

client.run()

async run(
  vm: string | VM,
  command: string | string[],
  opts?: {
    timeoutSec?: number;
    timeout?: number;
    transientRetries?: number;
  },
): Promise<CommandResult>

Description

Execute a command on a VM. String commands are passed as a single argv element to sh -c; pass an array for an explicit argv.

Parameters

ParamTypeDefaultDescription
vmstring | VMVM ID or VM object
commandstring | string[]Shell command string or explicit argv array
timeoutSecnumberundefinedServer-side command timeout in seconds
timeoutnumberundefinedClient-side transport timeout in milliseconds (defaults to constructor timeout)
transientRetriesnumber3Retry count on transient HTTP errors (502/503/504)

Returns

Promise<CommandResult>
FieldTypeDescription
exitCodenumberProcess exit code
stdoutstringStandard output
stderrstringStandard error
timedOutbooleanWhether the command timed out
stdoutTruncatedbooleanWhether stdout was truncated
stderrTruncatedbooleanWhether stderr was truncated
durationMsnumberExecution time in milliseconds

Example

typescript
const result = await client.run(vm, "python3 --version");
console.log(result.stdout);     // Python 3.11.4
console.log(result.exitCode);   // 0
console.log(result.durationMs); // 42

Long-Running Tasks

client.run() is connection-bound — if the SDK disconnects or the transport timeout is reached, the command is killed. For tasks that must outlive the connection, detach them inside the VM.

Fire-and-forget with nohup

Use nohup to start a background process that survives disconnection:

typescript
// Start a long-running training job in the background
await client.run(vm, "nohup python3 train.py > /tmp/train.log 2>&1 &");

// Check on it later
const result = await client.run(vm, "tail -20 /tmp/train.log");
console.log(result.stdout);

Persistent sessions with tmux

Use tmux when you need to re-attach or inspect live output:

typescript
// Start a tmux session with the long-running task
await client.run(vm, "tmux new-session -d -s train 'python3 train.py'");

// Capture output later
const result = await client.run(vm, "tmux capture-pane -t train -p");
console.log(result.stdout);
PatternUse when
client.run(vm, cmd)Commands that finish within the transport timeout
nohup cmd &Fire-and-forget background jobs
tmux / screenNeed to re-attach or inspect live output

Snapshots

client.snapshot()

async snapshot(
  vm: string | VM,
  opts?: {
    name?: string;
    timeout?: number;
  },
): Promise<Snapshot>

Description

Create a snapshot of a running VM. Blocks until the snapshot is ready.

Parameters

ParamTypeDefaultDescription
vmstring | VMVM to snapshot
namestringundefinedSnapshot name. Auto-generates UUID if omitted
timeoutnumber300_000Milliseconds to wait

Returns

Promise<Snapshot>
FieldTypeDescription
idstringUnique snapshot identifier
namestringSnapshot name
orgIdstringOrganization ID
vmIdstringSource VM ID
statusSnapshotStatusCurrent status ("creating", "ready", "error")
createdAtstringISO 8601 creation timestamp
firewallFirewallPolicy | undefinedFirewall policy from the source VM

Example

typescript
const snap = await client.snapshot(vm, { name: "before-deploy" });

client.listSnapshots()

async listSnapshots(): Promise<Snapshot[]>

Description

List all snapshots in the organization.

Returns

Promise<Snapshot[]>
FieldTypeDescription
idstringUnique snapshot identifier
namestringSnapshot name
orgIdstringOrganization ID
vmIdstringSource VM ID
statusSnapshotStatusCurrent status ("creating", "ready", "error")
createdAtstringISO 8601 creation timestamp
firewallFirewallPolicy | undefinedFirewall policy from the source VM

client.removeSnapshot()

async removeSnapshot(snapshot: string | Snapshot): Promise<void>

Description

Delete a snapshot.

Parameters

ParamTypeDefaultDescription
snapshotstring | SnapshotSnapshot ID or object

client.renameSnapshot()

async renameSnapshot(snapshot: string | Snapshot, name: string): Promise<Snapshot>

Description

Rename a snapshot.

Parameters

ParamTypeDefaultDescription
snapshotstring | SnapshotSnapshot ID or object
namestringNew name for the snapshot

Returns

Promise<Snapshot>
FieldTypeDescription
idstringUnique snapshot identifier
namestringSnapshot name
orgIdstringOrganization ID
vmIdstringSource VM ID
statusSnapshotStatusCurrent status ("creating", "ready", "error")
createdAtstringISO 8601 creation timestamp
firewallFirewallPolicy | undefinedFirewall policy from the source VM

Example

typescript
const snap = await client.renameSnapshot(snap, "v2-stable");

Firewall

VMs support public IPv6 ingress firewall policies. Pass a FirewallPolicy to launch() or restore() to configure which ports are open:

typescript
import { FastVM } from "@fastvm/sdk";
import type { FirewallPolicy } from "@fastvm/sdk";

const client = new FastVM();
await client.warmup();

const policy: FirewallPolicy = {
  mode: "restricted",
  ingress: [
    { protocol: "tcp", portStart: 22, description: "SSH" },
    { protocol: "tcp", portStart: 8080, description: "HTTP" },
  ],
};
const vm = await client.launch({ firewall: policy });

FirewallPolicy

FieldTypeDescription
mode"open" | "restricted"Firewall mode
ingressFirewallRule[] | undefinedList of ingress allow rules

FirewallRule

FieldTypeDescription
protocolstring"tcp" or "udp"
portStartnumberStart of port range
portEndnumber | undefinedEnd of port range (undefined = single port)
sourceCidrsstring[] | undefinedAllowed source CIDRs (empty = any)
descriptionstring | undefinedHuman-readable description

PatchFirewallPolicy

FieldTypeDescription
mode"open" | "restricted" | undefinedFirewall mode to set (undefined = unchanged)
ingressFirewallRule[] | undefinedIngress rules to set (undefined = unchanged)

Quotas

client.quotas()

async quotas(): Promise<OrgQuotaUsage>

Description

Fetch organization quota limits and current usage.

Returns

Promise<OrgQuotaUsage>
FieldTypeDescription
orgIdstringOrganization ID
limitsOrgQuotaValuesMaximum allowed resources
usageOrgQuotaValuesCurrently consumed resources

Example

typescript
const usage = await client.quotas();
console.log(`vCPUs: ${usage.usage.vcpu} / ${usage.limits.vcpu}`);

OrgQuotaUsage

FieldTypeDescription
orgIdstringOrganization ID
limitsOrgQuotaValuesMaximum allowed resources
usageOrgQuotaValuesCurrently consumed resources

OrgQuotaValues

FieldTypeDescription
vcpunumberNumber of vCPUs
memoryMibnumberMemory in MiB
diskGibnumberDisk in GiB
snapshotCountnumberNumber of snapshots

Branching

Branching is implemented via snapshot + restore. Snapshot a VM, then restore it as many times as needed — concurrently with Promise.all:

typescript
// Create a branching point
const snap = await client.snapshot(baseVm, { name: "branch-point" });

// Fork into 10 parallel paths
const branches = await Promise.all(
  Array.from({ length: 10 }, (_, i) =>
    client.restore(snap, { name: `branch-${i}` }),
  ),
);

// Run different strategies in parallel
const results = await Promise.all(
  branches.map((branch, i) =>
    client.run(branch, `python3 solve.py --seed=${i}`),
  ),
);

// Pick the winner
const best = results.reduce((a, b) => (a.durationMs < b.durationMs ? a : b));