The biggest barrier to writing WASM genes was the toolchain. v0.3 removes it entirely: write a TypeScript function, run rotifer compile, get a sandboxed WASM gene. Zero configuration.
The Toolchain Problem
Before v0.3, creating a WASM gene meant either writing Rust (which most AI developers don't use daily) or setting up a complex toolchain involving AssemblyScript, wasm-pack, or Emscripten. Each option required learning new build systems, debugging unfamiliar error messages, and maintaining additional configuration files. The result was predictable: developers prototyped in TypeScript and never compiled to WASM.
This created a two-class ecosystem. Native genes (real WASM) were portable and sandboxable. Wrapped genes (Node.js evaluation) were easy to create but couldn't travel across Bindings. v0.3 eliminates this friction by meeting developers where they are.
TS → WASM Pipeline
The new compilation pipeline chains three stages automatically:
TypeScript → esbuild (bundle) → WASI shim → IR compiler (QuickJS→WASM) → Rotifer IR
rotifer compile my-gene # auto-detects index.ts, compiles to WASM
rotifer compile my-gene --lang ts # force TypeScript mode
Under the hood, the IR compiler embeds QuickJS into a WASM module. The result is a fully sandboxed gene that runs in the same wasmtime sandbox as hand-written Rust genes — with the same fuel metering, memory limits, and security isolation.
No Rust. No AssemblyScript. No WASM toolchain setup. Same language you already use.
Why QuickJS?
We evaluated three approaches for TypeScript-to-WASM compilation:
-
AssemblyScript — a TypeScript-like language that compiles directly to WASM. Fast output, but it's not real TypeScript: no closures over complex types, no
async/await, limited standard library. Developers would need to learn a new language disguised as a familiar one. - wasm-bindgen / wasm-pack — the Rust ecosystem's answer. Excellent output quality, but requires Rust knowledge and a complete Rust toolchain installation.
- QuickJS-in-WASM — embed a JavaScript engine inside WASM. Supports full ES2023 including closures, destructuring, and dynamic typing. Slightly larger binary size (~500KB baseline), but zero developer friction.
We chose option 3. The guiding principle was: a gene author should never need to install anything beyond npm install -g @rotifer/playground. Binary size is a one-time cost that amortizes across every gene the developer creates. Developer friction is a per-gene cost that compounds.
WASI Sandbox Support
The Rust core's WasmtimeSandbox now supports two execution modes:
-
Direct — genes exporting an
expressfunction (original mode) -
WASI — genes using the
_startentry point (IR compiler output)
A minimal WASI shim provides 9 host functions (fd_read, fd_write, clock_time_get, etc.) — just enough for QuickJS to run, nothing more.
Security Implications
The WASI shim is deliberately minimal. QuickJS needs to read stdin (for input) and write stdout (for output), so fd_read and fd_write are required. It needs wall-clock time for Date.now(), so clock_time_get is provided. Everything else — file system access, network sockets, environment variables, random number generation — is either denied or stubbed with safe defaults.
This means a TypeScript gene compiled through the QuickJS path has exactly the same security guarantees as a hand-written Rust gene. The sandbox boundary is the WASM module boundary, regardless of the source language. A gene cannot read your file system, make network requests, or access other genes' memory — even if the TypeScript source code tries to.
IR Verifier Updates
- SIMD instructions downgraded from error to warning (common in QuickJS-based WASM output)
-
_startentry point accepted alongsideexpressfor WASI modules
By the Numbers
- 180 → 275 tests (91 TypeScript + 184 Rust)
- Documentation updated across README (EN/ZH), Getting Started, and website
The Developer Experience Impact
With v0.3, the entire gene development cycle becomes a three-command workflow:
rotifer init my-project # scaffold with genesis genes
# edit genes/my-gene/index.ts
rotifer compile my-gene # TypeScript → sandboxed WASM
rotifer arena submit my-gene # compete for ranking
No build configuration. No tsconfig.json for the compilation. No WASM-specific boilerplate. The developer writes a pure function that takes input and returns output, and the toolchain handles the rest. This is the "zero-config" promise that v0.3 delivers on.
Looking Ahead
v0.3 proved that the zero-config compilation promise was achievable. TypeScript developers could now participate in the gene ecosystem without learning Rust or configuring build tools. The next challenge was connecting these locally-compiled genes to a shared registry where they could be published, discovered, and compared across developers — which v0.4 delivered with the Cloud Binding.
The QuickJS-in-WASM approach also opened an unexpected door: any language that compiles to JavaScript (CoffeeScript, PureScript, ReasonML) could potentially produce Rotifer genes through the same pipeline. While not officially supported, several community members have already experimented with this path.
Get Started
npm install -g @rotifer/playground
Write a gene:
// genes/my-search/index.ts
export function express(input: { query: string }) {
return { results: [`Found: ${input.query}`], total: 1 };
}
Compile and submit:
rotifer compile my-search
rotifer arena submit my-search
Top comments (0)