A native, statically typed Lisp with a REPL that compiles to Odin.
48
stars
0
commits
Odin
primary language
Sep 9, 2026
updated
A practical Lisp for systems programming that compiles to Odin.
Kvist combines Clojure-inspired syntax, source macros, immutable data, and interactive development with a native, statically typed execution model. Ordinary values have Odin-like representation and ownership: allocation, mutation, and cleanup remain explicit, and generated programs require no VM or garbage collector.
Kvist transpiles to readable Odin, imports Odin core and vendor packages directly, and allows Kvist and Odin source files to live in the same package.
When data-oriented programming is a better fit, Data provides EDN in memory:
immutable maps, vectors, sets, lists, keywords, symbols, and tagged values.
This makes Hiccup, transactions, Datalog queries, configuration, and other data
DSLs feel like Lisp without making every runtime value dynamic.
Ordinary Kvist values stay concrete and statically typed. This transform over native structs lowers to one direct loop:
(defstruct User {
name: string
active?: bool
})
(defn active-names [users: []User] -> [dynamic]string
(into [dynamic]string
(comp
(filter .active?)
(map .name))
users))
When the shape itself is data, the same language can express Lisp-shaped DSLs as immutable values:
(defn page [title: string] -> Data
[:main {:class "page"}
[:h1 title]
[:p "Ready"]])
(def names-query
'[:find ?name
:where [?e :contact/name ?name]])
The official HTML package renders the
first value as Hiccup-shaped HTML. VevDB uses
the same Data model for Datomic-style transactions, Datalog queries, rules,
pull patterns, and query results.
Install the Odin compiler, clone this repository, and build the Kvist CLI from the repo root:
git clone https://github.com/kvist-lang/kvist.git
cd kvist
odin build src/cli/kvist
Add a main function to a hello.kvist file:
(defn main []
(println "hello from kvist"))
Run it:
$ ./kvist run hello.kvist
hello from kvist
Or use the same file as context for the native REPL:
$ ./kvist repl hello.kvist
Kvist native REPL
kvist=> (+ 1 1)
2
kvist=> (defn square [x: int] -> int (* x x))
kvist=> (square 11)
121
To install the compiler and shipped packages under a separate root:
./scripts/install.sh ~/.local/lib/kvist
export PATH="$HOME/.local/lib/kvist/bin:$PATH"
A REPL submission is ordinary Kvist: it is read, macro-expanded, type checked, ownership checked, lowered to Odin, compiled, loaded, and executed as native code. Definitions and supported typed values persist across submissions, and compatible redefinitions update later calls without replaying earlier forms.
The terminal client and editor-neutral JSONL protocol use the same native session. The Emacs client adds source-buffer evaluation, completion, documentation, retained value inspection, source-level stepping, execution traces, conditions and restarts, and attachment to running applications.
See the native REPL guide and Emacs guide.
Kvist imports Odin packages directly:
(import os "core:os")
(import sha2 "core:crypto/sha2")
(import raylib "vendor:raylib")
Procedures, types, constants, enums, multiple return values, allocators, and errors retain their Odin semantics. Kvist and Odin source may also live in the same package and call each other without a wrapper layer.
See the Odin interoperability guide and interop examples.
Data
matching.Data validation and decoding into native structs, enums, and arrays,
with precise error paths.Data../kvist check examples/language/hello.kvist
./kvist run examples/language/hello.kvist
./kvist repl examples/language/hello.kvist
./kvist test examples/coverage/packages/test-package-tests.kvist
./kvist eval examples/collections/higher-order.kvist '(threaded-total)'
./kvist expand examples/collections/higher-order.kvist '(threaded-total)'
./kvist lifetimes examples/collections/ownership-warnings.kvist
Run ./scripts/smoke.sh for a quick local check.
Kvist is tested on macOS and Linux. The core CLI and representative programs are also tested on Windows, but the complete test suite and shell-based tooling are not yet covered there.
Building Kvist requires an Odin toolchain supported by the host platform. The
scripts in scripts/ require a POSIX-compatible shell.
Kvist is licensed under the MIT License. See LICENSE.
Programs written in Kvist, and Odin code generated from user-authored Kvist source, are not required to use the MIT License merely because they were compiled with Kvist. Code copied from Kvist packages or runtime support remains under its applicable license.
Odin
84.4%
Clojure
7.9%
Emacs Lisp
4.8%
Shell
2.9%
A native, statically typed Lisp with a REPL that compiles to Odin.
48
stars
0
commits
Odin
primary language
Sep 9, 2026
updated
A practical Lisp for systems programming that compiles to Odin.
Kvist combines Clojure-inspired syntax, source macros, immutable data, and interactive development with a native, statically typed execution model. Ordinary values have Odin-like representation and ownership: allocation, mutation, and cleanup remain explicit, and generated programs require no VM or garbage collector.
Kvist transpiles to readable Odin, imports Odin core and vendor packages directly, and allows Kvist and Odin source files to live in the same package.
When data-oriented programming is a better fit, Data provides EDN in memory:
immutable maps, vectors, sets, lists, keywords, symbols, and tagged values.
This makes Hiccup, transactions, Datalog queries, configuration, and other data
DSLs feel like Lisp without making every runtime value dynamic.
Ordinary Kvist values stay concrete and statically typed. This transform over native structs lowers to one direct loop:
(defstruct User {
name: string
active?: bool
})
(defn active-names [users: []User] -> [dynamic]string
(into [dynamic]string
(comp
(filter .active?)
(map .name))
users))
When the shape itself is data, the same language can express Lisp-shaped DSLs as immutable values:
(defn page [title: string] -> Data
[:main {:class "page"}
[:h1 title]
[:p "Ready"]])
(def names-query
'[:find ?name
:where [?e :contact/name ?name]])
The official HTML package renders the
first value as Hiccup-shaped HTML. VevDB uses
the same Data model for Datomic-style transactions, Datalog queries, rules,
pull patterns, and query results.
Install the Odin compiler, clone this repository, and build the Kvist CLI from the repo root:
git clone https://github.com/kvist-lang/kvist.git
cd kvist
odin build src/cli/kvist
Add a main function to a hello.kvist file:
(defn main []
(println "hello from kvist"))
Run it:
$ ./kvist run hello.kvist
hello from kvist
Or use the same file as context for the native REPL:
$ ./kvist repl hello.kvist
Kvist native REPL
kvist=> (+ 1 1)
2
kvist=> (defn square [x: int] -> int (* x x))
kvist=> (square 11)
121
To install the compiler and shipped packages under a separate root:
./scripts/install.sh ~/.local/lib/kvist
export PATH="$HOME/.local/lib/kvist/bin:$PATH"
A REPL submission is ordinary Kvist: it is read, macro-expanded, type checked, ownership checked, lowered to Odin, compiled, loaded, and executed as native code. Definitions and supported typed values persist across submissions, and compatible redefinitions update later calls without replaying earlier forms.
The terminal client and editor-neutral JSONL protocol use the same native session. The Emacs client adds source-buffer evaluation, completion, documentation, retained value inspection, source-level stepping, execution traces, conditions and restarts, and attachment to running applications.
See the native REPL guide and Emacs guide.
Kvist imports Odin packages directly:
(import os "core:os")
(import sha2 "core:crypto/sha2")
(import raylib "vendor:raylib")
Procedures, types, constants, enums, multiple return values, allocators, and errors retain their Odin semantics. Kvist and Odin source may also live in the same package and call each other without a wrapper layer.
See the Odin interoperability guide and interop examples.
Data
matching.Data validation and decoding into native structs, enums, and arrays,
with precise error paths.Data../kvist check examples/language/hello.kvist
./kvist run examples/language/hello.kvist
./kvist repl examples/language/hello.kvist
./kvist test examples/coverage/packages/test-package-tests.kvist
./kvist eval examples/collections/higher-order.kvist '(threaded-total)'
./kvist expand examples/collections/higher-order.kvist '(threaded-total)'
./kvist lifetimes examples/collections/ownership-warnings.kvist
Run ./scripts/smoke.sh for a quick local check.
Kvist is tested on macOS and Linux. The core CLI and representative programs are also tested on Windows, but the complete test suite and shell-based tooling are not yet covered there.
Building Kvist requires an Odin toolchain supported by the host platform. The
scripts in scripts/ require a POSIX-compatible shell.
Kvist is licensed under the MIT License. See LICENSE.
Programs written in Kvist, and Odin code generated from user-authored Kvist source, are not required to use the MIT License merely because they were compiled with Kvist. Code copied from Kvist packages or runtime support remains under its applicable license.
Odin
84.4%
Clojure
7.9%
Emacs Lisp
4.8%
Shell
2.9%