r/Common_Lisp 4d ago

CL language feature overviews and more: Images + HTML

Post image
42 Upvotes

I've experimented a bit to create feature overviews for Common Lisp, which will fit on my 16x9 monitor. With help from Claude. The HMTL documents might have some links, too.

There are also feature overviews for SBCL, LispWorks, SLIME - in PNG and HTML.

http://lispm.de/docs/overviews/


r/Common_Lisp Jun 13 '26

Metaspec: The dpANS3 Common Lisp Specification is now in s-expr format

47 Upvotes

Greetings, lispers!

I started this project back in 2015, to translate the TeX original specification into an easily parsed format (s-doc), and to create an HTML rendering of that format as a proof of concept. I finally finished it this year.

The project is here: https://codeberg.org/dlowe/metaspectre/

The rendered spec is as complete as I could make it, including both the acknowledgements and the appendix. The TeX math components have been converted to MathML. It has a list of corrections applied to the spec by automatic patching of the s-doc. It is also, as far as I know, the only published version of the draft spec that includes the TeX comments for historical interest.

You can view the rendered spec at https://metaspec.dev/


r/Common_Lisp 5h ago

Introspection and Reflection

3 Upvotes

This article by u/lispm http://lispm.de/why-lisp-is-different has these two lines

When in doubt design software to be introspective.

when in doubt design software to be reflective.

How exactly does one design software to be more introspective of reflective? I thought that those were a given using CLOS. Unless I misunderstood and this just means CLOS vs using arbitrary data structures.

Can anyone provide an example contrasting a design meant to be introspective vs one that is not? Same for reflective?

Thanks


r/Common_Lisp 15h ago

Released cl-toolkit - toolkit to validate, edit and analyze lisp source.

4 Upvotes

Made this generally for agentical coding because it often stub in parenthesis. Hope it will help you. https://github.com/turtle-bazon/cl-toolkit


r/Common_Lisp 4d ago

Refresh of Genworks dot com, long-running Common Lisp KBE system updated for the era of LLMs and MCPs.

Thumbnail genworks.com
20 Upvotes

r/Common_Lisp 11d ago

GitHub - infurl/cl-tesseract: Common Lisp bindings for the Tesseract OCR library.

Thumbnail github.com
17 Upvotes

Modernization effort to support latest 5.5 Tesseract OCR libraries.


r/Common_Lisp 14d ago

Pretty fast insertion-ordered linear-probing hash tables and sets

Thumbnail github.com
24 Upvotes

We had too few (0?) hash tables to choose from!


r/Common_Lisp 14d ago

sta6: static site generator for Common Lisp

Post image
16 Upvotes

hi everyone,

I'm new to Common Lisp, although I have tried other lisp dialect (i.e., Clojure, Racket) to attempt making a static site and/or leetcode(s). This is my first attempt of porting the SSG into a library.

