r/lisp • • May 25 '26

New CL VSCode extension: OLIVE

Thumbnail marketplace.visualstudio.com
44 Upvotes

Also on Open VSX Registry (for VSCodium): https://open-vsx.org/extension/kchanqvq/olive

Why another VSCode extension? VSCode is important for getting newcomers nowadays. I have some very smart people at work who use VSCode, like everyone else. Selling Lisp and Emacs at the same time is ε2 harder, so I told them to use Alive, and start hacking on my super-duper research code. The result was shocking -- they come back reporting "unproductive" because "small problems here and there like REPL freezing". And they refuse to try Lisp again, because first impression matters, what a tragedy!

I have lived in our Emacs bubble comfortably for too long, and blundered recommending something I never used. I should have tried Alive at least once before recommending it!!! So I installed VSCode and Alive to see what's going on. I come to the conclusion that while Alive is a nobel experiment, some basic design choices make it very hard to get stable enough for a daily driver:

  • the author wants to compile Lisp file in the background "the VSCode way" and ditched SWANK because it's too "Emacs centric" to support that. However IMHO this is rather a Lisp problem and not an Emacs problem at all! compile-file runs arbitrary code and running it at arbitrary moment is not good for health. One reason for ditching SWANK is "debugger pops up at any moment" when they do so and they want to suppress it. Ummm debugger popups because the Lisp needs help?

    • IMHO most design choices in SWANK are Lisp-specific instead of Emacs-specific. There are lots of success using SWANK in other editors: SLIMA, SLIMV, LEM uses a simplified verion, etc.

  • REPL starts new thread for every evaluation. Why? Now good old (READ) and nested REPL don't work.

  • The LSP server is no where near as stable and complete as Swank. This is immediately obvious after 1 minute of use.

So I decide to fix it. Here is a VSCode extension that uses good old SWANK, and as the primary goal tries to get as good as Emacs as possible. Please ask people to use it (and learn Lisp)! Working with VSCode was really torturous, I hope I did not suffer in vain.


r/lisp • • 18d ago

Release Clozure CL 1.14 · Clozure/ccl

Thumbnail
github.com
55 Upvotes

r/lisp • • 3h ago

UK Racket meet-up (London) Tuesday 17 November 2026

3 Upvotes

UK Racket meet-up (London) Tuesday 17 November 2026

7:30pm at The City Pride 🍕 28 Farringdon Ln, London EC1R 3AU

Presentations and pizza: Grammar of Graphics and Picture Definition Language.

All welcome.😁!

https://luma.com/pk1fn5qh

https://racket.discourse.group/t/uk-racket-meet-up-london-tuesday-17-november-2026/4479


r/lisp • • 21h ago

An attempt at an OS

Post image
40 Upvotes

Hello, I've been reading about lisp for a while now and really got fascinated by its syntax and simplicity. So I started writting an OS while taking inspiration from it with some differences form x86_64. At this point it is very primitive as I'm writting a from scratch compiler in Lua so I can only show you this screenshot from the most recent version. The code in plain text is this:

;; This is the kernel

(func u8 :draw_vga (u16 :color)
  (var u64 :i 0)

  (loop

    (set [u16 (+ 0hB8000 1600 :i)] :color)

    (cond
      ((< :i (- 800 4)) (set :i (+ :i 4)))
      (else (break))
    )
  )

  (return 55)
)

(func u8 :calc ()
  (return 6)
)

(func :kmain ()
  (var u16 :value (+ 0h1F54 (:calc)))
  (var u64 :color :value)

  (:draw_vga :color)

  (loop))

If you wanna browse more its at staticos.org


r/lisp • • 1d ago

A Review of The Art of the Metaobject Protocol (1993) [pdf]

Thumbnail dreamsongs.com
37 Upvotes

r/lisp • • 2d ago

The entirety of "Let Over Lambda" is now freely available online

Thumbnail letoverlambda.com
172 Upvotes

r/lisp • • 3d ago

sift: format, lint and LSP for Scheme/Elisp/CL > 90 lint rules, one binary, and it also compiles to WASM (Guile Hoot)

Thumbnail
gallery
35 Upvotes

TL;DR: sift is three tools built on one reader. sift format rewrites whitespace, sift lint has 92 rules, and sift lsp gives Emacs, Neovim, VS Code (and more) the same answers over the protocol. It handles Scheme, Emacs Lisp and Common Lisp as three separate languages. Formatting is a total function and a fixed point: format a formatted file and you get it back byte-identical, with comments, blank lines, #; datum comments and #. read-time forms exactly where they were. Guile 3.0, MIT, no C, no build step.

