Skip to content
Fuse
Esc
navigateopen⌘Jpreview
On this page

Environments

Provisioning, running commands in, and tearing down microVMs

client.environments provisions, inspects, drives, and tears down microVMs. Here’s a complete flow: create one, run a command inside it, then tear it down.

const env = await client.environments.create({
  task_id: "build-1",
  spec: { cpus: 2, ram_mb: 2048, storage_gb: 10 },
});

const result = await client.environments.exec(env.id, { cmd: ["make", "test"] });
if (result.exit_code !== 0) {
  throw new Error(`tests failed: ${result.stderr}`);
}

await client.environments.destroy(env.id);
  • create provisions from a spec (CPUs, RAM, storage, and optionally GPU) and blocks server-side until the environment is running or provisioning fails, so the returned EnvironmentInfo already reflects the outcome. No separate poll-until-ready step is needed for the common case. Wire field names are snake_case throughout, task_id/ram_mb, not taskId/ramMb. Spec carries gpus, gpu_kind, and gpu_profile, so fractional MIG environments can be requested type-safely from this SDK.
  • exec runs one command inside the guest and returns its exit code with stdout/stderr kept apart. A non-zero exit_code is a resolved call, not a thrown error, the command ran and failed, which is the answer you asked for. Only a thrown error means the command couldn’t run at all (VM not found, VM not running, or the provider has no guest to exec into). exec requires the master token, see Errors.
  • destroy tears the environment down from any state and is idempotent, a second call on an already-gone environment throws a FuseApiError with code === "not_found" rather than hanging or throwing something unrelated.

Watching state instead of exec

If you need to react to lifecycle transitions rather than run a one-shot command, events returns an async iterable instead of a single call:

for await (const event of await client.environments.events(env.id)) {
  console.log(event.state);
}

The stream yields the current state immediately on connect, then one item per transition, and ends on its own after a terminal-state event (destroyed/failed). There is no built-in timeout, pass { signal } to cancel early. See the full walkthrough in Quickstart.

Everything else

Method Purpose
list({ taskId, state, hostId }) List environments, all filters optional.
get(vmId) Fetch one environment by ID.
drain(vmId) Phase one of teardown: signal the guest to stop gracefully without destroying the VM.
fork(vmId, { reuse_snapshot_id, comment }) Create a new environment seeded from a snapshot of this one.
rotateToken(vmId) Re-issue the guest’s credentials without recreating the VM.

The two option bags differ in case on purpose. list takes a client-side filter object, so it is camelCase; fork sends its object straight through as the JSON request body, so it uses the snake_case wire names.

Every method accepts a trailing { signal } for cancellation. Fork is unavailable wherever snapshotting is, GPU/QEMU-backed environments can’t be forked, see Providers. These mirror the HTTP API one to one.

Lifecycle states

export const State = {
  Provisioning: "provisioning",
  Running: "running",
  Draining: "draining",
  Destroying: "destroying",
  Destroyed: "destroyed",
  Failed: "failed",
} as const;

function isTerminalState(state: string): boolean;

isTerminalState reports whether state is Destroyed or Failed, the two states after which an event stream ends.

Was this page helpful?