Boot a base snapshot by passing its slug as snapshotId. They start in
about a second:
const { vm } = await freestyle.vms.create({
// Required: a VM reaches nothing it has not been allowed to.
firewall: { rules: [{ action: "allow", source: {}, destination: { public: true } }] },
snapshotId: "freestyle/ubuntu",
});
Hardware is baked in: a snapshot boots with the vCPU, memory, and disk
listed below. Omit snapshotId to get the default.
Available images
| Slug | Base | vCPU | Memory | Disk |
|---|---|---|---|---|
| BusyBox | 1 | 128 MiB | 1 GB | |
| Ubuntu 24.04 LTS | 2 | 4 GiB | 16 GB | |
| default | Ubuntu 24.04 LTS | 4 | 8 GiB | 32 GB |
| Ubuntu 24.04 LTS | 8 | 16 GiB | 64 GB | |
| Ubuntu 24.04 LTS | 16 | 32 GiB | 128 GB | |
| Ubuntu 24.04 LTS | 32 | 64 GiB | 128 GB | |
| Ubuntu 24.04 LTS | 64 | 128 GiB | 256 GB |
Click a slug to copy it.
Which sizes you can use depends on your plan’s per-VM maximums.
Free tops out at freestyle/ubuntu, Hobby at freestyle/ubuntu-lg, and Pro at
freestyle/ubuntu-2xl. freestyle/ubuntu-3xl is larger than any published
plan allows and needs custom limits — talk to
sales.
Which one to pick
freestyle/ubuntu— Ubuntu 24.04 with development tools preinstalled, and the default every guide assumes. systemd is pid 1, Docker runs from boot, and Node.js, Bun, Python, and coding agents are onPATH. See What’s Installed for the inventory and installation paths.-smthrough-3xlare that same image with different hardware. Nothing about the software changes between them, so pick by how much room the workload needs and check it against your plan’s maximums.freestyle/busybox— a minimal appliance: no package manager, no libc,shonly. For smoke tests, CI, and anything that has to fit where a 32 GB rootfs will not. Too small for editor connections: the VS Code/Cursor remote server needs a dynamic libc and more than 128 MiB of memory. Terminal SSH is fine — for IDE work, pick an Ubuntu snapshot.
What’s Installed
All Ubuntu sizes include the same software. The image is a development environment, so check the existing tools before installing your own:
| Software | Included tools and installation paths |
|---|---|
| Node.js LTS | node, npm, and npx; nvm lives at /usr/local/nvm, with binaries under /usr/local/nvm/versions/node/<version>/bin |
| JavaScript tools | bun, bunx, typescript, ts-node, and typescript-language-server, installed as global npm packages in the shared Node tree |
| Coding agents | claude, codex, opencode, and openclaw, also installed in the shared Node tree |
| Python | System Python at /usr/bin/python3; the development environment and its packages at /opt/freestyle/python |
| Python tooling | uv, pipx, and python-lsp-server in the development environment |
| Model and agent SDKs | anthropic, claude-agent-sdk, openai, openai-agents, ollama, instructor, pydantic-ai, daytona, langchain, and llama-index |
| Python data and web packages | numpy, scipy, pandas, matplotlib, seaborn, pillow, opencv-python, django, flask, requests, beautifulsoup4, and sqlalchemy |
| Docker | Docker Engine, Compose, and Buildx; the daemon starts at boot |
| System and network tools | git, curl, wget, jq, vim, nano, tmux, sudo, man pages, ping, dig, ss, traceroute, tcpdump, wg, and wg-quick |
The Node tree’s executables, including bunx and the coding agents, are
symlinked into /usr/local/bin. Python’s console scripts are linked there
too; python and python3 are wrappers that run the development venv.
/usr/bin/python3 remains the system interpreter. These tools work in
vm.exec() without sourcing a shell profile.
The shared Node tree is root-owned. For your own Node or Bun installation,
choose a separate directory and set its PATH explicitly; an installer
that tries to create /usr/local/bin/bunx will find an existing symlink.
For isolated Python dependencies, create your own venv with
/usr/bin/python3 -m venv <directory>.
There is an ubuntu user with passwordless sudo. vm.exec() defaults to
that user; use vm.linuxUser("root") for system-wide changes.
Inspect the exact versions and paths in your VM before building a custom snapshot. Saved snapshots keep their installed versions when the public base image is updated:
command -v node npm bun bunx claude codex python3 uv
readlink -f /usr/local/bin/bunx
node --version
npm list --global --depth=0
python3 -m pip list
dpkg-query -W
Custom snapshots
Start from a base snapshot, set it up however you want, resize if you need more, and capture its exact memory and disk. The source VM must be running or paused:
const { snapshotId, snapshot } = await vm.snapshot({
slug: "configured-worker",
});
const { vm: clone } = await freestyle.vms.create({
// Required: a VM reaches nothing it has not been allowed to.
firewall: { rules: [{ action: "allow", source: {}, destination: { public: true } }] }, snapshotId });
New snapshots are private, and snapshot() returns once the snapshot is fully
materialized and ready to boot.
Manage snapshots from freestyle.vms.snapshots:
const { snapshots } = await freestyle.vms.snapshots.list({ sourceVmId: vmId });
const current = await freestyle.vms.snapshots.get(snapshotId);
await freestyle.vms.snapshots.update(snapshotId, { slug: "golden-image" });
await freestyle.vms.snapshots.delete(snapshotId);