Scripts runtime
What the swarm-scripts runtime exposes to user code, what it does NOT expose, and how the typecheck stays aligned.
Swarm scripts are TypeScript modules persisted in the catalog via
/api/scripts/upsert and executed by the
scripts-runtime. The save-time typecheck and the runtime are deliberately
aligned — what passes the typecheck is what actually runs. This page documents
the full surface so script authors don't have to bisect.
What the runtime provides
Scripts run inside a bun run subprocess (src/scripts-runtime/eval-harness.ts)
with the environment stripped to a small allowlist. Everything below is
available as a plain global in user code AND typechecks cleanly.
ES2022 standard library
The typecheck loads lib.es2022.d.ts. All standard ES2022 built-ins resolve:
- Primitives + boxed types:
Number,String,Boolean,Symbol,BigInt - Collections:
Array,Map,Set,WeakMap,WeakSet - Errors:
Error,TypeError,RangeError,SyntaxError,ReferenceError - Async:
Promise,Promise.all,Promise.allSettled,Promise.race,Promise.any - Iteration:
Iterator,IterableIterator,Generator - Reflection:
Object,Reflect,Proxy - JSON / Math / Date / RegExp
- Free functions:
isFinite,isNaN,parseInt,parseFloat,encodeURIComponent,decodeURIComponent,encodeURI,decodeURI
Array<T>, Promise<T>, Record<K, V>, and structural object types all work
as you'd expect. No any-everywhere required.
Web platform — fetch, URL, encoding, timers, abort
These are exposed by Bun's runtime and explicitly declared in the typecheck runtime-globals shim:
fetch,Request,Response,Headers,RequestInit,ResponseInit,Blob,FormDataURL,URLSearchParamssetTimeout,clearTimeout,setInterval,clearInterval,setImmediate,clearImmediate,queueMicrotaskAbortController,AbortSignalTextEncoder,TextDecoder,atob,btoa,structuredClonecrypto.randomUUID(),crypto.getRandomValues(...),crypto.subtle
The fetch available in the runtime IS the one Bun provides — same shape as
Node 18+'s undici fetch. Prefer ctx.stdlib.fetch / ctx.stdlib.fetchJson for
built-in retries; bare fetch works too.
Console + logger
console.log / .warn / .error / .info / .debug are global. They also
hang off ctx.logger. Both write to the subprocess stderr (captured by the
executor and returned in the HTTP response's stderr field).
Node-compat surface
Bun's Node compatibility layer makes these available:
Buffer(Uint8Array-compatible, withBuffer.from(...),Buffer.concat(...), etc.)process.env— typed asRecord<string, string | undefined>. The environment is stripped to a small allowlist before the user script runs. You should NOT assume any specific env keys exist. Today's surviving keys:HOME,LANG,LC_ALL,PATH,TMPDIR,SWARM_SCRIPT_*(internal).process.platform,process.arch,process.version,process.cwd(),process.hrtime()
Swarm-specific imports
import { fetch, fetchJson, grep, glob, table, Redacted } from "stdlib";
// stdlib also flows through ctx.stdlib at runtimeimport type { ScriptContext, ScriptMain, SwarmConfig, Redacted } from "swarm-sdk";The ScriptContext passed to your default export carries:
ctx.swarm— typed SDK for in-swarm operations (memory, kv, tasks, scripts, repos, schedules). Method allowlist: seesrc/scripts-runtime/sdk-allowlist.ts.ctx.swarm.config—apiKey,agentId,mcpBaseUrl(all wrapped inRedacted<string>; unwrap viactx.stdlib.Redacted.value(...)).ctx.stdlib— the runtime helpers (fetch,fetchJson,grep,glob,table,Redacted).ctx.logger— Console-compatible logger; same destination as the globalconsole.
Allowed bare imports
The TypeScript import allowlist (src/scripts-runtime/import-allowlist.ts):
stdlibswarm-sdkzod— for declaringexport const argsSchema = z.object({...})
import "fs" / "node:fs" / "path" / any unlisted bare specifier is
rejected at upsert and at run time.
What the runtime does NOT provide
These are rejected by the typecheck and would also fail at runtime — they do NOT exist in the script sandbox:
- DOM APIs —
window,document,localStorage,sessionStorage,HTMLElement,Event, etc. The typecheck does NOT includelib.dom.d.ts. We did this on purpose; the runtime is not a browser. - Filesystem —
fs,node:fs,node:fs/promises. Usectx.stdlib.globandctx.stdlib.grepfor read-only file inspection inworkspace-rwmode (v2 only). - Subprocess —
node:child_process,Bun.spawn. Scripts cannot shell out. - Net —
node:net, raw TCP/UDP. Outbound HTTP viafetchonly. Bun.*globals — even though Bun is the runtime, scripts cannot access theBunobject directly. Usectx.stdlibinstead.
Typecheck diagnostics
When script-upsert rejects code, the response is structured:
{
"error": "typecheck_failed",
"diagnostics": ["...colorized full diagnostic..."],
"structured": [
{
"severity": "error",
"code": 2552,
"message": "Cannot find name 'Mat'. Did you mean 'Math'?",
"file": "/virtual/user-script.ts",
"line": 1,
"column": 28,
"endLine": 1,
"endColumn": 31,
"identifier": "Mat",
"suggestion": "Math"
}
]
}Each entry carries the TypeScript diagnostic code (TS2552, TS2304, …),
the precise location, the offending identifier when it's a name lookup, and
the compiler's "did you mean…" hint when one is offered.
Runtime errors
When a script throws at runtime, the HTTP response includes a
runtimeError field beside stderr:
{
"exitCode": 1,
"error": "eval_error",
"stderr": "Error: kaboom from line 4\n at user-script.ts:4:13",
"runtimeError": {
"name": "Error",
"message": "kaboom from line 4",
"stack": "Error: kaboom from line 4\n at .../user-script.ts:4:13\n ...",
"userFrames": [{ "file": "user-script.ts", "line": 4, "column": 13, "raw": "at user-script.ts:4:13" }],
"userScriptLine": 4,
"userScriptColumn": 13
}
}Stack frames inside the harness or node_modules are stripped from the
stderr text shown to clients (they remain in runtimeError.stack for
debugging). The user-script path is normalized to the basename
user-script.ts — absolute tmpdir paths never leak.
When to escalate
If you find code that runs fine in the runtime but fails the typecheck, treat
it as a swarm bug, not a script bug. Add a probe to src/tests/scripts-typecheck.test.ts
and either expand the runtime-globals shim
(SCRIPT_RUNTIME_GLOBALS in src/be/scripts/typecheck.ts) or open an issue
with the failing snippet.
Cost & context computation
How cost and context-window numbers are computed across harness providers, and how to read the costSource / contextFormula badges in the UI.
Shannon (experimental)
Opt-in alternate `claude` binary that keeps swarm runs on the Max/Pro subscription credit pool after Anthropic's 2026-06-15 programmatic-credit split