Understand how the Clojure CLI, Leiningen, and editor-driven REPLs decide classpaths, middleware, and daily workflow.
For a Java engineer, the phrase “REPL integration” can sound vague until you see what the build tool is actually doing.
In Clojure, your build tool is not just packaging code. It usually decides:
So the REPL is not separate from build tooling. The build tool is often what makes the REPL useful in the first place.
Think of it this way:
If the classpath is wrong, the REPL feels broken.
If the development aliases or profiles are wrong, hot reloading and editor commands feel broken.
If the middleware is missing, editor integrations lose much of their power.
This is why REPL setup in Clojure matters more than launching a one-off shell.
The first distinction to keep clear is:
A plain terminal REPL is often just clojure.main running in your terminal.
An editor REPL is usually richer. It commonly involves:
That is why “it works in the terminal” and “it works from my editor” are related but not identical states.
deps.ednIn a deps.edn project, the most basic project REPL is started from the project root with:
1clj
That gives you a REPL with the project’s classpath.
If you need extra development paths or tools, put them in aliases instead of depending on a pile of manual REPL steps. For example, a :dev alias might add:
dev source pathsThen the development REPL becomes something explicit and repeatable, such as:
1clj -M:dev
The important lesson is not the exact command. It is that the project owns the classpath shape.
That makes the environment reproducible for:
Leiningen gives you the same broad benefit through a different project model.
Inside a Leiningen project, this command starts a REPL with the project dependencies and source code available:
1lein repl
Leiningen centers configuration in project.clj, so the REPL environment often reflects:
:dependencies:repl-optionsFor a Java developer, this often feels closer to Maven or Gradle thinking: one file shapes the project, and the tool launches an environment derived from that file.
The big practical point is the same as with deps.edn: if your REPL depends on hidden local setup, the workflow will drift and eventually break.
A common beginner mistake is to think the build tool only matters at packaging time.
In Clojure, that is too narrow.
A healthy project usually encodes development concerns in the tool configuration too:
That is what makes a project REPL trustworthy.
Without that, you end up with private terminal rituals that nobody else can replay.
Once you move from a plain terminal REPL to an editor workflow, middleware becomes important.
Tools such as Calva and CIDER commonly rely on an nREPL server plus cider-nrepl middleware to support features like:
This is why “jack in” matters in editor docs. Jack-in usually means:
That is much more reliable than manually starting random processes and hoping the editor can guess what you meant.
In practice, serious projects often need at least two REPL shapes:
Sometimes there is also a third:
Trying to force one REPL shape to do everything is often what makes the workflow feel fragile.
Instead, define the shapes intentionally.
dev Namespace For Repeatable StartupNo build tool can save a workflow that still requires twenty manual steps after the REPL starts.
A strong pattern is to pair the build-tool setup with a small dev namespace containing helper functions such as:
startstoprestarttest-systemThat gives the REPL a stable control surface for your application.
The build tool answers:
The dev namespace answers:
Those two pieces belong together.
Java developers are used to builds being oriented around:
Clojure projects still need those things, but the development center of gravity is different. The build configuration is often judged by a more immediate question:
That shift is part of why Clojure teams care so much about classpath clarity, dev aliases, namespace reload behavior, and editor integration.
| Need | Typical Choice |
|---|---|
Quick terminal experimentation in a deps.edn project |
clj from the project root |
Development REPL with extra paths or helpers in a deps.edn project |
clj -M:dev or editor jack-in using the same project config |
| Project REPL in a Leiningen project | lein repl |
| Rich in-editor workflow with evaluation and inspection commands | Editor jack-in or connect workflow backed by nREPL/socket REPL |
| Repeatable local system control | Build-tool config plus a dedicated dev namespace |
The exact commands matter less than the repeatable structure behind them.