A current Clojure code-quality stack for Java engineers: clojure-lsp in the editor, clj-kondo in the terminal, cljfmt for formatting, and Eastwood as an optional deeper pass.
Java developers are used to layered code-quality tooling: compiler feedback, IDE inspections, formatters, linters, and CI checks. Clojure should be treated the same way. The difference is that the modern default stack is smaller and more composable.
For most JVM Clojure projects, a sensible default is:
clojure-lsp in the editor for project-aware navigation, refactoring, and diagnosticsclj-kondo in the terminal and CI for explicit lint runscljfmt for formatting checks and fixesThat stack is enough for most teams. You do not need five overlapping linters to get serious value.
clojure-lsp is more than autocompleteThe official clojure-lsp docs describe it as the language server used by clients such as Calva, Emacs lsp-mode, vim, and others. It handles navigation, code actions, refactorings, diagnostics, and project scanning.
A key practical detail from the docs: clojure-lsp discovers classpaths by invoking the tools your project already uses, such as lein, clojure -Spath, npx shadow-cljs classpath, or bb print-deps --format classpath, depending on the project files it finds.
That means two things for Java engineers:
PATHThe docs also state that clojure-lsp uses clj-kondo under the hood for much of its analysis, so editor diagnostics already benefit from that linting engine even when you are not running clj-kondo manually.
clj-kondo separatelyEven though clojure-lsp bundles linting capability for editor use, it is still worth installing clj-kondo directly.
Why?
The official clj-kondo docs recommend a project-level .clj-kondo directory, then a classpath-aware lint pass so the tool understands your dependencies and exported configs.
For a deps.edn project, the pattern is:
1clj-kondo --lint "$(clojure -Spath)" --dependencies --parallel --copy-configs
For a Leiningen project, the same idea usually becomes:
1clj-kondo --lint "$(lein classpath)" --dependencies --parallel --copy-configs
The point is not the exact shell command. The point is that clj-kondo becomes much more useful when it knows your real classpath instead of only the file you are editing.
cljfmt to settle formatting arguments fastFormatting should be automatic or at least mechanically checkable. The official cljfmt docs support both Clojure CLI tool installation and Leiningen plugin usage.
Once installed, the important commands are simple:
1clj -Tcljfmt check
2clj -Tcljfmt fix
If your project uses Leiningen instead, the equivalent pattern is lein cljfmt check and lein cljfmt fix.
For Java teams, this is the equivalent of using a formatter to stop wasting review time on indentation and layout noise.
Eastwood is still useful, but it should be used deliberately. Its own docs note that it loads namespaces and therefore causes the side effects that loading those files would normally cause.
That makes Eastwood better as:
It is usually not the tool you want firing on every keystroke.
If I were setting a baseline for a Java-heavy Clojure team, I would start here:
clojure-lsp enabled in the editorclj-kondo wired into CI and available locallycljfmt run in check mode on pull requestsThat gives you fast feedback locally and explicit quality gates in automation without making the toolchain fragile.