Quickstart
Install the cubicle CLI, log in, create a service account with a write API key, then use @cubicle/sdk from TypeScript to create a Box, run uname -a in it, print the output and delete the Box.
You will create a Box, run uname -a in it from TypeScript, read its output and delete it.
Concepts defines the terms this guide uses.
Prerequisites
- A Cubicle account. Cubicle is invite-only: sign in with the email address on your invitation.
- Membership in an organization where you may create Boxes. This guide calls it
acme.- To create the API key yourself, you must be an owner or admin of
acme. Otherwise, ask one of them for awriteAPI key and skip step 2. - A personal organization cannot create Boxes until a Cubicle operator allows it. After you log
in,
cubicle whoami --jsonshowsboxCreateAllowedfor each of your organizations.
- To create the API key yourself, you must be an owner or admin of
- macOS or Linux, on x64 or arm64, for the CLI.
- Node.js 22 or later.
Create, use and delete a Box
-
Install the CLI and log in.
curl -fsSL https://api.cubicle.sh/downloads/install | sh cubicle loginThe installer asks before it installs the CLI in your home directory, then offers the optional tunnel, a network helper that runs as root and connects your computer to the Cubicle private network for SSH. This guide does not need the tunnel, so you can decline it. Install the CLI covers the details.
cubicle loginprints a link and a code:To log in, open: https://app.cubicle.sh/device?user_code=WDJB-MJHT and confirm the code WDJB-MJHT. Press Enter to open the browser…Open the link, sign in, check that the page shows the same code and choose Authorize. The CLI finishes on its own and prints
Logged in as <your email>. -
Create a service account and an API key.
Programs authenticate as a service account, a non-interactive member of one organization.
cubicle service-accounts create --org acme ci cubicle api-keys create --org acme ci github-actions --scope writeThe first command prints
created acme/ci (<ID>). The second prints the key, which starts withcbk_, followed byStore this key now; it is not shown again.Copy the key now.The key needs the
writescope: areadkey can only makeGETrequests. You can also create both in the Dashboard. Sign in and API keys covers scopes, expiry and the Dashboard steps. -
Install the SDK and set its environment.
mkdir cubicle-quickstart && cd cubicle-quickstart npm init -y npm pkg set type=module npm install @cubicle/sdk npm install --save-dev tsx export CB_SDK_API_URL=https://api.cubicle.sh export CB_SDK_API_KEY=cbk_… # the key from step 2@cubicle/sdkis ESM-only andindex.tsuses top-levelawait, so the project needs"type": "module".new Cubicle()reads both variables. -
Write
index.ts.index.ts import { Cubicle } from "@cubicle/sdk" const cubicle = new Cubicle() // Creates job-1 in the key's organization and waits until it is ready. const box = await cubicle.boxes.create({ name: "job-1" }) try { const result = await box.exec(["uname", "-a"]) process.stdout.write(result.stdout) console.log(`exit code: ${result.exitCode}`) } finally { // Deletes the Box and waits until its Node has removed it. await box.delete() }createuses the API key's organization. It resolves once SSH and exec can be used, and waits up to 5 minutes by default.- The service account gets a grant, the per-Box permission to run commands in a Box and reach it, on every Box it creates.
execruns the argument vector without a shell and resolves when the command ends.deletewaits up to 5 minutes, until the Box's Node, the Cubicle host that runs it, has removed it and released its resources.
-
Run it.
npx tsx index.tsOn Node.js 24,
node index.tsalso runs it, withouttsx.You should see the Box's kernel line, then the exit code. The kernel version varies.
Linux box-job-1 … x86_64 GNU/Linux exit code: 0
If something fails
If the script stops before finally runs, for example because create timed out, the Box still
exists. Delete it with the CLI and the same key, in the shell where you exported it:
CB_CLI_API_URL=$CB_SDK_API_URL CB_CLI_API_KEY=$CB_SDK_API_KEY cubicle boxes delete acme/job-1The service account created the Box, so its grant lets it delete the Box. With your own login,
cubicle boxes delete acme/job-1 works only if you are an owner or admin of acme.
| Error | Cause | Fix |
|---|---|---|
missing_api_url or missing_api_key | CB_SDK_API_URL or CB_SDK_API_KEY is not set. | Export both in the shell that runs the script. |
403 insufficient_scope | The key is a read key. | Create a write key. |
403 box_create_disabled | The organization cannot create Boxes. | Use another organization, or ask a Cubicle operator to allow Box creation. |
409 conflict: "a box named job-1 already exists" | An earlier run left job-1 behind. | Delete it with the command above, or choose another name. |
503 capacity | No Node has room for the Box right now. | Try again later. |
Troubleshooting covers more errors.
Try it from the CLI
The CLI does the same with your own login. Box commands lists every option.
cubicle boxes create --org acme job-1 --wait
cubicle exec acme/job-1 -- uname -a
cubicle boxes delete acme/job-1--waitwaits up to 10 minutes, until SSH and exec can be used. As the Box's creator, you get the grant thatexecneeds.cubicle execprints the command's output and exits with its exit code. Everything after--is the command.cubicle boxes deletereturns once the deletion is accepted and prints<ID> deletion pending. The Box stays incubicle boxes list --org acmeuntil its Node has removed it.
What you just did
- You signed in as a person and created a service account with a
writeAPI key, the credential programs use. - The service account created a Box, which gave it a grant on that Box, so it could run a command there.
- You ran a command without a shell, read its output and exit code when it finished, and deleted the Box.
Next steps
Run commands
Shell syntax, timeouts, output limits and working directories.
TypeScript SDK
Handles, waiting, errors and retries in @cubicle/sdk.
Box lifecycle
Start, stop, hibernate and delete, and what each one keeps.
SSH into a Box
Add an SSH key and connect over the private network.
Run CI jobs in Boxes
Run Boxes from CI with scoped, expiring API keys.
Sign in and API keys
Scopes, expiry, revocation and what API keys cannot do.
Cubicle documentation
Cubicle runs QEMU/KVM virtual machines called Boxes that you create, run commands in and delete from the TypeScript SDK, the HTTP API or the cubicle CLI, and reach over SSH and a private network.
Install the CLI
Install the cubicle CLI on macOS or Linux (x64 or arm64) with the one-line installer or by hand with a SHA-256 checksum, add the optional root tunnel for SSH and the private network, upgrade, uninstall and log in.

