🧭 Decision Guide
Why trending now: Cannot be determined from the provided materials
Try it if you
-
You need to compile `hello.ts` or a Node.js `node:http` service into an executable that does not require Node.The README sections “Build a program” and “Use Node APIs” show `scriptc build`, `./hello`, and `node:http`.
-
You need TypeScript output as IR, C, LLVM IR, assembly, or object files under `.scriptc/`.The README section “Build a program” lists `--emit=ir|c|llvm|asm|obj` and the corresponding files.
-
You need to embed an npm package such as `picocolors` into an executable instead of reading `node_modules` at runtime.The README section “Use npm packages” requires `--dynamic` and states that the result does not read `node_modules` at runtime.
-
Your target is WASI Preview 1 and you can install Zig and use `SCRIPTC_CC=zigcc`.The README section “Build WebAssembly” provides commands using `SCRIPTC_TARGET=wasm32-wasi` and Zig.
Skip it if you
-
Your WASI program depends on network sockets, fetch, child processes, OS signals, or filesystem watching.The README section “Build WebAssembly” says these capabilities fail before linking with `SC3002` on WASI Preview 1.
-
You need to use `--emit=obj` directly as a standalone library.The README explicitly says `--emit=obj` is a relocatable program object, not a standalone library, and contains undefined `scr_*` references.
-
Your project requires a mature production-grade compiler rather than an experimental v0.1.7 project.The README says scriptc is experimental; release metadata shows the latest version is v0.1.7.
-
You can use only Node.js 23 or older.The README section “Installation” requires Node.js 24 or newer.
Requirements
- Node.js 24 or newer.
- `--emit=ir|c|llvm` requires only Node.
- `--emit=asm|obj` uses the matching optional platform helper installed with scriptc on supported macOS, Linux, and Windows hosts.
- Ordinary LLVM-tier executable builds require a platform linker driver and SDK/sysroot.
- WASI and other cross-target builds require Zig, with `zig` available on `PATH`.
- `--dynamic` is used for npm packages and `any`-typed code, and explicitly embeds `quickjs-ng`.
First step (verbatim from README)
$ npm install -g scriptc
Watch out
-
`SCRIPTC_CC=zigcc` selects Zig's `cc` subcommand; it is not a standalone executable.The README section “Build WebAssembly” explicitly explains `SCRIPTC_CC=zigcc`.
-
On macOS 15+ arm64, helper artifacts use the `arm64-apple-macosx14.0.0` deployment target.The README section “Build a program” specifies the helper platform and deployment target.
-
WASI sanitizer builds, native FFI, and library-mode archive builds become target diagnostics.The README section “Build WebAssembly” lists these WASI limitations.
-
External object consumption is still experimental and requires `--print=native-link-info` to generate a JSON recipe with an ABI marker.The README section “Build a program” explicitly calls external object consumption experimental.
Not stated in the README
- The README does not provide a complete support list for different TypeScript projects or Node.js APIs.
- The README provides no performance benchmarks against Node.js, the TypeScript compiler, or other native compilers.
- The README does not state the artifact-size or runtime overhead of embedding `quickjs-ng` with `--dynamic`.
- The README does not provide a complete compatibility matrix for macOS, Linux, and Windows versions.
- The README does not describe API, CLI-parameter, or compatibility commitments after v0.1.7.
- The README does not specify the exact ABI, platform boundaries, or example coverage for native FFI.
💡 Deep Analysis
6
No
I want to compile TypeScript into an object file consumed by a C driver or the Apple linker. Can I treat `--emit=obj` as a standalone library and link it directly?
No. You should not treat --emit=obj as a standalone library; the README explicitly says it is a relocatable program object, not a standalone library.
- The object contains undefined
scr_*runtime references and requires ascr_runtime_abi_v2marker, so matching runtime and ABI information are still required. - External object consumption is experimental; the README requires
--print=native-link-infoto emit a versioned JSON recipe. - That recipe records the target,
mainentry, exact@scriptc/runtimesource pack, system libraries, FFI inputs, and ABI marker. The link command should not be reconstructed from hidden cache paths. - For a self-contained archive, the README points to
scriptc build --lib --profile ...; however, library-mode archives are diagnosed as unsupported for WASI targets.
C-driver or direct Apple-linker integration is possible, but only by following the complete recipe rather than treating the .o as an ordinary library.
- Build a program: `--emit=obj` writes a relocatable program object, not a standalone library
- Build a program: It has undefined `scr_*` runtime references and a required `scr_runtime_abi_v2` marker
- Build a program: Use `--print=native-link-info` to emit a versioned JSON recipe
- Build a program: `scriptc build --lib --profile ...` remains the self-contained archive interface
Yes
My TypeScript tool targets `wasm32-wasi`, the build machine can install Zig, and the program only needs stdin/readline, Promises, timers, and filesystem APIs. Is scriptc suitable?
Yes, provided that the program strictly follows the capability boundary of WASI Preview 1.
- The README requires Zig for WASI and other cross-target builds and uses bundled WASI libc to produce a WASI Preview 1 module.
- It explicitly lists async/await, Promises, generators, timers, stdin/readline events, and callback- and Promise-based filesystem APIs as supported capabilities.
- Network sockets/fetch, child processes, OS signals, and filesystem watching fail before linking with
SC3002; your constraints avoid those limitations. - The build requires
SCRIPTC_CC=zigcc,SCRIPTC_TARGET=wasm32-wasi, andzigonPATH;zigccis not a standalone executable.
If the tool also needs native FFI, sanitizers, or library-mode archives, those capabilities are diagnosed as unsupported for the WASI target.
- Build WebAssembly: WASI and other cross-target builds require Zig
- Build WebAssembly: The WASI target supports async/await, promises, generators, timers, stdin/readline events, callback and promise filesystem APIs
- Build WebAssembly: network sockets/fetch, child processes, OS signals, and filesystem watching fail with `SC3002`
- Build WebAssembly: `$ SCRIPTC_CC=zigcc SCRIPTC_TARGET=wasm32-wasi scriptc build hello.ts --no-keep-c -o hello.wasm >/dev/null`
$ SCRIPTC_CC=zigcc SCRIPTC_TARGET=wasm32-wasi scriptc build hello.ts --no-keep-c -o hello.wasm >/dev/null
Yes
My TypeScript project contains any usage and npm dependencies. Can scriptc tell me which statements compile statically and which sites require dynamic execution before I choose a build mode?
Yes. coverage is specifically designed to support this decision.
- The README says
scriptc coveragereports the percentage of a program that can compile statically and gives a coded diagnostic for every dynamic or unsupported site. - Its example reports
statements analyzed,compile statically, andfully static, allowing you to identify whether a dynamic remainder exists before building. - The README also states that npm packages and any-typed code generally require
--dynamic, so coverage can guide the choice between changing source code, accepting an embedded runtime, or abandoning the native path. - Coverage does not prove full Node compatibility; the project remains experimental, and results depend on target-platform and runtime support.
Running coverage first is therefore the documented way to inspect code locations and diagnostics before choosing a static build or a quickjs-ng-backed dynamic build.
- Check static coverage: `scriptc coverage` shows how much of a program can compile statically
- Check static coverage: gives a coded diagnostic for every dynamic or unsupported site
- README: For npm packages and `any`-typed code, `--dynamic` embeds quickjs-ng explicitly
- README: scriptc is experimental
$ scriptc coverage hello.ts
Yes
I have a type-safe TypeScript CLI, build with Node.js 24+, and target macOS 15+ arm64. Can I use scriptc to produce a standalone program that does not require Node at deployment time?
Yes, this is a good fit because the README explicitly supports producing standalone native executables, and those executables do not require Node at runtime.
- The compiler requires Node.js 24 or newer, but that is a build-time requirement rather than a deployment requirement.
- On macOS 15+ arm64, ordinary LLVM-tier executables use the bundled helper and precompiled runtime pack; clang acts only as the platform linker driver and does not compile the generated program or runtime C.
- Static builds contain a small native runtime but no Node or JavaScript engine. A typed CLI with little dynamic behavior is the best match for this path.
- The README demonstrates the standalone workflow with
scriptc build hello.ts -o hellofollowed by./hello.
However, API coverage and dynamic-language compatibility remain limited, so scriptc should not be treated as a complete Node.js replacement.
- Installation: The compiler requires Node.js 24 or newer
- Installation: The executables it produces do not require Node
- README: On macOS 15+ arm64, ordinary LLVM-tier executables use scriptc's bundled helper and precompiled runtime pack
- Build a program: `$ scriptc build hello.ts -o hello`
$ scriptc build hello.ts -o hello
It depends
My TypeScript CLI uses an npm package such as picocolors and may contain any-typed code. Can I package it with scriptc without having the final executable read node_modules?
It depends, but the README provides a clear compatibility path if you accept an embedded QuickJS runtime.
- The README says npm packages and any-typed code should use
--dynamic; this mode explicitly embeds quickjs-ng. - The resulting executable does not read
node_modulesat runtime, which fits single-file CLI delivery. - The trade-off is that the result is no longer a purely static native program: JavaScript execution comes from embedded QuickJS, so runtime size, performance, and compatibility differ from the static path.
- The project is experimental and does not promise that every npm package, native extension, or Node-specific behavior will work.
The README demonstrates this exact workflow by installing picocolors and running scriptc build cli.ts --dynamic -o cli, so this is the natural path for such a CLI.
- README: For npm packages and `any`-typed code, `--dynamic` embeds quickjs-ng explicitly
- Use npm packages: The result does not read `node_modules` at runtime
- Use npm packages: `$ scriptc build cli.ts --dynamic -o cli`
- README: scriptc is experimental
$ scriptc build cli.ts --dynamic -o cli
It depends
I maintain a TypeScript service using `node:http`, Promises, and filesystem APIs. Can I compile it into a native service that does not require Node on Linux or macOS?
It depends. The README demonstrates that some Node APIs can use the native runtime, but suitability depends on the service’s actual API boundary.
- The
Use Node APIsexample creates an HTTP service withnode:httpand builds it withscriptc build server.ts -o server. - Project insights list support for filesystem, async operations, Promises, generators, timers, and stdin/readline, although coverage depends on the target platform.
- Static builds contain no Node or JavaScript engine; unsupported or non-statically-compilable code is reported diagnostically.
- Ordinary LLVM-tier executables still need a platform linker driver and SDK/sysroot. The precompiled runtime pack does not remove those build requirements.
A controlled HTTP service may therefore fit, while a service depending on the full Node ecosystem, dynamic loading, or unsupported APIs should not be migrated directly.
- Use Node APIs: `import { createServer } from "node:http";`
- Use Node APIs: `$ scriptc build server.ts -o server`
- Installation: Ordinary LLVM-tier executable builds need a platform linker driver and SDK/sysroot
- README: Code that cannot compile statically is reported as a diagnostic
$ scriptc build server.ts -o server
✨ Highlights
-
Supports IR, C, LLVM IR, assembly, and native executables
-
Static artifacts require neither Node nor a JavaScript engine at runtime
-
Can build WASI Preview 1 modules with Zig
-
The project is explicitly experimental and currently at v0.1.7
🔧 Engineering
-
Uses the TypeScript compiler for parsing and type checking, producing typed IR, C, LLVM IR, and native artifacts.
-
`--dynamic` can embed npm package JavaScript and `quickjs-ng` into an executable.
-
`scriptc coverage` reports coded diagnostics for each dynamic or unsupported site.
⚠️ Risks
-
The README calls scriptc experimental; the project has only 4 contributors and 5 releases.
-
`any`, npm packages, and code that cannot compile statically require `--dynamic` or produce diagnostics.
-
WASI Preview 1 does not support networking, child processes, OS signals, or filesystem watching.
-
`--emit=obj` is not a standalone library and contains undefined `scr_*` runtime references.
👥 For who?
-
Developers who need to compile TypeScript CLIs or Node.js APIs into programs that run without Node.
-
Developers experimenting with native compilation for macOS, Linux, Windows, or WASI Preview 1.
-
TypeScript teams that need `scriptc coverage` to inspect static coverage and dynamic-code boundaries.