Xo is experimental. The source code is not public yet; until then, try Xo in your browser.
Menu · The toolchain: binaries and commands

Docs

The toolchain: binaries and commands

Xo is experimental, and the commands and flags below may change before 1.0. The specification’s section 10.1 is the authoritative list of commands and flags; this page is the practical guide to it.

What xo is

xo is one binary: the compiler, the formatter, the test runner, the module tools, and the editor and agent servers. It is written in Xo (the self-hosted compiler, built from selfhost/xo in the repository; you may see it called xo1 in the project’s notes). The original implementation, written in Go, is frozen and serves as the seed that builds the first Xo compiler on a machine.

The layout

An installed toolchain is a directory, and xo finds the rest of the toolchain relative to itself:

bin/xo          the toolchain
bin/xo-gobind   a helper that binds Go packages for use go
lib/xo/         std, third_party, the prebuilt native runtime, zoneinfo.zip

Keep the layout: bin/xo looks for the standard library and the runtime in ../lib/xo, so a copy of bin/xo on its own does not work. Put bin on your PATH, or link bin/xo from a directory on your PATH (symbolic links are followed). Set XO_STD to point at the standard library when it lives somewhere else, as it does in a checkout.

Building it from source

From a checkout of the repository, the Go seed (Go 1.26 or later) builds the first Xo xo. On an arm64 host (Apple silicon, arm64 Linux):

go build -o .tools/bin/xo-seed ./cmd/xo
XO_SELF_DRIVER=0 .tools/bin/xo-seed build --backend=arm64 -o .tools/bin/xo selfhost/xo
export XO_STD="$PWD/std"

On an x86-64 host, with clang installed:

go build -o .tools/bin/xo-seed ./cmd/xo
XO_SELF_DRIVER=0 XO_LLVM_SPLIT=12 XO_LLVM_LTO=none \
  .tools/bin/xo-seed build --backend=llvm -o .tools/bin/xo selfhost/xo
export XO_STD="$PWD/std"

The arm64 build takes a few minutes; the x86-64 build took about 36 minutes and 10 GB of memory on a 16 vCPU Linux machine. After that, any Xo xo rebuilds itself without Go (scripts/bootstrap-xo.sh; see the bootstrap post for how that is checked). Getting started walks through a first program.

Backends and targets

--backend picks how a program is built. Each backend needs different tools on the machine.

BackendFlagBuilds forNeeds
Go (default)--backend=go or noneevery target in --targets: linux, darwin, windows (amd64 and arm64), and wasip1/wasmthe go command, Go 1.24 or newer (or XO_GO naming it)
LLVM--backend=llvmthe host, including x86-64 Linux and Intel Macsclang
arm64--backend=arm64darwin/arm64 and linux/arm64a C compiler driver (cc), or none with --ld=macho and a prebuilt runtime
WebAssembly (experimental)--backend=wasmWASI preview 1nothing else; the module runs under any WASI runtime
  • --no-gc builds on a native backend whose memory is reference counted instead of collected: arm64 on arm64 hosts, LLVM otherwise. --backend=llvm and --backend=arm64 already imply it. A construct a native build does not support yet is error XO1201 at compile time.
  • --targets=all (Go backend) builds linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64, windows/arm64, and wasip1/wasm, one binary per target.
  • --ld=macho links an arm64 program with Xo’s own assembler and linker, with no cc. It needs the prebuilt runtime in lib/xo of a packaged toolchain (or XO_RTPACK). On a Mac it is the default when that runtime is present. --ld=cc uses the system linker.
  • Windows (x86-64) and Intel Macs build natively through the LLVM backend; this work is in progress and tested on a smaller scale than the arm64 hosts.
  • Linux programs with no C library at all are an opt-in experiment (XO_NOLIBC=1 with a native backend), in progress: they refuse use c and TLS for now.
  • use c works only on the native backends, and use go only on the Go backend.
  • A program that names time zones reads them from Go’s zoneinfo.zip, lib/xo/zoneinfo.zip, XO_ZONEINFO, or with --tzdata=system, from the system’s zone files.

Commands

xo help lists every command, and xo help <command> or -h/--help prints a command’s usage. Every command that reports diagnostics or results accepts --json, and xo query answers in JSON by default when its output is not a terminal. The examples run in a module directory.

