Runtime

How to upload a folder to a sandbox

Call sbx.files.upload(localDir, "/workspace/project"); the whole folder travels as one compressed archive and keeps its permissions.

On Runtime a folder upload is one call and one archive, not a loop of file writes. Scripts stay runnable because each file keeps its mode, and single large files go in parallel 1 MiB chunks, each checked by SHA-256, resuming after a dropped connection. There is no size limit beyond the sandbox's disk. The sandbox that receives it started in a median 207 ms from create to running, measured on 24 September 2026 (speed).

Upload a project and run it

TypeScriptimport { mkdtemp, writeFile } from "node:fs/promises";import { tmpdir } from "node:os";import { join } from "node:path";import { Sandbox } from "withruntime";const project = await mkdtemp(join(tmpdir(), "project-"));await writeFile(join(project, "main.py"), "print('hi')\n");await writeFile(join(project, "run.sh"), "python3 main.py\n", { mode: 0o755 });await using sbx = await Sandbox.create();await sbx.files.upload(project, "/workspace/project");console.log(await sbx.files.list("/workspace/project"));const run = await sbx.exec("./run.sh", { cwd: "/workspace/project" });console.log(run.stdout);
Pythonimport pathlibimport tempfilefrom withruntime import Sandboxproject = pathlib.Path(tempfile.mkdtemp())(project / "main.py").write_text("print('hi')\n")with Sandbox.create() as sbx:    sbx.files.upload(str(project), "/workspace/project")    for entry in sbx.files.list("/workspace/project"):        print(entry["type"], entry["size"], entry["path"])    print(sbx.exec(["python3", "main.py"], cwd="/workspace/project").stdout)

From a terminal, cp takes a sandbox path as <id>:/path and copies directories whole:

Terminalid=$(runtime sandbox create)mkdir -p project && echo "print('hi')" > project/main.pyruntime sandbox cp ./project "${id}:/workspace/project"runtime sandbox files "${id}" /workspace --depth 2runtime sandbox stop "${id}"

One file, or many small ones

files.write is for a single file you already hold in memory. It makes parent directories and replaces the file atomically, and mode sets its permissions:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.files.write("/workspace/bin/start.sh", "#!/bin/sh\necho ready\n", { mode: 0o755 });await sbx.files.write("/workspace/data/input.csv", "a,b\n1,2\n");console.log(await sbx.files.exists("/workspace/data/input.csv"));
Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx:    sbx.files.write("/workspace/bin/start.sh", "#!/bin/sh\necho ready\n", mode=0o755)    sbx.files.write("/workspace/data/input.csv", "a,b\n1,2\n")    print(sbx.files.exists("/workspace/data/input.csv"))

For a whole tree, upload sends one archive instead of a write per file.

Sizes, speeds and costs

What Figure
How a folder travels One compressed archive, unpacked in the sandbox with permissions kept
Large single files Parallel 1 MiB chunks, each checked by SHA-256, resumed after a dropped link
Size limit None beyond the disk
Default disk 4 GiB, about 2.5 GiB free (measured 24 September 2026); ask for more with diskMiB
Trial disk Up to 10 GiB
Disk speed Bursts to about 250 MB/s for 30 seconds, then about 40 MB/s
Default mode 0o644 for write without mode; upload keeps each file's own
Cost Nothing per upload; the disk is part of the sandbox

Mistakes to avoid

  • Filling the default disk. The system image and installed packages share diskMiB. A large repository or dataset needs Sandbox.create({ diskMiB: 16_384 }) (disk_mib in Python) (disk, CPU and memory).
  • Relative sandbox paths. SDK paths are absolute. /workspace is the sandbox user's home; sudo reaches the rest.
  • Uploading the same tree on every run. When every sandbox needs the same code or packages, bake them into a custom image once, or keep data on a volume that outlives sandboxes.
  • A script that will not run. A file made with write and no mode gets 0o644. Pass mode: 0o755, or upload the folder, which keeps the mode it had.

Facts on this page were checked on 25 September 2026.