Scope-B milestone NI-1, runtime side. Programs whose IR has a `nodeIsland.*` operation link scr_node_island.c and the SCR_NODE_ISLANDS build of scr_async.c; every other program links neither, byte for byte. - scr_node_island.c dlopens the bridge of a libnode pack on the first call (RTLD_NOW | RTLD_GLOBAL), checks its bridge ABI and that it links exactly the Node version recorded at build time, starts one Node environment and runs the embedded bootstrap (scr_node_island_host.cjs). A run that never calls into Node never maps libnode. The pack directory is SCRIPTC_LIBNODE at run time, else the recorded path; a `$ORIGIN/` path resolves against the executable's directory (the beside packaging, and the hook for shipping Node with the program). - scr_node_bridge.h is the C ABI between the runtime and the bridge; the runtime includes no Node or V8 header. The bridge (packages/libnode-common/bridge/scr_node_bridge.cc) initializes Node once with no default signal handling, no debug-signal handler or inspector, no stdio reinitialization and one platform worker, creates the environment from the built-in snapshot, routes Node's process exit to the runtime's exit sequence, promotes libnode to the global scope for native addons, and runs calls in a CallbackScope with a TryCatch. build-pack.mjs assembles a pack (libnode, the bridge, manifest.json) from a Node --shared build and the matching headers. - The SCR_NODE_ISLANDS build of scr_async.c adds a loop slot through which the runtime's loop drives Node's until NI-3 hosts the runtime's queues on Node's libuv: it keeps the program alive while Node has ref'd work, sleeps on Node's backend fd up to its next timer, and runs one non-blocking turn per loop turn. - The `nodeIsland` runtime feature (rule, link features, unit table, pack matrix row and scr_async.c variant), the nodeIsland.call/callSync libCalls, the install call in main, and the build-time record of the pack (node-islands/libnode.ts: --libnode=<pack>|beside or SCRIPTC_LIBNODE, SC8005 when none is usable, Node >=24.13.1). - The zero-cost gate and the bench nm test require that no good-code executable defines a Node island symbol. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scriptc
Compile TypeScript and JavaScript to native executables or WASI WebAssembly modules that run without Node.js installed.
$ cat fib.ts
function fib(n: number): number {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
console.log(fib(30));
$ scriptc run fib.ts
832040
$ scriptc build fib.ts -o fib >/dev/null && ./fib
832040
scriptc compiles the same TypeScript you run on Node.js, type-checked by the TypeScript compiler. npm packages your program imports compile along with it. Code scriptc can't compile fails the build with an error code and, where available, a rewrite hint.
scriptc is experimental. See the limitations and the Node.js compatibility reference.
Install
$ npm install -g scriptc
npm installs the native compiler for your platform (macOS, Linux, or Windows). Node.js 24 or later is needed to install it and to run WASI modules with scriptc run; compiling and running executables doesn't need Node.js.
Building executables needs a linker and the platform SDK or sysroot, such as the Xcode Command Line Tools on macOS. Set SCRIPTC_LINKER to choose the linker driver. --emit=ir|llvm|asm|obj needs no external tools. See the quickstart for details.
Commands
scriptc build <file.ts>: compile to a native executable or another artifact selected with--emit.scriptc run <file.ts>: compile and run.scriptc coverage <file.ts>: report what compiles, and explain what doesn't.scriptc build --lib --profile <profile.json>: compile a static library, or a Wasm reactor onwasm32-wasi.
See the CLI reference for every option.
Cross-compilation and WebAssembly
Set SCRIPTC_TARGET to build for another platform, for example SCRIPTC_TARGET=aarch64-linux-gnu.2.36 or SCRIPTC_TARGET=wasm32-wasi. Install the matching @scriptc/runtime-<target> package in your project, at the same version as scriptc --version, or set SCRIPTC_RUNTIME_PACK to a runtime pack directory. See platform support and WebAssembly modules.
Native code
Call C functions by declaring their signatures in TypeScript and binding them to C symbols in a manifest passed with --ffi <manifest.json>. See the Native FFI guide.
Build cache
Builds reuse a bounded persistent cache. Set SCRIPTC_NO_CACHE=1 to bypass it or SCRIPTC_CACHE_DIR to choose its location.
Docs: scriptc.dev