Write a file into a disposable microVM, read it back, and list the directory — all over the SDK's built-in file API, no exec or shell required. Uses the official @tenkicloud/sandbox SDK.
import { TenkiSandbox } from "@tenkicloud/sandbox";
const tenki = new TenkiSandbox({ authToken: process.env.TENKI_AUTH_TOKEN });
// `await using` auto-terminates the sandbox when the scope ends.
await using sandbox = await tenki.createAndWait({
cpuCores: 1,
memoryMb: 1024,
workspaceId: process.env.TENKI_WORKSPACE_ID,
});
const path = "notes.txt";
const text = "hello from tenki\n";
// Write a text file. Relative paths resolve under the guest home, /home/tenki.
await sandbox.writeFile(path, text);
// Read it back — readFile returns bytes (Uint8Array); decode to a string.
const roundTrip = new TextDecoder().decode(await sandbox.readFile(path));
console.log(`read back -> ${JSON.stringify(roundTrip)}`); // "hello from tenki\n"
// List the working directory. Each entry is a FileInfo { path, size, isDir, ... }.
for (const f of await sandbox.list(".")) {
console.log(`${f.isDir ? "d" : "-"} ${f.path} (${f.size} bytes)`);
}npm install
export TENKI_AUTH_TOKEN=... # from `tenki login` (~/.config/tenki/config.yaml)
export TENKI_WORKSPACE_ID=...
node run.mjsOr prove it end-to-end against live Tenki — writes, reads back, lists, asserts the round-trip, and disposes the sandbox:
node verify.mjs # ✓ files-in-a-sandbox: write → read "hello from tenki" → list (1 entry) → disposeThree methods on the session handle the whole loop — no subprocess needed:
sandbox.writeFile(path, data)—datais astringorUint8Array. Writes atomically to the guest filesystem.sandbox.readFile(path)— returns aUint8Array. Wrap it innew TextDecoder().decode(...)for text.sandbox.list(path)— returnsFileInfo[], each{ path, size, isDir, mode, modifiedUnixNs, ... }.pathis the entry's basename andsizeis abigint(useNumber(size)orString(size)).
The session also exposes mkdir(path), stat(path), and remove(path) for the rest of the basics, plus readFileStream / writeFileStream for large payloads.
- Tenki confines file I/O to
/home/tenki(the guest home and default working dir). Relative paths likenotes.txtresolve there;sandbox.list(".")lists it. sizeon aFileInfois abigint— compare withNumber(f.size)or format withString(f.size), not directly against a JS number literal in arithmetic-sensitive code.- The sandbox boots in ~2s and is billed per second.
await usingdisposes it automatically (Sessionis anAsyncDisposable); or callawait sandbox[Symbol.asyncDispose]()explicitly. - Requires Node 20+ for
await using.
Learn more at tenki.cloud.