Machines
Create, get and list machines; drive their lifecycle; wait for a desktop; read the event log.
Create
const machine = await client.machines.create({ name: "research", size: "small" });machine = client.machines.create(name="research", size="small")name?string
Lowercase, digits and dashes. Generated when omitted.
stringsize?"small" | "standard" | "large"
A named size rather than free-form CPU and memory. The numbers behind each name are server-owned so they can change without a client release.
"small" | "standard" | "large""small"template?string
A template id to start from. The machine boots that template's captured disk. The template pins the image; the size is still this call's to choose.
stringimageId?string
TypeScript `imageId` / Python `image_id`.
stringregion?string
A placement hint.
stringmetadata?Record<string, string>
Caller-defined pairs, echoed back unchanged.
Record<string, string>start?boolean
Boot immediately. When false the machine is born `stopped`.
booleantrueidempotencyKey?string
TypeScript `idempotencyKey` / Python `idempotency_key`. Makes the call safe to retry.
stringRunning is not ready
create returns once the machine is running. A machine has a working shell before it has a
working desktop, so running says nothing about whether the screen routes will answer.
const display = await machine.waitForDesktop();
display.width;
display.height;display = machine.wait_for_desktop()
display["width"], display["height"]waitForDesktop polls the display until it reports up. Until then that route answers
compute_unavailable, which is a normal boot state to wait through rather than a failure — see
errors.
To wait on a state instead:
await machine.waitForState("stopped", { timeoutMs: 60_000 });
await machine.waitForState(["running", "error"]);machine.wait_for_state("stopped", timeout=60)
machine.wait_for_state(["running", "error"])error is a rest state and is returned rather than raised when you ask for it — which states
are acceptable is your decision, not the method’s. Ask for it and you get it; leave it out and it
throws.
Both take a timeout, a poll interval, and a cancellation handle (signal in TypeScript, cancel
in Python).
Get and list
const machine = await client.machines.get("mch_...");
for await (const m of client.machines.list({ state: "running" })) {
console.log(m.id, m.name);
}machine = client.machines.get("mch_...")
for m in client.machines.list(state="running"):
print(m.id, m.name)list filters on state and name, and walks every page for you. See
pagination.
Lifecycle
await machine.stop(); // keeps the disk
await machine.start();
await machine.restart();
await machine.refresh(); // replace the local snapshot with what the api reports
await machine.update({ name: "renamed", metadata: { owner: "ana" } });
await machine.delete(); // destroys the diskmachine.stop() # keeps the disk
machine.start()
machine.restart()
machine.refresh() # replace the local snapshot with what the api reports
machine.update(name="renamed", metadata={"owner": "ana"})
machine.delete() # destroys the diskA handle carries the last representation it saw. machine.id, machine.state and machine.name
read off it, and machine.data is the whole record. Nothing polls in the background, so a
state you read is a state the API actually reported — call refresh() when you want a newer one.
Starting is a normal boot, not a resume: nothing that was running survives a stop. See snapshots.
Events
for await (const event of machine.events()) {
console.log(event.type, event.created_at);
}for event in machine.events():
print(event["type"], event["created_at"])Newest first, cursor-paginated. The type list is a closed set — see machines for all nineteen. The same events stream live over the gateway’s events channel.
Cleaning up
await machine.close();with machine:
...
# or: machine.close()close releases the input lease and closes the session. Call
it. Without it the machine holds a lease until it expires and nobody else can type.
close does not stop or delete the machine — it stays running and keeps its disk.