This guide gets a sandbox running from JavaScript or TypeScript. You'll start an isolated Firecracker microVM, run code in three languages, move files, and stream output from a long job. Every step is a short snippet.
You need Node.js 18+ (or Deno, or Bun) and an EQVPS account.
1. Get a token
The SDK authenticates with an ordinary account token. Connecting your account shows how to get one from the dashboard, the API or the MCP server.
export EQVPS_API_KEY="your-token"
A new account with no balance gets $1 of sandbox credit the first time it creates a sandbox. That covers this guide many times over.
2. Install the SDK
npm i @eqvps/sdk
The examples use ES modules and top-level await. Save them as .mjs files, or as .ts and run them with npx tsx.
3. Start a sandbox and run code
import { Sandbox } from "@eqvps/sdk";
await Sandbox.with({ tariff: "small" }, async (sb) => {
console.log(sb.id);
const r = await sb.run("import platform; print(platform.python_version())");
console.log(r.exit_code, r.stdout);
});
The output is the sandbox id (sb_ and 24 more characters), then 0 3.12.x. Sandbox.with deletes the sandbox when the callback finishes, also if it throws.
The default language is Python. The other two are one option away:
await Sandbox.with({}, async (sb) => {
const js = await sb.run("console.log(process.version)", { language: "node" });
const sh = await sb.run("uname -r && nproc", { language: "bash" });
console.log(js.stdout, sh.stdout);
});
A failing script doesn't throw. Check r.ok, which is true when exit_code is 0 and the command didn't time out.
4. Shell commands and packages
exec takes a shell string or an argv array. The sandbox has internet access, so npm and pip installs work:
await Sandbox.with({ tariff: "small" }, async (sb) => {
await sb.exec("mkdir -p /root/app && cd /root/app && npm init -y && npm i lodash", { timeout: 55 });
const r = await sb.exec(["node", "-e", "console.log(require('/root/app/node_modules/lodash').VERSION)"]);
console.log(r.stdout);
});
A synchronous call can run for 55 seconds at most. Anything longer goes into a background task (step 6).
5. Files
await Sandbox.with({}, async (sb) => {
await sb.upload("/root/input.json", JSON.stringify({ values: [3, 5, 8] }));
await sb.run("import json; d = json.load(open('/root/input.json')); open('/root/out.txt', 'w').write(str(sum(d['values'])))");
console.log(await sb.downloadText("/root/out.txt")); // 16
});
upload takes a string or a Uint8Array. download returns a Uint8Array, downloadText a string. One transfer is limited to 5 MB.
6. Long jobs with live output
await Sandbox.with({ tariff: "standard" }, async (sb) => {
const task = await sb.exec("for i in 1 2 3 4 5; do echo step $i; sleep 20; done", { background: true });
const res = await task.wait({ onOutput: (out) => process.stdout.write(out) });
console.log(res.state, res.exit_code); // done 0
});
The task returns immediately and has no 55-second limit. wait polls every 2 seconds by default (pollIntervalMs changes that). task.kill() stops it; sb.task(id) reattaches from another process.
Errors
import { Sandbox, InsufficientBalanceError, RateLimitError } from "@eqvps/sdk";
try {
await Sandbox.with({}, async (sb) => console.log((await sb.run("print(1)")).stdout));
} catch (e) {
if (e instanceof InsufficientBalanceError) console.log("Top up the balance");
else if (e instanceof RateLimitError) console.log("Busy, retry in", e.retryAfter);
else throw e;
}
The SDK retries 429 and 503 itself, up to three times, when the server sends Retry-After. The most common 429 comes from running more than two commands at once on one account. Every class is in the SDK reference.
Cost of this guide
Each example lived a few seconds and was billed the 60-second minimum: $0.00055 on small, $0.0011 on standard. The step 6 job ran for about 100 seconds on standard, about $0.002. All of it together is well under a cent. The full price list is in sandbox limits and billing.
Next steps
- The same in Python: Python sandbox SDK in 5 minutes.
- Connect a model and let it run its own code: your first agent task in a sandbox.
- Tariffs and the $1 trial: the sandbox page.
Comments
No comments yet. Be the first.