macOS · Linux · Windows
TypeScript-to-Native
Compiler
Ordinary TypeScript becomes a small, fast native binary — no Node, no V8, no JavaScript engine required. What compiles behaves byte-for-byte like Node.
$ 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 && ./fib
832040Three tiers, always explicit
Every construct in your program lands in exactly one tier, and the tier is the promise.
Compiled statically
The default. Ordinary TypeScript — classes, closures, async/await, the stdlib, Node's fs/path/process/http surface — becomes native code with no engine in the binary. What compiles behaves byte-for-byte like Node.
Runs dynamically
Opt in with --dynamic: an embedded JavaScript engine (~620KB) executes what can't be static — npm dependencies' shipped JS, any-typed code. Every value crossing back into static code is validated at runtime.
Rejected at compile time
Everything else fails the build with a specific error code, a code frame, and usually a rewrite hint. Nothing is ever silently miscompiled.
Staticness you can see
Most TypeScript is far more static than the ecosystem assumes. scriptc decides, construct by construct, what can compile to native code — and tells you. A binary never silently grows an engine: the dynamic tier is opt-in, and the coverage report names every site that needs it.
Reading coverage reports →$ scriptc coverage cli.ts
statements analyzed 4
compile statically 3 (75%)
runs with --dynamic 2 sites (embeds a JS engine, ~620KB — static stays the default)
×1 importing 'picocolors' requires the embedded dynamic engine — the package's implementation runs there SC2013No code changes
No annotations, no dialect, no special stdlib. The same TypeScript you run on Node, type-checked by the real TypeScript compiler.
Small and fast
A hello-world binary is ~320KB, starts in about 4ms, and links against nothing but libSystem. Node needs a ~120MB runtime and ~35ms to print the same line.
Measured coverage
scriptc coverage tells you, statement by statement, what compiles statically, what needs the dynamic engine, and exactly what blocks the rest.
Differentially tested
Every corpus program runs under Node and as a native binary; stdout, stderr, and exit codes must match byte-for-byte. The whole corpus re-runs under AddressSanitizer.
Compile your first binary
Clone the repository, build the compiler, and turn a TypeScript file into a native executable in a couple of minutes.