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.
| 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.
deps.ednThe 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 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.
| 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.