Skip to content

ChadScriptShip TypeScript as a tiny native program.

ChadScript compiles ordinary TypeScript into one small executable that starts instantly. If it compiles, it prints exactly what Node would. If it can't promise that, it tells you why and how to fix it.

Building a TypeScript file into a 128 KB native binary and running it
128 KB
the whole program, no runtime to install
1.4 ms
to start and run
42.6 ms
the same file on Node

Measured on examples/shapes.ts, Apple M4, 2026-09-23, mean of 40 runs, startup included. More benchmarks, including where Node is still faster.

Your TypeScript, as a native program ​

No new language and no annotations. This is a plain .ts file:

ts
interface Order {
  customer: string;
  total: number;
}

const orders: Order[] = [
  { customer: "ada", total: 120 },
  { customer: "lin", total: 80 },
  { customer: "ada", total: 45.5 },
];

const byCustomer = new Map<string, number>();
for (const o of orders) {
  byCustomer.set(o.customer, (byCustomer.get(o.customer) ?? 0) + o.total);
}
for (const name of byCustomer.keys()) {
  console.log(`${name.padEnd(5)}${byCustomer.get(name)}`);
}
sh
$ bin/chad build hello.ts -o orders
$ ./orders
text
ada  165.5
lin  80

Run the same file with Node and you get the same bytes. That is the promise.

No silent surprises ​

ChadScript knows the shape of every object when the program is compiled, which is a big part of why the binary is small and fast. Code that would change an object's shape later is stopped before it ships, with a message that points at the line and says how to fix it:

ts
interface User {
  name: string;
  email?: string;
}

const user: User = { name: "ada" };
user.email = "ada@example.com";
console.log(user);
text
$ bin/chad check rejected-shape.ts
error[CS1235]: assigning `.email` can add a property to an object created without it (the object literal at rejected-shape.ts:8); objects cannot gain properties
  --> rejected-shape.ts:9:1
  help: create every such object with the property: declare it `email?: T | undefined` and initialize it (`email: undefined`), or use a class that declares `email`

1 error(s)

Declare the property up front and it compiles, and prints what Node prints:

ts
interface User {
  name: string;
  email?: string | undefined;
}

const user: User = { name: "ada", email: undefined };
user.email = "ada@example.com";
console.log(user);
text
{ name: 'ada', email: 'ada@example.com' }

A program either behaves exactly like Node or does not compile. There is no third outcome.

Why try it ​

Small and instant

One self-contained executable, about 130 KB for a small program. It starts in about a millisecond: no engine to boot and no warm-up. Copy it to a machine without Node and run it.

Same results as Node

More than 380 test programs are run with Node and as native binaries on every change, and any difference in output fails the build. Fuzzers add over 100 generated programs to every run.

The TypeScript you already write

Modules and imports, classes, interfaces, unions, generics, closures, Map and Set, async/await, typed JSON.parse, node:fs and node:path.

Is it for you? ​

A good fit today

  • Command-line tools you want to hand someone as a single file
  • Scripts and jobs where startup time matters
  • Data processing with files, JSON, maps and classes
  • Learning how TypeScript maps to machine code

Not yet

  • npm packages that ship only JavaScript
  • any, eval, and adding properties at runtime
  • Browser APIs, HTTP servers and sockets
  • Anything in production: this is an alpha

When ChadScript says no, your code is still valid TypeScript, so the same file runs on Node. See the full list of what works and the limitations.

Try it in a few minutes ​

You need bun, clang and git.

sh
git clone https://github.com/cs01/ChadScript.git && cd ChadScript
bun install && sh scripts/setup-milo.sh
bin/chad run examples/word-count.ts

Next: the getting started guide builds a multi-file program, then the language guide shows what you can write.

ChadScript is an alpha, not released yet, and developed in the open. If you find a program that compiles but prints something different from Node, that is the most important kind of bug: please open an issue. Curious how it works? Read how it works or see the roadmap.