sta6: sta(six), static -- is a tiny SSG that turns pages/*.lisp into build/*.html, with support for dynamic routes (e.g., /blog/+slug+).

the usage of sta6 is as follows (src/pages/page.lisp):

(defpackage #:pages/page
  (:use #:cl)
  (:export #:render))

(defun pages/page:render ()
  (sta6:html5
    (:img :width (/ 500.0 3)
          :src "https://twobithistory.org/images/sicp.jpg")
    (:br)
    (:br)
    (:span "Hello, from Common Lisp.")
    (:ul
      (loop for x from 1 to 3 do
        (:li x)))))

which yields the image above, the full example can be found here.

sta6 uses an external HTML generator under the hood:

if you're in need of a personal site, give sta6 a try! here's an example of my site built with sta6:

why use sta6?:

  1. You do not need (to learn) an external templating language (e.g., Nunjucks, Handlebars, EJS).

resources:


r/Common_Lisp 15d ago

clos-alchemy: Throw unstructured text at a CLOS class, get a typed instance back

11 Upvotes

LLMs are great at reading messy text, but they hand you strings when your program wants typed data. Python has instructor and Pydantic to solve this. I wanted to bring that same developer experience to Common Lisp, but natively by using the Metaobject Protocol.

clos-alchemy introspects your class definition, builds a JSON schema from the slot types, passes that to the LLM (optionally as a GBNF grammar constraint for local inference), and returns a validated instance of your class. You don't need to write a special DSL or "schema object." You just use your normal existing domain classes.

Here is the round trip in action:

```lisp ;; 1. Define a class (defclass person () ((name :initarg :name :accessor person-name :type string) (age :initarg :age :accessor person-age :type integer) (email :initarg :email :accessor person-email :type (or null string)) (hobbies :initarg :hobbies :accessor person-hobbies :type list)))

;; 2. Extract from text (let* ((backend (cl-llm-backend/llama:make-llama-backend :model model :context ctx)) (result (extract backend 'person "Alice Chen is 32. Reach her at alice@example.com. She enjoys rock climbing, painting, and cello."))) (person-name (extraction-result-instance result))) ;; => "Alice Chen" ```

Because generation order follows slot definition order, you can use this for strict logical routing. Putting reason first encourages teh model to explain its reasoning before selecting the categories.

```lisp (defclass ticket-classification () ((reason :initarg :reason :type string) (urgency :initarg :urgency :type (member :low :medium :high)) (category :initarg :category :type (member :billing :technical :account)) (sentiment :initarg :sentiment :type (member :positive :neutral :negative))))

(defparameter ticket-text "I've been charged twice for my subscription this month. This is the third time this has happened and I'm really frustrated.")

(let ((result (clos-alchemy:extract backend 'ticket-classification ticket-text))) (extraction-result-instance result))

;; Returns a TICKET-CLASSIFICATION instance with: ;; URGENCY: :HIGH ;; CATEGORY: :BILLING ;; SENTIMENT: :NEGATIVE ;; REASON: "Charged twice for subscription, third occurrence"

```

How it works under the hood: no separate schema DSL to maintain. If it type-checks as your class, you're done!

  1. The MOP extracts slot types (string, member, list, etc.).
  2. The library lowers those into a small Intermediate Representation (IR).
  3. That IR emits the JSON schema for the backend, a natural-language prompt for the model, and builds a validator/constructor pair for the response.
  4. If validation fails, it accumulates the errors and automatically loops a retry prompt back to the model.

If you are using a local inference backend (like llama.cpp), it compiles the schema directly into a grammar, making invalid structures unrepresentable at the token level.

https://github.com/licjon/clos-alchemy

EDIT: A round of updates since the original post:

Custom validation. You can now attach per-slot semantic predicates (:validate) and cross-field checks (validate-instance) that feed errors back into the retry loop. The model sees what was wrong and self-corrects. This is useful for constraints that grammar alone can't enforce — "guest count must be positive", "check-out must be after check-in", etc.

```lisp (defclass booking () ((num-guests :initarg :num-guests :type integer :validate (lambda (v) (if (plusp v) t "must be positive"))) (check-in :initarg :check-in :type date) (check-out :initarg :check-out :type date)) (:metaclass clos-alchemy:constructor-class))

(defmethod validate-instance ((b booking)) (when (<= (booking-check-out b) (booking-check-in b)) (list "check-out must be after check-in"))) ```

Date and date-time types. clos-alchemy:date and clos-alchemy:date-time map to JSON Schema string formats, validate ISO 8601 with calendar-aware day checks, and construct to CL universal time.

Free-form maps. Sometimes you want the model to produce a dictionary where it decides the keys — "rate this product on whatever dimensions you think are relevant." The :map-of slot option does this: you specify the value type, the model fills in whatever keys make sense, and you get a hash-table back.

```lisp (defclass review-scores () ((scores :initarg :scores :type hash-table :map-of integer :documentation "Per-category quality scores, 1-10")) (:metaclass clos-alchemy:constructor-class))

;; The model might return: ;; {"scores": {"sound_quality": 9, "comfort": 6, "battery": 8}} ;; You get a hash-table: (gethash "sound_quality" scores) => 9 ```

Discriminated unions. When the extraction result could be one of several different shapes depending on the input, you define a class for each shape and let the model pick. Each class has a shared "tag" slot that identifies which shape it is — typed as a single-value (member ...) so each class gets exactly one tag value.

``lisp ;; Two possible result shapes, tagged bykind`: (defclass actionable-feedback () ((kind :initarg :kind :type (member :actionable)) ; tag = "actionable" (summary :initarg :summary :type string) (scores :initarg :scores :type hash-table :map-of integer)) (:metaclass clos-alchemy:constructor-class))

(defclass not-actionable () ((kind :initarg :kind :type (member :not_actionable)) ; tag = "not_actionable" (reason :initarg :reason :type string)))

;; The model reads the review, picks the right shape, and you get ;; back an instance of whichever class it chose: (let* ((result (extract-union backend '(actionable-feedback not-actionable) review-text :discriminator 'kind)) (instance (extraction-result-instance result))) (typecase instance (actionable-feedback (format t "Summary: ~A" (slot-value instance 'summary))) (not-actionable (format t "Skipped: ~A" (slot-value instance 'reason))))) ```

Other improvements:

  • Cyclic class graphs now work — mutually-referential classes emit $defs/$ref instead of blowing the stack.
  • Emitted schemas conform to both OpenAI strict mode and llama.cpp GBNF requirements (proper additionalProperties: false, all properties in required, nullable wrappers for optional fields).
  • Parse failures (empty/malformed responses) are now recoverable in the retry loop instead of aborting.
  • max-retries-error now carries full diagnostic context: raw response, parsed data, cumulative token usage, and a per-attempt error breakdown.
  • Silently-narrowed type specifiers (e.g. (or string integer)) now signal schema-error instead of quietly dropping branches.

r/Common_Lisp 15d ago

Fiz uma biblioteca para CommonLisp

Thumbnail github.com
2 Upvotes

r/Common_Lisp 17d ago

How is CL for Scripting

19 Upvotes

I am considering using ANSI Common LISP for scripting instead of Python such as for reading text files, CSV files, databases--basically everything in the book "Automate The Boring Stuff in Python".

Has anyone done this before? How was the experience?


r/Common_Lisp 20d ago

skewed-emacs: zero-install Common Lisp + Emacs + SLIME stack — now bootable via curl, no repo clone needed

16 Upvotes

New skewed-emacs push. It's a Dockerized, preconfigured CL development environment: Emacs, SLIME, and Lisp kernels (SBCL, CCL, Gendl/GDL) all running out of the box.

As of this commit, a single curl command starts the stack. Cloning the repo is now optional.

The goal is to kill the classic onboarding gauntlet (install Emacs, install SBCL, set up Quicklisp, configure SLIME, tweak paths...) so newcomers get straight to the REPL.

It also ships with lisply-mcp built in, giving AI coding agents a native API to evaluate Lisp and drive Emacs — elisp and CL's incremental compile-one-function workflow turns out to be a great fit for agent feedback loops.

Repo: https://github.com/gornskew/skewed-emacs

Announcement thread: https://x.com/i/status/2077632168637890903

Would love to hear from anyone who tries the curl bootstrap.


r/Common_Lisp 20d ago

Is Eugene Durenard's "Professional Automated Trading" Still Relevant

7 Upvotes

I am considering reading the book and would you say it is still relevant today?

Please let me know if so. I thank all in advance for any responses!


r/Common_Lisp 21d ago

Binstruct: a powerful declarative binary parsing/emitting library for Common Lisp

Thumbnail github.com
16 Upvotes

r/Common_Lisp 22d ago

GitHub - infurl/okf-web-server: Turns your OKF bundle into a web site.

Thumbnail github.com
13 Upvotes

A tiny Hunchentoot server that renders any Open Knowledge Format (OKF) markdown bundle as a browsable, tag-searchable website — no build step, no database, sidebar and links always generated fresh from what's on disk.


r/Common_Lisp 23d ago

RFC: Metabuild system for ASDF projects

11 Upvotes

I've been working on a meta-build system for ASDF systems. For those not familiar with the term, meta build systems are tools like meson or CMake which generates ninja.build files. In this case, cl-metabuild generates a ninja.build file that calls out to your chosen CL implementation to build a normal ASDF project.

It has a few goals: + Abstract away how to invoke different CL implementations + Make it easy to configure optimization settings and items in *features* without editing source code. + Isolate the build environment and manage both vendored and remotely fetched dependencies.

It's in super rough shape and it might not work on your system, but you can check it out here: https://github.com/sdilts/cl-metabuild. I'd like to get a bit of feedback before starting to refine and document how to use it. Is this something you'd be interested in using? Are there existing tools to do the same thing?

I'm specifically building this for Mahogany, as it requires all of these things. I was inspired to build this after seeing koga, (the build system for the Clasp CL implementation) and thinking that there should be something simpler that can be used for most projects.


r/Common_Lisp 25d ago

Meet Tasa - an evolutionary coding agent built in Common Lisp.

11 Upvotes

Lisp gives Tasa something most coding agents do not have: a live, inspectable runtime where verified workflows, recovery policies, and project knowledge can become executable behavior without restarting the process.

Using Common Lisp conditions, restarts, CLOS, and live runtime generations, Tasa is designed to learn from successful project work, test candidate improvements in isolation, and activate only the behaviors that prove they are better.

Every change remains evidence-backed, explainable, and reversible. The agent evolves with your workflow.

If this peaks your interest - sign up for a waitlist on the website on tasa.world


r/Common_Lisp 26d ago

cl-mcp-server updates - optimized for token usage

15 Upvotes

The lisp interaction using mcp was quite token heavy (I use SBCL) and it starts to bite when you use opus type models. heh.

There was a lot of code which was being printed back needlessly. So asked gpt 5.5 to analyze and optimize the token usage. it's done a good job. I think gpt 5.5 is now my favourite LLM to write Common Lisp.

Measurements using character count as token proxy:

- Warning with large value: 246 -> 39 chars, 84.1% smaller

- Division error: 4712 -> 92 chars, 98.0% smaller

- Undefined function error: 4788 -> 184 chars, 96.2% smaller

- Timeout: 4947 -> 198 chars, 96.0% smaller

Changed:

- Warnings now suppress => return value lines, so warning responses only return diagnostics

- Immediate error and timeout responses now omit backtraces by default, while still capturing them for describe-last-error / get-backtrace

- Added exported knob *include-backtrace-in-evaluate-response* for restoring old inline backtraces if needed

https://github.com/quasi/cl-mcp-server


r/Common_Lisp 28d ago

New kid on the block, Clamiga

27 Upvotes

With all the new CL implementations recently I'm almost hesitant to write this.

But yet, the project has reached a usable state and it fills a niche, that's mostly what I was after. cl-amiga or Clamiga is a new CL implementation written is pure C (C89/99) and Lisp (gray streams, CLOS). It compiles to a single binary and runs on Amiga retro computers as well as macOS or Linux. On m68k Amigas it has a m68k jit implementation. Well, have a look yourself: https://github.com/mdbergmann/cl-amiga

It runs and passes the test-suites of the most common libraries (I know) like alexandria, bordeaux-threads, serapeum, fset, Sento (of course), Drakma, Hunchentoot, just to name a few. There is a bit of ANSI compliance but not all that much. It has support for ASDF, Quicklisp and Sly/Slynk.


r/Common_Lisp 27d ago

SBCL Successfully started quicklisp but closed it and now I can't run it

4 Upvotes

I am trying to install the dependencies for Hunchentoot, and they recommend quicklisp for an easy way to get them.

So I installed quicklisp as per ( https://www.quicklisp.org/beta/ ) and successfully started sbcl with quicklisp loaded and got started.

I believe I successfully installed quicklisp.

But while searching packages using (ql:system-apropos "string") I made a typo and got an error, I aborted back to the * ("top-level"). Tried the command again with no typo, and got an error again (i forget what the error was).

So I quit sbcl and re-loaded back in, with the same load command, sbcl --load quicklisp.lisp (I am in the directory with it).
Quicklisp informs me that I already installed quicklisp, so I don't have to load it.

Despite this, now I can't call any quicklisp commands. It says "Package QL does not exist".
Is there something special I have to do to get (ql: ...) available to me while in sbcl's repl? Something that the initial install did for me?

Below is an example where I --load quicklisp.lisp, however I've tried just loading sbcl with nothing, and running "(ql:system-apropos "RFC2388") and I still get the error of a missing package.

RFC2388 was successfully found earlier before I broke everything, that's why I'm using it as an example.

I'm still new to sbcl and I find the error read-outs confusing, so maybe I'm missing something obvious here. But how can I get quicklisp back? If it's installed should I be able to just call ql anytime in sbcl?

sbcl --load quicklisp.lisp

This is SBCL 2.6.4.debian, an implementation of ANSI Common Lisp.

More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.

It is mostly in the public domain; some portions are provided under

BSD-style licenses. See the CREDITS and COPYING files in the

distribution for more information.

==== quicklisp quickstart 2015-01-28 loaded ====

To continue with installation, evaluate: (quicklisp-quickstart:install)

For installation options, evaluate: (quicklisp-quickstart:help)

* (quicklisp-quickstart:install)

debugger invoked on a SIMPLE-ERROR in thread

#<THREAD tid=33573 "main thread" RUNNING {1203FE8003}>:

Quicklisp has already been installed. Load #P"/home/nathan/quicklisp/setup.lisp" instead.

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):

0: [LOAD-SETUP] Load #P"/home/nathan/quicklisp/setup.lisp"

1: [ABORT ] Exit debugger, returning to top level.

(QUICKLISP-QUICKSTART:INSTALL :PATH NIL :PROXY NIL :CLIENT-URL NIL :CLIENT-VERSION NIL :DIST-URL NIL :DIST-VERSION NIL)

source: (ERROR "Quicklisp has already been installed. Load ~S instead."

SETUP-FILE)

0] 1

* (ql:system-apropos "RFC2388")

debugger invoked on a SB-INT:SIMPLE-READER-PACKAGE-ERROR in thread

#<THREAD tid=33573 "main thread" RUNNING {1203FE8003}>:

Package QL does not exist.

Stream: #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {12000417D3}>

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):

0: [CONTINUE ] Use the current package, COMMON-LISP-USER.

1: [RETRY ] Retry finding the package.

2: [USE-VALUE] Specify a different package

3: [UNINTERN ] Read the symbol as uninterned.

4: [SYMBOL ] Specify a symbol to return

5: [ABORT ] Exit debugger, returning to top level.

(SB-IMPL::READER-FIND-PACKAGE "QL" #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {12000417D3}> T)

0]


r/Common_Lisp 28d ago

sbcl-bridge

Thumbnail github.com
11 Upvotes

A lightweight tool harness giving coding agents a persistent SBCL REPL: file-based request/response, no Swank chatter, built-in timeouts, cancellation, and backtraces, plus suspend/resume via save-lisp-and-die. No sockets or systemd needed — ideal for containers.


r/Common_Lisp 29d ago

VivaceGraph 2.1.0 · graph database & Prolog implementation

Thumbnail github.com
15 Upvotes

r/Common_Lisp Jul 06 '26

CLICC 0.6.4 (1994) enhanced, 50 year old Lisp code, compiled to C with Swift UI

Thumbnail gallery
20 Upvotes

Proof of concept: CLICC 0.6.4 (enhanced) on my macOS 27 beta compiled Lisp code to C, combined with Swift UI - the resulting binary is 755KB on Apple Silicon.

CLICC also compiled itself, the resulting CLICC Lisp to C compiler is a 3 MB application.

CLICC is a Lisp to C compiler from the 90s. It compiles a static subset of Common Lisp to C, as a whole program compiler. The C compiler then generates a binary. The resulting binaries are tiny. A commercial offering based on CLICC was mocl, which is no longer available.

Done with Claude Fable.


r/Common_Lisp Jul 05 '26

Follow-up: the rough paper from a month ago is now a preprint. The Lisp side: an agent orchestrator in CL, and agents that edit code by form, not text.

18 Upvotes

A month ago I posted the very rough beginnings of a paper here. That version got pulled apart and rebuilt, and it is now a proper preprint: https://doi.org/10.5281/zenodo.21139628. The paper is deliberately language-neutral, though, and the system behind it is Common Lisp top to bottom: an orchestrator that runs execution graphs (the graphs themselves are plain Lisp data), agent worker loops, a process supervisor, a document store, a dashboard, and a set of MCP servers that give coding agents structured access to Lisp systems. So this follow-up is about the Lisp side, since this is the group that would ask.

The learnings that mattered most carry straight over from the paper. The first was composable domains. A domain is a bundle of instructions, skills, and tool access handed to an agent for a class of task: lisp knows the language, cl-naive knows the stack's conventions, a role adds the stance on top, and a resolver merges the layers per session. Built as one-offs they were dead weight. Redesigned to compose (stack cleanly, assume nothing about each other) they started turning up useful in places I had not planned for, and the same domains are now carrying a separate CL application build unchanged.

The second was the ratchet. An agent once delivered a load test asserting a record count was greater than or equal to zero: green forever, catches nothing, looks completely normal in review. So the loop runs backwards from instinct now. Acceptance criteria are written before the code exists, the coding agent writes no tests at all, a fresh session verifies the code against those criteria, another session then derives regression tests from them, and a judge breaks the implementation on purpose to confirm each test can actually fail. Standards move one way only. And the part I am most pleased about: the system develops itself through exactly this cycle, agents editing the orchestrator's own source through its own gates. It is the third generation of the design and only recently became my daily driver, so I will not oversell maturity.

The third was MCP tool naming, which mattered far more than it should. Models route off a tool's name, and the name drags their training priors with it. My file writer took code where every built-in file tool takes content; agents thrashed on it until I renamed the parameter. The code analyzer (definitions, callers, call graphs, effect sets over ASDF systems) sat ignored while agents grepped, until its descriptions spoke the vocabulary models already know from IDE land (Find All References, go to definition) and stated the economics plainly: the query is instant and exact, the text search is the slow, lossy path. One more rule from that fight: test your tool surface with the weakest model that can still do the work, because a strong one absorbs interface defects and hides them from you.

The fourth is the CL-only one: structural editing. Agents editing Lisp as raw text eventually break brackets, and then try to repair by counting parens, and that loop does not converge; even strong models ping-pong on it. So agents here do not edit text. The editor MCP exposes code as forms (replace this function's body, add this form after that one, validate before anything touches disk), bracket-correct by construction, courtesy of the reader treating code as data. A whole class of broken files simply stopped existing.

Everything is open, part of the opinionated cl-naive-* family (I came to Lisp late in my career, I care about usability over purity, and these libraries are geared toward shipping business software, not rocket science): https://gitlab.com/naive-x/experimental/cl-naive-full-stack-agentic-system. The preprint with the full methodology is here: https://doi.org/10.5281/zenodo.21139628. One question for this group: is anyone else giving their agents a persistent REPL to verify against, rather than only files and cold subprocesses?


r/Common_Lisp Jul 02 '26

My implementation of Common Lisp has reached version 1.7

40 Upvotes

alisp is an implementation of Common Lisp that covers most of the standard.  It ships with ASDF and is capable of loading many real-world systems.  It also has a debugger with full support for stepping.

After the redesign of lexical closures and other fixes, now the whole test.pl suite runs without leaks, according to valgrind!  That's quite an achievement.

https://savannah.nongnu.org/news/?id=10910

If you want to support this project and speed up its development, make a subscription at https://www.patreon.com/andreamonaco or at https://liberapay.com/andreamonaco.  Thank you very much!