Self-hosted service
fukamachi/qlot avatar
fukamachi/qlot

qlot pins Common Lisp libraries to your project, not to the month

A project-local library installer for Common Lisp

577 stars51 forksCommon LispMIT

At a glance

What is it?
qlot is a project-local library installer for Common Lisp built on the Quicklisp facility, with a qlfile manifest and a qlfile.lock that record exactly which version of each dependency a project uses, so two people on the same project get the same libraries. It suits a Common Lisp team tired of Quicklisp's rolling snapshot, and it installs several different ways.
Who is it for?
Adopt qlot when you build a Common Lisp application that has to run identically on your machine, a colleague's and a server, because the lock file is the point and Quicklisp's snapshot model cannot give you that. Do not adopt it for experimenting with a single throwaway script, since the point is the recorded lock file.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly Common Lisp, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Quicklisp cannot solve

There is a section titled What Qlot is trying to solve, and it explains the gap in a way most package manager docs do not. Quicklisp is the central library registry and it made installation of libraries very easy, but what only you can specify is the month of distribution, which means you have to use all libraries of the same moment and you cannot use a newer or older version of a library for your project. The alternatives have two problems. Local-projects directories and ASDF configurations are not project-local, so if you have multiple projects that use different versions of the same library it becomes a problem. And they are difficult to fix the version or to update, because if your project needs to work on other than your machine, on other people's machines or on servers, the version of the depending libraries should be the same. That second point is the one that matters for a working team, and it is the reason qlot describes itself as aiming to be like Bundler for Ruby or Carton for Perl. The name is pronounced kyü-lät, like culotte, which is a small human touch in a document about dependency resolution.

qlot init creates a manifest, a lock file and a directory

The usage section is a short shell session that shows the whole life of a project. You move to your project directory, initialise it with qlot init, install the libraries project-locally with qlot install, add the upstream version of a library with qlot add mito --upstream, add a library from GitHub with qlot add fukamachi/anypool, update specific libraries with qlot update mito, and run a REPL with a project-local Quicklisp using qlot exec sbcl. What qlot init creates is three things: a file named qlfile, a file named qlfile.lock, and a directory called .qlot at the root of the project directory. The qlfile is the manifest clarifying the project dependencies, and the qlfile.lock is the record of the resolved versions, so the two files have the same division of labour as Gemfile and Gemfile.lock. The .qlot directory is where the libraries themselves are installed, which is why the executable is invoked with qlot exec rather than by setting up a load path by hand.

The shell session is short:

shell
$ cd /path/to/myapp

# Initialize the project to start using Qlot.
$ qlot init

# Install libraries project-locally.
$ qlot install

# Add the upstream version of a library
$ qlot add mito --upstream

# Add a library from GitHub
$ qlot add fukamachi/anypool

# Update specific libraries
$ qlot update mito

# Run a REPL with a project-local Quicklisp
$ qlot exec sbcl

An experimental REPL API that mirrors the shell

The README documents a REPL interface marked experimental, and it is worth knowing about because it changes how you work in an editor. You set qlot:*project-root* to a path, which is not necessary if the REPL was invoked through qlot exec, then call qlot:init, qlot:install, qlot:add, qlot:update. The argument style differs from the shell in a way that shows it is the same operations underneath. qlot:add :mito :upstream t is the Lisp spelling of qlot add mito --upstream, and qlot:add "fukamachi/anypool" is the spelling of qlot add fukamachi/anypool. The qlot:update call takes a keyword, so qlot:update :mito corresponds to qlot update mito. The reason this matters is the editor integration sections, which cover Lem, Emacs and Vim or Neovim, and an interactive REPL where you can install and update dependencies without leaving the editor is the difference between a project-local setup and a setup you only maintain on the command line.

Four installation routes, and a warning about ASDF

The installation section covers several ways in, and each suits a different situation. The automatic installer is recommended and is a single command, curl -L https://qlot.tech/installer piped to sh, which also needs curl or wget and tar. If you already use Roswell, ros install qlot installs from the Quicklisp dist and ros install fukamachi/qlot installs the latest from the git repository, and Roswell adds an executable script under $HOME/.roswell/bin, which must be in your PATH. If Quicklisp is set up on your home directory, ql:quickload:qlot works, and you update with ql:update-all-dists. And a manual install from a release tarball needs nothing but sbcl and OpenSSL, which is the point of that route. There is also a Docker route with docker run --rm -it fukamachi/qlot, and a Dockerfile that builds from fukamachi/sbcl, installs the UltraLisp distribution, installs qlot and sets the entrypoint to qlot. The warning is the part to read carefully. Do not add the Qlot source directory to any ASDF loadable directory such as ~/common-lisp or ~/quicklisp/local-projects, because ASDF accidentally loads dependencies of Qlot in a REPL even when you do not need it.

