clojure-lsp: A Language Server That Analyses Clojure Statically
Clojure & ClojureScript Language Server (LSP) implementation
At a glance
- What is it?
- clojure-lsp is a language server for Clojure and ClojureScript that takes a Cursive-like approach of statically analysing code rather than evaluating it, and it ships with completion, navigation, refactorings, code lens, semantic tokens and call hierarchy. It runs inside editors such as lsp-mode, Calva and vim, and also as a CLI and API.
- Who is it for?
- clojure-lsp fits a Clojure or ClojureScript team that wants one analysis engine behind several editors, that needs the server to run in CI or scripts as well as in an IDE, and that prefers static answers to answers that require starting the application.
- 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 1 day ago.
- What is it written in?
- Mainly Clojure, 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
Reading the Code Instead of Running It
The architectural decision in clojure-lsp is stated in one line in the README: it takes a Cursive-like approach of statically analysing code. That single sentence explains most of what the project does and, just as importantly, what it does not do.
A static analyser derives its answers by reading the source rather than by evaluating it. For a language where a function body is data that the compiler interprets at runtime, that choice has consequences. Definitions can be located without starting the application, so a jump to definition works on a namespace whose dependencies are not even on the classpath, and the server never has to run project code to tell you what a symbol refers to. The cost is that the analysis has to be good at understanding the shapes a Clojure program can take before it runs, which is the hard part of the language.
The stated goal is to bring good editing tools for Clojure and ClojureScript to all editors, and programmatically through its CLI and API. The project describes itself as more than 30,000 lines of code, and it is the base for Clojure clients including Emacs with lsp-mode, VSCode with Calva, and vim, along with other editors.
The Feature List Covers the Usual Language Server Surface
The README enumerates what you get, and it is a conventional language server feature set with a couple of Clojure specific additions:
Autocomplete
Jump to definition/implementation
Find references
Renaming
Code actions
Errors
Automatic ns cleaning
Lots of Refactorings
Code lens
Semantic tokens (syntax highlighting)
Call hierarchy
Java interopTwo entries stand out for a Lisp. Automatic ns cleaning removes namespace declarations that are no longer needed, which is a maintenance task that is tedious by hand and easy to automate once you know which forms are used. Java interop means the analysis understands the interop forms rather than treating every interop call as an unknown symbol, which matters for any code base that touches the host platform.
Semantic tokens and code lens are the two features that pull in editor rendering rather than editor intelligence, and they are worth separating conceptually from the rest. A client that supports them shows the analyser results in a different visual style or as an inline annotation, and a client that does not still gets the underlying information through the protocol.
The Server Is Also a Command Line Tool and an API
The README makes a point that is easy to miss in a language server announcement: clojure-lsp does not need to run only with an editor. There is a whole section of the documentation under Outside editor, described as the API, that explains what the server is when there is no editor attached.
This is a differentiator for CI. A lint or refactoring check that only exists as an editor plugin is a check that only runs on the machine of whoever remembered to run it. The same analysis engine exposed as a CLI can be a build step, and the API form allows other tools to drive it.
The repository layout is consistent with that claim. The cli/ directory holds the command line entry points, lib/ holds the implementation, scripts/ holds helper scripts, and the release and install directories handle packaging, with docs/ and mkdocs.yml driving the website that the README links to for features, installation, settings, clients and troubleshooting. The presence of a .lsp/ directory in the repository, which is the conventional place for server configuration in a client, also shows that the project is designed to be pointed at from an editor rather than embedded in one.
Installation Runs Through Clojars, an Install Script and Native Binaries
The distribution story is visible in the repository and the badges. The project is published to Clojars under the coordinate com.github.clojure-lsp/clojure-lsp, and it is also documented on cljdoc at that same coordinate, so the API documentation is generated from the source rather than written separately. The installation instructions themselves live on the project website, under the installation page linked from the README header.
Two directories in the repository hint at the other routes. The install/ directory suggests a script based install, and the release/ directory suggests the packaging work is scripted too. The repository topics also list native-binaries and graalvm, which is how a JVM-language project advertises that it ships as a native image rather than requiring a JVM on the target machine, and that is relevant for anyone who wants to run the server in a small container or on a machine without a Java runtime.
There is a Nix flake in the tree, flake.nix with flake.lock, and a bb.edn for the Babashka task runner, along with deps.edn and a deps-lock.json for dependency pinning. So the build tooling is Clojure-native throughout.
Date Based Versions and a Nightly Build Alongside the Tags
The release numbering encodes the build moment, not a semantic version. The recent tags are 2026.10.15-11.42.38, 2026.07.06-14.34.19 and 2026.05.05-12.58.26, which is a date followed by a build counter and a time. There is also a nightly workflow badge in the README pointing at a nightly.yml workflow, so the project publishes continuous builds in parallel with its dated tags.
For a tool that a team pins inside an editor configuration, that matters. A dated version tells you exactly which build you are on without looking up a changelog entry, and a nightly channel means a regression can often be bisected to a day. The CHANGELOG.md at the root is where the changes are recorded, and the AGENTS.md file suggests the project has started documenting conventions for automated contributors.
The repository is not archived and the last push was on 2026-10-15, matching the newest tag, so the tree is current. There is a Slack community channel and a Clojurists Together sponsorship history, with the README noting sponsorship in Q3 2021 and Q1 2022 and that there are currently no gold sponsors.
What Static Analysis Does Not Tell You
The honest limitation of this design is that an analyser and a running program can disagree, and the README does not claim otherwise. The approach is described as statically analysing code, and everything the project offers is derived from that reading rather than from evaluating your namespaces.
In practice the gap shows up where the language is most dynamic. Code that computes a var name at runtime, resolves a keyword through a map, or dispatches on a value read from configuration cannot be resolved by reading the source, so features that depend on knowing what a symbol is will be less certain there. The same applies to behaviour that depends on macro expansion order or on a namespace loaded at runtime. The project compensates with Java interop support and with configuration settings for the analysis, which is what the settings page on the website exists for, but the compensation is configuration and conventions, not a guarantee.
The other limit is scope of intent. The features list is long, and it covers editing concerns: navigation, renaming, code actions, refactorings, lenses, tokens, hierarchy. It does not claim to be a test runner, a build tool or a formatter of record, and the repository does contain a .cljfmt.edn file and a .clj-kondo/ directory, which suggests the project composes with those tools rather than replacing them.
One Engine, Many Editors, and Who Maintains It
The client story is the strongest argument for the project. Because it speaks the Language Server Protocol, the same analysis is available to Emacs with lsp-mode, VSCode with Calva, vim and other editors, and the documentation site has a clients page listing them. A team that mixes editors, or that has members on different platforms, gets identical results rather than different plugins with different accuracy.
The README is also candid about the economics of that. It says that to keep more than 30,000 lines of code working, the project needs help with issues and new features, and that the support keeps the project going and being updated and maintained. Sponsorship is handled through GitHub Sponsors and OpenCollective, and the maintainers note a funding history with Clojurists Together.
The licence is MIT, which means an organisation can read, fork or vendor the server without the obligations that come with a copyleft codebase, and the project is distributed on Clojars, on cljdoc and as native binaries, so adoption does not require building from source. The one thing to keep in mind when evaluating is that the analysis behaviour is configurable and its defaults are opinionated, so the settings page is worth reading before you judge the results on a large codebase.
Editorial conclusion
clojure-lsp fits a Clojure or ClojureScript team that wants one analysis engine behind several editors, that needs the server to run in CI or scripts as well as in an IDE, and that prefers static answers to answers that require starting the application. It is a poor fit for a project that needs runtime values, and it is the wrong choice if your build already depends on a different Clojure analysis stack, since the static approach has its own blind spots around macros and dynamic dispatch. Before adopting it, read the settings and troubleshooting pages on the project website rather than relying on editor defaults, and note that the release numbers are date based, 2026.10.15-11.42.38 being the newest, with a nightly workflow running alongside the tagged builds. The project is MIT licensed and the last push was on 2026-10-15.
Frequently asked questions
What editor support does clojure-lsp provide?
The server speaks the Language Server Protocol and is described as the base for Clojure clients including Emacs with lsp-mode, VSCode with Calva, vim and other editors. The project documentation has a clients page listing the supported setups.
Does clojure-lsp analyse code statically or run my project?
Statically. The README describes the project as taking a Cursive-like approach of statically analysing code, and it also points out that clojure-lsp does not need to run only with an editor, with a separate API section for use outside an editor.
Where is clojure-lsp published?
On Clojars under the coordinate com.github.clojure-lsp/clojure-lsp, with API documentation on cljdoc at the same coordinate. The project website at clojure-lsp.io carries the installation, features, settings, clients and troubleshooting pages, and the repository also includes install/ and release/ directories.
How are clojure-lsp release versions numbered?
By date and build, with tags such as 2026.10.15-11.42.38, 2026.07.06-14.34.19 and 2026.05.05-12.58.26. The README also shows a nightly workflow badge, so continuous builds run alongside the dated releases.
Which refactoring features does clojure-lsp include for Clojure?
Alongside completion, jump to definition and implementation, find references, renaming, code actions, errors, code lens, semantic tokens and call hierarchy, the feature list names automatic ns cleaning, lots of refactorings and Java interop support.
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/clojure-lsp-clojure-lsp)Was this useful?