Repo: https://github.com/jjba23/sift Try it (WASM version): https://jointhefreeworld.org/sift/

Why

sift reads the file as a tree of forms with source positions, then prints it back. Everything else follows from that: diffs with hunks that are just the change, quickfixes that replace exactly one range, suppression comments that can't drift away from the code they silence.

The reader and printer are inverse operations. The test suite asserts byte-exact preservation and idempotence on every fixture.

Dialects

Square brackets are a vector in Emacs Lisp and a cond clause in Scheme. #{ ... }# is a Guile symbol and only Guile's reader knows it. So the dialect has to be decided before anything else, and sift decides in a fixed order, stopping at the first answer: --dialect, then the extension (.scm .ss .sld .sls / .el / .lisp .cl .asd .lsp), then the shebang, then a marker in the first 200 lines ((in-package ...), (define-module ...), lexical-binding: t).

If none of that answers, sift says so and names the three dialects. It doesn't guess. A guess will eventually rewrite a Common Lisp file as Scheme, and the diff will get blamed on your code.

Each dialect is read by its own rules: character literals, reader macros, #| ... |# block comments, package prefixes, LOOP keyword style, docstring conventions, whether ) goes on its own line.

doc/style.org has the long form for each choice: what it beat and why, including which of Riastradh's rules sift keeps and which it declines, and which "Emacs Lisp conventions" are really byte-compiler warnings.

The linter

92 rules. Each one is a record: a name, a stable code (SIFT012), a sentence, the dialects it applies to, a severity, a procedure, an example, and its own test file. The catalogue, docs and editor integrations are generated from those records, so they can't drift from the code.

$ sift lint small.scm
small.scm:2:4: warning: [if-without-else] `if` has no else branch; `when` says it once

That's the whole output format: file:line:column: severity: [rule] sentence. Vim's :make, Emacs's compilation-mode, grep and CI log viewers already parse it. Suggestions are findings too; a deeply nested body gets reported, not silently rewritten.

You can ask what a rule means instead of reading a wiki:

$ sift explain if-without-else
CODE        SIFT012
NAME        if-without-else
DIALECTS    scheme
SEVERITY    warning
FAILING EXAMPLE  (if (ready?) (go))
EXPECTED FIX     (when (ready?) (go))

Two decisions I'd defend in a code review:

  • A fix replaces exactly one range, and if the set of fixes in a run would introduce a parse error, all of them are discarded. No invented delimiters, no renamed identifiers.

  • Suppression is a comment next to the code: ;; sift:disable-next-line keyword-arguments for one line, disable for the rest of the form, enable to turn it back on. Not an exception list in a config file.

The language server

sift lsp speaks LSP over stdin/stdout. Findings are computed once. The same modules that print text on the command line produce the diagnostics, so editor and CI can't disagree.

It answers diagnostics, quickfixes, formatting, go-to-definition and references, outline, completion, inlay hints naming a call's arguments, hover (a symbol or the rule under your cursor), import organization (unused imports removed, specs sorted), and file rename that keeps the module in step. Definition and references reach into the standard library and installed packages, including the compressed sources most Emacs installations ship.

On open and on save, in a thread, on a temporary copy, it asks the dialect's own compiler (guild, emacs, sbcl) about the names, arity and types sift doesn't check, and publishes what the compiler says. If the compiler isn't installed, it isn't asked. compiler-diagnostics: false turns it off.

Two limits, stated not hidden: references are matched by name within one dialect (sift expands no macro and follows no import), and the project is read once per session unless the editor reports a change. Requests it can't answer get "method not found."

In Emacs

emacs/sift.el is a single file, Emacs 28.1+, no dependencies. Two ways in: a Flymake backend for the rules with its own keymap, and Eglot for the code actions. The docstring, lexical-binding, interactive and provide rules land in Flymake and in CI, from one program instead of three.

One thing to know: sift and TAB will disagree about a third-party macro, because sift doesn't expand macros and indent-region does. doc/emacs.org explains why and what to do about it.

Also in the repo: a Neovim vim.lsp.start setup with no plugin, a Vim plugin with :SiftLint/:SiftFormat/:SiftFix/:SiftExplain, a VS Code extension with no build step and no dependencies, and a Helix recipe.

In a pipeline

sift ci src/ tests/

One command asks both questions (is it formatted, does it lint), prints both reports, and exits 1 if either found something, 2 if a file couldn't be read or parsed. It never writes and never fixes.

