The primitive surface: built-in modules

The reference for the 21 cruft:* built-in modules, the runtime's own primitive layer beneath the node:* compatibility modules. Each is minimal, promise-native, bytes-first, and capability-gated. Lists every module, its exports, and how the tier is organized.

Beneath every node:* module Cruft ships sits its own tier: the host primitives, importable directly as cruft:*. The node:* modules carry Node's full API history; each is shaped over a smaller primitive that names what the operation fundamentally is, and the cruft:* specifiers expose that primitive tier directly. The contrast shows in the surface sizes: node:fs carries dozens of functions across three calling conventions, cruft:fs is seven verbs. This page is the reference for that surface, all 21 modules.

The primitive tier is Cruft-owned and intentional, but at 0.0.10 it is not yet a stability-guaranteed public API the way the node:* adapters are. Treat it as the runtime's native idiom, attractive for Cruft-first code, and expect the surface to keep refining.

What "primitive" means here

The Node compatibility layer is deliberately two-tiered (subsystems): the node:* modules absorb Node's API archaeology, and each rests on a primitive that expresses the core operation. The cruft:* tier is that primitive layer, and it has four consistent properties:

  • Minimal and designed. One obvious way per operation, no legacy variants.
  • Promise-native where async. cruft:fs operations return promises; there is no callback convention here.
  • Bytes-first. Binary data is Uint8Array in and out, with no implicit string-coercion layer.
  • Capability-gated by construction. The capability checks live at this tier, so sealed and audit modes cover it automatically.

The same objects also exist as __cruft_* non-enumerable globals; prefer the module form.

Inventory

ModuleExportsWhat it is
cruft:fsread write stat readdir mkdir remove existsThe seven filesystem verbs, promise-native
cruft:pathjoin resolve normalize relative dirname basename extname format parse isAbsolute sep delimiterPath algebra
cruft:osarch platform type release version hostname homedir tmpdir cpus totalmem freemem uptime endianness availableParallelism EOLHost facts
cruft:processargv argv0 env cwd exit pid platform arch title uptime hrtime memoryUsage nextTick version versionsProcess identity and control
cruft:spawnrun execMinimal subprocess: run(cmd, args){code, stdout, stderr}
cruft:child_processNode-shaped set (spawn exec fork spawnSync …)The full process family on the primitive tier
cruft:httpcreateServer createSecureServer requestHTTP server and client primitives
cruft:tlsconnect createServerTLS 1.3 transport
cruft:dnslookup resolve4 resolve6Name resolution
cruft:urlURL URLSearchParams fileURLToPath pathToFileURL domainToASCII domainToUnicodeURL algebra
cruft:querystringparse stringifyQuery-string codec
cruft:bufferBufferThe binary-data type
cruft:eventsEventEmitterThe eventing primitive
cruft:presssqueeze juiceByte compression: squeeze(bytes, {as}) / juice(bytes, {as}), formats gzip/zlib/deflate/brotli
cruft:sqliteopenSQLite over Cruft's own engine, SQL stack
cruft:ormopenSqlite openPostgresCrizzle, the boundary-validating ORM, full page
cruft:serveserve staticDirFetch-shaped HTTP(S) server, full page
cruft:pmresolve canonicalKeyPackage-manager resolution primitives
cruft:prestoescapeHtml slugify titleCase classAttr openTag applyPipeEmbedded CruftScript templating kernel, full page
cruft:testTestNode runNodePrimitive test-tree kernel beneath node:test, full page
cruft:vmcompile run createContextIn-context evaluation, isolated by default (see Limitations)

Behavior

A sampler:

// cruft:fs — promise-native, bytes-first
import * as fs from "cruft:fs";
await fs.write("/tmp/probe.txt", "pure bytes");
const bytes = await fs.read("/tmp/probe.txt");   // Uint8Array
new TextDecoder().decode(bytes);                 // "pure bytes"
await fs.exists("/tmp/probe.txt");               // true
Object.keys(await fs.stat("/tmp/probe.txt"));
// size, mode, uid, gid, dev, ino, …, atimeMs, ctimeMs, birthtimeMs
// (numeric fields only; isFile()/isDirectory() are methods and atime/birthtime
//  are non-enumerable getters, so none appear in Object.keys)

// cruft:press — one compression call, format as data
import * as press from "cruft:press";
const sq = press.squeeze(new TextEncoder().encode("hello hello hello"),
                         { as: "gzip" });        // Uint8Array(27)
new TextDecoder().decode(press.juice(sq, { as: "gzip" }));
// "hello hello hello"

// cruft:spawn — the whole subprocess result in one value
import * as spawn from "cruft:spawn";
await spawn.run("echo", ["pure"]);
// { code: 0, stdout: "pure\n", stderr: "" }

// cruft:presto — templating helpers
import * as presto from "cruft:presto";
presto.escapeHtml("<a&b>");        // "&lt;a&amp;b&gt;"
presto.slugify("Hello World!");    // "hello-world"
presto.titleCase("hello world");   // "Hello World"

The names have personality on purpose (squeeze/juice rather than compress/decompress). The primitive tier does not imitate anyone's API, so its names are chosen for the operation itself.

Reading the tier

Three groups are worth telling apart. The primitive duals of Node modules are the primitives the node:* adapters are shaped over. The Cruft-native capabilities exist first at the primitive tier and have no Node equivalent; some, like the ORM's boundary role in CruftScript, are architectural surfaces in their own right. The runtime-internal helpers are the package manager's resolution primitives, exposed for tooling.

Primitive duals of Node modules
fspathosprocessurlquerystringeventsbufferhttptlsdnsspawnchild_processvm
Cruft-native capabilities
presssqliteormserveprestotest
Runtime-internal helpers
pm

Limitations

  • Not a stability-guaranteed API yet. As the blockquote above says, the primitive tier is still refining at 0.0.10. The node:* adapters are the surface to build on when you need a stable contract; reach for cruft:* when you want the native idiom and can absorb changes.
  • cruft:vm is isolation-by-default, not a security sandbox. With no context, run evaluates in a fresh context that never sees the caller's globalThis, and a context you build only reaches what you put in it. That contains honest code, it does not contain adversarial code. To run untrusted code, use the Compartment API and the agent sandbox, which are the real isolation boundary.