The Sandbox#
Scripts run in a sandboxed environment: a fixed, small set of building blocks, with no operating system access and nothing to install. This page lists what a script can use and where the boundaries are.
Imports#
A script starts with imports. The built-in modules are imported by
name, and your own .js files with relative paths:
// report.js
import fs from "fs";
import env from "env";
import { formatDate } from "./format.js";
Top-level await is supported, so asynchronous code reads top to
bottom. Scripts use modern JavaScript: top-level await, classes,
optional chaining, and other recent language features all work.
Imports work anywhere in your file system: a script can pull in a shared helper, a config file, or a library of functions you wrote earlier.
The Built-In File System#
Your account has a file system. This is what makes GearTrain more
than a scheduler. The workbench manages your files in it, and scripts
read and write it with the fs module while they run.
The file system holds whatever you put in it: scripts, data files,
downloads, config. Only the script a job points at must be a .js file.
The file system is persistent: files your script creates survive between runs, so a job can build on the results of the previous run: append to a data file, keep a checkpoint, or store downloaded files.
Paths are absolute and always start with /:
import fs from "fs";
await fs.writeTextFile("/reports/last-run.txt", new Date().toISOString());
const text = await fs.readTextFile("/reports/last-run.txt");
console.log(text);
The path rules are strict: no relative paths (data.txt is invalid),
no . or .. segments, and no trailing slashes. The
fs module documents every rule and function.
The file system has a storage quota that depends on your plan. If a run exceeds it, the write fails with an error.
Modules#
Two modules are available to every script: fs for
the built-in file system, and env for secrets and
environment variables. Each link documents the module in full.
Web APIs#
The familiar Web APIs from the browser are available as globals:
fetch for HTTP requests, console for logging, URL, timers,
TextEncoder, and more. See the
API Reference for the complete list, including the
differences from the browser standards.
No Module System#
There is no third-party module system. Scripts cannot import packages,
there is no package manager, and none is planned. fetch retrieves
data over HTTP; it cannot load code.
When you need third-party functionality, call the service’s HTTP API
with fetch. All it takes is fetch and your API key.
We are considering allowing third-party modules via HTTP in the future,
but the recommendation today is to design jobs around fetch and the
built-ins.
Limits#
Each run operates within limits that depend on your plan. For the free plan:
| Limit | Applies to | Free plan |
|---|---|---|
| Compute time | How long the script may actively compute | 100 ms |
| Run time | Total run duration, including network waits | 10 s |
| Concurrent runs | How many of your jobs may run at once | 1 |
| Memory | How much memory the script may use | 10 MB |
| Schedule interval | How often a single job may run | 15 min |
| Storage | Files kept in your file system | 25 MB |
| Jobs | Scheduled jobs on your account | 5 |
| Runs | Runs per month | 5,000 |
| Log history | How long console output is kept | 3 days |
When you already have the maximum number of concurrent runs in progress, the next scheduled run waits until one finishes. It is not skipped or dropped. Paid plans raise this limit (up to 5 concurrent runs at a time).
fetch adds its own per-run limits, a request count and an idle
timeout, documented on the
fetch page.