Common Lisp implementation on .NET. Lisp source is compiled to CIL (Common Intermediate Language) and runs on the .NET JIT — so the same Lisp image runs on Windows, macOS, and Linux across x86-64 and ARM64 without per-platform porting work.
Broadly conforms to the ANSI Common Lisp standard — verified against the ansi-test suite.
- Embedding Common Lisp in .NET applications.
dotcl.runtimeis a regular .NET library; you load it from any C# / F# / VB.NET project, evaluate Lisp code, and call back and forth. - Writing .NET code in Lisp. The
dotnet:package gives direct access to .NET types:(dotnet:new "System.Text.StringBuilder"),(dotnet:invoke sb "Append" "x"),(dotnet:static "System.Math" "Sin" 1.0). You can subclass .NET types from Lisp viadotnet:define-class— the compiler emits real .NET classes, so frameworks like MAUI, ASP.NET Core, and MonoGame just see them as ordinary subclasses. - Cross-platform CL with NuGet ecosystem access. Any NuGet package is reachable from Lisp; any Quicklisp library that doesn't rely on SBCL-only internals tends to work too (asdf, alexandria, etc. are routinely loaded).
# Install dotcl as a global .NET tool (works on any host with .NET SDK 10+).
dotnet tool install --global dotcl
# REPL
dotcl repl
# Evaluate a form
dotcl --eval "(format t \"hello, ~a~%\" (lisp-implementation-type))"
# Run a file
dotcl --load my-program.lispThe framework-dependent dotcl package is portable across OS / arch but
JIT-compiles the core on first launch (~3 s cold start). For faster
startup, install the RID-specific package — it bundles ahead-of-time
(R2R) FASLs:
# Pick the one matching your host:
dotnet tool install --global dotcl.win-x64
dotnet tool install --global dotcl.win-arm64
dotnet tool install --global dotcl.linux-x64
dotnet tool install --global dotcl.linux-arm64
dotnet tool install --global dotcl.osx-x64
dotnet tool install --global dotcl.osx-arm64The two variants share the dotcl command name, so install only one.
For Roswell users, per-RID tarballs are also published on each release page.
- .NET SDK 10+ — see install table below
| OS | Command |
|---|---|
| macOS (Homebrew) | brew install --cask dotnet-sdk |
| Ubuntu 24.04+ | sudo apt install dotnet-sdk-10.0 |
| Debian | add the Microsoft package repository, then apt install dotnet-sdk-10.0 — see official guide |
| Windows (winget) | winget install Microsoft.DotNet.SDK.10 |
| Windows (Scoop) | scoop install dotnet-sdk |
| Cross-platform script | dotnet-install.sh / dotnet-install.ps1 |
| Other | https://dotnet.microsoft.com/download |
If you want to hack on dotcl itself rather than just use it, clone the repo and bootstrap with Roswell:
make cross-compile # uses Roswell/SBCL to bootstrap the compiler
make compile-asdf-fasl # pre-compiles ASDF (required by samples)
make install # builds and installs the local nupkg as `dotcl`After the first cross-compile, dotcl can self-host: DOTCL_LISP=dotcl make cross-compile rebuilds the compiler using dotcl itself.
A cross-platform desktop window from one plain Lisp file — no C# project,
no csproj. nuget (bundled, dotcl 0.1.16+) resolves NuGet packages
and their transitive dependencies at run time:
;;;; hello-gui.lisp — run with: dotcl --load hello-gui.lisp
(require "dotnet-class") ; dotnet:define-class (ships with dotcl)
(require "nuget") ; NuGet resolver (ships with dotcl)
(nuget:require "Avalonia.Desktop" :version "12.0.4")
(nuget:require "Avalonia.Themes.Fluent" :version "12.0.4")
(dotnet:load-assembly "Avalonia.Desktop")
(dotnet:load-assembly "Avalonia.Themes.Fluent")
(dotnet:define-class "Hello.App" ("Avalonia.Application")
(:ctor ()
(dotnet:invoke (dotnet:invoke self "get_Styles") "Add"
(dotnet:new "Avalonia.Themes.Fluent.FluentTheme")))
(:methods
("OnFrameworkInitializationCompleted" () :returns Void :override t
(let ((win (dotnet:new "Avalonia.Controls.Window"))
(button (dotnet:new "Avalonia.Controls.Button"))
(clicks 0))
(dotnet:invoke win "set_Title" "Hello from Common Lisp")
(dotnet:invoke win "set_Width" 420d0)
(dotnet:invoke win "set_Height" 240d0)
(dotnet:invoke button "set_Content" "Click me")
(dotnet:invoke button "set_HorizontalAlignment"
(dotnet:static "Avalonia.Layout.HorizontalAlignment" "Center"))
(dotnet:invoke button "set_VerticalAlignment"
(dotnet:static "Avalonia.Layout.VerticalAlignment" "Center"))
(dotnet:add-event button "Click"
(lambda (s e) (declare (ignore s e))
(dotnet:invoke button "set_Content"
(format nil "~r click~:p from Lisp!" (incf clicks)))))
(dotnet:invoke win "set_Content" button)
(dotnet:invoke (dotnet:invoke self "get_ApplicationLifetime")
"set_MainWindow" win)))))
(let* ((builder (dotnet:static-generic "Avalonia.AppBuilder" "Configure" (list "Hello.App")))
(builder (dotnet:static "Avalonia.AppBuilderDesktopExtensions" "UsePlatformDetect" builder))
(args (dotnet:static-generic "System.Array" "Empty" (list "System.String"))))
(dotnet:static "Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions"
"StartWithClassicDesktopLifetime" builder args))The first run downloads Avalonia from NuGet (a minute or two); after that
it starts in seconds. The same file is in
examples/hello-gui.lisp. Note the Lisp side is
ordinary object wiring — the same dotnet:new / dotnet:invoke /
dotnet:add-event calls work against WinForms, WPF, or any other .NET UI
toolkit you have on hand.
- paalam — a NeeView-style
image / comic / PDF viewer (Avalonia). UI and application logic are
Common Lisp end to end: CLOS protocol for page sources
(folder / zip / rar / PDF), Lisp threads for prefetch,
dotnet:ffifor PDFium text extraction, installers for Windows / macOS / Linux. Read it as the scaled-up version of the five-minute example above.
Working integrations in samples/:
- MauiLispDemo — a .NET MAUI app (Windows + Android) where
Application/ContentPage/ view model are all defined in Lisp viadotnet:define-class. - AspNetLispDemo — ASP.NET Core controller written in Lisp, with attribute routing.
- MonoGameLispDemo —
Gamesubclass in Lisp; theDrawoverride runs on the MonoGame frame loop and animates the background colour. - McpServerDemo — Model Context Protocol server exposing a Lisp REPL to MCP clients (Claude Desktop, etc.).
Each sample's README.md walks through the boot pattern.
- Compiler (
compiler/, written in Lisp): transforms S-expressions into a flat list of CIL instructions (SIL). - Runtime (
runtime/, written in C#): object representation, reader, CIL assembler (PersistedAssemblyBuilder-based for.fasloutput andReflection.Emitfor in-memory codegen), and the standard library functions that aren't expressible in pure Lisp. - Bootstrap is by cross-compile: a Roswell SBCL runs
compiler/cil-compile.lispto emitcompiler/cil-out.sil, which the .NET runtime loads to bring up the Lisp environment. From that point dotcl can rebuild itself.
Architectural detail and design history are in
DESIGN.md.
MIT. See LICENSE.