Output is --format=json, --format=sarif (2.1.0), --format=github (workflow annotations on the lines of the diff), or null for a script that only cares about exit status. A run distributes files over the processors and prints in file order, so a parallel run writes exactly the bytes a sequential one writes.

sift ci over sift's own tree (151 files, ~34k lines of Scheme) takes about 2 seconds on my machine, interpreter startup included. sift check src/ on the sources it formats itself exits 0.

Ready-made: a reusable GitHub workflow (one file, no flags, uploads SARIF to code scanning), a composite action, sift install-hooks for a plain pre-commit hook, and three hooks for the pre-commit framework.

In the browser

Format and lint are compiled to WebAssembly with Guile Hoot, with an editor page around it. Same reader, same formatter, all 92 rules. The module is the modules in src/sift/.

It's not a port. Writing it again in JavaScript would be a second formatter, and therefore a second style: two tools that agree until the first file that exercises them.

The contract between the page and the Scheme is one procedure from string to string, and nothing in src/sift/ names the browser, WebAssembly or Hoot. Eight tests hold that dependency running one way. The hard part was SRFI-13, which Hoot doesn't ship. The stand-in is thirteen procedures written against (scheme base), plus a test that runs the browser's copy in a second process and fails unless its answers are byte-for-byte what Guile's library gives.

| Buffer | format | lint | | 300 chars | 17 ms | 56 ms | | 1.2 kB | 52 ms | 145 ms | | 6 kB | 780 ms | 1.2 s |

A screenful stays under the editor's 300 ms debounce, so the first two rows never reach you. Past ~2 kB it's perceptible. No JIT, a record per node, four records per character in the reader. That's the price of Scheme on a Wasm GC.

Live at https://jointhefreeworld.org/sift/ — your buffer never leaves the tab.

Install

guix install sift                                   # guix-jointhefreeworld channel
nix run git+https://github.com/jjba23/sift -- version
docker run --rm --volume "$PWD:/src" sift ci .      # Debian's Guile + the library
git clone https://github.com/jjba23/sift && cd sift && ./bin/sift version

Guile 3.0 is the only runtime requirement. gzip, curl and tar are for reading compressed sources and fetching stdlib archives during navigation; a missing one is reported and the feature is skipped, not a hard failure. sift doctor prints the Guile it runs on, the library it loaded, the rules it found, and which configuration layer won.

bin/sift is a POSIX shell launcher that puts src/ on Guile's load path and calls (sift cli). The program reduces to five lines of Scheme if you don't want the launcher.

What it doesn't do

No macro expansion, no type-checking, no knowledge of your project's conventions. It reports; you decide. Where an answer can be wrong, the rule says so: wrap-in-let is a suggestion, keyword-arguments counts, and the thresholds are settings.

Configuration is sift.yaml (data, never code) or a sift.scm the project has explicitly trusted. Four layers, system to command line, validated against one schema. A key sift doesn't have is refused with its position rather than ignored, and sift config show --verbose tells you which layer won.

Contributing

The most useful contribution is a rule, and the shape is fixed: one record, one test file, a name, the next free code, a sentence, the dialects, a severity, an example, and three cases — one that passes, one that fails at a known line and column, and when a fix can be stated safely, the fixed text plus a re-lint that must find nothing. The catalogue, docs and editor integrations follow from it.

A file sift refuses to parse is a bug even when the file is broken, and the message has to say where. A question the README doesn't answer is the most useful bug report.

The project's own style is the style it enforces, so it formats itself: maak fmt, maak test, maak self-check, maak fixture-check.


r/lisp • • 3d ago

Scheme Kawa - A optionally typed scheme for JVM which is performant

18 Upvotes

I was looking for a Lisp in the JVM which can consume JVM libraries but is also performant as well as in it should be possible to get to Java level speed with minimum fuss.

I was surprised with Kawa which seems to tick all the boxes including being able to flag type mismatch which to me is a big plus.

It's built grounds up to be able to seamlessly work with Java, like Kotlin and a statically typed version should give the same performance as Java natively. There is no unnecessary boxing and if one use Java arrays and primitives using static typing then the performance is supposed to match Java.

Additionally, with full Scheme macro and runtime eval it is good option especially as I have all the goodies of JVM available out of the box.

Only downside seems to be it looks not to be in active development as the last version was from 2020 and it does not support Java generics, though there is a workaround in developing the Option [T] in Java and importing it.

Just want to check, if anyone have used it for production use and how is its performance under such conditions.