A directory argument covers every directory below it, skipping testdata, vendor/, and names starting with . or _. So xo check . checks every module under the current directory, and the Go-style pattern ./... (or cmd/...) means the same thing: xo check ./..., xo test ./.... A pattern that matches no .xo files is an error, and xo run takes one directory, not a pattern.

Build, run, and test

CommandWhat it doesExample
xo buildBuild binariesxo build --targets=all -o out .
xo runBuild for the host and run; arguments after -- go to the programxo run --backend=arm64 . -- --port 8080
xo testRun the test blocks, property tests, and contract fuzzing, with deterministic schedulingxo test --explore=100 .

Useful flags of all three: --backend, --no-gc, -o, --json, --tzdata=embedded|system. xo build and xo run take --stamp NAME=VALUE (sets a string constant for this build). xo build also takes --targets, --ld, --ci (fail on unformatted code or a leftover dbg), and --release. xo test takes --seed=N, --explore=N, --cases=N, --run=NAME, -v, and --real (tests that declare effects run with real capabilities).

Check and edit

CommandWhat it doesExample
xo checkParse and type check, no code generationxo check --fix .
xo fmtFormat to the one canonical layoutxo fmt --check .
xo fixApply every machine fix until none appliesxo fix --dry-run .
xo vetAdvisory checks that never fail the buildxo vet .
xo querySemantic queries: type, def, callers, effects, holes, api, imports, deps, hashxo query callers greet
xo editSemantic edits: rename, add-field, change-sig, rechecked before writingxo edit rename --dry-run greet salute
xo docDocumentation from doc commentsxo doc .
xo explainThe long explanation of a diagnostic codexo explain XO0201

xo check --fix is the agent loop’s check: it applies every unambiguous fix, reformats what it changed, and reports what remains.

Modules and dependencies

CommandWhat it doesExample
xo initStart a modulexo init example.com/hello
xo getRequire a module version, printing its API and effect changesxo get github.com/acme/billing@v1.4.1
xo mod tidyTidy xo.mod and xo.lockxo mod tidy
xo mod accept-effectsRecord a dependency’s wider effects in xo.lockxo mod accept-effects github.com/acme/billing
xo vendorCopy dependencies into vendor/xo vendor
xo auditSupply chain report: each dependency’s effects, escape hatches, and the capabilities you pass itxo audit .
xo publishCheck a release of your module against its previous tagxo publish --check

xo mod clean empties the module cache, and xo mod proxy serve serves it as a module proxy. Every module command takes --offline. See Dependencies and capabilities for effect ceilings and vouches.

Bindings

CommandWhat it doesExample
xo bindGenerate bindings of Go packages for use go (runs xo-gobind)xo bind github.com/google/uuid
xo bind --cGenerate bindings of C headers for use cxo bind --c --link z zlib.h

You rarely need to run these yourself: xo check and the builds bind a missing package or header on first use.

Servers and debugging

CommandWhat it doesExample
xo lspLanguage Server Protocol server over stdio, for editorsconfigure your editor to run xo lsp
xo mcpModel Context Protocol server over stdio, for agents: check, query, edit, explain, fmt, test, buildconfigure your agent to run xo mcp
xo serveA resident checker on a Unix socket; xo check and xo query use it when it answersxo serve
xo dumpThe task tree of a running programxo dump 4121
xo replayReplay a run recorded with xo run --record=trace.xotrace (Go backend), or a crash bundle (.xocrash)xo replay trace.xotrace
xo versionThe toolchain version and hostxo version

Environment variables

VariableWhat it does
XO_STDWhere the standard library is, when xo is not in the toolchain layout (a checkout: $PWD/std)
XO_GOThe go command the Go backend uses, when it is not go on the PATH
XO_ZONEINFOA zoneinfo.zip for programs that name time zones
XO_RTPACKA directory of prebuilt native runtimes, instead of lib/xo/rtpack
XO_NOLIBC=1Linux native builds with no C library (opt-in, in progress)

Two more apply only to the Go seed when it builds the first Xo xo: XO_SELF_DRIVER=0 makes the seed do the build itself (as in the commands above), and XO1 points it at an Xo compiler you already built.

Coming later

Developer harnesses written in Xo, under an xo dev command, are planned (decision 0209) but do not exist yet.