A native TypeScript compiler written in Rust. Compiles TypeScript directly to executables using SWC and LLVM.
cargo add perryPerry
Write TypeScript. Ship native. Everywhere.
Perry compiles the TypeScript you already write into real machine-code executables — for macOS, Windows, Linux, iOS, Android, watchOS, and TV. No Node.js to install. No Electron to bundle. No runtime at all. Just a binary. (The same codebase can also target the web, emitted as JavaScript or WebAssembly.)
Website · Documentation · Showcase · Examples
perry compile src/main.ts -o myapp
./myapp # a standalone native binary — ~330 KB for hello world
The language you know. The deployment you wish it had.
Millions of developers write TypeScript every day — but shipping it has always meant shipping a JavaScript engine: a Node install on every server, ~100 MB of embedded runtime per CLI, or a whole browser engine per desktop app. Perry removes the engine. SWC parses your code, LLVM compiles it to machine code, and you get what systems languages get: instant cold starts, tiny self-contained binaries, real threads — without leaving TypeScript.
| Perry | Node.js | Bun | Electron | |
|---|---|---|---|---|
| What you ship | One native binary, from ~330 KB | Your code + a Node install | One binary embedding the JS engine | App bundle with a browser engine |
| Execution | Ahead-of-time machine code | JIT | JIT | JIT |
| Cold start | Instant — no engine to boot, no warmup | Engine boot + warmup | Engine boot + warmup | Browser boot |
| Native UI (no WebView) | ✅ AppKit, UIKit, Android Views, Win32, GTK4 | — | — | Chromium |
| iOS · Android · watchOS · TV | ✅ from the same codebase | — | — | — |
| Multicore | Real OS threads, data-race-safe at compile time | worker_threads | workers | processes |
Table describes Perry's native targets. --target web / --target wasm emit JavaScript / WebAssembly that runs in the browser rather than as a native binary.
Performance
Ahead-of-time machine code means no engine boot and no JIT warmup — and on measured workloads, real multiples over the JS runtimes. Highlights from our open benchmark harnesses (Apple M1 Max, medians of repeated runs):
| Workload | Perry | Node.js | Bun | Rust |
|---|---|---|---|---|
| Image convolution (4K, 5×5 Gaussian) | 354 ms | 1,207 ms — 3.4× slower | 915 ms — 2.6× slower | 392 ms |
| Fibonacci (recursive calls) | 309 ms | 987 ms — 3.2× slower | 518 ms — 1.7× slower | 316 ms |
| JSON pipeline (100 records) | 39 ms | 144 ms — 3.7× slower | 51 ms — 1.3× slower | 34 ms |
| Object allocation (1M objects) | 2 ms | 8 ms — 4× slower | 6 ms — 3× slower | <1 ms |
| Array write (10M elements) | 3 ms | 9 ms — 3× slower | 6 ms — 2× slower | 7 ms |
| Peak memory (JSON pipeline) | 3.5 MB | 36 MB — 10× more | 11 MB — 3× more | 1.2 MB |
Look at the Rust column again: on convolution, fibonacci, and the array-write loop, TypeScript compiled with Perry runs even with — or ahead of — Rust. And Electron isn't in the table because it doesn't compete here: it ships a whole browser engine per app, where a comparable Perry app is a single-digit-MB native binary.
Sources: convolution & JSON from the systems-language report; fibonacci, object allocation & array write from the polyglot sweep (Perry default mode, no fast-math).
We publish everything, including the workloads where V8's JIT still beats us — no cherry-picked table can survive an open harness. Run it yourself: ./benchmarks/run_public_baseline.sh (methodology).
Why developers pick Perry
- ⚡ Native speed, zero warmup. LLVM-optimized machine code with escape analysis, scalar replacement, and a generational GC — see the numbers above.
- 📦 Binaries you can actually email. Hello world is ~330 KB. Perry links only the runtime your program uses. A real MongoDB GUI built with Perry ships as a ~7 MB app.
- 🔌 Your Node code mostly just works. ~97% pass rate on Node's own test suite across 53
node:*modules — real implementations offs,http/http2,net/tls,crypto,stream,child_process,worker_threads,fetchand the web globals, plus ~50 popular npm packages (Fastify, Express, mysql2, pg, ioredis, ws, bcrypt, jsonwebtoken…). Plain JavaScript compiles too. - 🖥️ One UI codebase, 11 targets. A SwiftUI-like API that compiles to real platform widgets — macOS, iOS, iPadOS, visionOS, tvOS, watchOS, Android, Wear OS, Windows, Linux, Web/WASM. Even home-screen widgets.
- 🧵 All your cores, safely.
parallelMap,parallelFilter, andspawnon real OS threads — the compiler rejects shared mutable state, so data races don't compile. - 🔋 Batteries included. Databases, WebSockets, containers, i18n, keychain, notifications, auto-update, a TUI framework — natively implemented and statically linked.
Get started in 60 seconds
# Install (macOS · Linux · Windows)
npm install -g @perryts/perry # or: brew install perryts/perry/perry
# or: winget install PerryTS.Perry
# Create and run a project
perry init my-app && cd my-app
perry run .
npm packages and ES modules work as you'd expect:
import fastify from 'fastify';
const app = fastify();
app.get('/api/users', async () => [{ id: 1, name: 'Alice' }]);
app.listen({ port: 3000 }, () => console.log('Listening on :3000'));
perry compile src/main.ts -o api && ./api # one binary — no node_modules on the server
Same code, other platforms: --target ios, --target android, --target web… full list in the platforms guide. APT, Scoop, install script, and source builds are in the installation guide; run perry doctor to verify your setup.
Built with Perry
Real products, shipping today:
| Project | What it is | Platforms |
|---|---|---|
| Bloom Engine | Native TypeScript game engine — Metal, DirectX 12, Vulkan, OpenGL | macOS, Windows, Linux, iOS, tvOS, Android |
| Mango | Native MongoDB GUI — ~7 MB binary, sub-second cold start | macOS, Windows, Linux, iOS, Android |
| Hone | AI-powered native code editor with terminal, Git, and LSP | macOS, Windows, Linux, iOS, Android, Web |
| dB Meter | Real-time sound level measurement at 60 fps | iOS, macOS, Android |
More in the showcase — built something with Perry? Open a PR and add it.
Documentation
Everything else lives in the docs:
- Getting started — install, hello world, project config
- Language support — supported TypeScript features and limitations
- Native UI · Multi-threading · Standard library
- Platforms — per-platform guides from macOS to watchOS to WASM
- CLI reference — commands, flags,
perry.toml, privacy & telemetry - Contributing — architecture, building from source, and the release process
Community
Perry is built in the open — come say hi:
- 💬 Join the Discord — get help, share what you're building, and talk directly to the people building Perry
- 🐛 Issues — bug reports and feature requests
- 🚀 Showcase — apps the community is shipping
Privacy
Telemetry is opt-in: nothing leaves your machine unless you explicitly enable it in ~/.perry/config.toml, and PERRY_NO_TELEMETRY=1 (or CI=true) always wins. What can be sent is anonymous and redacted — never your source, paths, or project names. Inspect it any time with perry doctor, and see exactly what's in the payload in the privacy & telemetry docs.
Sponsors
Perry's development is backed by our sponsors. 🙏
💎 Skelpo — Premium Sponsor
Want to support Perry and see your logo here? Get in touch via perryts.com.
License
MIT