Skip to main content
株式会社オブライト
Software Development2026-07-287 min read

Scriptc: Compile TypeScript to Native Binaries, No Node

Vercel Labs' scriptc compiles TypeScript into native binaries with no Node or V8 inside — how the three-tier model works and how it compares to Bun and Deno.


scriptc compiles ordinary TypeScript into native executables that contain no JavaScript engine. Released by Vercel Labs under Apache-2.0, it hit the Hacker News front page on July 27, 2026. There is no dialect and no special annotation: the same TypeScript you run on Node is type-checked by the real TypeScript compiler and lowered to native code.

What is new: a three-tier compilation model

Turning TypeScript into a single executable is not new — Node SEA, bun build --compile, and deno compile all do it — but every one of them ships a JavaScript engine inside the binary. scriptc splits the problem into three tiers instead.

- Static compilation (default): TypeScript is lowered directly to native code, with no engine in the binary
- Dynamic mode (opt in with --dynamic): only what cannot be staticized runs on an embedded QuickJS (~620KB) — typically the JavaScript that npm packages ship, and any-typed code
- Rejection: anything neither tier can handle fails at build time with a specific error code and a rewrite suggestion

That third tier matters in practice: the compiler refuses rather than silently miscompiling. A scriptc coverage command additionally reports which parts of your code compile natively and which fall back to the engine.

What the static surface covers

"No engine" sounds like it would mean a tiny usable subset, but the static surface documented in the repository is fairly broad across both language features and the standard library.

AreaDocumented static support
LanguageClasses with inheritance, closures, generics, async/await, try/catch/finally, destructuring, template literals, regular expressions
Standard libraryStrings, arrays, Map, Set, JSON, Math, typed arrays, Error hierarchy
Node APIsfs (sync and promises), path, process, child_process, net / http / https / tls, dns, streams
Web standardsfetch, WHATWG Streams, Headers
npmResolved with Node's algorithm, type-checked against shipped .d.ts files

Note the caveat on npm: types resolve, but what the package actually ships is JavaScript, so in most cases those paths land in dynamic mode. Dependency-light CLI tools get the full benefit of static compilation most directly.

comptime and FFI

- comptime(() => ...) runs TypeScript at build time inside an isolated VM in the compiler and bakes the result into the binary as a literal — useful for precomputed tables and generated constants
- Native FFI (--ffi) binds signature-only TypeScript declarations to direct C ABI calls and links manifest-declared archives, object files, and system libraries

Together these push scriptc past "a way to distribute Node scripts" and into territory Rust and Go have owned, but with TypeScript syntax. For a different take on lightweight native desktop builds, see Tauri v2 performance and bundle size.

Claimed performance and size

Metricscriptc (claimed)Comparison
Startup~2.4ms (README) / ~4ms hello-world (site)Node ~35–47ms
Binary size170–200KB static / ~320KB hello-worldNode runtime ~120MB
Dynamic mode~3MB with dependencies
Memory1–4MB typical RSS

The spread between the README and the site reflects different benchmark programs; both are vendor-reported figures. Any real decision should rest on scriptc coverage plus your own measurements. Still, "a few milliseconds to start, a few hundred kilobytes on disk" is a level where the difference is genuinely felt in CLI tools, Git hooks, CI helper scripts, and short-lived serverless-style work.

Installing and using it

- Install: the README documents npm install -g scriptc; the official site instead walks through cloning the repository and building the compiler in its Quickstart
- Prerequisite: clang (included with the Xcode Command Line Tools on macOS)
- Platforms: the primary target is macOS arm64; Linux and Windows are described as verified through cross-compilation and differential testing
- Cost: open source under Apache-2.0, free to use

CommandPurpose
scriptc run fib.tsExecute directly
scriptc build fib.tsCompile to a native binary
scriptc coverage app.tsAnalyze how much compiles statically

How correctness is enforced

The scariest failure mode for a compiler like this is code that runs but behaves subtly differently. Two mechanisms are described as running continuously to guard against that.

- Differential testing: 800+ test programs run under both Node and as native binaries, with stdout, stderr, and exit codes required to match byte for byte
- Memory-safety lane: AddressSanitizer runs plus reference-count auditing to catch leaks and use-after-free

How it differs from existing options

ToolEngine in binaryTypical sizePositioning
scriptcNone (QuickJS ~620KB only in dynamic mode)Hundreds of KB to a few MBCompiles TypeScript to native code
Bun compileBundles JavaScriptCoreTens of MBPackages the runtime into one file
Deno compileBundles V8Tens of MBPackages the runtime into one file
Node SEABundles the Node runtimeTens of MB and upDistribution format for existing Node apps

In short, Bun, Deno, and Node SEA exist to collapse distribution into a single file; scriptc exists to produce an executable that never had an engine in the first place. It is not a drop-in replacement for an existing Node application — the realistic path is to look for dependency-light tools first. For practical use of the surrounding runtimes including Bun, see Setting up Hono, Inertia and React with Bun and Vite.

Caveats today

- It is under active development. This is the immediate post-launch window; treat APIs and supported surface as moving
- Dependency-heavy code staticizes poorly. Estimate with scriptc coverage before committing
- macOS arm64 is the primary target. Other platforms are validated differently, so verify on your own before production use
- clang is required, which means preparing your CI image accordingly

FAQ

How is scriptc different from bun compile or deno compile?

Bun and Deno bundle a JavaScript engine (JavaScriptCore or V8) into the executable to achieve single-file distribution, which puts binaries in the tens of megabytes. scriptc statically compiles TypeScript to native code by default and ships no engine in the binary; only when parts cannot be staticized does dynamic mode embed a roughly 620KB QuickJS. If your goal is simpler distribution, the former fits; if it is startup time and size, scriptc is the closer option.

Can I convert an existing Node.js application as is?

Code with heavy npm dependencies tends to land in dynamic mode, because what packages actually ship is JavaScript, which dilutes the benefit of static compilation. The practical approach is to run scriptc coverage to see how much compiles statically, and to start with dependency-light CLI tools and scripts.

Do I need to learn a new syntax or annotations?

No. It targets the same TypeScript you run on Node rather than a dialect, and type checking is done by the real TypeScript compiler. Constructs it cannot handle are rejected at build time with an error code and a rewrite suggestion.

Does it cost anything?

It is published as open source under the Apache-2.0 license, so there is no usage fee. Vercel Labs is the company's vehicle for experimental projects, and scriptc can be used independently of any Vercel hosting plan.

Does it work on Windows and Linux?

macOS, Linux, and Windows are listed as supported, but the primary target is macOS arm64, with Linux and Windows described as verified via cross-compilation and differential testing. Since the project is still under active development, it is safer to build and test on your own target platform before committing to production use.

Summary

The core of scriptc is this: keep writing ordinary TypeScript, get a few-hundred-kilobyte binary with no engine inside. The three tiers — static, dynamic, rejected — plus scriptc coverage make it visible how much actually compiled natively, which avoids the opacity these tools usually carry. It is still under active development and is not suited to wholesale replacement of dependency-heavy applications. A sensible entry point is a dependency-light CLI tool or CI helper script, where you can measure the startup and size difference for yourself.

Related free tools (no sign-up, instant results)

Feel free to contact us

Contact Us