A stable systems interface for the native TypeScript compiler — over stdio, with no forks and no patches.
corsa-bind is a multi-crate workspace for talking to Corsa
(the native TypeScript 7 implementation line) from Rust and JavaScript runtimes.
Hot paths live in Rust and stay zero-cost; napi-rs, Rustler, and a shared C
ABI carry that performance to JS/TS, Elixir, C, C++, Go, Zig, C#, Swift, and
MoonBit — so you can author custom checker tooling and lint rules without
reimplementing the checker.
It is deliberately not a reimplementation of the TypeScript Compiler API. It is the layer between upstream's checker and everything that wants to use it:
Vize · Oxlint · Node · Rust · C · Go · Swift · …
│
┌────────────────────▼────────────────────┐
│ corsa-bind │
│ stable API/ABI · worker pools │
│ snapshot + process lifecycle │
│ virtual projects · cancellation │
│ backpressure · observability │
└────────────────────┬────────────────────┘
│
upstream native compiler service
TypeScript 7+
As upstream's own API matures, this layer should get thinner — and more important. See the Architecture charter.
Warning
This repository is still evolving. The local Rust and Node API/LSP surfaces are hardened for production-style use, but some upstream-facing endpoints remain explicitly experimental.
Important
corsa-bind is built around upstream-supported Corsa workflows. We follow
Corsa's recommended stdio/API/LSP integration points, keep
ref/corsa-upstream as an exact upstream checkout, and preserve a strict
no forks, no patches policy.
The second half of that policy is own integration, not TypeScript semantics: checker semantics are never ours, checker lifecycle is aggressively ours, and when upstream ships something we approximate today, we delete ours and wrap theirs. The Architecture charter spells out what that rules in and out.
Enter the Nix dev shell and build the workspace:
nix develop
vp install
vp run -w buildA first program in Rust — no Corsa binary required:
use corsa::{
lsp::{VirtualChange, VirtualDocument},
runtime::block_on,
};
use lsp_types::{Position, Range};
fn main() -> Result<(), corsa::CorsaError> {
block_on(async {
let mut doc =
VirtualDocument::untitled("/virtual/minimal.ts", "typescript", "const answer = 41;\n")?;
doc.apply_changes(&[VirtualChange::splice(
Range::new(Position::new(0, 15), Position::new(0, 17)),
"42",
)])?;
Ok(())
})
}cargo run -p corsa --example minimal_startThe Getting started guide covers the Node.js and type-aware Oxlint entry points and how to run against the real pinned Corsa binary.
Full guides live under docs/:
| Guide | What it covers |
|---|---|
| Getting started | First program in Rust, Node.js, and Oxlint |
| Architecture charter | The ownership boundary and the rules that follow from it |
| Architecture | Workspace shape, upstream policy, extension points, naming |
| Node.js binding | @corsa-bind/napi for Node, Deno, and Bun |
| Language bindings | Native bindings for Elixir, C, C++, Go, Zig, C#, Swift, MoonBit |
| Type-aware Oxlint | corsa-oxlint rule authoring and native rules |
| Native rules | The type-aware Rust lint rules and their options |
| Performance | Benchmark entry points and measured numbers |
| CI and local checks | Reproduce the GitHub checks locally |
| Production readiness | Runtime controls and release gates |
| Support policy | Supported platforms, bindings, and experimental scope |
The generated documentation site starts at docs/index.md
and is built with vp run -w docs_build.
- License: MIT
- Upstream:
ref/corsa-upstreamis pinned by exact commit incorsa_ref.lock.toml, with no local patching - Default transport:
SyncMsgpackStdio(msgpack-first) - Runtime: custom in-house runtime, no
tokio - Published packages:
@corsa-bind/napiandcorsa-oxlint(both expect a caller-provided Corsa executable) - Process isolation: every checker query crosses a process boundary on purpose — crash, GC, ABI, and TypeScript-version isolation, plus timeouts, cancellation, restart, and memory kill
- Scaling: single-machine worker pools with project affinity, and repo-level sharding above that; the Raft-backed replication layer was removed in 2.0
Public APIs are still 0.x, so treat compatibility as conservative. See
Known limitations for the current experimental scope.
CI/CD runners for this project are supported by Blacksmith.