Jolt logo

Jolt

A Clojure implementation on Chez Scheme.
Self-hosted compiler, Clojure-compatible standard library, no JVM.

Get Started GitHub

Why Jolt?

Self-Hosted Compiler

Reads Clojure, analyzes it to a host-neutral IR, emits Scheme, and runs it on Chez. The compiler is written in Clojure and compiles itself.

No Build Step

A checked-in bootstrap seed runs on a fresh clone immediately. The build is a self-hosting fixpoint — a rebuild reproduces the seed byte-for-byte.

Standalone Binaries

jolt build ahead-of-time compiles a project — runtime, standard library, app, and its deps — into a single self-contained executable. No Chez, no JVM, no source needed to run it.

Real Concurrency

future/promise/agent/pmap run on OS threads over a shared heap, matching JVM semantics. core.async provides channels and go blocks.

Full Numeric Tower

Exact integers and bignums, exact ratios ((/ 1 2)1/2), and flonum doubles. = is category-aware; == is value-equality.

Persistent Data

Immutable vectors (32-way tries), cons lists, and HAMT maps/sets with Clojure value semantics. Transients are real mutable scratch collections.

Clojure-Compatible

Lazy/infinite seqs, transducers, destructuring, multimethods, protocols/records, metadata, namespaces, runtime eval, and the full reader.

Quick Start

Install the self-contained joltc binary — it bundles the runtime, compiler, and standard library, so there's nothing else to install.

# Homebrew
brew install jolt-lang/jolt/jolt

# or the install script (Linux / macOS)
curl -sL https://raw.githubusercontent.com/jolt-lang/jolt/main/install | bash

joltc -e '(+ 1 2)'        # => 3

Or run from a clone (needs Chez Scheme) — no build step, the bootstrap seed is checked in:

git clone --recurse-submodules https://github.com/jolt-lang/jolt.git
cd jolt
bin/joltc -e '(+ 1 2)'        # => 3

Usage

Evaluate an expression

$ bin/joltc -e '(->> (range 10) (filter even?) (map (fn [x] (* x x))) (reduce +))'
# 120
$ bin/joltc -e '(/ 1 2)'
# 1/2

Run a project

bin/joltc run -m myapp.core   # resolve deps.edn, then run -main
bin/joltc -M:test [args]      # run an alias's :main-opts
bin/joltc path                # print the resolved source roots

Compile a standalone binary

bin/joltc build -m myapp.core -o myapp   # single self-contained executable
./myapp arg1 arg2                        # runs anywhere; args reach -main
# --opt for the optimized build, --dev for an unoptimized one

nREPL

bin/joltc --nrepl-server      # auto-resolves deps.edn, writes .nrepl-port
# connect CIDER / Calva / Cursive via the .nrepl-port file, then
# redefine a var and the next call sees it — no restart

Develop against a live process: see REPL-Driven Development.

Read the documentation for installation, writing libraries, and host interop.

Differences from Clojure

Jolt targets Clojure semantics but runs on Chez, not the JVM. Most portable Clojure runs unchanged — persistent collections, the numeric tower, lazy seqs, transducers, multimethods, protocols/records, atoms, future/agent/pmap, core.async, runtime eval, and the full reader all behave as on the JVM. The genuine divergences:

AspectDifference
Java interopNo JVM, so no general Java interop, reflection, or gen-class/proxy — a shimmed subset of java.* is available, plus a C FFI
BigDecimalNot available (decimal? is always false); the rest of the numeric tower matches
RegexCompiled by irregex, not java.util.regex — common patterns work, some Java-specific features differ