core

Execution

Send code, get back what it printed. There is no machine to create first and nothing left running afterwards — the process starts straight into fresh namespaces with its limits already set, so a run costs milliseconds rather than a container boot. Big environments like pytorch are bind-mounted read-only off the host instead of reinstalled per run.

language codes

Every run names its language. It is never inferred — not from a file extension, not from the code itself. A .py file is as likely to be torch as plain Python, and inline code has no extension at all, so one rule you apply every time beats two with a boundary to remember.

codelanguagewritten ashow it runs
pythonPython 3.pyinterpreted
nodeNode.js.jsinterpreted
goGo.gocompiled
cC.ccompiled
cppC++.cppcompiled

The code is python, not python3 — which Python the image ships is ours to change. There is no pytorch code either: torch is a library inside the Python environment, not a language, so torch code is python like any other. bzlabs languages and boltzlabs.languages() return this list live.

compiled languages

go, c and cpp are built before they run. That is two passes over the same workspace: the compiler first, then the executable it produced. You send the same request either way — the only thing that changes is what comes back when the code is wrong.

compiled.py
res = boltzlabs.execute(file="main.go", language="go")

res.compile_ms      # how much of duration_ms was the compiler
res.compile_failed  # True when the program never ran at all

A program that does not compile is still a result, not an exception: the call worked, your code was rejected. compile_failed is what separates that from a program that ran and wrote to stderr — the exit code alone cannot tell you which happened, and the stderr you are reading belongs to the compiler in one case and to your program in the other. duration_ms covers both passes, because both are time the machine spent, and that is what a run is billed for.

The compiler is reachable only during the build. Once your program starts it is running on a filesystem with no toolchain on it at all — a separate mount set, which is the reason the build is its own pass rather than a step inside the run.

python

Either the code itself or a path to read it from — plus the language, in both cases. The path is resolved on your machine, so the platform only ever receives code, never a path it would have to trust.

run.py
import boltzlabs

print(boltzlabs.execute("print(sum(range(101)))", language="python"))   # 5050
print(boltzlabs.execute(file="train.py", language="python"))
print(boltzlabs.execute("console.log(40 + 2)", language="node"))        # 42

boltzlabs.execute(file="slow.py", language="python", timeout=10)   # 30s is both the default and the cap
boltzlabs.languages()   # the codes above, from the platform

The result is the same object sb.exec() returns, so printing it gives you the output and testing it gives you success:

result.py
res = boltzlabs.execute(file="tests.py", language="python")

print(res)          # stdout
if res:             # True when the exit code was 0
    ...
res.check()         # raises if it failed

# .stdout .stderr .exit_code .duration_ms when you want them.
# A non-zero exit is data, not an exception: your program failed, not the call.

cli

shell
bzlabs run --language python train.py
bzlabs run --language python -c 'print(1)'
bzlabs run --language node app.js
bzlabs run --language go main.go        # built, then run
bzlabs run --language cpp solve.cpp
bzlabs run --language python slow.py --timeout 10   # 30 s is the cap, not a default to raise

bzlabs languages     # the codes, and which of them compile

Your program's exit code becomes the CLI's, so && and || compose the way they would locally.

limits

languages

python · node · go · c · cpp

timeout

30 s — a hard ceiling

compile

30 s, not from your timeout

code size

1 MiB

filesystem

wiped after each run

Every run gets its own workspace and that workspace is destroyed with the process, so nothing one run writes can be seen by the next. When you want state to survive between commands — installed packages, files, a process left running — use a sandbox instead: the first command pays for the boot and every one after it is free.