Praxis
Praxis is a Clojure-shaped Lisp that compiles to the BEAM and to JavaScript. Its compiler, runtime, standard library and toolchain are written in Praxis and compile themselves. It is in active development and not published yet.
What it is
Praxis takes Clojure’s syntax — literals for vectors, maps and sets, sequence functions, threading — and puts it on Erlang/OTP’s semantics: immutable bindings, multi-clause functions with guards, pattern matching everywhere, processes, supervision and hot code reload. It is a Lisp-1 and homoiconic; macros are written with syntax-quote.
On the BEAM every namespace becomes an ordinary .beam module, so Erlang and Elixir can call it like any other. On JavaScript every namespace becomes an ES module for node or the browser. Interop is direct: a Praxis record is an Elixir struct, a Praxis protocol is an Elixir protocol.
A first taste
(ns demo "A few functions.")
(defn split "Divides `total` among `people`."
[total people] :spec [integer integer -> number]
(/ total people))
(defn classify
([n] :when (< n 0) :negative)
([0] :zero)
([_n] :positive))
(split 4260 3) ; => 1420
(split 4250 3) ; => 4250/3
(seq/map [-5 0 7] classify) ; => (:negative :zero :positive)
(-> " night market " string/trim string/upper-case)
; => "NIGHT MARKET"Division is exact — 4250/3 is a ratio, not a rounded float. :spec declares the signature, which feeds Dialyzer, TypeScript declarations and property tests. The standard library takes its subject first, so -> is the pipeline.
Design
- BEAM conformity first: where another BEAM tool could tell the difference, Praxis does what the BEAM does.
- Few special forms.
condis the one primitive branch;if,when,and,or,caseandwithare macros over it. - A name keeps its value. Rebinding is a compile error, as in Erlang.
- Numbers never overflow and division is exact: bignums, ratios and decimals are part of the language.
- One source, two machines. Portable code runs unchanged on the BEAM, on node and in the browser — processes included.
- Tools talk to people and to machines. Every
prxcommand can answer in JSON, and an MCP server comes with the toolchain.
The name is Greek: πρᾶξις, doing — action that carries its end in itself, as distinct from knowing (theoria) and making (poiesis). Praxis is the compiled sibling of Logos, the embeddable Lisp; the two share a specified grammar but no code.
The toolchain
| Tool | Does |
|---|---|
praxis | Compiles files and runs scripts; praxis explain PRX0128 explains a diagnostic |
prx | The project tool: manifest, lock file, dependencies from Hex, git or paths, tasks, releases, plugins |
prepl | The interactive prompt, with live redefinition and :h for documentation |
| plugins | prx test, fmt, lint, check (Dialyzer, reported in Praxis terms), docs, release, a language server, a debug adapter and an MCP server |
| editors | A tree-sitter grammar and a VS Code extension |
Libraries written in Praxis include ports of Cooper for configuration, Dextrin for DXN data, Ichor for grammars, the test framework Touchstone — and Webglue, a web framework.
File types
The extension says which machines a file is for; a namespace can also declare what it needs, such as processes or blocking I/O, and a machine what it offers.
| Extension | For |
|---|---|
.prax | every machine |
.praxe | the BEAM only |
.praxj | JavaScript — node and browser |
.praxn / .praxb | node only / the browser only |
.pxn | data, such as the project manifest project.pxn |
Where it stands
The current release is v0.60.0 (22 September 2026) — sixty releases since the first commit on 20 August. The compiler, runtime and toolchain are written in Praxis and bootstrap themselves; only a small seed compiler in Elixir remains. The language itself is frozen at v0.56.0: its forms and shapes are settled, while the toolchain keeps moving. The work now is a book — the tutorial — and after it, distribution: publishing packages, an installer, and a stability commitment on the way to 1.0.