JSCL is a Common Lisp compiler that bootstraps itself
A Lisp-to-JavaScript compiler bootstrapped from Common Lisp
At a glance
- What is it?
- JSCL compiles Common Lisp to JavaScript, and the interesting part of the design is that the compiler is written in Common Lisp and compiles itself. The result runs in a browser, in Node and in Deno, and implements a substantial subset of the language, from multiple values and non local exits to packages, SETF places and CLOS.
- Who is it for?
- JSCL suits someone who wants to read a Lisp implementation that is small enough to hold in their head, and who wants to run real Common Lisp in a browser tab without a server, which is the demo that the project leads with.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 2 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 compiler is written in the language it compiles
JSCL is a Common Lisp to JavaScript compiler which is bootstrapped from Common Lisp and executed from the browser, and that second clause is the design. The repository is not a compiler written in JavaScript that happens to emit JavaScript, it is a Lisp program that compiles Lisp, and the bootstrapping means the compiler can compile itself. The tree shows the shape of that, with the source of the compiler in `jscl.lisp` at the root, a `bootstrap.sh` script, a `src/` directory, and separate `web/`, `node/` and `deno/` directories for the three runtimes it targets. There is also a `worker/` directory, which suggests a fourth shape for running the compiler somewhere without a user interface. For a reader, the appeal is that a language implementation in its own language is the easiest kind of implementation to follow, and a reader can trace a macro expansion from the source to the emitted JavaScript without leaving one language.
Building it and running it in three places
The build is three commands, and the output is a distribution directory with a runnable file per runtime:
git clone https://github.com/jscl-project/jscl.git
npm install
./make.shThe script generates `jscl.js` and the rest of the distribution files in the `jscl/dist` directory, and then the readme explains what to do with them. To use it in the browser you open `dist/index.html`. To use it in Node you run `node dist/jscl-node.js`. To use it in Deno you run `deno --allow-env --allow-read dist/jscl-deno.js`, and the two permissions in that command are the whole story of what the runtime needs, the environment and the file system, which is a small and readable contract for a compiler. If you would rather not build anything, the npm package can be installed globally with `npm install -g jscl`, which puts a `jscl` command on your path to run in Node, and there is a demo online that runs the whole thing in a page.
What Common Lisp actually works
The status section is honest about the shape of the implementation, that JSCL is and will be a subset of Common Lisp, that it is far from complete, but that it supports partially most common special operators, functions and macros. The list is specific enough to be useful. Multiple values work. Explicit control transfers work, which means `tagbody` and `go`. Static and dynamic non local exit works, so `catch` and `throw` and `block` and `return-from`. Lexical and special variables work, with the caveat that `declare` expressions are missing and you have to `proclaim` a variable special instead. Optional and keyword arguments work, as do SETF places, packages, the `LOOP` macro and the `format` function. That is a large fraction of what ordinary Lisp code touches, which is why the subset is usable rather than a toy.
CLOS is the last big piece, and it is the newest release
CLOS is listed in the same feature list as `LOOP` and `format`, but it is worth separating, because the release history shows it arriving late. The tagged releases are v0.7.0 in November 2018, whose note is CLOS support, and v0.6.1 in May 2018. So the object system came after everything else and is the most recent thing the project announced as done. For a Lisp, CLOS is not a small feature, since it brings the generic function dispatch, the method combination rules, the metaclass and class protocols and the whole story of how a method is selected, and implementing it on top of a JavaScript object model is a substantial piece of work. The package version in the manifest is now 0.9.0-alpha.0, which suggests the project has moved past 0.7 without tagging, so the interesting question for an adopter is how much of the object system they actually need, since the rest of the subset is well established.
The generated code is verbose, and the project says so
There is a paragraph in the status section that is worth reading as guidance rather than as criticism. The compiler is very verbose, some simple optimizations or minification could help to deal with it, and the invitation follows, feel free to hack it yourself. That is an accurate description of what a straightforward compiler from a dynamic language to a dynamic language produces, since every Lisp construct expands into the JavaScript needed to implement it and the intermediate values are not obviously optimisable away. If you are building JSCL to run in a browser, that verbosity is the thing to measure, and if you are reading it, it is the thing to keep in mind when you wonder why a small function produces a large file. The repository also ships a `HACKING.org` file, which is where that invitation is expanded, and the tree has a `tests.lisp` and a `tests/` directory with a `run-tests.sh`, so the Lisp implementation carries its own test suite.
Packaging, licence and the state of the work
The manifest is small and shows the shape of the project. The package is `jscl` at version 0.9.0-alpha.0, described as a Common Lisp implementation for Javascript, with `dist/jscl.js` as the main entry, a `bin` entry mapping the `jscl` command to the Node build, and the published files limited to the three distribution bundles, `jscl.js`, `jscl-node.js` and `jscl-web.js`. There is a workspace for the web directory, a `serve` script for serving the distribution locally during development, a test script that runs `run-tests.sh`, and prettier for formatting with a check variant. The only development dependencies are prettier and the `serve` package, which is a good sign for a project whose own build is written in Lisp rather than in JavaScript. The licence is GPL-3.0, the project site is jscl-project.github.io, the last push to the repository was on 2026-10-17, and the last tagged release is still v0.7.0 from 2018, which tells you the work continues on the branch while the tags lag.
Editorial conclusion
JSCL suits someone who wants to read a Lisp implementation that is small enough to hold in their head, and who wants to run real Common Lisp in a browser tab without a server, which is the demo that the project leads with. It is a poor fit if you need a complete Common Lisp, since the documentation is explicit that this is and will be a subset, and it is a poor fit if you care about the size of the generated JavaScript, since the project itself says the compiler is very verbose and that minification would help. Before you use it, check three things: which subset you actually need, since the missing pieces are documented rather than discovered at runtime, which runtime you want, since the same source is built for the browser, for Node and for Deno, and the version, with the package at 0.9.0-alpha.0 and the last tagged release still v0.7.0 from 2018.
Frequently asked questions
What is JSCL?
A Common Lisp to JavaScript compiler that is bootstrapped from Common Lisp and executed from the browser. It is a subset of Common Lisp that supports multiple values, explicit control transfers, non local exits, lexical and special variables, optional and keyword arguments, SETF places, packages, the LOOP macro, CLOS and the format function.
How do I build JSCL?
Clone the repository, run `npm install` and then `./make.sh`, which generates `jscl.js` and the rest of the distribution files in the `jscl/dist` directory. You can then open `dist/index.html` in a browser, run `node dist/jscl-node.js` in Node, or `deno --allow-env --allow-read dist/jscl-deno.js` in Deno.
Can I use JSCL without building it?
Yes. The npm package can be installed globally with `npm install -g jscl`, which provides a jscl command to run in Node, and there is an online demo that runs the compiler in a page.
Is JSCL a complete Common Lisp?
No, and the documentation says so directly, that it is and will be a subset and is far from complete, though it supports partially most common special operators, functions and macros. One documented gap is that declare expressions are missing, so a variable has to be proclaimed special instead.
What licence is JSCL under and what is its version?
GPL-3.0, with the package at version 0.9.0-alpha.0. The tagged releases are v0.7.0 in November 2018, whose note is CLOS support, and v0.6.1 in May 2018, and the last push to the repository was on 2026-10-17.
Official sources
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.
[](https://hysenlabs.com/projects/jscl-project-jscl)Was this useful?