Quickstart
From a key to a machine you have used and put away, in about five minutes. You need a terminal and an API key.
Get a key#
For now, keys are made in Wheelmachine's console by your account's owner: ask for one that holds
cloud:* to follow this page. A key looks like ak_live_ and 40 letters and digits. Keep it
like a password: anyone who has it can use your machines.
Coming A page where you make your own keys.
Get wm#
wm is the command line. For now it is built from its source, with Go 1.27 or later, which writes
wm and wm-mcp (the server for agents):
$ cd frontend/cli
$ go build -o bin/ ./cmd/...
$ export PATH="$PWD/bin:$PATH"Log in#
$ wm login
To sign in, open https://app.wheelmachine.ai/device and enter this code:
BCDF-GHJK
Your browser is opening it. Sign in, type the code, then approve.
Waiting for you to approve (the code works until 09:10; Ctrl-C to stop)...
Logged in to account you@example.com.
Signed in. A key of your own, "wm on laptop" (key_3f9a1c2b4d5e6f70), is kept in /home/you/.config/wheelmachine/config.json, readable by you only.You sign in on the page with GitHub or Google, and wm checks the key it is given with the API before it
keeps it. On a computer with no browser, open the address on any other device; to keep a key you already have, use
wm login --key. To use a key without keeping it, put it in WHEELMACHINE_API_KEY instead.
Make a machine#
$ wm machines create --name box
ID NAME STATE SIZE LOCATION AGE
m_01jb2xk3n4p5q6r7s8t9v0w1x2 box running 2 CPU, 4 GB Helsinki, FI 0sIt answers once the machine runs, usually in well under a second. This one has 2 CPUs and 4 GB of memory;
--cpus 4, 8 or 16 give it more. From here on, the machine is named by its id
or by its name.
Run a command#
$ wm exec box -- uname -s
Linux
$ wm sh box 'echo hello > note.txt && ls -la | wc -l'
4wm exec runs a program with its words, without a shell; wm sh runs a line of shell,
with pipes and redirections. Both print what the command wrote, and exit with its exit code. Commands start in the
machine's work folder.
Copy a file in and out#
$ wm cp ./data.csv box:work/
$ wm exec box -- wc -l data.csv
1201 data.csv
$ wm cp box:work/note.txt .In a machine, a path begins work/ (the work folder, where commands start) or home/ (its
home). A path that ends in / is a folder, and the file keeps its name in it.
Pause it#
$ wm machines pause box
ID NAME STATE SIZE LOCATION AGE
m_01jb2xk3n4p5q6r7s8t9v0w1x2 box paused 2 CPU, 4 GB Helsinki, FI 3mPaused, it keeps its memory and no running time is charged. A command wakes it, and so does
wm machines start box; it carries on where it was. A machine also pauses by itself once it has been
idle for five minutes: see Sleep when idle.
Delete it#
$ wm machines rm box
Delete m_01jb2xk3n4p5q6r7s8t9v0w1x2 and all its files? [y/N] y
m_01jb2xk3n4p5q6r7s8t9v0w1x2Deleting takes its files with it, for good. In a script, add --yes.
The same, in code#
The libraries and the API do the same steps. Each reads the key from WHEELMACHINE_API_KEY.
Python
from pathlib import Path
from wheelmachine import Wheelmachine
client = Wheelmachine() # reads WHEELMACHINE_API_KEY
machine = client.machines.create(name="box")
machine = client.machines.wait(machine.id, "running") # at once when it already runs
result = client.machines.exec(machine.id, ["uname", "-s"])
print(result.exit_code, result.stdout)
client.machines.write_file(machine.id, "work/data.csv", Path("data.csv"))
client.machines.read_file(machine.id, "work/data.csv", to="data-back.csv")
client.machines.pause(machine.id)
client.machines.delete(machine.id)TypeScript
import { Wheelmachine } from "wheelmachine";
const client = new Wheelmachine(); // reads WHEELMACHINE_API_KEY
let machine = await client.machines.create({ name: "box" });
machine = await client.machines.wait(machine.id, "running"); // at once when it already runs
const result = await client.machines.exec(machine.id, ["uname", "-s"]);
console.log(result.exit_code, result.stdout);
await client.machines.writeFile(machine.id, "work/data.csv", { path: "data.csv" });
await client.machines.readFile(machine.id, "work/data.csv", { to: "data-back.csv" });
await client.machines.pause(machine.id);
await client.machines.delete(machine.id);curl
API=https://api.wheelmachine.ai
AUTH="Authorization: Bearer $WHEELMACHINE_API_KEY"
# make a machine, and keep its id (jq reads it from the answer)
ID=$(curl -s -X POST $API/v1/machines -H "$AUTH" -H "Content-Type: application/json" \
-d '{"name": "box"}' | jq -r .id)
# run a command
curl -s -X POST $API/v1/machines/$ID/exec -H "$AUTH" -H "Content-Type: application/json" \
-d '{"command": ["uname", "-s"]}'
# copy a file in, and back out
curl -s -T data.csv "$API/v1/machines/$ID/files?path=work/data.csv" -H "$AUTH"
curl -s "$API/v1/machines/$ID/files?path=work/data.csv" -H "$AUTH" -o data-back.csv
# pause it, then delete it
curl -s -X POST $API/v1/machines/$ID/pause -H "$AUTH"
curl -s -X DELETE $API/v1/machines/$ID -H "$AUTH"Next#
- Machines: sizes, states, sleeping when idle, copies and snapshots.
- Commands and files: long work, output, root, environment.
- Keys and scopes: a key of its own for each program and each agent.
- Agents: give an agent machines through
wm-mcp.