TypeScript SDK
TypeScript SDK for the FastVM microVM platform. Launch, snapshot, restore, and run commands on microVMs over a multiplexed HTTP/2 connection.
Installation
npm install @fastvm/sdkQuick Start
Set your API key, then create a client:
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:
| Variable | Required | Default | Description |
|---|---|---|---|
| FASTVM_API_KEY | Yes | — | API key for authentication |
| FASTVM_BASE_URL | No | https://api.fastvm.org | API base URL |
You can also pass credentials explicitly:
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:
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
| Param | Type | Default | Description |
|---|---|---|---|
| machine | MachineType | "c1m2" | Machine type — c{vCPUs}m{GiB RAM}. Options: "c1m2", "c2m4", "c4m8", "c8m16" |
| name | string | undefined | VM name. Auto-generates UUID if omitted |
| diskGib | number | undefined | Disk size in GiB |
| firewall | FirewallPolicy | undefined | Public IPv6 ingress firewall policy |
| timeout | number | 300_000 | Milliseconds to wait for 'running' status |
Returns
Promise<VM>
| Field | Type | Description |
|---|---|---|
| id | string | Unique VM identifier |
| name | string | VM name |
| orgId | string | Organization ID |
| machineName | string | Machine type name |
| cpu | number | Number of vCPUs |
| memoryMib | number | Memory in MiB |
| diskGib | number | Disk in GiB |
| status | VMStatus | Current status ("provisioning", "running", "stopped", "deleting", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| sourceName | string | undefined | Source snapshot or image name |
| publicIpv6 | string | undefined | Public IPv6 address if assigned |
| firewall | FirewallPolicy | undefined | Firewall policy if configured |
| deletedAt | string | undefined | Deletion timestamp |
Example
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
| Param | Type | Default | Description |
|---|---|---|---|
| snapshot | string | Snapshot | — | Snapshot ID or Snapshot object |
| name | string | undefined | VM name. Auto-generates UUID if omitted |
| firewall | FirewallPolicy | undefined | Override the snapshot's firewall policy |
| timeout | number | 300_000 | Milliseconds to wait |
Returns
Promise<VM>
| Field | Type | Description |
|---|---|---|
| id | string | Unique VM identifier |
| name | string | VM name |
| orgId | string | Organization ID |
| machineName | string | Machine type name |
| cpu | number | Number of vCPUs |
| memoryMib | number | Memory in MiB |
| diskGib | number | Disk in GiB |
| status | VMStatus | Current status ("provisioning", "running", "stopped", "deleting", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| sourceName | string | undefined | Source snapshot or image name |
| publicIpv6 | string | undefined | Public IPv6 address if assigned |
| firewall | FirewallPolicy | undefined | Firewall policy if configured |
| deletedAt | string | undefined | Deletion timestamp |
Example
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
| Param | Type | Default | Description |
|---|---|---|---|
| vm | string | VM | — | VM ID or VM object |
Returns
Promise<VM>
| Field | Type | Description |
|---|---|---|
| id | string | Unique VM identifier |
| name | string | VM name |
| orgId | string | Organization ID |
| machineName | string | Machine type name |
| cpu | number | Number of vCPUs |
| memoryMib | number | Memory in MiB |
| diskGib | number | Disk in GiB |
| status | VMStatus | Current status ("provisioning", "running", "stopped", "deleting", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| sourceName | string | undefined | Source snapshot or image name |
| publicIpv6 | string | undefined | Public IPv6 address if assigned |
| firewall | FirewallPolicy | undefined | Firewall policy if configured |
| deletedAt | string | undefined | Deletion timestamp |
client.list()
async list(): Promise<VM[]>
Description
List all VMs in the organization.
Returns
Promise<VM[]>
| Field | Type | Description |
|---|---|---|
| id | string | Unique VM identifier |
| name | string | VM name |
| orgId | string | Organization ID |
| machineName | string | Machine type name |
| cpu | number | Number of vCPUs |
| memoryMib | number | Memory in MiB |
| diskGib | number | Disk in GiB |
| status | VMStatus | Current status ("provisioning", "running", "stopped", "deleting", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| sourceName | string | undefined | Source snapshot or image name |
| publicIpv6 | string | undefined | Public IPv6 address if assigned |
| firewall | FirewallPolicy | undefined | Firewall policy if configured |
| deletedAt | string | undefined | Deletion timestamp |
client.remove()
async remove(vm: string | VM): Promise<void>
Description
Delete a VM.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| vm | string | VM | — | VM ID or VM object |
client.rename()
async rename(vm: string | VM, name: string): Promise<VM>
Description
Rename a VM.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| vm | string | VM | — | VM ID or VM object |
| name | string | — | New name for the VM |
Returns
Promise<VM>
| Field | Type | Description |
|---|---|---|
| id | string | Unique VM identifier |
| name | string | VM name |
| orgId | string | Organization ID |
| machineName | string | Machine type name |
| cpu | number | Number of vCPUs |
| memoryMib | number | Memory in MiB |
| diskGib | number | Disk in GiB |
| status | VMStatus | Current status ("provisioning", "running", "stopped", "deleting", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| sourceName | string | undefined | Source snapshot or image name |
| publicIpv6 | string | undefined | Public IPv6 address if assigned |
| firewall | FirewallPolicy | undefined | Firewall policy if configured |
| deletedAt | string | undefined | Deletion timestamp |
Example
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
| Param | Type | Default | Description |
|---|---|---|---|
| vm | string | VM | — | VM ID or VM object |
| policy | FirewallPolicy | — | New firewall policy |
Returns
Promise<VM>
| Field | Type | Description |
|---|---|---|
| id | string | Unique VM identifier |
| name | string | VM name |
| orgId | string | Organization ID |
| machineName | string | Machine type name |
| cpu | number | Number of vCPUs |
| memoryMib | number | Memory in MiB |
| diskGib | number | Disk in GiB |
| status | VMStatus | Current status ("provisioning", "running", "stopped", "deleting", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| sourceName | string | undefined | Source snapshot or image name |
| publicIpv6 | string | undefined | Public IPv6 address if assigned |
| firewall | FirewallPolicy | undefined | Firewall policy if configured |
| deletedAt | string | undefined | Deletion timestamp |
Example
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
| Param | Type | Default | Description |
|---|---|---|---|
| vm | string | VM | — | VM ID or VM object |
| patch | PatchFirewallPolicy | — | Partial firewall update (mode and/or ingress rules) |
Returns
Promise<VM>
| Field | Type | Description |
|---|---|---|
| id | string | Unique VM identifier |
| name | string | VM name |
| orgId | string | Organization ID |
| machineName | string | Machine type name |
| cpu | number | Number of vCPUs |
| memoryMib | number | Memory in MiB |
| diskGib | number | Disk in GiB |
| status | VMStatus | Current status ("provisioning", "running", "stopped", "deleting", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| sourceName | string | undefined | Source snapshot or image name |
| publicIpv6 | string | undefined | Public IPv6 address if assigned |
| firewall | FirewallPolicy | undefined | Firewall policy if configured |
| deletedAt | string | undefined | Deletion timestamp |
Example
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
| Param | Type | Default | Description |
|---|---|---|---|
| vm | string | VM | — | VM ID or VM object |
| command | string | string[] | — | Shell command string or explicit argv array |
| timeoutSec | number | undefined | Server-side command timeout in seconds |
| timeout | number | undefined | Client-side transport timeout in milliseconds (defaults to constructor timeout) |
| transientRetries | number | 3 | Retry count on transient HTTP errors (502/503/504) |
Returns
Promise<CommandResult>
| Field | Type | Description |
|---|---|---|
| exitCode | number | Process exit code |
| stdout | string | Standard output |
| stderr | string | Standard error |
| timedOut | boolean | Whether the command timed out |
| stdoutTruncated | boolean | Whether stdout was truncated |
| stderrTruncated | boolean | Whether stderr was truncated |
| durationMs | number | Execution time in milliseconds |
Example
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:
// 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:
// 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);
| Pattern | Use when |
|---|---|
| client.run(vm, cmd) | Commands that finish within the transport timeout |
| nohup cmd & | Fire-and-forget background jobs |
| tmux / screen | Need 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
| Param | Type | Default | Description |
|---|---|---|---|
| vm | string | VM | — | VM to snapshot |
| name | string | undefined | Snapshot name. Auto-generates UUID if omitted |
| timeout | number | 300_000 | Milliseconds to wait |
Returns
Promise<Snapshot>
| Field | Type | Description |
|---|---|---|
| id | string | Unique snapshot identifier |
| name | string | Snapshot name |
| orgId | string | Organization ID |
| vmId | string | Source VM ID |
| status | SnapshotStatus | Current status ("creating", "ready", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| firewall | FirewallPolicy | undefined | Firewall policy from the source VM |
Example
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[]>
| Field | Type | Description |
|---|---|---|
| id | string | Unique snapshot identifier |
| name | string | Snapshot name |
| orgId | string | Organization ID |
| vmId | string | Source VM ID |
| status | SnapshotStatus | Current status ("creating", "ready", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| firewall | FirewallPolicy | undefined | Firewall policy from the source VM |
client.removeSnapshot()
async removeSnapshot(snapshot: string | Snapshot): Promise<void>
Description
Delete a snapshot.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| snapshot | string | Snapshot | — | Snapshot ID or object |
client.renameSnapshot()
async renameSnapshot(snapshot: string | Snapshot, name: string): Promise<Snapshot>
Description
Rename a snapshot.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| snapshot | string | Snapshot | — | Snapshot ID or object |
| name | string | — | New name for the snapshot |
Returns
Promise<Snapshot>
| Field | Type | Description |
|---|---|---|
| id | string | Unique snapshot identifier |
| name | string | Snapshot name |
| orgId | string | Organization ID |
| vmId | string | Source VM ID |
| status | SnapshotStatus | Current status ("creating", "ready", "error") |
| createdAt | string | ISO 8601 creation timestamp |
| firewall | FirewallPolicy | undefined | Firewall policy from the source VM |
Example
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:
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
| Field | Type | Description |
|---|---|---|
| mode | "open" | "restricted" | Firewall mode |
| ingress | FirewallRule[] | undefined | List of ingress allow rules |
FirewallRule
| Field | Type | Description |
|---|---|---|
| protocol | string | "tcp" or "udp" |
| portStart | number | Start of port range |
| portEnd | number | undefined | End of port range (undefined = single port) |
| sourceCidrs | string[] | undefined | Allowed source CIDRs (empty = any) |
| description | string | undefined | Human-readable description |
PatchFirewallPolicy
| Field | Type | Description |
|---|---|---|
| mode | "open" | "restricted" | undefined | Firewall mode to set (undefined = unchanged) |
| ingress | FirewallRule[] | undefined | Ingress rules to set (undefined = unchanged) |
Quotas
client.quotas()
async quotas(): Promise<OrgQuotaUsage>
Description
Fetch organization quota limits and current usage.
Returns
Promise<OrgQuotaUsage>
| Field | Type | Description |
|---|---|---|
| orgId | string | Organization ID |
| limits | OrgQuotaValues | Maximum allowed resources |
| usage | OrgQuotaValues | Currently consumed resources |
Example
const usage = await client.quotas(); console.log(`vCPUs: ${usage.usage.vcpu} / ${usage.limits.vcpu}`);
OrgQuotaUsage
| Field | Type | Description |
|---|---|---|
| orgId | string | Organization ID |
| limits | OrgQuotaValues | Maximum allowed resources |
| usage | OrgQuotaValues | Currently consumed resources |
OrgQuotaValues
| Field | Type | Description |
|---|---|---|
| vcpu | number | Number of vCPUs |
| memoryMib | number | Memory in MiB |
| diskGib | number | Disk in GiB |
| snapshotCount | number | Number of snapshots |
Branching
Branching is implemented via snapshot + restore. Snapshot a VM, then restore it as many times as needed — concurrently with Promise.all:
// 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));