Runtime

How to download files from a sandbox

Call sbx.files.readText(path) or read(path) for one file, and sbx.files.download(dir, localDir) for a whole folder.

On Runtime you can take files out of a sandbox even after its work is paused. A paused sandbox keeps its whole disk, and a request for a file wakes it by itself, usually in about half a second. Keeping it paused costs $0.08 per decimal GB of saved state a month, against $0.03125 an hour to leave a 2 vCPU, 4 GiB sandbox running idle (pricing, checked 25 September 2026).

Read one file

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.files.write("/workspace/out/report.csv", "name,score\nada,9\n");const text = await sbx.files.readText("/workspace/out/report.csv"); // a stringconst bytes = await sbx.files.read("/workspace/out/report.csv"); // raw bytesconsole.log(text, bytes.length);console.log(await sbx.files.stat("/workspace/out/report.csv"));
Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx:    sbx.files.write("/workspace/out/report.csv", "name,score\nada,9\n")    text = sbx.files.read_text("/workspace/out/report.csv")  # str    data = sbx.files.read("/workspace/out/report.csv")  # bytes    print(text, len(data))    print(sbx.files.stat("/workspace/out/report.csv"))

Use read for images, archives and anything else that is not text; it gives you the bytes unchanged.

Download a folder

TypeScriptimport { mkdtemp } from "node:fs/promises";import { tmpdir } from "node:os";import { join } from "node:path";import { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.files.write("/workspace/results/summary.txt", "all tests passed\n");await sbx.files.write("/workspace/results/logs/run.log", "ok\n");const local = await mkdtemp(join(tmpdir(), "results-"));await sbx.files.download("/workspace/results", join(local, "results"));
Pythonimport pathlibimport tempfilefrom withruntime import Sandboxwith Sandbox.create() as sbx:    sbx.files.write("/workspace/results/summary.txt", "all tests passed\n")    local = pathlib.Path(tempfile.mkdtemp()) / "results"    sbx.files.download("/workspace/results", str(local))    print(sorted(p.name for p in local.rglob("*")))

The folder travels as one compressed archive, and each file keeps its permissions. From a terminal, cat prints a file and cp with <id>:/path as the source copies one out:

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

Find what to download first

files.list walks a directory to a depth, and files.glob matches a pattern, so an agent can collect every chart or report it made without knowing the names:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.files.write("/workspace/charts/a.png", "png bytes");for (const entry of await sbx.files.list("/workspace", { depth: 2 }))  console.log(entry.type, entry.size, entry.path);console.log(await sbx.files.glob("**/*.png"));

Ways out, compared

Method Best for Notes
files.readText(path) Logs, JSON, CSV Decoded as text
files.read(path) Images, archives, binaries Raw bytes, unchanged
files.download(dir, local) A folder of results One compressed archive; permissions kept
runtime sandbox cat / cp A terminal or a CI step <id>:/path names a sandbox path; a name works for the id
runtime_sandbox_files_read An agent over MCP Whole files, or a range of lines
GET …/files/content?path= Your own HTTP client The file's raw bytes

Reading a file costs nothing on its own. The sandbox is billed for measured CPU at $0.025 per active vCPU-hour and memory at $0.0075 per GiB-hour.

Mistakes to avoid

  • Stopping before copying out. A stopped sandbox is not a backup. Download what you need first, or keep the files on a volume, which outlives sandboxes and is backed up off its server every day (volume backups).
  • Reading a huge command output through exec. A plain result holds at most 64 KiB of stdout. Redirect the command to a file and read the file.
  • A relative path. Paths are absolute; /workspace is the sandbox user's home.
  • Checking for a file by catching an error. files.exists(path) answers true or false, and stat gives type, size, mode and times.

Facts on this page were checked on 25 September 2026.