EDIT: I am aware of Clojure but its performance out of the box is not very good especially for numeric loads where there is a lot of boxing.


r/lisp • • 3d ago

Emacs Lisp pix-el

Post image
12 Upvotes

el-gpu & pix-el & canvas.

EmacsConf 2026 warmup. All lispers welcome. Including GNU Emacs users :)

PS. Dutch flag of no special importance (here). 🇳🇱

PPS. Recognize the sprite? Original but blended. Black belt by now. 1990 (?) 🕌


r/lisp • • 3d ago

Common Lisp with Pixi - blog post at prefix.dev

Thumbnail
prefix.dev
13 Upvotes

r/lisp • • 4d ago

FLX: An OSI embeddable Lisp-2 interpreter and runtime implemented in Kotlin

4 Upvotes

Hi r/lisp,

I wanted to share FLX, an open-source, embeddable Lisp dialect and runtime implemented in Kotlin:

https://github.com/Fuusio/flx-lisp-2

Design & Dialect Characteristics

FLX is implemented as a Lisp variant that maintains distinct namespaces for variable bindings and function definitions (in the style of Common Lisp), which provides clean separation when interacting with host-language objects and methods.

Key aspects of the engine and dialect include:

  • Lisp Namespace Architecture: Separate value and function cells prevent accidental shadowing of standard forms and primitives by local variables.

  • Embeddable Runtime: Designed from the ground up to serve as an embedded evaluation engine inside Kotlin and JVM hosts, rather than demanding an isolated runtime environment.

  • Host Interop & Extensible Environments: Clean bridging allowing host functions, state objects, and callbacks to register directly into the global or lexical scopes.

  • Modular Structure: Cleanly split between the core evaluation/AST runtime (flx) and interactive tooling/REPL modules.

  • Idiomatic Modern Host Implementation: Written to leverage Kotlin's immutability constructs, sealed class hierarchies for AST representations, and clean error-handling models.

Quick Example

Evaluating S-expressions and interacting with the environment:

Lisp

;; Defining functions and manipulating values: 

(fun square [x] (* x x)) 
(val numbers [1 2 3 4 5]) 

;; Higher-order mapping: functions are values, so no #' is needed:

(map square numbers) ;; => (1 4 9 16 25)

And embedding it in the host:

Kotlin

import org.fuusio.flx.core.FlxEngine

fun main() {
    val engine = FlxEngine()
    
    // Evaluate expressions directly
    val result = engine.eval("(+ (* 6 7) (- 10 8))")
    println(result) // 44
}

Repo & Source

If you enjoy exploring Lisp implementations, host runtimes, or language semantics on modern platforms, I'd welcome any thoughts on the dialect choices, AST evaluation model, or runtime ergonomics.

🔗 GitHub:https://github.com/Fuusio/flx-lisp-2


r/lisp • • 6d ago

Common Lisp Common Lisp in the browser: large improvements to miricl

26 Upvotes

I've posted my sloppy proof of concept last week and the project is already much more feasible for actual use:

  • Green threads (run in a single worker, follow the BT2 API)

  • Compact, optimized FASL format (loadable Wasm bundles)

  • New native compiler focused on size

  • Optional full ASDF support (see the game-of-life example app using FSET)

  • Self-hosted development server which also acts as a bridge between the Emacs inf-lisp REPL and the browser

  • Self-hosted application bundler (including whole-program native compilation)

You'll find a few demos that showcase what is possible (native compiled for faster startup, hosted entirely in the browser). Chromium-based browsers are currently somewhat faster compared to Firefox.

As for the runtime files:

  • miricl.wasm: the smallest option. I recommend using this if you want to write a bit of CL in HTML script tags. It can still bootstrap the native compiler on first use, but it takes a while (try it with the compilation example in the browser REPL app).

  • miricl-precompiled.wasm: this is a bit larger. I'd recommend it for development and for cases where you intend to use the compiler at runtime.

  • miricl-repl.wasm: the Node / Wasmtime WASI terminal REPL, not intended for the browser. Ideal for running the development server.

  • miricl-asdf.wasm: a natively precompiled version of ASDF. Ideally you'd only include this for development.

See image sizes for a size comparison and the README for more details.

I've ran out of tokens for now, but I'm planning on working on better stacktraces, debugging and SLIME / Sly support in the future.


r/lisp • • 6d ago

Lisp I wrote a Lisp indenter mimic SLIME's indentation rules for NeoVIM

12 Upvotes

Hi all,

