runtime:system

Child processes. A command is a program plus an argv — there is no shell, so nothing is word-split, glob-expanded, or re-parsed. Output moves over web streams.

Capability: Run

Spawning is the one grant that ends the sandbox: a child runs outside every confinement here — no capability check, no root jail, no execution deadline. Never implied by another capability. Status: Available.

Import

JavaScript
import { Command } from "runtime:system";

// Or the default aggregate:
import system from "runtime:system";

Exports

ExportTypeDescription
CommandclassA command to run: new Command(program, options?).
ChildProcessclassA running child, from spawn(). Not constructed directly.

new Command(program, options?)

program is a path (absolute, or relative to cwd) or a bare name looked up on the host PATH. The env you pass describes the child's environment, never where the runtime looks for executables.

OptionTypeDefaultDescription
args(string | number | boolean)[][]Passed verbatim — no quoting or escaping needed.
cwdstring | URLthe parent'sThe child's working directory.
envRecord<string, string | Secret | undefined>{}The child's environment. A Secret is unwrapped for the child; undefined removes an inherited key.
inheritEnvbooleanfalseStart from the host environment. Needs Env as well as Run.
stdin"null" | "piped" | "inherit", or a body"null"A body — string, bytes, Blob, Response, ReadableStream — is written to the child, then stdin closed.
stdout / stderr"piped" | "inherit" | "null""piped"How the output is connected.
signalAbortSignalAborting kills the child; output() rejects with the reason.
timeoutnumber (ms)Kill the child after this long; output() rejects with a TimeoutError.
killSignalSignalName"SIGTERM"Signal used by kill(), a timeout, or an abort.
maxBuffernumber (bytes)16777216output() only: past this the child is killed and the call throws ERR_MAX_BUFFER.
MethodTypeDescription
output()Promise<CommandOutput>Run to completion, collecting output. Both streams are read while the child runs, so a full pipe cannot deadlock the wait.
spawn()Promise<ChildProcess>Start the child. Async: a failure to start belongs to this call, not to a stream settled later.

CommandOutput is { success, code, signal, stdout, stderr }code is null when a signal ended the process, stdout/stderr are Uint8Array.

ChildProcess

MemberTypeDescription
pidnumberThe OS process id.
stdinWritableStream | nullnull unless piped. Closing it is the child's EOF.
stdout / stderrReadableStream<Uint8Array> | nullnull unless piped. Pulled chunk by chunk.
statusPromise<{ success, code, signal }>Resolves when the child exits.
kill(signal?)(SignalName?) => Promise<void>Defaults to killSignal. A no-op on an exited child.
[Symbol.asyncDispose]()await using kills and reaps at end of scope.
What keeps the program alive

Streams are created on first use, and reading status is what holds the program open. A child nobody waits on keeps nothing alive — and is killed, not orphaned, when the runtime exits.

Examples

JavaScript
import { Command } from "runtime:system";

// Buffered
const { success, code, stdout } = await new Command("git", {
  args: ["rev-parse", "HEAD"],
}).output();

// Streaming, both ways
const child = await new Command("ffmpeg", {
  args: ["-i", "pipe:0", "-f", "mp3", "pipe:1"],
  stdin: request.body,
  stderr: "inherit",
}).spawn();
return new Response(child.stdout);

// Bounded
await new Command("slow-tool", { timeout: 30_000, killSignal: "SIGKILL" }).output();

Not provided

AbsentWhy
A shell (exec, shell: true, $`…`)The shell-injection class stays out.
fork() / IPCWorker processes want their own design.
stdio arrays, raw fdsAn fd hands the guest authority over anything inherited.
detached, uid/gidPrivilege manipulation belongs to the embedder.
Sync variantsOps run inside the async runtime.
PTYThis runtime pipes.
Last updated on
Edit this page