Browse Learn Clojure Foundations as a Java Developer

Clojure CLI vs Leiningen

Compare the Clojure CLI with deps.edn and Leiningen with project.clj so Java engineers can run existing projects, choose new-project defaults, and avoid tool migration churn.

Java developers usually ask this question early:

Is the Clojure equivalent of Maven or Gradle called Leiningen or tools.deps?

The practical answer is: both matter. Learn the tool your project uses first, then form opinions later.

The Core Difference

Concern Clojure CLI + deps.edn Leiningen + project.clj
Main command clj / clojure lein
Project file deps.edn project.clj
Feel Classpath and execution aliases Project task runner
Common commands clj, clojure -M, clojure -X, clojure -T lein repl, lein test, lein run, lein uberjar
New official docs Centered on the CLI Still relevant, especially in existing projects
Java analogy Closer to explicit classpath plus aliases Closer to a conventional build tool

Do not force a one-to-one Maven or Gradle analogy. Clojure workflows often split dependency/classpath construction, REPL startup, project tasks, and packaging across smaller tools.

Clojure CLI And deps.edn

The CLI workflow is centered on data configuration:

1{:paths ["src" "resources"]
2 :deps {org.clojure/clojure {:mvn/version "1.12.5"}}
3 :aliases
4 {:test {:extra-paths ["test"]}}}

Typical commands:

1clj
2clojure -Spath
3clojure -M -m my.app
4clojure -X my.app/run

This workflow rewards understanding the JVM classpath. That is good news for Java engineers: your classpath instincts transfer, but the configuration is expressed as Clojure data.

Leiningen

Leiningen remains common in existing Clojure applications:

1(defproject my-app "0.1.0-SNAPSHOT"
2  :dependencies [[org.clojure/clojure "1.12.5"]]
3  :main my-app.core)

Typical commands:

1lein repl
2lein test
3lein run
4lein uberjar

Leiningen often feels more familiar to Java developers because it exposes named project tasks. If a repository already has project.clj, use it confidently instead of trying to migrate the project on day one.

Choosing For A New Project

Situation Sensible default
Following current official Clojure docs Clojure CLI
Joining an existing project.clj app Leiningen
Building a small learning project Clojure CLI
Maintaining a mature Leiningen app Leiningen until there is a real migration reason
Integrating with a larger Java build Decide based on module boundaries and existing build ownership

The wrong move is tool churn without a teaching or operational payoff. A Clojure team can be productive with either workflow when commands are documented and CI agrees with local development.

Knowledge Check

### What should you do first when joining an existing Clojure project? - [x] Learn and run the toolchain the project already uses. - [ ] Migrate it immediately to your preferred tool. - [ ] Delete either `deps.edn` or `project.clj` without asking. - [ ] Set a global classpath. > **Explanation:** Existing projects often encode important workflow knowledge in their chosen tool. Understand it before changing it. ### Which file usually indicates a Leiningen project? - [x] `project.clj` - [ ] `package.json` - [ ] `pom.lock` - [ ] `src/main/java` > **Explanation:** Leiningen projects are typically configured with `project.clj`. ### What Java skill transfers strongly to the Clojure CLI workflow? - [x] Understanding how classpaths and dependency coordinates affect runtime behavior. - [ ] Writing inheritance hierarchies. - [ ] Configuring servlet containers for every REPL. - [ ] Avoiding command-line tools. > **Explanation:** The Clojure CLI makes classpath construction explicit, which Java engineers can learn quickly.
Revised on Saturday, May 23, 2026