I write a Lisp indenter for NeoVIM and try to mimic the SLIME's indent rules.

You can find the plugin here: https://github.com/yiranlus/nvim-lispindent

It uses a very simple Lisp tree-sitter I wrote to analyse the s-expressions. And it is better to use with a plugin like parinfer to force pairing parenthesis. I have been testing and using it when editing the Guix files for some time. You can add your own rules, too.


r/lisp • • 6d ago

Do anyone ported emacs back to Clisp?

0 Upvotes

Given that there are multiple generative tools available, do anyone tried to port back emacs to CLISP and put an end to the mess?

I know that hemlock is still there, but its functionality and compatibility with emacs is limited.


r/lisp • • 8d ago

Help AffrescoUI: an Elisp-inspired language where each GUI app is a live Lisp program

53 Upvotes

I’ve been working on AffrescoUI, an open-source engine for native desktop apps, and I’d love feedback from people who know Lisp far better than I do.

Each app is a program in AffrescoUI Lisp, a small language in the spirit of Emacs Lisp. It has commands, settings, hooks and advice, and the program holds the app’s whole layout, data and behaviour. The engine builds it into a single tree that a native C++/OpenGL renderer draws, and changes are applied to the running app without a restart. The same app can also be written as JSON, and the examples ship both.

The goal is Emacs-style malleability for everyday apps like a photo editor or a 3D modeller: wrap a handler with advice, add a hook, and change how an app behaves while you use it. Users can also describe a change in plain words and have an AI propose the Lisp edit, which they preview and then keep or undo. Code as data made that part much simpler, since every change is a small edit to a tree.

I’d really value your take on:

  • Does the way apps are written in AffrescoUI Lisp feel natural to you, or does anything look off?

  • Are hooks and advice enough for users to reshape an app, or is something missing?

  • What would you try to build or change first?

GitHub repo if interested: https://github.com/RiccardoSottini/AffrescoUI


r/lisp • • 8d ago

Teeny Scheme

Thumbnail
reddit.com
6 Upvotes

r/lisp • • 8d ago

Exploring Janet and the httpf web framework

Thumbnail nick.gs
16 Upvotes

r/lisp • • 9d ago

Hexmaw, a first-person real-time roguelike in Common Lisp on Trial

39 Upvotes

Hi all,

I’d like to present Hexmaw, a first-person fantasy roguelike built on Shinmera’s Trial. It has Hexen-like combat, randomly generated levels, a spellforge where you build your own spells, a town partway down and a boss at the bottom. It runs on SBCL, and every edit is hot-reloaded into the running game.

There’s a build for Linux, Windows and macOS (the Mac one is untested): https://gwathlobal.itch.io/hexmaw. The code is zlib-licensed on GitHub: https://github.com/gwathlobal/hexmaw.

The code, art, sound and music were all generated with AI. I wanted to see how far a solo developer can get with building a shippable product nowadays, and, well, pretty far, it seems.

If you try it, I’d like to hear how it went. Thanks in advance!


r/lisp • • 10d ago

Common Lisp Sloppy CL interpreter experiment targeting Wasm

Thumbnail github.com
12 Upvotes

r/lisp • • 10d ago

True: a cyclic, self-modifying language. How does it compare to Lisp's code=data idea? (MVP, feedback welcome)

2 Upvotes

Hi!

I'm making a language called True and an interpreter for it called Simple.

It's an MVP, and I'd be glad to get some feedback on the design.

I'm posting here because True is built on ideas that should feel familiar to Lisp folks: code as data, self-modification, minimal syntax. But I've taken them in a direction that I think is quite different from Lisp, and I'd love to hear what you think.

The key stuff about the language

In True, a program is a tape of lines (I call them lines, not strings - because a "string" can mean the whole text, a block of code, or a single character, while a "line" is unambiguous: one line of the cycle/tape). And I call programs cycles because they run cyclically.

The agent-observer is the first line of the .cycle file, and it's part of the program itself. It walks the tape top-down, swaps itself with the line below, and executes what it reads.

The agent is part of the program, executor and data at the same time. So the program is self-modifying, changes in memory are reflected back into the text, and the type in the agent line updates on every step.

Here's a simple Elevator cycle where the lift goes up and down:

Mr.Green, #5fb85f | Data as <type> | Aim: 1

6 = max
1 = floor
1 = dir

= lift

dir > 0 ? floor =>| lift:y(, ):floor
dir < 0 ? lift:y(, ):last -> ::nothing

floor == max ? -1 => dir
floor == 1 ? 1 => dir

