Xo is experimental. v0.9 is out; expect breaking changes before 1.0. Read the release notes
v0.9 · experimental · linux, darwin, windows, wasi

Agents write the code. The compiler reviews every line.

Xo (pronounced ex-oh, like the letters X and O) is a small, statically typed language for backends and web services. Every check reports JSON with stable codes and ready-made fixes, so an agent can write, check, and repair a service before it ever reaches review.

Finan the fennec fox, alert
xo check --json ./main
{
  "code": "XO0401",
  "severity": "error",
  "message": "expected `()`, found `Result[Str, Error]`",
  "span": { "file": "main/main.xo", "line": 6, "col": 3 },
  "notes": [{ "message": "the value is a `Result`; propagate
    the error with `?` or handle it with `match`" }],
  "fixes": [{
    "title": "propagate with ?",
    "edits": [{ "span": { "line": 6, "col": 11 }, "replace": "?" }]
  }]
}
// why xo

Ideas from great languages, in one small one.

Xo borrows what has proven itself in Go, Rust, Swift, and Kotlin, and turns the bugs tests usually miss into compile errors. In a study of 30 planted safety bugs, Xo caught or prevented 23 to 29, against 13 for Go with strict analyzers and 9 for plain Go.

from Go

Small and fast

Few keywords, one obvious way, one formatter, fast builds, and static binaries for linux, darwin, windows, and wasi.

from Rust

Errors you can't ignore

Result and ?; an unhandled error is a compile error.

from Rust and ML

Sum types, exhaustive match

Every case handled, and every match target.os arm type checked for every target.

from Swift and Kotlin

No nil

Optionals are T? and checked at every use.

from Swift and Kotlin

Structured concurrency

No task outlives its scope; value semantics mean no data races.

new in Xo

Effects you can see

uses net, fs.read in the signature, with capabilities passed from main.

interop · Go

Use any Go package

Bindings are generated on the fly. (T, error) becomes T ! go.Error, and a nil pointer becomes T?.

use go "regexp"
use go "github.com/google/uuid" as uuid
interop · C

Call C from native builds

The LLVM and arm64 backends bind C headers directly, with effects declared at the boundary.

use c "zlib.h" link "z" uses none
// zlib.crc32(0, b"hello")
// one binary

Tools made for machines and people.

Semantic queries and edits work on resolved symbols, so tools never guess from text.

xo check --jsonType, effect, and concurrency checks
xo build --targets=allStatic binaries for four OSes
xo test --explore=NSearches task interleavings
xo query callersSemantic queries for agents
xo edit renameEdits rechecked before writing
xo explain XO0401Every code, explained
// after the fixes

Zero errors. Finan goes back to sleep.

Fennec foxes rest through the heat of the day. A service that compiled clean can too.

zsh
$ xo check ./...
1 module(s), 0 error(s), 0 warning(s)
$ xo build --targets=all ./main
# static binaries for linux, darwin, windows, wasi
Finan curled up asleep