Skip to content


Below you can find all available features that clojure-lsp provides with examples using Emacs lsp-mode as the client.

LSP features#

Find a function/var definition#

Find defprotocol/defmulti implementations#

Find a function/var declaration in the ns#

Find all references of a function, var, keyword or namespace alias#

Show all workspace/project symbols#

Show all symbols on current file#

Rename symbols#

Also, it's possible to live rename symbols on the same buffer with linkedEditingRange feature.

Document highlight on hover showing symbol usages#

Documentation and clojuredocs integration#

Java support#

To understand what is supported and how to configure it, check the settings section.



Snippets are templates that make it easier to enter repeating code patterns, such as common functions/forms, they are available during completion. Tabstops are defined as $number with $0 as last tabstop.

Check all available snippets here
name description raw content
comment Insert comment block (comment\n ${0:body}\n )
comment-heading Insert comment Header ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; ${1:Namespace summary title}\n;;\n;; ${2:Brief description}\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n$0
comment-separator Insert comment separator ;; ${1:Namespace summary title}\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n$0
rich-comment Insert rich comment (comment $0 #_())
rich-comment-rdd Insert rich comment rdd block #_{:clj-kondo/ignore [:redefined-var]}\n(comment\n $0 #_())
rich-comment-hotload Insert rich comment library hotload #_{:clj-kondo/ignore [:redefined-var]}\n(comment\n ;; Add-lib library for hot-loading\n (require '[ :refer [add-libs]])\n (add-libs '{${1:domain/library-name} {:mvn/version \"${2:1.0.0}\"}$3})\n $0\n)
condp Insert condp (condp ${1:pred} ${2:expr}\n $0)
def Insert def (def ${1:name} $0)
def- Insert def private (def ^:private ${1:name} $0)
def-doc Insert def with docstring (def ${1:name}\n \"${2:docstring}\"\n $0)
defmethod Insert defmethod (defmethod ${1:name} ${2:match}\n [${3:args}]\n $0)
defmulti Insert defmulti (defmulti ${1:name} ${2:dispatch-fn})
defn Insert public defn (defn ${1:name} [$2]\n $0)
defn-doc Insert public defn with docstring (defn ${1:name}\n \"${2:docstring}\"\n [${3:args}]\n $0)
defn- Insert private defn (defn%s ${1:name} [$2]\n $0)
defprotocol Insert defprotocol (defprotocol ${1:Name}\n $0)
defrecord Insert defrecord (defrecord ${1:Name} [${2:fields}]\n ${3:Protocol}\n $0)
deftype Insert deftype (deftype ${1:Name} [${2:fields}]\n ${3:Protocol}\n $0)
fn Insert fn (fn [${1:arg-list}] $0)
for Insert for (for [${1:item} ${2:coll}]\n $0)
if Insert if (if ${1:test-expr}\n ${2:then-expr}\n ${3:else-expr})
kwargs Insert keyword args {:keys [${1:keys}] :or {${2:defaults}}}
let Insert let (let [$0])
letfn Insert letfn (letfn [(${1:name} [${2:args}]\n $0)])
ns Insert ns (ns ${1:name}\n $0:references})
ns-doc Insert ns with docstring (ns ${1:name}\n \"${2:docstring}\"\n ${0:references})
require Insert ns :require (:require [${1:namespace}])$0
require-as Insert ns require with :as alias (:require [${1:namespace} :as ${2:alias}]$3)
require-refer Insert ns :require with :refer (:require [${1:namespace} :refer [$2]]$3)
require-rdd Insert require for rich comment experiments (require '[${1:namespace} :as ${2:alias}]$3)$0
req-as Insert single require dep :as alias [${1:namespace} :as ${2:alias}]
req-refer Insert single require dep with :refer [${1:namespace} :refer [$2]]
import Insert import (:import [${1:package}])
use Insert require refer preferred over use (:require [${1:namespace} :refer [$2]])
deps-alias Insert alias with extra path & deps :${1:category/name}\n {:extra-paths [\"${2:path}\"]\n :extra-deps {${3:deps-maven or deps-git}}}$0
deps-maven Insert maven dependency ${1:domain/library-name} {:mvn/version \"${2:1.0.0}\"}$0
deps-git Insert git dependency ${1:domain/library-name}\n {:git/sha \"${2:git-sha-value}\"}$0
deps-git-tag Insert git tag dependency ${1:domain/library-name}\n {:git/tag \"${2:git-tag-value}\"\n :git/sha \"${3:git-sha-value}\"}$0
deps-git-url Insert git URL dependency ${1:domain/library-name}\n {:git/url \"$1\"\n :git/sha \"${2:git-sha-value}\"}$0
deps-local Insert local dependency ${1:domain/library-name} {:local/root \"${2:/path/to/project/root}\"}$0
deftest Insert deftest clojure.test (deftest ${1:name}-test\n (testing \"${2:Context of the test assertions}\"\n (is (= ${3:assertion-values}))$4)) $0
testing Insert testing clojure.test (testing \"${1:Context of the test assertions}\"\n $0)
is Insert is clojure.test (is (= ${1:assertion-values}))
Custom snippets#

User can register additional custom snippets. For more information, check the snippets config documentation.

Code actions#

See below for screenshots.

Code lenses showing symbol references#

Format a whole file or range#

Signature help#

Semantic tokens#

The LSP server is the best to say what is the semantic value of a token on the editor, semantic tokens allows server return to client all tokens of a buffer and how client show apply highlight.

Note: server return the semantic token (e.g. function) and the client/editor apply the color that matches the user's theme.

Call hierarchy#

Show the incoming or outgoing call hierarchy of a function/variable as a lazy tree


Show functions that call the current one recursively


Show functions that the current one call, recursively

Test Tree#

Show the tests tree hierarchy of a file

Project tree#

Show the project tree ns and external dependencies.

Diagnostics (linter)#

All linters besides the ones below come from clj-kondo that clojure-lsp calls under the hood to lint the code and retrieve the analysis to make most of features work.

Every linter configuration should be done on clj-kondo side, so anything related to unresolved symbols or unknown macros are probably related to wrong clj-kondo for the project. For more information on how to configure clj-kondo check here.

Below you can find the custom linters implemented on clojure-lsp side that uses the :custom-lint-fn from clj-kondo:


For more information on how to configure it, check the diagnostics settings section.


For more information on how to configure it, check the diagnostics settings section.


Clojure-lsp has a optional integration with clj-depend, making it easier to configure namespaces relationship.

For more information on how to configure it, check the diagnostics settings section.

Stub generation#

It's possible to configure clojure-lsp to generate and analyze stubs for specific namespaces available on your project classpath, this is useful for closed source dependencies like datomic.api, with that clojure-lsp will be able to make most features work with those dependencies. For more information check the stubs settings section.

Execute command#

Commands that client can request. Most code actions use these commands as actions.

Note: Most of these are available via code actions and clients or users may choose to use the code action menu to execute them instead of mapping.

All functions in clojure-lsp have a two-letter mnemonic shortcut. E.g. tf for thread-first-all. We strongly suggest that client authors and users use these shortcuts keys when choosing to map these commands to key chords or menus; this allows for users to maintain muscle memory and familiarity as they switch between clients and editors. Thank you to clj-refactor for this system and other tools that adhere to it.

LSP clients will allow you to bind these commands to shortcuts or menu items using LSP's workspace/executeCommand and passing a map with "command" and "arguments" keys.

Arguments: - file-uri: Absolute file uri. e.x. file:///home/user/project/src/main.clj - row: line-number of the cursor, 0 based. - col: col-number of the cursor, 0 based. - name: Used when introducing a name, usually a string for a valid clojure symbol. - filename: Filename path. e.x. src/utils.clj

Shortcut Command Name Arguments Available via code action Example
ab drag-param-backward Drag param backward [file-uri,row,col] Screen recording of Drag param forward and backward
af drag-param-forward Drag param forward [file-uri,row,col] Screen recording of Drag param forward and backward
ai add-missing-import Add import to namespace [file-uri,row,col[,name]] Screen recording of Add import to namespace
am add-missing-libspec Add missing require [file-uri,row,col] Screen recording of Add missing require
as add-require-suggestion Add require suggestion [file-uri,row,col,ns,alias,refer] Screen recording of Add require suggestion
cc cycle-coll Cycle collection (#{}, {}, [], ()) [file-uri,row,col]
ck cycle-keyword-auto-resolve Cycle keyword auto-resolve [file-uri,row,col] Screen recording of Cycle keyword auto resolve
cn clean-ns Clean namespace [file-uri,row,col] Screen recording of Clean namespace
cp cycle-privacy Cycle privacy of def/defn [file-uri,row,col]
ct create-test Create test [file-uri,row,col]
df demote-fn Demote fn to #() [file-uri,row,col] Screen recording of Promote fn to defn
db drag-backward Drag backward [file-uri,row,col] Screen recording of Drag forward and backward
df drag-forward Drag forward [file-uri,row,col] Screen recording of Drag forward and backward
dk destructure-keys Destructure keys [file-uri,row,col] Screen recording of Destructure keys
ed extract-to-def Extract to def [file-uri,row,col,name] Screen recording of Extract to def
ef extract-function Extract function [file-uri,row,col,name] Screen recording of Extract function
el expand-let Expand let [file-uri,row,col]
fe create-function Create function from example [file-uri,row,col] Screen recording of Create function from example
ga get-in-all Move all expressions to get/get-in [file-uri,row,col] Screen recording of Threading get
gl get-in-less Remove one element from get/get-in [file-uri,row,col] Screen recording of Threading get
gm get-in-more Move another expression to get/get-in [file-uri,row,col] Screen recording of Threading get
gn get-in-none Unwind whole get/get-in [file-uri,row,col] Screen recording of Threading get
il introduce-let Introduce let [file-uri,row,col,name]
is inline-symbol Inline Symbol [file-uri,row,col] Screen recording of Inline symbol
ma resolve-macro-as Resolve macro as [file-uri,row,col] Screen recording of Resolve macro as
mf move-form Move form [file-uri,row,col,filename]
ml move-to-let Move expression to let [file-uri,row,col,name] Screen recording of Move expression to let
pf promote-fn Promote #() to fn, or fn to defn [file-uri,row,col,fn-name] Screen recording of Promote fn to defn
rr replace-refer-all-with-refer Replace ':refer :all' with ':refer [...]' [file-uri,row,col,refers] Screen recording of Replace refer all with refer
ra replace-refer-all-with-alias Replace ':refer :all' with alias [file-uri,row,col] Screen recording of Replace refer all with alias
rk restructure-keys Restructure keys [file-uri,row,col] Screen recording of Restructure keys
sc change-coll Switch collection to {}, (), #{}, [] [file-uri,row,col,"map"/"list"/"set"/"vector"] Screen recording of Switch collection
sl sort-clauses Sort map/vector/list/set/clauses [file-uri,row,col] Screen recording of Sort clauses
tf thread-first-all Thread first all [file-uri,row,col] Screen recording of Thread first all
th thread-first Thread first expression [file-uri,row,col]
tl thread-last-all Thread last all [file-uri,row,col]
tt thread-last Thread last expression [file-uri,row,col]
ua unwind-all Unwind whole thread [file-uri,row,col]
uw unwind-thread Unwind thread once [file-uri,row,col]
fs forward-slurp Paredit: forward slurp [file-uri,row,col]
fb forward-barf Paredit: forward barf [file-uri,row,col]
bs backward-slurp Paredit: backward slurp [file-uri,row,col]
bb backward-barf Paredit: backward barf [file-uri,row,col]
rs raise-sexp Paredit: Raise sexp [file-uri,row,col]
ks kill-sexp Paredit: Kill sexp [file-uri,row,col]
gt go-to-test Go to test [file-uri,row,col]


Server information#

Return basic information about the server.

Cursor information#

Return debug information about the element at point.

Last update: May 22, 2024