Command line
wm drives Wheelmachine from a terminal: machines, commands, files, projects and keys.
Every command answers -h with its flags.
$ wm login
$ wm machines create --name box --cpus 4
$ wm exec box -- make test
$ wm cp box:work/report.html .
$ wm machines rm --yes boxInstall#
For now wm is built from its source, with Go 1.27 or later (an older go fetches 1.27 by
itself). It is one file, with nothing else to install, and the same build gives wm-mcp, the server for
agents:
$ cd frontend/cli
$ go build -o bin/ ./cmd/... # writes bin/wm and bin/wm-mcp
$ go install ./cmd/... # or puts them in $(go env GOPATH)/bin
$ wm --version
wm 1.0.0Log in#
wm login signs you in through your browser, with GitHub or Google: it shows a short code and opens
https://app.wheelmachine.ai/device, where you sign in, type the code and approve. wm is
then given a key of its own, named for this computer ("wm on laptop", say), checks it with the API and
keeps it in ~/.config/wheelmachine/config.json (under $XDG_CONFIG_HOME when that is set), in
a file only you can read. On a computer with no browser, open the address on any other device. To keep a key you
already have, wm login --key asks for it without showing it as you type, or reads it from standard input:
wm login --key < keyfile.
| Variable | What it does |
|---|---|
WHEELMACHINE_API_KEY | The key to use. When set, it is used before the one wm login kept. |
WHEELMACHINE_BASE_URL | Where the API is; https://api.wheelmachine.ai when not set. |
XDG_CONFIG_HOME | Where wm login keeps the key, in wheelmachine/config.json. |
The basics#
- Names. A machine is named by its id (
m_...) or its name, a project by its id (prj_...) or its name, and a key by its id (key_...) or its name. When two share a name, give the id. - Output. Tables for people.
--jsonprints the API's own JSON, and-q(--quiet) prints ids only, one a line, for scripts. Both go on any command. - Asking first.
wm machines rmandwm keys revokeask before they act; away from a terminal they need--yes. - Trying again. A call refused for a moment (too many calls, no room just now) is tried again after the
wait the API asks for, and
wmsays so at a terminal. A command run in a machine is never sent twice.
Exit codes#
| Code | When |
|---|---|
| 0 | Done. |
| 1 | The API or the network refused. wm prints why, with the refusal's code and request id. |
| 2 | The command was not right: a missing word, a flag that does not exist. |
| Any | wm exec and wm sh exit with the command's own exit code (255 for one outside 0 to 255). |
| 130 | Stopped with Ctrl-C. |
Machines#
wm machines ls#
wm machines ls [flags]
List machines, newest first.
| Flag | What it does |
|---|---|
--project <project> | Only this project's machines. |
--state <state> | Only machines in this state: starting, running, paused, stopped, archived or recovering. |
--label key=value | Only machines with this label; repeat for more. |
--limit <n> | Show at most this many (0, the default: all). |
wm machines create#
wm machines create [flags]
Make a machine. It answers once the machine runs, usually in well under a second; when a server has to be made
ready for it first, wm waits for it, up to --timeout.
| Flag | What it does |
|---|---|
--name <name> | A name for people; ids are made by the API. |
--project <project> | Its project; the account's first when left out. |
--cpus <n> | Its CPUs: 2, 4, 8 or 16, with 2 GB of memory each; 2 when left out. |
--region <region> | A place to run near, from wm regions. |
--label key=value | A label; repeat for more. |
--from-snapshot machine[:snapshot] | Start from a snapshot's files: the machine's latest when no snapshot is named. |
--idle-after <duration> | Pause by itself once nothing has reached it, and its programs have been quiet, this long: 1m to 24h; 5m when left out. |
--no-sleep | Never pause by itself: it runs, and is charged, until it is paused or stopped. |
--timeout <duration> | How long to wait for it to run; 10m when left out. |
--no-wait | Answer at once, while it may still be starting. |
--gpu <gpu> | Coming A GPU to give it, from wm gpus. Not open to every account yet. |
wm machines get#
wm machines get <machine>
Show one machine: its state, size, where it runs, how it pauses, its labels, its running time and what it uses now.
$ wm machines get box
id: m_01jb2xk3n4p5q6r7s8t9v0w1x2
name: box
state: running
project: prj_01jb2xk3n4p5q6r7s8t9v0w1x2
size: 2 CPU, 4 GB memory
location: Helsinki, FI
pauses: after 5m 00s idle (nothing reached it, its programs quiet)
labels: team=ml
files sealed: yes
running time: 42m 10s
processors used: 0.12
memory used: 612.4 MiB
created: 2026-10-23 09:30 UTC (42m ago)
last used: 2026-10-23 10:11 UTC (1m ago)wm machines rm#
wm machines rm [--yes] <machine>...
Delete machines and all their files. This cannot be undone.
| Flag | What it does |
|---|---|
-y, --yes | Delete without being asked. |
wm machines pause#
wm machines pause <machine>...
Pause machines with their memory kept: nothing runs and no running time is charged. start brings
them back where they were.
wm machines start#
wm machines start <machine>...
Run machines again, from paused, stopped or archived.
| Flag | What it does |
|---|---|
--timeout <duration> | How long to wait for each to run; 10m when left out. |
--no-wait | Answer at once, while it may still be starting. |
wm machines stop#
wm machines stop <machine>...
Stop machines: their files stay, their memory does not.
wm machines archive#
wm machines archive <machine>...
Put machines' files away in storage, the cheapest way to keep them. start brings them back.
wm machines copy#
wm machines copy <machine> [flags]
Make a new machine, a copy of this one as it is now, beside it where there is room. Its name and labels are the original's unless given.
| Flag | What it does |
|---|---|
--name <name> | The copy's name. |
--label key=value | A label for the copy, in place of the original's; repeat for more. |
--timeout <duration> | How long to wait for it to run; 10m when left out. |
--no-wait | Answer at once, while it may still be starting. |
wm machines snapshot#
wm machines snapshot <machine> [--note <words>]
Keep a machine's files as they are now. Make a machine from it with
wm machines create --from-snapshot <machine>:<snapshot>.
| Flag | What it does |
|---|---|
--note <words> | A note to know it by, at most 200 characters. |
wm machines wait#
wm machines wait <machine> [--state <state>] [--timeout 10m]
Wait until a machine is in a state.
| Flag | What it does |
|---|---|
--state <state> | The state to wait for; running when left out. |
--timeout <duration> | How long to wait; 10m when left out. |
wm machines label#
wm machines label <machine> key=value... [key-]...
Set a machine's labels: key=value sets one, key- takes one off. Labels not named stay as
they are.
wm machines rename#
wm machines rename <machine> <name>
Give a machine another name.
Commands and files#
wm exec#
wm exec <machine> [flags] -- <command> [args...]
Run a command in a machine, without a shell. What it wrote is printed as it came, stdout and stderr apart, and
wm exits with its exit code. A paused machine is woken for it. Flags go before the machine, or between
the machine and --.
| Flag | What it does |
|---|---|
--root | Run it as root, inside the machine (never on our servers). |
--cwd <path> | Where it starts: an absolute path; the work folder when left out. |
--env KEY=VALUE | A variable for its environment; repeat for more. |
wm sh#
wm sh <machine> [flags] '<shell line>'
Run a line of shell in a machine (sh -lc), with its pipes and redirections. What it wrote is printed
as it came, and wm exits with its exit code. It takes the same flags as wm exec; with
flags after the machine, put the line after --.
wm cp#
wm cp <file> <machine>:work/<path> or wm cp <machine>:home/<path> <file>
Copy a file to or from a machine, as a stream. In a machine, a path begins home/ (its home) or
work/ (where commands start); a path ending in / is a folder, and the file keeps its name in
it. - is standard input or output. At a terminal, the bytes copied and the speed are shown as it goes.
One side is always this computer: wm cp copies one file, between here and a machine.
Account#
wm login#
wm login [--scope <scope>...] [--name <name>] [--no-browser] or wm login --key
Sign in through your browser, with GitHub or Google, and keep a key of your own on this computer, for
wm and wm-mcp: the key is made when you approve the code wm shows, checked with
the API, and kept in a file only you can read. --scope asks for less than every scope (repeat it, or join
scopes with commas), --name names the key, and --no-browser shows the address without opening
a browser here. --key keeps a key you already have instead: asked for at a terminal and not shown as you
type, otherwise read from standard input (wm login --key < keyfile).
wm logout#
wm logout
Forget the key kept on this computer. The key itself still works until it is revoked
(wm keys revoke).
wm me#
wm me
The account and key in use: the key's scopes, projects, rate and end, and whether the account can spend and what is left.
wm usage#
wm usage [--month YYYY-MM] [--project <project>]
What each machine ran for and cost in a month.
| Flag | What it does |
|---|---|
--month YYYY-MM | The month; this month when left out. |
--project <project> | Only this project's machines. |
Projects#
wm projects ls#
wm projects ls
List the account's projects.
wm projects create#
wm projects create <name>
Make a project.
wm projects rename#
wm projects rename <project> <name>
Give a project another name.
wm projects rm#
wm projects rm <project>...
Delete projects. Only an empty project can be deleted: delete its machines first.
Keys#
wm keys ls#
wm keys ls
List the account's machine keys: id, name, the characters it is known by, state, scopes, projects and when it was last used. A key's secret is never shown again after it is made.
wm keys create#
wm keys create <name> --scope <scope>... [flags]
Make a key. It can hold only scopes and projects the key in use holds. Its secret is shown this once: store it
then. The scopes are machines:read, machines:write, machines:exec,
gpus, projects:write, keys:write, or all: see
Scopes.
| Flag | What it does |
|---|---|
--scope <scope> | What it may do; repeat, or join with commas. |
--project <project> | A project it is limited to; repeat for more. Every project when left out. |
--expires <time> | When it stops working: in a while (30d, 12h) or on a date (2026-12-31). |
--rate <n> | Calls a minute it may make, 1 to 6000; the key in use's own when left out. |
With -q, it prints the secret alone, for a script to store.
wm keys revoke#
wm keys revoke [--yes] <key>...
Revoke keys: they stop working within seconds, everywhere. This cannot be undone.
| Flag | What it does |
|---|---|
-y, --yes | Revoke without being asked. |
Catalogue#
wm regions#
wm regions
Places a machine can be asked to run near (wm machines create --region). A machine says where it
actually runs in its location.
wm gpus#
wm gpus
Coming GPUs, where they are and what an hour costs. GPU machines are not open to
every account yet, and wm gpus says so under the list of what is coming.
On every command#
| Flag | What it does |
|---|---|
--json | Print JSON. |
-q, --quiet | Print ids only. |
-h, --help | Show the command's flags. |
--version | Print the version (wm --version). |