Skip to content
cajulang
v0.5.0 · x86-64 · WebAssembly

Simple code.
Native executables.

Caju is a simple, statically typed language that compiles straight to x86-64 machine code, producing native executables for Linux and Windows, and to WebAssembly. The compiler is written in Caju and compiles itself, and it ships with a test runner and a package manager.

curl -fsSL https://raw.githubusercontent.com/cajulang/cajulang/main/install.sh | sh
hello.caju
fn greet(name: str) -> str {
return "Hello, " + name + "!"
}
print(greet("world"))
$ caju run hello.caju
Hello, world!
x86-64
native machine code
ELF, PE, wasm
Linux, Windows and WebAssembly
52 KB
a static hello world
Stage 2 = 3
compiles itself

Simple to write, native to run

A lean syntax with optional types. The compiler produces a small static binary, with no runtime to install.

Native compilation

Caju compiles straight to x86-64 machine code, with no virtual machine. A hello world becomes a 52 KB static executable.

Linux, Windows and WebAssembly

Produces ELF for Linux and PE for Windows: from Linux itself, caju build --target windows builds an .exe. --target wasm builds a WebAssembly module that runs in Node or in the browser, like the playground.

Written in Caju

The compiler and runtime are written in the language itself. The compiler compiles itself, and the output is byte-for-byte identical.

A complete language

Structs, methods, interfaces, pointers, slices, maps, closures, defer, panic and recover, and errors as values.

Optional types

Annotate types when you want to: with them, the compiler catches errors before the program runs. Without them, types are inferred.

Standard library

strings, strconv, math, bytes, os, fs, path, net, http, json, toml, crypto, hash, hex, base64, cli and testing.

Built-in testing

caju test runs your _test.caju files with describe, it and expect, with nothing to install.

Package manager

Packages are GitHub repositories. caju pkg picks the versions and pins everything in a caju.lock with hashes.

See it in code

Two short programs, with the output they print. There are more on the examples page.

Errors are values

The function returns the result and an error, with no hidden exceptions.

divide.caju
fn divide(a: int, b: int) -> (int, error) {
if b == 0 { return 0, errors.New("division by zero") }
return a / b, nil
}
for _, d := range []int{5, 0} {
q, err := divide(10, d)
if err != nil {
print("error:", err)
continue
}
print("10 /", d, "=", q)
}
$ caju run divide.caju
10 / 5 = 2
error: division by zero

Structs, methods and interfaces

A type satisfies an interface just by having its methods, with nothing to declare.

shapes.caju
interface Shape { area() -> num }
struct Rect { w: num, h: num }
struct Circle { r: num }
fn (r: Rect) area() -> num { return r.w * r.h }
fn (c: Circle) area() -> num { return 3.14159 * c.r * c.r }
shapes := []Shape{Rect{2, 3}, Circle{1}}
for _, s := range shapes { print(s.area()) }
$ caju run shapes.caju
6
3.14159
See all examples

Side by side with Go, Rust and Python

The same algorithms, with the same order of operations, in each language. Caju beats or ties Go on every challenge, stays close to Rust and is far ahead of Python.

Run time (lower is better)
ChallengeCajuGoRustPython
fib n=3525 ms38 ms21 ms1.21 s
sieve n=10M22 ms21 ms24 ms2.17 s
nbody n=1M66 ms173 ms66 ms9.10 s
mandelbrot n=1k39 ms38 ms37 ms6.40 s
matmul n=30010 ms32 ms11 ms5.86 s
sort n=2M142 ms142 ms135 ms7.24 s
maps n=3M513 ms612 ms358 ms1.94 s

Executable size

The same program (fib), compiled in each language.
Caju85 KB
Go2,298 KB
Rust4,436 KB

Measured in November 2026 on an AMD Ryzen 7 5700G: best of up to 3 runs, including process startup. Caju 0.3.0, Go 1.27.3, Rust 1.99.1 (opt-level=3), Python 3.12.3. Full programs and results in bench/compare.

HTTP server: Caju + web against Go

The same JSON API written with web, the Caju web framework, with Gin, and with Go's standard net/http. On the same CPUs, Caju serves 1.5 to 2.2 times as many requests per second.

1 CPU, 50 connections

req/s
GET /users/:id2.2×
Caju + web72,468
Gin33,424
Go net/http32,687
GET /users2×
Caju + web41,463
Gin18,824
Go net/http21,054
POST /users2.1×
Caju + web65,638
Gin29,354
Go net/http31,434

4 cores, 1,000 connections

req/s
GET /users/:id1.9×
Caju + web134,502
Gin70,738
Go net/http71,297
GET /users1.5×
Caju + web64,907
Gin43,028
Go net/http38,256
POST /users1.8×
Caju + web122,580
Gin60,591
Go net/http66,844

Requests per second with keep-alive (higher is better). The server is pinned to its CPUs and the load generator runs on the others; Ryzen 7 5700G, WSL2. GET /users returns a list of 50 structs; POST /users reads JSON into a struct. The framework: github.com/cajulang/web · Method and all rounds in bench/http

Packages straight from GitHub

caju pkg ships with the language. There is no central server: a package is a GitHub repository with a caju.toml, and its name is what you import.

  1. Declare
    Dependencies live in caju.toml, each with the minimum version the project needs.
  2. Resolve
    When two packages ask for different versions, the highest of the minimums wins. The choice only changes if someone asks for a higher version.
  3. Lock
    caju.lock records the version, commit and SHA-256 hash of each package's files.
  4. Verify
    Before compiling, caju build and caju run check the hashes. A modified file stops the build.
terminal
$ caju pkg init github.com/acme/app
created caju.toml for github.com/acme/app
$ caju pkg add github.com/acme/strutil
downloading github.com/acme/strutil@1.1.0
added github.com/acme/strutil@1.1.0; 1 packages ok
$ caju run app.caju
CAJU!
$ caju pkg tree
github.com/acme/app@0.1.0
└── github.com/acme/strutil@1.1.0

From code to executable

  1. Install
    curl -fsSL https://raw.githubusercontent.com/cajulang/cajulang/main/install.sh | sh
    Linux x86-64. On Windows, use WSL.
  2. Run
    caju run hello.caju
    Compiles in memory and runs.
  3. Build the executable
    caju build -o hello hello.caju caju build --target windows hello.caju
    A binary for Linux and an .exe for Windows.

Compile your first Caju program

In progress in the native compiler: goroutines, channels and select, plus the native features still missing on Windows.