# Machines

A Quivvo machine is a Linux virtual machine in the cloud: a Firecracker microVM with its own kernel, root access, and a persistent disk at `/data`. Your home directory is `/data/home`. The default is 2 vCPUs and 4 GiB with a 10 GiB disk, in `ams` (Amsterdam), on the `universal` template, which has Docker.

## What states can a machine be in?

| State | What it means | What it costs |
| --- | --- | --- |
| `creating`, `starting` | On its way up | Disk only, until it's running |
| `running` | Working | CPU and memory per second, plus disk |
| `suspending`, `stopping` | On its way down | CPU and memory per second until the provider confirms it has stopped running, plus disk |
| `suspended` | Paused with memory and processes kept | Disk only |
| `stopped` | Shut down. Files kept, memory and processes gone; the next start boots fresh | Disk only |
| `failed` | Didn't boot, or crashed. `error` says why, and `quivvo logs` shows what's known. Restart it | Disk only |

Through the CLI and REST API, commands, files, jobs, connecting and the shell all wake a suspended or stopped machine. That restarts its bill, so the CLI and the answer say so. `quivvo logs`, `quivvo status`, `quivvo ps` and `quivvo history` don't wake it, and nor does a request to its public URL. The [MCP server's](https://tryquivvo.com/docs/mcp) read tools don't either.

## What does suspend actually do?

Suspend tries to keep memory and running processes. Our provider documents that up to 2 GB of memory, so it may not work on a 4 GiB machine. When it can't be done, the machine is stopped instead: the disk is kept, and memory and processes are lost.

Both count as success, and the API and CLI report which one happened:

- `suspend_outcome` on the machine is `suspended` or `stopped`.
- `resume_outcome` on the machine is what its last boot came back as: `resumed`, with memory back, or `cold_boot`, a fresh boot from the disk. A command that woke the machine has it on its own answer too, with a warning if it was a cold boot.

If your work depends on what's in memory, check those fields rather than assuming. Webhooks follow what really happened: you get `machine.stopped` for a suspend that became a stop.

## When does a machine suspend itself?

A machine with no commands, shells, tunnels or running background jobs for its auto-suspend time suspends itself, with the same fallback to a stop. The default is 30 minutes. Paid plans can turn it off; the Free plan goes up to 15 minutes and uses that by default. A running background job counts as activity, so a server started as a job keeps its machine awake and billing until the job ends. A job is killed at its timeout: 3600 seconds by default, and 86400 at most. So pass `--timeout 86400` for a server, and start it again when it ends.

To have a machine deleted whatever happens, create it with `--delete-after MIN` (`delete_after_minutes` in the API). `auto_delete_at` shows when.

## What is kept, and for how long?

Everything under `/data` survives stops, restarts and resizes. Snapshots copy the `/data` disk, and you can start new machines from them or restore one onto a machine.

Only `/data` is guaranteed. Packages installed with `apt-get` live on the root filesystem, which is meant to stay through stops and restarts. Snapshots and forks don't copy it, and a copy doesn't run the original's setup script. Restoring a snapshot, or a move to another host, can give the machine a fresh root filesystem from its template, and a setup script doesn't run again then either. So keep what you can't lose on `/data`, and be ready to install the rest again. See [setting a machine up once](https://tryquivvo.com/docs/recipes#set-a-machine-up-once).

Command history keeps a machine's newest 100 commands for 30 days, and goes when the machine is deleted. A workspace keeps the newest 8 MiB of history across its machines, so very long output pushes out older commands sooner.

When a machine is deleted, its setup script and ports go at once. A record of it stays for 35 days, so that repeating a delete succeeds and this month's usage can name it, and a workspace keeps the newest 500 of those. A workspace keeps its newest 1 MiB of [feedback](https://tryquivvo.com/docs/api#feedback), for 90 days.

The disk lives on one host, and there are no automatic backups. Keep anything you can't lose somewhere else as well, such as a git remote.

## How do snapshots and forks work?

`quivvo snapshot save` copies the disk. `quivvo fork` copies a machine's disk into new machines. Copies boot fresh with no running processes, whatever state the source was in. Each fork stands alone, and a partial failure lists the ones that couldn't be made in `failed`. Copies are made by the provider. If it won't make one, the answer is a [`provider_error`](https://tryquivvo.com/docs/errors#provider_error), nothing is created and the source is untouched. A snapshot is charged as disk, $0.20 per GiB-month for the size of the disk it copied, from when it's ready until it's deleted.

A copy can still be reading from what it was copied from after it boots. So a machine can't be deleted while a snapshot or fork of it is being made, and a snapshot can't while a machine is being made from it. That's a `conflict` with `retry_after_seconds`: try again later. `quivvo rm` leaves a machine's snapshots: delete those with `quivvo snapshot rm`.

A fork counts as a running machine, so on the Free plan, where 1 runs at a time, suspend or stop the source first and make one copy at a time.

## What sizes, templates and regions are there?

| Size | vCPUs | Memory | Per running hour |
| --- | --- | --- | --- |
| `small` | 1 | 2 GiB | $0.027 |
| `medium` (default) | 2 | 4 GiB | $0.054 |
| `large` | 4 | 8 GiB | $0.108 |
| `xlarge` | 8 | 16 GiB | $0.216 |

vCPUs are shared: a machine bursts to full cores, then settles to a baseline if it stays busy for long stretches. Memory and disk are yours alone.

| Template | What's on it |
| --- | --- |
| `universal` (default) | Debian 13 with Claude Code, Codex, Docker, the GitHub CLI, Node.js 22, Bun, Python 3.13, Go, build tools, Chromium with Playwright MCP, and a desktop on demand. |
| `minimal` | Debian 13 with git, curl and Python 3.13. The smallest image. |

The `universal` template also has Chromium, with Playwright MCP to let an agent drive it, and a desktop that runs only when you start it: see [letting an agent use a browser](https://tryquivvo.com/docs/recipes#let-an-agent-use-a-browser) and [watching on a desktop](https://tryquivvo.com/docs/recipes#watch-it-on-a-desktop). Anything else, you can install: you're root, so run `apt-get update` and then `apt-get install`. The `minimal` template has no browser or desktop.

Regions: `ams` (Amsterdam), `iad` (Ashburn, Virginia). With no `--region`, a new machine goes to `ams`, or to the other region if that has no room, and `region` on the machine says where. Naming a region means that region and no other.

A machine's disk lives on one host. If that host is full when a stopped or suspended machine starts, Quivvo tries to move it to another host in its region, with a copy of `/data` and the same URL. It comes back as a cold boot, and anything installed outside `/data` may be gone. If there's no room anywhere in the region, the start fails with [`capacity`](https://tryquivvo.com/docs/errors#capacity) and nothing changes.

## What are the Free plan's limits?

New workspaces get $5 of credit, with no card needed, once per email address. On Free, 1 machine runs at a time and a workspace keeps 3, each up to 2 vCPUs, 4 GiB and 20 GiB of disk, with 3 snapshots, and creates up to 60 machines an hour. See [pricing](https://tryquivvo.com/pricing) for the other plans, or run `quivvo whoami` to see your own limits.

New accounts wait in a queue for now, and the credit arrives with their turn. Each person who signs up with your invite link moves you up 10 places, and a paid plan skips it.

## How long can a command run?

A command that waits for its result stops at 280 seconds, which is also its default, and exits 124. A background job takes up to 86400 seconds, 3600 by default, and goes on if you disconnect. See [recipes](https://tryquivvo.com/docs/recipes#run-something-long-in-the-background).

If the caller of a waiting command goes away, the command gets SIGTERM, then SIGKILL 3 seconds later. A job isn't affected. An agent's tool timeout (often 120 seconds) is a caller going away, so use `--background` for anything that might outlast it.

`quivvo exec` prints output as it's produced, all of it, so what ran before a kill is already on your side. Under `--json` without `--stream`, or with `--tail-bytes`, nothing prints until the end, so get it back with `quivvo history` and then `quivvo output`. Under `--json` and through the API, long output keeps its first 256 KiB and last 768 KiB per stream, with a line saying how many bytes were left out, and `--tail-bytes` keeps just the end. `quivvo output` shows the first 16 KiB and last 48 KiB of each stream of a past command, including what a stopped command had printed by then. It can only keep what the command's answer kept, so after `--tail-bytes` that's just the tail. A job's output is in `quivvo jobs logs`.

## What does exit 137 mean?

It was killed, usually for running out of memory. When the kernel's out-of-memory killer fired while a command ran, `oom_killed` is true on the result, the job and the history entry. That's machine-wide, so on its own it doesn't prove this command was the victim, but together with 137 it usually does. Use a bigger size: stop the machine, then `quivvo resize work --vcpus 2 --mem-mib 4096`.

## How do public URLs work?

`quivvo port publish` serves a port on the machine's URL.

- A machine has one URL, and it serves one port: the last one published. `replaced_port` says which one it stopped serving.
- A machine can have 10 published ports. `quivvo port ls` lists them all, including ones its URL no longer serves, until you unpublish them, and `default` marks the one it does. Unpublish that one and the URL serves the highest port left.
- It answers only while the machine runs. A request to it doesn't wake a suspended machine, so resume it first. To keep a server up, start it as a background job with `--timeout 86400`, which counts as activity but ends at that timeout, or on a paid plan turn auto-suspend off with `quivvo auto-suspend dev 0`.
- Use `quivvo port-forward` for a private tunnel to any port. It runs until it's killed, so in a tool call start it in the background. With `--json` it prints the port at once.

## How do I run Claude Code or Codex inside a machine?

The `universal` template has both installed, not signed in. See [handing a task to Claude Code or Codex](https://tryquivvo.com/docs/recipes#hand-a-task-to-claude-code-or-codex). Sign-ins are saved in `~/.claude` and `~/.codex`, on the persistent disk, so they survive stops and restarts. Snapshots include them, so any machine started from a snapshot is signed in as well. Snapshots are private to your workspace.

## When are machines and snapshots deleted?

Abandoned machines and snapshots are deleted, always after an email warning and a final reminder 2 days before.

- **Credit at zero:** everything goes 7 days after the warning, or 30 days if the workspace has ever paid.
- **On the welcome credit alone:** a machine not used for 14 days goes 7 days after the warning, and so do snapshots once no machine in the workspace has been used for that long.

Adding credit, resuming the machine, or starting a machine from the snapshot cancels it. Disks and snapshots are charged until then, so a balance can dip below zero. Active paid plans are exempt, and the `delete_after` field on machines and snapshots shows the date.
