CLI Reference

The CLI has three commands. scriptc --help prints this same surface.

$ scriptc --help
scriptc — TypeScript/JavaScript to native and WebAssembly executables (experimental)

Usage:
  scriptc build <file.ts|.js> [options]     compile to an executable target artifact
  scriptc run <file.ts|.js> [options]       compile and run
  scriptc coverage <file.ts|.js>            how much compiles statically, and why not
  scriptc coverage <file.ts|.js> --dynamic  what a --dynamic build compiles, and what still blocks it
  scriptc coverage <file.ts|.js> --external-types <specifier=file.d.ts>
                                            type-resolve an embedder-provided module for analysis

scriptc build

Compiles a TypeScript (or JavaScript) entry file to a native executable, or to a WebAssembly module when the wasm32-wasi target is selected. The program is type-checked first — by the real TypeScript compiler, honoring the nearest tsconfig.json — and any construct without a lowering is a compile error with an SC-prefixed code, a code frame, and usually a rewrite hint.

$ scriptc build fib.ts -o fib
$ ./fib
832040

Without -o, the executable lands in .scriptc/<name> next to the input, and the generated C translation unit is kept beside it (see --keep-c):

$ scriptc build fib.ts --emit-ir
$ ls .scriptc/
fib
fib.c
fib.ir.json

scriptc run

build followed by executing the binary, with stdio inherited. For wasm32-wasi, the CLI starts the module through Node's WASI Preview 1 host, preopens the current working directory as /, and exposes the host's /tmp as the guest's /tmp.

$ scriptc run fib.ts
832040

Note: run does not forward extra command-line arguments to the program. To pass arguments, build the executable and invoke it directly.

scriptc coverage

Analyzes the program without producing a binary and reports, statement by statement, what compiles statically, what needs the embedded dynamic engine, and what blocks the rest. With --dynamic it answers a different question: what would a --dynamic build compile, and what still blocks it. Both forms are covered in depth in Coverage Reports.

Options

-o, --out <path>
Output executable path. Default: .scriptc/<name> next to the input file.
--dynamic
Embed the dynamic engine (~620KB) so npm dependencies and any-typed code can run. Static stays the default — without this flag, dynamic-tier sites are per-site compile errors. See npm Dependencies.
--ffi <file>
Bind signature-only TypeScript declarations to native C ABI symbols and link the manifest's archive, object, and system-library inputs. See Native FFI.
--backend <c|llvm>
Code generator: llvm (default — emits LLVM IR text, compiled by the same clang) or c (the readable debugging backend). Unset, a native build can fall back to C when the program is outside the LLVM tier. The production wasm32-wasi target never falls back: a missing LLVM lowering is SC3001. Use --backend c explicitly only when inspecting generated C; on WASI that inspection lane accepts async-free programs only and reports SC3001 for coroutine-dependent surfaces.
--npm-static <pkg[,pkg…]|auto>
EXPERIMENTAL. Compile the named npm packages' shipped JS statically as program modules instead of embedding them for the engine (repeatable; auto opts in every eligible direct import). A package the preflight refuses falls back to the island with a coverage-report note. See npm Dependencies for maturity notes.
--provenance-sources
EXPERIMENTAL. Compile npm dependencies from their provenance-attested source, fetched at the attested commit, as static program modules; packages without a usable attestation keep the engine path (a note, never a failure).
--external-types <specifier=file.d.ts>
Coverage only. Map an exact bare module specifier to a local declaration file supplied by an embedder. Repeat the option for multiple modules. The declaration supplies checker types so application coverage can continue; runtime imports and values remain explicit SC1010 blockers. Relative paths resolve from the current working directory. Accepted files end in .d.ts, .d.mts, or .d.cts.
--sanitize
Build with AddressSanitizer plus the runtime reference-count audit — the same lane the compiler's own test corpus runs under. Useful when a program misbehaves and you want leaks or memory errors to be loud.
--emit-ir
Also write the typed IR as JSON (<name>.ir.json) next to the executable.
--keep-c / --no-keep-c
Keep (default) or delete the generated program translation unit next to the executable — the .ll file under the default LLVM backend, or the .c under --backend c (and when the default build fell back). The generated C is readable and annotated with source lines.
--from-c
Treat the input as a C (or .ll) file. Toolchain plumbing and debugging. These arbitrary translation units bypass the persistent artifact cache because their header dependency graph is caller-owned.
-h, --help
Show usage.

Environment variables

SCRIPTC_CACHE_DIR
Override the persistent build-cache root. By default it is $XDG_CACHE_HOME/scriptc/build when that variable is set, $HOME/Library/Caches/scriptc/build on macOS, %LOCALAPPDATA%\scriptc\cache\build on Windows, and $HOME/.cache/scriptc/build on other platforms. The cache stores checksum-verified, content-addressed executables, library archives, and per-flavor runtime objects. Identities include the compiler's resolved system-header dependencies and linker/assembler identities. The compiler remains required so dependency selection is rediscovered on every cache-enabled invocation. FFI builds with archive/object inputs or ambient system_libraries always relink against their current dependencies while retaining runtime-object reuse. Mutable compiler input paths such as CPATH and SDKROOT, and compiler wrappers, bypass persistent artifacts and objects so dependencies rebuilt in place cannot go stale. Opaque archiver wrappers rebuild library program members and archives while retaining runtime-object reuse. Direct Clang, Apple's system Clang shim, zig cc, trusted platform archivers, and zig ar retain their applicable persistent tiers. An existing POSIX override must already be private; otherwise caching is bypassed without changing the directory's permissions.
SCRIPTC_NO_CACHE
Set to 1 to bypass all build-cache reads and writes. An explicitly empty SCRIPTC_CACHE_DIR has the same effect.
SCRIPTC_CACHE_MAX_MB
Maximum build-cache size in megabytes. The default is 4096; the default cache is swept periodically, while an explicitly configured cap is checked after every successful cache write. Least-recently-used entries are removed when the cache exceeds the cap.
SCRIPTC_CC
The C compiler to invoke. zigcc selects zig's bundled clang, which enables cross-compilation with its bundled sysroots.
SCRIPTC_TARGET
Target triple for cross-compilation, e.g. aarch64-linux-gnu.2.36, x86_64-windows-gnu, or wasm32-wasi. WASI builds default to a .wasm output name. See Platform Support.
$ SCRIPTC_CC=zigcc SCRIPTC_TARGET=aarch64-linux-gnu.2.36 scriptc build fib.ts -o fib-linux
$ file fib-linux
fib-linux: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 2.0.0, with debug_info, not stripped

Backends

The default backend emits textual LLVM IR, compiled by the same clang that links the runtime. On native targets, a program outside that tier is never miscompiled—the build falls back to the C backend transparently and says so in one stderr line. The production wasm32-wasi target uses LLVM's 32-bit ABI path and never falls back; an LLVM coverage gap is a build diagnostic. Dynamic npm embedding is LLVM surface on every target.

The C backend is a debugging aid: deliberately readable, source-line-annotated output with differential tests against LLVM wherever the two overlap. Pin it when you want to inspect what your program became:

$ scriptc build fib.ts --backend c -o fib
$ ./fib
832040
$ head -1 fib.c
/* Generated by scriptc from fib.ts. Do not edit. */

An explicit --backend llvm pins the LLVM backend and fails with diagnostic SC3001, naming the unsupported construct, instead of falling back — useful for CI lanes that must notice tier changes.