Browse Clojure Foundations for Java Developers

Leiningen vs deps.edn

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.

  • The Clojure CLI + deps.edn is the workflow you will encounter first in the current official Clojure guides.
  • Leiningen is still common in real projects, especially older or long-lived ones, and it remains a solid project automation tool.

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.

The Practical Difference

Clojure CLI and deps.edn

This workflow is centered on:

  • the clj and clojure commands
  • one or more deps.edn files
  • explicit execution modes such as REPL, -X, -M, and -T

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

  • REPL-first development
  • data-based configuration
  • small, composable tools instead of one giant build script

Leiningen

Leiningen is centered on:

  • the lein command
  • a project.clj file
  • named tasks such as lein run, lein test, lein repl, and lein uberjar

It feels more familiar to many Java developers because it looks more like a traditional project tool:

  • one main project file
  • built-in task verbs
  • templates for scaffolding
  • plugin-based extensions

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.

What People Mean By “tools.deps”

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:

  • if you are editing deps.edn and running clj or clojure, you are in the CLI workflow
  • if you are editing project.clj and running lein, you are in the Leiningen workflow

That distinction is the one that matters when you open a real project.

The Fast Comparison

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.

How To Choose Without Overthinking It

Use the workflow already chosen by the codebase unless you have a strong reason not to.

That rule alone avoids most wasted effort.

Start with the Clojure CLI when:

  • you are learning from the current official Clojure guides
  • you are creating a small or medium project from scratch
  • you want to understand modern deps.edn, aliases, and CLI execution modes
  • you prefer a lightweight, explicit toolchain

Reach for Leiningen when:

  • the project already uses project.clj
  • your team already uses lein repl, lein test, and lein uberjar
  • you want a more all-in-one task-oriented workflow
  • you benefit from existing Leiningen templates or plugin conventions

Learn enough of both to read them

This is the most pragmatic advice for a Java engineer moving into Clojure professionally:

  • be comfortable with deps.edn
  • be able to navigate a project.clj
  • do not force a migration just because one tool feels more familiar

The Java Analogy Helps, But Only Up To A Point

It is tempting to say:

  • deps.edn = Gradle
  • Leiningen = Maven

That comparison is too crude.

The more accurate comparison is:

  • the CLI workflow is closer to a composable execution and dependency model
  • Leiningen is closer to a batteries-included project automation tool

Neither one is “the OOP build tool translated into Clojure.” Each reflects a different part of the Clojure ecosystem’s history and style.

A Good First Learning Sequence

If you are brand new and not constrained by an existing team:

  1. Learn to install the Clojure CLI.
  2. Start a REPL with clj.
  3. Learn what deps.edn controls.
  4. Learn enough Leiningen to read older or existing projects.

That sequence matches the current documentation landscape while still preparing you for the real world, where many production projects use Leiningen.

Common Migration Mistakes

  • assuming Leiningen is obsolete and therefore safe to ignore
  • assuming deps.edn must replace Leiningen immediately in every repo
  • treating either tool as a one-to-one copy of Maven or Gradle
  • choosing the tool before understanding the team’s actual workflow

The goal is not ideological purity. The goal is a fast, reliable development loop.

Knowledge Check: Choosing The Right Workflow

### Which workflow appears first in the current official Clojure guides? - [x] The Clojure CLI with `deps.edn` - [ ] Leiningen only - [ ] Maven - [ ] Gradle > **Explanation:** The current official Clojure documentation centers the Clojure CLI and `deps.edn` workflow, even though Leiningen remains important in many real projects. ### What file usually indicates a Leiningen project? - [x] `project.clj` - [ ] `deps.edn` - [ ] `pom.xml` - [ ] `settings.gradle` > **Explanation:** A Leiningen project is usually organized around `project.clj`, while the CLI workflow is usually organized around `deps.edn`. ### What is the most pragmatic default when joining an existing Clojure codebase? - [x] Use the workflow the codebase already uses unless there is a strong reason to change it. - [ ] Convert every project to `deps.edn` immediately. - [ ] Convert every project to Leiningen immediately. - [ ] Ignore the build tool and work only in the REPL. > **Explanation:** Existing team and project conventions matter more than abstract tool preference. Follow the established workflow first. ### Which of the following is more characteristic of the Clojure CLI workflow? - [x] Explicit execution modes like REPL, `-X`, `-M`, and `-T` - [ ] A single `project.clj` task file - [ ] Built-in `lein uberjar` - [ ] Project templates as the primary entry point > **Explanation:** The CLI workflow is centered on execution modes and `deps.edn`, not on a task-oriented `project.clj` model. ### When is Leiningen still a good fit? - [x] When an existing project or team already depends on its task model, templates, or plugin ecosystem - [ ] Never, because `deps.edn` replaced it entirely - [ ] Only for Java interoperability - [ ] Only for library publishing > **Explanation:** Leiningen remains useful and common, especially in mature codebases and workflows built around its tasks and plugins.
Revised on Friday, April 24, 2026