floor + dir => ::math => floor

I made a video of how it works:

Where True is similar to Lisp

Code is data. In Lisp, a program is a list, and that list can be manipulated like any other data. In True, a program is a tape of lines, and the agent can read and change those lines while the program runs.

Self-modification. In Lisp, macros and eval let a program rewrite itself. In True, the program rewrites itself on every step, because memory is flushed back into the text.

Minimal syntax. Lisp has S-expressions and brackets. True has lines and empty lines as separators.

Where I think it differs from Lisp

In Lisp, the executor (interpreter or compiler) is outside the program. It reads S-expressions and evaluates them. In True, the executor is part of the program, it's the first line, and it physically moves through the tape, swapping itself with the line below.

In Lisp, code is data as lists. In True, code is data as lines and chains of lines.

In Lisp, self-modification happens through macros or eval, powerful, but still a deliberate action. In True, self-modification happens every step, by default.

True has no types. A program is made of lines and chains of lines, and how you work with them is determined by the executor, the agent. In Lisp, values have dynamic types.

A line, a container, or a chain can be seen as a shape with axes. name:x(, ):i for the horizontal axis, name:y(\n):i for the vertical one (each works like a list). Indexing is 1-based.

Extensions: ::math for arithmetic, ::nothing for deletion.

There are goto jumps: ^ name, ^ N, ^ :cycle:N. The agent can jump anywhere, in any cycle.

And one more thing worth mentioning: the line as a qubit in quantum mechanics. The agent determines the type of a line only when it observes it - before that, the line has no type. In a sense, a line is like a qubit in quantum mechanics: nothing is defined until there is an observer. The agent is that observer. When it reads a line, the line collapses into a definite type (named, action, condition, jump, container, separator, version), and only then is it executed. This is not just a metaphor - it's how the interpreter actually works: resolve_line determines the type at the moment of reading, and the same text can be a different type depending on context and memory.

That's a brief description, I guess. More details in the docs, or we can just discuss in the comments.

I wanted to make the language simple, the process visual, and programming live, and here's what came out of it 😄

I'd be very interested to hear your thoughts on the language, especially from people who've worked with Lisp's code=data philosophy. Does the "agent as part of the program" idea make sense to you, or is it just a gimmick? And is there anything from Lisp that you think True should steal?


r/lisp • • 11d ago

Racket Racket (online) meet-up: Saturday, 7 November 2026 at 18:00 UTC

Thumbnail pasterack.org
4 Upvotes

Racket (online) meet-up: Saturday, 7 November 2026 at 18:00 UTC EVERYONE WELCOME 😁 Details at https://racket.discourse.group/t/racket-online-meet-up-saturday-7-november-2026-at-18-00-utc/4460


r/lisp • • 11d ago

Building and Rendering a Space Station in Scheme

Thumbnail
youtu.be
38 Upvotes

r/lisp • • 12d ago

ZParen: a free Common Lisp IDE for macOS, with SBCL included, Vim keys, and a built-in course

10 Upvotes

I like Common Lisp, but I kept losing time to my Emacs and Vim setups, especially after upgrades. So I made a Lisp IDE that works the way I want, and I'd like feedback from people who write Lisp every day.

What it is

  • A macOS app (Apple silicon, macOS 13+) that includes SBCL and Swank. Open a project folder and Lisp starts. No setup.

  • One live image per project. Evaluate a form, click the result to inspect the real object, stop in the debugger, fix the code, and use Restart Frame.

  • Vim keys first, plus SLIME's Emacs sequences (C-c C-c, M-., C-M-f…), parinfer and structural editing.

  • Projects stay plain ASDF systems, with Quicklisp, ocicl, qlot or vendored dependencies. ZParen adds no files of its own.

  • It supports Coalton too: .ct files, types on hover, and type errors on the expression Coalton blames.

  • An optional AI assistant (Claude or Codex) and an MCP server. They run code in your image, not a copy. Leave them unconfigured and they stay out of the way.

New in this release: a Learn Lisp course. It follows ANSI Common Lisp and On Lisp. You start a course project with a file and FiveAM tests for each lesson. Each lesson gets a git branch, so your progress is in git history. There are 15 lessons so far, from first forms to macros, conditions and CLOS. The advanced lessons from On Lisp come later.

Full disclosure: I built most of it with Claude Code. The repo has a doc on how (built with Claude Code). The app itself is Rust and Tauri with a CodeMirror UI, talking to SBCL over Swank.

I hope it helps beginners find their way into Lisp more easily.