TypeScript compiled to native: Vercel's scriptc ships a 178KB binary with no JS engine
Vercel Labs open-sourced scriptc, a TypeScript-to-native compiler with no JS engine in the binary. Its README claims 2.4ms startup. Hacker News is not convinced.
Vercel Labs published scriptc last week, a compiler that turns TypeScript into native executables. The binaries it produces carry no JavaScript engine at all. A Fibonacci example builds to 178KB, and the project clocks its own startup at roughly 2ms. Hacker News gave it 192 points and a rough reading.
That is a different claim from the one every other “ship your TypeScript as a binary” tool makes. Bun’s --compile flag bundles your code “along with a copy of the Bun runtime”, per Bun’s docs. deno compile ships “a slimmed down version of the Deno runtime”, per Deno’s docs. Node’s single-executable feature injects a blob into a copy of the node binary, V8 included. All three hand you one file. None hands you a small one, and none removes the interpreter boot you pay on every cold start. scriptc’s pitch is that the engine isn’t in there to boot.
What we know
The repo went public on July 22 and sits at about 1,070 stars under Apache-2.0, with five contributors and 12 forks. It’s a Vercel Labs experiment rather than a Vercel product, and the README leads with two words: “Zero-runtime TypeScript”. The route it takes is ahead-of-time compilation through the real tsc type checker into a typed intermediate representation, then into C or LLVM, then clang. clang is required.
- Three tiers, and it tells you which one you’re in. Static native code is the default. Adding
--dynamicembeds QuickJS (the quickjs-ng fork, about 620KB) to run npm dependencies’ shipped JavaScript andany-typed code. Everything else is rejected outright with a numbered diagnostic such as SC1090, andscriptc coverageprints the statement-by-statement split before you build. (README) - The performance figures are the project’s own. Its benchmark table claims roughly 2.4ms startup against Node’s 47ms on Apple M-series, 170KB to 200KB static binaries against Node SEA’s 60MB to 100MB, and 1MB to 4MB of resident memory against Node’s 67MB to 116MB. Nobody has reproduced them.
- The runtime is hand-written C. It uses reference counting with a cycle collector, stackful fibers, a kqueue event loop, vendored mbedTLS for TLS. Feature units link only when a program uses them, which is how the Fibonacci example lands at 178KB instead of megabytes.
- The Node surface is wider than you’d guess.
fs,path,process,child_process,crypto,zlib, plus the server stack (net,http,https,tls,dns) andfetchover the same native TLS. “Real proxy servers compile,” the README says. - Correctness is enforced by differential testing. Over 800 corpus programs must match Node byte-for-byte on stdout, stderr, exit code, and the whole corpus re-runs under AddressSanitizer with a reference-count audit.
What’s still unproven
Nothing above has been checked by anyone outside the repo, and most of the 99 comments on the Hacker News thread were about provenance rather than architecture. Simon Willison pointed out that coding agents “landed 918,000 lines of code in a single week”; another commenter linked a single commit carrying 802,000 of them. Treat everything below as open questions, not verdicts.
- How often real code falls back into the engine. A commenter who says “I make dynamic languages fast for a living” argued that untyped dependencies are unavoidable in this ecosystem and put explicit
anyusage at “79.5% of TS repos” in the same thread. He also said he got that number by asking Claude, so it’s directional at best. Still, a program that spends its time inside QuickJS gets neither the size nor the startup win. - Whether the numbers hold on a neutral harness. The same commenter called the project’s measurements uncredible and said he plans to re-run them “using generally accepted methods”. The README concedes the gap itself: “integer inference and ownership analysis are on the roadmap”, and the C it emits declares a
doublefor every number, loop counters included. - Whether Vercel keeps it alive. Several commenters pointed at zerolang, another Vercel Labs project launched in May that went quiet by mid-June. Vercel’s open-source record is mixed rather than bad. The AI SDK is thriving. zerolang is the closer analogue, and scriptc ships with no roadmap and no support policy.
- Whether any of this becomes a product. Nothing in the repo or on scriptc.dev connects scriptc to Vercel Functions, which is the obvious home for a 2.4ms boot time.
What this means for you
The honest audience is narrow and real: single-file CLI tools, cron jobs, container entrypoints, the things you’d otherwise rewrite in Go just to get one small binary. If your program has a dependency tree, you get QuickJS and a roughly 3MB artifact, and at that point Deno and Bun already work with years of bug reports behind them. Cold start is where the pitch bites. A function that boots in 2.4ms instead of 47ms changes what you’re willing to put on a request path, and that’s the workload Vercel spent Ship 2026 selling. If you want the same idea from a project that has been grinding at it for years, Porffor compiles JavaScript ahead of time “instead of bundling an interpreter” too.
My read: worth an afternoon on a throwaway CLI, not worth a rewrite. Watch two things first. Does an independent benchmark reproduce the README’s numbers? And is anyone still committing to the repo in October?
Share this article
Quick reference
- ahead-of-time compilation
- Ahead-of-time compilation: turning source into machine code before the program runs, instead of interpreting it or JIT-compiling it at startup.
- QuickJS
- A tiny embeddable JavaScript engine by Fabrice Bellard, roughly 600KB compiled. Projects embed it when they need to run JS but can't afford V8's footprint.
Sources
- vercel-labs/scriptc — GitHub
- Scriptc by Vercel: TypeScript-to-Native compiler, no JavaScript engine in binary — Hacker News
- Single-file executables (bun build --compile) — Bun
- deno compile — Deno
- Single executable applications — Node.js
- Porffor — Porffor