Skip to content
sistemo.io beta

Cloud quickstart

Private beta

Signups are invite-only. Request an invite. The SDKs are on PyPI and npm; you still need a dashboard API key to run anything. Source is on GitHub.

First Firecracker microVM from your laptop. About ten minutes if you already have an invite.

Guests ship python3, not python. sb.run("python -c '…'") exits 127.

1. Get an API key

  1. Sign in to the dashboard.
  2. API Keys → Create key.
  3. Scope full (read cannot create or exec). Copy sk_live_… — shown once.
export SISTEMO_API_KEY=sk_live_xxxxxxxxxxxxxxxx

2. Install the SDK

python3 -m venv .venv && source .venv/bin/activate
pip install sistemo

A venv is required on Debian, Ubuntu and Fedora (PEP 668). Needs Python 3.9+.

npm install @sistemo/sdk

Node 18+ (uses global fetch).

3. Run it

Two ways. Same API.

Paste in a terminal

python3 -c "from sistemo import Sandbox; sb=Sandbox(); print(sb.run('uname -a').stdout); sb.close()"
node --input-type=module -e 'import { Sandbox } from "@sistemo/sdk"; const sb = await Sandbox.create(); console.log((await sb.run("uname -a")).stdout); await sb.close();'

Sandbox() boots a real microVM (1 vCPU / 1 GB / 10 GB / base — fits the free quota), runs the command, prints stdout, destroys the VM. Compute billing stops at close().

Save a file, then run it

This is the form you want in a project. The with / finally block destroys the machine even if run() throws.

Save as hello.py:

from sistemo import Sandbox

with Sandbox() as sb:                       # reads SISTEMO_API_KEY
    r = sb.run("uname -a")
    print(r.stdout)                         # Linux …
    print(r.exit_code)                      # 0
python3 hello.py

Save as hello.mjs (the .mjs matters — import + top-level await):

import { Sandbox } from "@sistemo/sdk";

const sb = await Sandbox.create();          // reads SISTEMO_API_KEY
try {
  const r = await sb.run("uname -a");
  console.log(r.stdout);
  console.log(r.exitCode);                  // 0
} finally {
  await sb.close();
}
node hello.mjs

4. More commands in the same sandbox

The VM stays up for the whole with / try block. Install once, run many times.

from sistemo import Sandbox

with Sandbox() as sb:
    print(sb.run("python3 -c 'print(2 + 2)'").stdout)     # 4
    print(sb.run("python3 --version").stdout)
    sb.run("pip install requests", timeout=180)
    print(sb.run("python3 -c 'import requests; print(requests.__version__)'").stdout)
import { Sandbox } from "@sistemo/sdk";

const sb = await Sandbox.create({ stack: "node" });
try {
  console.log((await sb.run("node -e 'console.log(2 + 2)'")).stdout);  // 4
  console.log((await sb.run("node -v")).stdout);
} finally {
  await sb.close();
}

Always look at exit_code and stderr, not only stdout. A missing binary prints the error on stderr and a bare 127 — empty stdout with no message looks like the product returned nothing.

run() waits until the command finishes (default 120 s, max 24 hours). A build or a test suite: sb.run("npm test", timeout=3600) — long-running.

5. Without the SDK (cURL)

Create a machine in the dashboard, wait until it is running, then:

curl -sS -X POST "https://api.sistemo.io/v1/machines/$MACHINE_ID/execs" \
  -H "Authorization: Bearer $SISTEMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"exec_id":"hello-1","script":"uname -a","timeout_sec":120}'

# The command runs in the background. Its record says when it is done:
curl -sS "https://api.sistemo.io/v1/machines/$MACHINE_ID/execs/hello-1" \
  -H "Authorization: Bearer $SISTEMO_API_KEY"
# → "state": "succeeded", "exit_code": 0

# Its output is a separate call, and `data` is base64:
curl -sS "https://api.sistemo.io/v1/machines/$MACHINE_ID/execs/hello-1/output?stream=stdout&offset=0" \
  -H "Authorization: Bearer $SISTEMO_API_KEY" \
  | python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin)['data']).decode(), end='')"

An exec_id is yours to choose and identifies one run: sending hello-1 again to the same machine answers 409. Use a new id per command.

See Exec.

What run() returns

Field Python JS
Standard output stdout stdout
Standard error stderr stderr
Exit code exit_code exitCode
Success? ok (exit_code == 0) —

Under the hood

Step Endpoint
Create POST /v1/machines
Run sb.run(...) → POST /v1/machines/{id}/execs (start + wait)
Destroy DELETE /v1/machines/{id}

Default shape is 1 vCPU / 1024 MB / 10 GB / base. Raising a default without raising the free quota 403s every first-time Sandbox().

Next