Browse Clojure Foundations for Java Developers

Linting and Static Analysis Tools

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.

The current default stack

For most JVM Clojure projects, a sensible default is:

  • clojure-lsp in the editor for project-aware navigation, refactoring, and diagnostics
  • clj-kondo in the terminal and CI for explicit lint runs
  • cljfmt for formatting checks and fixes
  • Eastwood only when you want an occasional deeper lint pass beyond the normal day-to-day loop

That stack is enough for most teams. You do not need five overlapping linters to get serious value.

clojure-lsp is more than autocomplete

The 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:

  • your editor must have the right tools on PATH
  • classpath problems are often tool-environment problems, not mysterious editor bugs

The 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.

Why you should still install clj-kondo separately

Even though clojure-lsp bundles linting capability for editor use, it is still worth installing clj-kondo directly.

Why?

  • you can run it in CI
  • you can lint whole projects explicitly from the terminal
  • you can warm caches and copy library configs deliberately
  • you can make code-quality checks visible outside the editor

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.

Use cljfmt to settle formatting arguments fast

Formatting 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 optional, not the default inner loop

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:

  • an occasional batch lint pass
  • a deeper CI or pre-release check
  • a targeted analysis step for mature JVM projects

It is usually not the tool you want firing on every keystroke.

A practical setup for Java teams

If I were setting a baseline for a Java-heavy Clojure team, I would start here:

  1. clojure-lsp enabled in the editor
  2. clj-kondo wired into CI and available locally
  3. cljfmt run in check mode on pull requests
  4. Eastwood only if the team benefits from an extra batch pass

That gives you fast feedback locally and explicit quality gates in automation without making the toolchain fragile.

Knowledge Check

### Why is it still useful to install `clj-kondo` separately even if your editor already uses `clojure-lsp`? - [x] Because you still want explicit CLI and CI lint runs outside the editor - [ ] Because `clojure-lsp` cannot work with Clojure projects - [ ] Because `clj-kondo` only formats code - [ ] Because `clj-kondo` replaces the REPL > **Explanation:** Editor diagnostics are not enough on their own. Separate CLI linting makes checks reproducible in CI and visible to the whole team. ### What is the main reason `clj-kondo` becomes more effective after a classpath-aware project lint? - [x] It learns about your dependencies and exported library configs instead of treating files in isolation - [ ] It stops needing any project files - [ ] It becomes a formatter instead of a linter - [ ] It disables editor integration > **Explanation:** Classpath-aware linting gives `clj-kondo` the context it needs to analyze real project usage instead of a single file in isolation. ### Why should Eastwood usually be treated as an occasional batch tool rather than the default live editor loop? - [x] Because it loads namespaces and can trigger normal load-time side effects - [ ] Because it cannot run on JVM projects - [ ] Because it only works for Java source files - [ ] Because it replaces `clojure-lsp` > **Explanation:** Eastwood is powerful, but it is not designed for the same role as lightweight editor diagnostics. It is better used intentionally as a deeper pass.
Revised on Friday, April 24, 2026