What If You Could Compile TypeScript Straight to a Native Binary?
You've probably shipped TypeScript by bundling it with a JavaScript engine. That means a Node install on every server, a hundred megabytes of embedded runtime in your CLI, or a full browser engine inside your desktop app. Perry asks a simple question: what if you didn't have to ship any of that? It compiles the TypeScript you already write into real machine-code executables.
What It Does
Perry is a compiler that takes TypeScript source and produces standalone native binaries for macOS, Windows, Linux, iOS, Android, watchOS, and TV. There's no Node.js to install, no Electron to bundle, and no runtime at all. The pipeline is straightforward: SWC parses your code, LLVM compiles it to machine code, and you get an executable. A hello-world binary comes in around 330 KB.
The same codebase can also target the web, emitted as JavaScript or WebAssembly. So you're not locked into native if you later need a browser build. On the UI side, Perry supports native interfaces without a WebView, using AppKit, UIKit, Android Views, Win32, and GTK4 depending on the platform. It also gives you real OS threads that are data-race-safe at compile time, rather than the worker-thread model JavaScript runtimes are stuck with.
Why It's Cool
No engine means no cold start. Because Perry compiles ahead of time, there's no engine to boot and no JIT warmup. Your binary starts executing immediately. That's the kind of thing you stop thinking about until you're deploying a CLI tool that needs to feel instant.
The binaries are genuinely small. A hello world is roughly 330 KB. Compare that to an Electron app shipping a whole browser engine, or a bundled runtime adding tens of megabytes before your code even runs. For CLI tools and desktop utilities, that difference is practical, not cosmetic.
The benchmarks are worth reading closely. On the project's open harnesses (medians on an Apple M1 Max), Perry beats Node.js by 3.4× on a 4K image convolution and 3.2× on recursive Fibonacci. Peak memory on the JSON pipeline is 3.5 MB versus Node's 36 MB. The README is also honest enough to show where Perry loses: on a 500k-record, 108 MB JSON pipeline, Node is 1.6× faster and Bun is 2.5× faster. That kind of transparency is a good sign.
It runs alongside Rust on some workloads. On convolution, Fibonacci, and an array-write loop, Perry's numbers sit at or ahead of the Rust column. That's a striking claim for TypeScript, and it's backed by a linked benchmark report rather than a vague assertion.
One codebase, many targets. iOS, Android, watchOS, and TV from the same source is a real reduction in platform-specific work, and native UI without a WebView means your app looks and behaves like a platform citizen rather than a web page in a frame.
How to Try It
- Grab the latest release from the releases page.
- Compile a file and run it:
perry compile src/main.ts -o myapp
./myapp
That's the whole loop. If you want to target the browser instead, the README notes --target web and --target wasm emit JavaScript and WebAssembly respectively.
For deeper material, there's the documentation, a showcase, and a set of examples to work from. The repository is where you'll find the source and the benchmark harnesses, and there's a Discord if you want to ask questions directly.
Final Thoughts
Perry is aimed at people who like TypeScript but want the deployment characteristics of a systems language: small binaries, instant startup, real threads, native UI. The benchmark caveat matters, though. Performance is workload-dependent, and the README itself shows cases where Node and Bun win, so measure against your own use case before assuming the multiples carry over. If you're building CLIs, desktop apps, or anything that ships to mobile and would rather not drag a runtime along, this is worth a serious look. The project is still early, but the approach is sound, and the honest benchmarking suggests the team knows what they're doing.
Follow @githubprojects for more developer tools and open source projects.