Language Server Protocol¶
Language Server Protocol provides a standard to provide a common set of development tools, e.g. code completion, syntax highlighting, refactor and language diagnostics.
Each language requires a specific LSP server implementation.
An editor or plugin provides an LSP client that uses data from language servers, providing information about source code and enabling development tools to understand the code structure.
Clojure LSP¶
clojure-lsp is an implementation of an LSP server for Clojure and ClojureScript languages. Clojure LSP is built on top of
clj-kondo which provides the static analysis of Clojure and ClojureScript code.
Most Clojure aware editors provide an LSP client.

Install¶
Clojure LSP installation guide covers multiple operating systems.
Practicalli recommends downloading the clojure-lsp-native-linux-amd64 from GitHub release page
Extracts the clojure-lsp binary to ~/.local/bin/clojure-lsp
Check Clojure LSP server is working via the command line
Editors may provide install mechanism for Clojure LSP
Spacemacs LSP layer will prompt to install a language server when first opening a file of a major mode where LSP is enabled. E.g. when a Clojure related file is opened, the Clojure LSP server is downloaded if not installed (or not found on the Emacs path).
Neovim package called mason manages the install of lint & format tools as well as LSP servers, or an externally installed LSP server can also be used.
VSCode Calva plugin includes the clojure-lsp server, although an external server can be configured.
Configure¶
Practicalli Clojure LSP Configuration
config.edn is the recommended configuration from Practicalli.
Include :extra-paths and :extra-deps from project & user level aliases in LSP classpath. e.g. support a custom user namespace in dev/user.clj
Include Java Sources installed via Debian / Ubuntu package openjdk-21-source to support calls to Java Objects and Methods.
:java
{:jdk-source-uri "file:///usr/lib/jvm/openjdk-21/lib/src.zip" ;;
:home-path nil ;; jdk-source-uri takes precedence
:download-jdk-source? false}
Disable Java analysis
If not using Java Interop with Clojure, it can be an advantage to disable the Java analysis. This should remove Java functions from autocomplete.
Clean namespace ns forms but do not sort require names
:clean {:automatically-after-ns-refactor true
:ns-inner-blocks-indentation :next-line
:ns-import-classes-indentation :next-line
:sort {:ns false
:require false
:import false
:import-classes {:classes-per-line 3} ;; -1 for all in single line
:refer {:max-line-length 80}}}
Use ^private metadata for private function definitions rather than defn-
Location of cljfmt configuration for formatting, path relative to project root. The defaults for cljfmt are used, except :remove-consecutive-blank-lines? which is set to false to enable more readable code.
cljfmt configuration included example
:indentsrules for clojure.core, compojure, fuzzy rules and examples used by the Clojure LSP maintainer.
Practicalli snippets¶
Practicalli Snippets are defined in the :additional-snippets section of the Practicalli Clojure LSP config.
Docs / comments¶
comment-heading- describe purpose of the namespacecomment-separator- logically separate code sections, helps identify opportunities to refactor to other name spacescomment-section- logically separate large code sections with start and end line commentswrap-reader-comment- insert reader comment macro,#_before current form, informing Clojure reader to ignore next form
Repl Driven Development¶
rich-comment- comment blockrich-comment-rdd- comment block with ignore :redefined-var for repl experimentsrich-comment-hotload- comment block with add-libs code for hotloading libraries in Clojure CLI replwrap-rich-comment- wrap current form with comment reader macrorequire-rdd- add a require expression, for adding a require in a rich comment block for RDD
Standard library functions¶
def- def with docstringdef-- private def with docstringdefn- defn with docstringdefn-private defn with docstringns- namespace form with docstring
Clojure CLI deps.edn aliases¶
deps-alias- add Clojure CLI aliasdeps-maven- add a maven style dependencydeps-git- add a git style dependency using:git/shadeps-git-tag- as above including:git/tagdeps-git-url- add git style dependency using git url (url taken from dependency name as it is typed - mirrored placeholder)deps-local- add a:local/rootdependency
Requiring dependencies¶
require-rdd- add a require expression, for adding a require in a rich comment block for RDDrequire- simple requirerequire-refer- require with:referrequire-as- require with:asaliasuse- creates a require rather than the more troublesome use
Unit testing¶
deftest- creates a deftest with testing directive and one assertiontesting- creates a testing testing directive and one assertionis- an assertion with placeholders for test function and expected results
References¶
- LSP mode - A guide on disabling / enabling features - if the Emacs UI is too cluttered or missing visual features
- Configure Emacs as a Clojure IDE
- Language Server Protocol support for Emacs