Minimal REST API for executing single-file code in a sandboxed environment. Supports Python, JavaScript (Node.js), C++, and Java. Built to support CodeAlong. A platform for single file real-time collaborative code editing and execution.
This project was originally inspired by EngineerMan's Piston API. Check out his video breakdown!
This API is free for public use and does not require any authentication, but please be mindful of the rate limits and resource constraints. If you need higher limits or more features, consider hosting your own instance.
The service is hosted on a Digital Ocean Droplet, where code changes are deployed through CI/CD pipelines managed by GitHub Actions. On the Droplet, Caddy sits in front of the app as a reverse proxy and handles HTTPS automatically, so the app itself only has to speak plain HTTP internally.
The Docker image deployed on the Droplet bakes in the runtimes for every supported language (Python, Node.js, g++, and the JDK), so no language installation happens at request time.
Inside the app container, code isn't run directly on the host or in a per-request Docker container; it runs inside one of the three isolated sandboxes built around isolate, a sandbox originally built for the IOI programming contest.
API URL: https://runlet.codealong.live
You can also access the OpenAPI spec at https://runlet.codealong.live/openapi.json or the Swagger UI at https://runlet.codealong.live/docs.
| Method | Path | Description | Rate limit |
|---|---|---|---|
| POST | /execute |
Run a single file of code | 10/minute |
| GET | /runtimes |
List supported languages and versions | 10/minute |
| GET | /health |
Health check | 10/minute |
Runs one submission inside a sandbox and returns its result.
Request schema:
{
"language": "python | javascript | cpp | java",
"code": "string",
"stdin": "string, optional, defaults to \"\""
}Response schema:
{
"status": "OK | TLE | MLE | RE | OLE | CE",
"stdout": "string",
"stderr": "string",
"time": "float | null, seconds",
"memory": "int | null, KB"
}Example request:
curl -X POST https://runlet.codealong.live/execute \
-H "Content-Type: application/json" \
-d '{
"language": "python",
"code": "print(input())",
"stdin": "hello"
}'Example response:
{
"status": "OK",
"stdout": "hello\n",
"stderr": "",
"time": 0.031,
"memory": 8192
}status values:
| Status | Meaning |
|---|---|
OK |
Ran successfully |
TLE |
Time limit exceeded |
MLE |
Memory limit exceeded (only enforced when USE_CGROUPS=true) |
RE |
Runtime error (non-zero exit, signal, etc.) |
OLE |
Output limit exceeded (stdout/stderr exceeded OUTPUT_LIMIT) |
CE |
Compile error (C++ and Java only) |
Other responses:
-
422— body failed validation (e.g.languageisn't one of the four supported values, orcode/stdinexceedCODE_LIMIT/STDIN_LIMIT):{ "detail": [ { "type": "string_too_long", "loc": ["body", "code"], "msg": "String should have at most 1024 characters", "input": "...", "ctx": { "max_length": 1024 } } ] } -
500— the sandbox itself failed to run the submission,{"detail": "<error>"}
Lists the language runtimes baked into the Docker image. No request body.
Response schema:
[
{
"language_name": "string",
"language_version": "string"
}
]Example request:
curl https://runlet.codealong.live/runtimesExample response:
[
{ "language_name": "Python", "language_version": "3.13.14" },
{ "language_name": "JavaScript (Node.js)", "language_version": "20.19.2" },
{ "language_name": "C++ (g++)", "language_version": "14.2.0" },
{ "language_name": "Java", "language_version": "21.0.11" }
]Health check. No request body.
Example request:
curl https://runlet.codealong.live/healthExample response:
{ "status": "healthy" }Make sure you have the following installed:
- Clone the repo and install dependencies (needed for running tests and lint/format locally; the API itself runs inside Docker)
git clone https://github.com/GiridharRNair/Runlet.git
cd Runlet
uv sync- Start the API in development mode
docker compose -f docker-compose.dev.yml upThe container mounts the repo into /app and runs fastapi dev, so the API hot-reloads on code changes. It'll be available at http://localhost:8000.
- Verify it's up
curl http://localhost:8000/health- Stop the API
docker compose -f docker-compose.dev.yml downNote
docker-compose.dev.yml overrides two environment variables from their production defaults:
-
USE_CGROUPS=false— Isolate uses cgroups, a Linux kernel feature, to enforce memory limits, but Docker Desktop on macOS (used for local development) doesn't expose cgroup control the way a native Linux host does. With cgroups disabled, memory limits aren't enforced andMLEis never returned locally. In production,USE_CGROUPSis set to true and enforces memory limits normally. -
CODE_EXECUTION_RATE_LIMIT=100— a looser rate limit than production's10/minute, so manual testing and the test suite don't get throttled.
The container also runs with privileged: true, which isolate needs to set up its sandboxes. Docker Desktop allows this by default.
Set via environment variables — see app/config.py:
| Variable | Default | Description |
|---|---|---|
TIME_LIMIT |
5.0 |
Execution wall time limit (seconds) |
MEMORY_LIMIT |
256 |
Execution memory limit (MB) |
COMPILE_TIME_LIMIT |
30.0 |
Compile step time limit (seconds), C++/Java |
COMPILE_MEMORY_LIMIT |
512 |
Compile step memory limit (MB), C++/Java |
OUTPUT_LIMIT |
1 |
Max stdout/stderr a submission may write (KB), enforced via isolate's --fsize |
CODE_LIMIT |
1 |
Max size of the code field accepted by /execute (KB) |
STDIN_LIMIT |
1 |
Max size of the stdin field accepted by /execute (KB) |
MAX_BOXES |
3 |
Number of concurrent isolate sandboxes |
USE_CGROUPS |
true |
Enforce memory limits via cgroups (disabled in docker-compose.dev.yml) |
CODE_EXECUTION_RATE_LIMIT |
10 |
Requests per minute allowed to /execute per IP |
Common tasks are run through Poe the Poet. Task definitions are in pyproject.toml.
uv run poe format # format code with ruff
uv run poe lint # lint code with ruff
uv run poe test_python # run Python language tests
uv run poe test_js # run JavaScript language tests
uv run poe test_cpp # run C++ language tests
uv run poe test_java # run Java language tests
uv run poe test_all_langs # run all language tests
uv run poe test_memory_limit # run memory limit tests against the local API
uv run poe test_prod_memory_limit # run memory limit tests against the production API
uv run poe test_input_limit # run code/stdin size limit testsThe tests hit a running instance of the API over HTTP. They use the API_URL environment variable, defaulting to http://localhost:8000 if it isn't set, so start the API locally first (see "Local Development" above) before running them.
This project is licensed under the MIT License.

