scriptc compiles TypeScript and JavaScript to native executables and WebAssembly modules. It uses the TypeScript compiler for parsing and type checking, then emits LLVM IR for clang to compile. A readable C backend remains available for debugging, and the experimental native-only Rust backend emits memory-safe Rust and invokes rustc directly.
Static builds include a small native runtime, but no Node or JavaScript engine. Code that cannot compile statically is reported as a diagnostic. For npm packages and any-typed code, --dynamic embeds quickjs-ng explicitly.
scriptc is experimental and targets macOS, Linux, Windows, and WebAssembly via WASI Preview 1.
The compiler requires Node.js 24 or newer and clang. Experimental --backend rust builds require Cargo and rustc instead of clang. The executables it produces do not require Node.
$ npm install -g scriptcCreate hello.ts:
const who = process.argv.length > 2 ? process.argv[2] : "world";
console.log(`hello, ${who}`);Compile and run it in one step:
$ scriptc run hello.ts
hello, worldOr write a standalone executable:
$ scriptc build hello.ts -o hello
$ ./hello ctate
hello, ctateTo exercise the experimental memory-safe subset, select Rust explicitly:
$ scriptc build hello.ts --backend rust -o hello-rust
$ ./hello-rust ctate
hello, ctateRust builds emit #![forbid(unsafe_code)], do not translate through C, and
report unsupported constructs instead of falling back to another backend. The
current subset includes classes with constructors, fields, accessors,
monomorphic and virtual methods, generic specializations, abstract dispatch,
first-class constructor values, lexical this captures, object identity,
single inheritance, runtime instanceof, composition, collectable cycles,
array identity searches and higher-order callbacks, and insertion-ordered
Map and Set containers with live iteration. Compact type-directed
JSON.stringify covers scalars, nested
arrays, records, unions, optional fields, and circular-value errors. Typed
JSON.parse(...) as T boundaries validate and build the same JSON-safe types.
Common string searches, slicing, trimming, repetition, case conversion, and
UTF-16 indexed access are also available. Basic synchronous filesystem,
process, POSIX path, typed-array, and Buffer workflows are supported too.
Supported Node APIs compile to the native runtime. For example, server.ts:
import { createServer } from "node:http";
const server = createServer((req, res) => {
res.setHeader("content-type", "application/json");
res.end(JSON.stringify({ path: req.url }));
});
server.listen(8080, () => {
console.log("listening on http://localhost:8080");
});$ scriptc build server.ts -o server
$ ./server
listening on http://localhost:8080scriptc coverage shows how much of a program can compile statically and gives a coded diagnostic for every dynamic or unsupported site.
$ scriptc coverage hello.ts
statements analyzed 2
compile statically 2 (100%)
fully static — this program has no dynamic remainder.WASI and other cross-target builds require Zig. Its bundled WASI libc produces a portable WASI Preview 1 module through the production LLVM backend:
$ SCRIPTC_CC=zigcc SCRIPTC_TARGET=wasm32-wasi scriptc build hello.ts --no-keep-c -o hello.wasm >/dev/null
$ file hello.wasm
hello.wasm: WebAssembly (wasm) binary module version 0x1 (MVP)
$ SCRIPTC_CC=zigcc SCRIPTC_TARGET=wasm32-wasi scriptc run hello.ts
hello, worldThe WASI target supports the same executable language tiers as the native targets, including async/await, promises, generators, timers, stdin/readline events, callback and promise filesystem APIs, and --dynamic. APIs that require capabilities absent from portable WASI Preview 1—network sockets/fetch, child processes, OS signals, and filesystem watching—fail before linking with SC3002; sanitizer builds, native FFI, and library-mode archive builds are target diagnostics too. See platform support for the precise boundary.
Pass --dynamic to embed an npm package's JavaScript in the executable. The result does not read node_modules at runtime.
import pc from "picocolors";
console.log(pc.green("hello from scriptc"));$ npm install picocolors
$ scriptc build cli.ts --dynamic -o cli
$ ./cli
hello from scriptcSee the quickstart and CLI reference for the complete workflow. The docs also describe npm dependencies, native FFI, platform support, and the current limitations.
$ pnpm install && pnpm -r build
$ pnpm test:sandboxThe test corpus runs each program under Node and as a compiled native binary, then compares stdout, stderr, and exit codes byte for byte. The full gate also runs the corpus with AddressSanitizer and the runtime reference-count audit.