Lasm compiles Lean 4 to WebAssembly, with a 117-theorem sample app

Lasm compiles Lean 4 to WebAssembly, with a 117-theorem sample app

Lasm is a project that compiles ordinary Lean 4 programs ahead of time to WebAssembly. According to its README, one Lean code base can become a Node server, a serverless or edge function, a WASI or Fastly module, or a browser app. The pitch is that because the code is Lean, you can prove properties of the code you deploy. Lasm ships on npm and brings Lean, Lake and its build tools with it, so you only need Node (or Bun or Deno). A project starts with npm create @lasm@latest my-app -- --template hono, and a single file needs no project at all: save a main function as Main.lean and run npx @lasm/cli Main.lean.

The flagship example is Conduit, the RealWorld app (a Medium clone), written entirely in Lean: the REST API, the server-rendered browser app and the proofs. It comes with 117 theorems about the code that actually runs, checked with no sorry and only Lean's standard axioms. They cover authorization (only authors change their articles and comments), follows and favorites, slugs that never collide, pagination that never skips or repeats, validation shared by client and server, JSON round trips and Markdown link safety. The endpoints are written against a Store of functions, and the proofs run that same code on a model of the tables.

The README is explicit about what is not proved. Trusted rather than proved: that each SQL statement does what its model says, the JSON text layer, concurrency between requests, and Lean, Lasm and the JavaScript runtime. Conformance to the whole RealWorld spec is tested, not proved. On the tested side, the official RealWorld API suite passes unmodified (13 of 13 files, 154 requests) on Node with node:sqlite, Cloudflare Workers with D1 and Bun with bun:sqlite. The official Playwright end-to-end suite passes with no retries on Node with Chromium, Firefox and WebKit, and on Workers and Bun with Chromium. All of this runs in CI (run 40615274657, with @lasm/cli 0.3.4). By project policy CI never deploys to a real cloud account; each hosted platform is tested with its local runtime, image or emulator.

The README also shows a fullstack template: one Lean project with a server (Lasm.Fetch), a browser app (Lasm.UI) and the API between them (Lasm.RPC). A validation rule such as checkTitle is written and proved once in a shared file that both sides import. The server's Store.add demands a proof that the title passed the check, and a client theorem states that the browser app never sends an invalid title. In that template, the JSON/HTTP transport, the JavaScript that applies patches to the real DOM, the Lasm compiler and runtime, and the browsers are not proved but tested in CI. Lean's own compiler is trusted, as in any Lean program.

To call JavaScript, you declare each function with a one-line @[js "module" "export"] binding, and the Lean type says how values convert. There are no premade bindings for npm packages; Lasm.Web covers the core web platform. Each call crosses from a Lean thread to Node's main thread and costs about 24 µs, so the README advises one coarse call over many small ones.

The README lists the costs. Node builds have Lean's full runtime (threads, files, processes, sockets). Edge, Bun/Deno, WASI and browser builds run Lean single-threaded, without sockets or processes, and without files except on WASI. Pure-Lean Std.Http on Node is slow at 1,290 req/s, so it recommends Hono, Express, Fastify or Lasm.Fetch for production HTTP. Cold starts are CPU-bound and grow on small serverless CPU shares. Arithmetic on numbers with thousands of digits is slower than native Lean because there is no GMP. The first build on a new machine downloads Lean and build tools (about 250 to 275 MB; 19 s on the Linux CI runner); later dev builds of a one-line change take about 1 to 2 s, and lasm dev rebuilds about 2 s after each save and keeps the last good build running when there is a type error.

Other limits: Lasm is ahead-of-time only, so a deployed program cannot elaborate, evaluate or compile Lean. Only Lean 4.35.0 is supported; other toolchain versions are rejected. A built Node server needs Node 24+, and an app should get at least 512 MB because it reserves about 22 GB of virtual address space. Prebuilt native libraries cannot be linked. There is no Windows ARM64 or Alpine/musl build machine, though built apps run on Alpine. The README says performance numbers come from a free GitHub runner (4-CPU AMD EPYC, Linux x64) on candidate build 0.1.0-experimental.40494203854 from 2026-10-27, with full tables in BENCHMARKS.md. The README also asks for sponsorship, and it points AI agents to an llms.txt index and a docs/AI.md rules file.

Key facts

  • Lasm compiles ordinary Lean 4 ahead of time to WebAssembly; one code base can target a Node server, serverless or edge functions, WASI/Fastly modules or a browser app.
  • The flagship Conduit (RealWorld) app is written entirely in Lean and ships with 117 proved theorems, checked with no sorry and only Lean's standard axioms.
  • The official RealWorld API suite passes unmodified (13 of 13 files, 154 requests) on Node, Cloudflare Workers and Bun; the README says SQL behavior, JSON text handling, concurrency and the runtime are trusted, not proved.
  • Costs are stated openly: pure-Lean Std.Http on Node manages 1,290 req/s, each JS call costs about 24 µs, and Node apps should get at least 512 MB.
  • Only Lean 4.35.0 is supported, and deployed programs cannot elaborate or compile Lean at run time.

Why it matters

Lasm aims to let a Lean developer ship real web software on the platforms people already use, from Node servers to Cloudflare Workers, Fastly and the browser, while keeping Lean's ability to prove properties of the deployed code. The Conduit example makes this concrete: authorization, pagination, slug uniqueness and shared client/server validation are covered by theorems about the code that actually runs, not a separate model of it.

Who it affects

Lean 4 users who want to build web backends, edge functions or browser apps, and developers interested in proving properties of application code. Because Lasm ships on npm and needs only Node, Bun or Deno, JavaScript developers can try it without installing Lean by hand. The README also directs AI agents to llms.txt and docs/AI.md.

How to use it

Start a project with npm create @lasm@latest my-app -- --template hono, then cd my-app && npm install && npm run dev. Templates and deploy options cover Node servers (Hono, Express, Fastify, std-http, fetch), AWS Lambda, Vercel, Netlify, Azure, Google Cloud Functions, Cloudflare Workers, Fastly Compute, Spin, WASI, browser apps and a fullstack template. A single file works with npx @lasm/cli Main.lean. Lasm never installs or starts a platform's own CLI such as wrangler, vercel or fastly; you run those. The toolchain must be Lean 4.35.0 exactly. The README asks for sponsorship, but the terms are not in the text seen.

How solid is it

The claims come from the project's own README, written by the project's author. The 117 theorems are runnable with npm run proofs, and the README says each is listed in plain English in PROOFS.md. The test results are tied to a CI run (conduit.yml, run 40615274657, with @lasm/cli 0.3.4), and the performance numbers to a candidate build, 0.1.0-experimental.40494203854 from 2026-10-27, on a free GitHub runner. The version string marks it as experimental. The README says that CI never deploys to a real cloud account, and it mentions no production users.

Risks and caveats

Verification is partial. Only the listed properties of Conduit are proved; SQL statements matching their model, the JSON text layer, concurrency between requests, and Lean, Lasm and the JavaScript runtime are trusted, and conformance to the whole RealWorld spec is tested, not proved. Performance has a price: Lean on Node pays for WebAssembly and its threads, pure-Lean Std.Http runs at 1,290 req/s, cold starts grow on small CPU shares, and big-number arithmetic is slower than native Lean. Edge, Bun/Deno, WASI and browser builds are single-threaded without sockets or processes. A Node app reserves about 22 GB of virtual address space and should get at least 512 MB. There is no Windows ARM64 build, and prebuilt native libraries cannot be linked.

“Because it is Lean, you can prove properties of the code you deploy.”

— Lasm README