The ASDF exclusion, and why it exists

There is an optional settings section devoted to preventing Qlot from being loaded by accident, and the mechanism is a small snippet you add to your init file, such as ~/.sbclrc for SBCL. The problem it solves is that ASDF loads any ASD files under a directory called ~/common-lisp including its subdirectories, which is easy to understand and convenient, but it leads to a problematic situation where ASDF accidentally loads libraries under .qlot even when you do not need it. The fix pushes .qlot onto asdf::*default-source-registry-exclusions* and then calls asdf:initialize-source-registry. Roswell does not require the setting because it ignores directories starting with a dot, which tells you the problem only exists if you use the plain ASDF registry. This is a small detail with an outsized effect on the experience, because a REPL that quietly loads a second copy of a library is the kind of bug that costs an afternoon.

Shared cache, qlfile syntax and the toolchain around it

The remaining sections cover the parts of a package manager you would expect. A shared dependency cache section addresses the fact that every project reinstalling the same libraries wastes time and disk, and the qlfile syntax section defines the manifest format, with the qlfile syntax reference in the README linked from the tutorial. Priorities of distributions is a separate section, which matters when several distributions provide the same library, because the order in which they are consulted decides which version wins. Working with local git repositories covers the case where a dependency is not published anywhere, and the examples section closes with building a Docker image. The repository layout matches the structure of the tool, with src/ for the implementation, bin/ for the executable, scripts/ for the setup, install, uninstaller and run scripts, roswell/ and quicklisp-client/ for the two distribution integrations, local-init/ for the init files the tool installs, qlot.asd and qlot-tests.asd for the ASDF systems, tests/ and a Dockerfile. The release history shows 1.8.4 on 2026-05-31, 1.8.3 on 2026-02-10 and 1.8.2 on 2025-12-05, with the last push on 2026-10-08 and an MIT licence.

Editorial conclusion

Adopt qlot when you build a Common Lisp application that has to run identically on your machine, a colleague's and a server, because the lock file is the point and Quicklisp's snapshot model cannot give you that. Do not adopt it for experimenting with a single throwaway script, since the point is the recorded lock file. Verify first that you have Roswell or SBCL and OpenSSL on Unix, that the ASDF exclusion for the .qlot directory is in your init file if you use ~/common-lisp, and that the qlfile you write names the distribution sources you actually intend to use.

Frequently asked questions

What problem does qlot solve for Common Lisp developers?

Quicklisp gives you the month of distribution and no way to use a newer or older version of a library for a project, and the local-projects and ASDF alternatives are not project-local and are hard to fix or update. qlot installs libraries into a .qlot directory inside your project and records the resolved versions in qlfile.lock, so the project runs against the same libraries on every machine.

How do I install qlot?

With the automatic installer, curl -L https://qlot.tech/installer piped to sh, which needs curl or wget and tar. With Roswell, ros install qlot or ros install fukamachi/qlot. With Quicklisp, ql:quickload :qlot. Or manually from a release tarball, which requires only sbcl and OpenSSL. There is also a Docker image, fukamachi/qlot.

What does qlot init create in my project?

It creates two files, qlfile and qlfile.lock, and a directory called .qlot at the root of the project directory. The qlfile is the dependency manifest and the qlfile.lock records the resolved versions, and the libraries themselves are installed under .qlot.

Why should I not put the Qlot source directory in ~/common-lisp?

Because ASDF loads any ASD files under that directory including its subdirectories, and it will accidentally load libraries under .qlot and Qlot's own dependencies in a REPL even when you do not need them. The README recommends adding the .qlot directory to asdf::*default-source-registry-exclusions* in your init file, and notes that Roswell does not need this because it ignores directories starting with a dot.

Official sources

  1. fukamachi/qlot on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/fukamachi-qlot.svg)](https://hysenlabs.com/projects/fukamachi-qlot)

Was this useful?