Understand the two common Clojure project workflows so you can choose the right tool without importing Java build habits blindly.
Java developers usually ask this question early:
Is the Clojure equivalent of Maven or Gradle called Leiningen or tools.deps?
The short answer is: both matter, but they solve the problem in different ways.
deps.edn is the workflow you will encounter first in the current official Clojure guides.If you try to map both of them directly onto “one build tool with a slightly different syntax,” you will miss what makes the Clojure workflow different.
deps.ednThis workflow is centered on:
clj and clojure commandsdeps.edn files-X, -M, and -TIt is flexible and composable. Instead of assuming one project lifecycle with a fixed set of phases, it lets you build exactly the classpath and execution style you need.
Typical commands:
1clj
2clojure -M -m my.app
3clojure -X my.app/run :port 8080
4clojure -Spath
This model fits Clojure’s culture well:
Leiningen is centered on:
lein commandproject.clj filelein run, lein test, lein repl, and lein uberjarIt feels more familiar to many Java developers because it looks more like a traditional project tool:
Typical commands:
1lein new app my-app
2lein repl
3lein test
4lein run
5lein uberjar
That familiarity is useful, especially when joining an existing codebase with a well-established Leiningen workflow.
You will hear developers say “tools.deps” in conversation. In day-to-day usage they often mean the whole CLI plus deps.edn workflow, even though the underlying dependency resolution pieces and the user-facing CLI are not exactly the same thing.
For practical learning, do not overcomplicate the terminology:
deps.edn and running clj or clojure, you are in the CLI workflowproject.clj and running lein, you are in the Leiningen workflowThat distinction is the one that matters when you open a real project.
| Concern | Clojure CLI + deps.edn |
Leiningen |
|---|---|---|
| Main config | deps.edn |
project.clj |
| Default learning path in current official docs | Yes | No |
| REPL support | Strong, CLI-first | Strong, task-based |
| Dependency management | Core strength | Core strength |
| Task automation | More explicit/composable | More built-in |
| Templates/scaffolding | Minimal by default | Strong |
| Plugin ecosystem | Smaller, tool-oriented | Mature and broad |
| Best fit | Current official workflow, flexible execution | Existing projects, task-heavy workflows, mature app setup |
This is not a “new good, old bad” comparison. It is a workflow choice.
Use the workflow already chosen by the codebase unless you have a strong reason not to.
That rule alone avoids most wasted effort.
deps.edn, aliases, and CLI execution modesproject.cljlein repl, lein test, and lein uberjarThis is the most pragmatic advice for a Java engineer moving into Clojure professionally:
deps.ednproject.cljIt is tempting to say:
deps.edn = GradleThat comparison is too crude.
The more accurate comparison is:
Neither one is “the OOP build tool translated into Clojure.” Each reflects a different part of the Clojure ecosystem’s history and style.
If you are brand new and not constrained by an existing team:
clj.deps.edn controls.That sequence matches the current documentation landscape while still preparing you for the real world, where many production projects use Leiningen.
deps.edn must replace Leiningen immediately in every repoThe goal is not ideological purity. The goal is a fast, reliable development loop.