The VM CLI accepts either a VM ID or your team-local slug wherever it asks for
<vmId>. See Freestyle CLI for installation and authentication.
Create, List, And Inspect
freestyle vm create --slug development --display-name "Development VM"
freestyle vm list
freestyle vm get development
create is the default action: freestyle vm --slug development creates a VM.
At a terminal, vm create opens a shell in the new VM, which keeps running
after you exit. --no-ssh prints the record instead. Scripts, CI, and coding
agents get the record without passing anything.
A new VM can reach the Internet. --no-internet leaves it with no outbound
access. Inbound access is separate: see Firewall.
If --slug is already taken, the CLI asks whether to take it from the VM
holding it, which keeps running without a slug. --replace-slug answers yes
up front. Scripts, CI, and coding agents get an error naming the flag instead
of a question.
freestyle vm create --snapshot-id freestyle/ubuntu --slug builder
freestyle vm create --vpc private --ipv4 10.40.0.10
freestyle vm create --slug scratch --no-ssh
Use repeatable --metadata key=value flags on create or update. Filter lists
with --state, --slug, --snapshot-id, or comma-separated
--metadata key:value pairs.
Run Commands
Put the guest command after -- so its flags are passed through unchanged:
freestyle vm exec development -- uname -a
freestyle vm exec development --timeout-ms 60000 \
--env NODE_ENV=production -- npm test -- --runInBand
vm exec streams stdout and stderr, then exits with the guest command’s exit
status. Allocate an interactive PTY with -it:
freestyle vm exec -it development -- bash
freestyle vm exec -it development --linux-user developer -- python3
For a login shell, use freestyle vm ssh development. Despite the name, the
CLI opens the same Freestyle PTY API directly and does not need a local SSH
key. The session runs bash where the guest has it, and the login shell where
it does not.
Update And Lifecycle
freestyle vm update development --display-name "Build worker" \
--idle-timeout-seconds 600 --metadata environment=staging
freestyle vm resize development --cpu 8 --memory 16384 --storage 81920
freestyle vm pause development
freestyle vm start development
freestyle vm delete development
Memory and storage are measured in MiB. Resizing is grow-only.
Snapshots
Capture a VM you already have, and manage the snapshots you keep:
freestyle snapshot create development --slug configured-worker
freestyle snapshot list --source-vm-id development
freestyle snapshot get configured-worker
freestyle snapshot update configured-worker --display-name "Configured worker"
freestyle snapshot delete configured-worker
snapshot create returns once the snapshot is materialized and ready to boot
from. Each of these is also available as freestyle vm snapshot ....
Taken slugs work as they do for VMs: the CLI asks, --replace-slug answers
yes up front, and the snapshot that held the slug keeps its data under its id.
Without --slug, snapshot create offers to name the snapshot once it exists.
Press Enter to leave it addressable by id.
Build A Snapshot From Scratch
Without a VM, snapshot create boots one, opens a shell in it, captures it
when you exit, and deletes the VM. create is the default action here too, so
freestyle snapshot --slug configured-worker says the same thing:
freestyle snapshot create --slug configured-worker
--base sets the snapshot to start from. The VM has Internet access;
--no-internet removes it:
freestyle snapshot create --base freestyle/ubuntu-lg --slug build-box
A command after -- runs in place of the shell, with your keyboard attached
to it. The VM is captured when the command exits:
freestyle snapshot -- claude login
freestyle snapshot --slug configured-worker -- npm install -g @anthropic-ai/claude-code
--script runs a local script instead, streamed to your terminal as it runs.
A script with a shebang runs under it; one without runs under bash, or sh on a
guest without bash:
freestyle snapshot create --script ./setup.sh --slug configured-worker
A command or script that exits non-zero deletes the VM and takes no snapshot,
as does Ctrl-C during a script. --keep-vm keeps the VM instead.
Building by hand requires a terminal. In CI, in a pipeline, or under a coding
agent, snapshot create requires a command or --script unless you pass
--interactive.
Files And SCP
freestyle vm fs write development /root/app.tar ./app.tar
freestyle vm fs read development /var/log/app.log --out ./app.log
freestyle vm fs ls development /root
freestyle vm fs mkdir development /root/output
freestyle vm fs stat development /root/app.tar
freestyle vm fs rm development /root/output
freestyle vm scp ./app.tar development:/root/app.tar
freestyle vm scp development:/var/log/app.log ./app.log
freestyle vm scp ./site development:/srv/site
freestyle vm scp development:/root/results ./results
A directory copies recursively, in either direction. A destination that already
exists as a directory receives the copy under the source’s own name, so
scp ./site development:/srv writes /srv/site.
scp and the fs commands operate as root inside the VM, while vm exec and
vm ssh run as the VM’s default user (uid 1000, or root where the image has no
such account). A file you copy in is therefore root-owned: chown it with
freestyle vm exec <vm> --linux-user root "chown ubuntu:ubuntu /path" if the
default user needs to write to it.
The filesystem commands stream large files and use the SDK’s resumable upload transport automatically.
JSON Output
--output is a global option. Use it instead of the removed --json flag:
freestyle --output json vm list | jq '.vms[] | {id, state}'