Leiningen dependency commands in Clojure CLI

At work, we have recently converted our projects to the Clojure CLI and deps.edn. There were a few commands from Leiningen that I needed to find an equivalent for when working with dependencies.

Download all dependencies

Often in a CI environment, you want to download all of the dependencies for a project before building the project. In Leiningen, you can use lein deps to do this.

You can use clojure -P to Prepare the project with the Clojure CLI. This downloads libs and caches the classpath.

Note that you should avoid running clojure -P in parallel on new environments (like CI). When running clojure -P for the first time, it will set up files in ~/.clojure and clone gitlibs. If you run multiple processes doing this simultaneously, you can get race conditions that throw errors.

View the dependency tree

When debugging dependency issues, it’s often helpful to see which library pulled in a transitive dependency.

Leiningen can print the dependency showing the resolved transitive dependencies.

$ lein deps :tree
 [clansi "1.0.0"]
 [clj-kondo "2022.03.09" :scope "test"]
 [babashka/fs "0.1.2" :scope "test"]
 [cheshire "5.10.2" :scope "test"]
 [com.fasterxml.jackson.dataformat/jackson-dataformat-cbor "2.12.4" :scope "test" :exclusions [[com.fasterxml.jackson.core/jackson-databind]]]
 [com.fasterxml.jackson.dataformat/jackson-dataformat-smile "2.12.4" :scope "test" :exclusions [[com.fasterxml.jackson.core/jackson-databind]]]
 [tigris "0.1.2" :scope "test"]
 [com.cognitect/transit-clj "1.0.324" :scope "test"]
 # ...

clojure has a similar command, though with a slightly different output. In contrast to Leiningen, clojure prints the entire dependency tree. Dependencies clojure didn’t select get an X in front of them, and a short reason like :older-version or :excluded. These views can be helpful when debugging why you didn’t get the version you expected.

$ clojure -Stree
org.clojure/clojure 1.11.0
 . org.clojure/spec.alpha 0.3.218
 . org.clojure/core.specs.alpha 0.2.62
org.clojure/java.classpath 1.0.0
clansi/clansi 1.0.0
org.clojure/data.json 2.4.0
org.slf4j/slf4j-simple 2.0.0-alpha1
 . org.slf4j/slf4j-api 2.0.0-alpha1
org.owasp/dependency-check-core 7.0.2
 . us.springett/cpe-parser 2.0.2
 X org.slf4j/slf4j-api 1.7.30 :older-version
 . com.vdurmont/semver4j 3.1.0
 X org.slf4j/slf4j-api 1.7.36 :older-version

View the Classpath

While dependency trees can help track down dependency problems, sometimes you need to see the actual classpath.

Tip: I like to use | tr ':' '\n' | sort to get a sorted list of the classpath entries.

You can do this in Leiningen:

lein classpath
# or
lein classpath | tr ':' '\n' | sort

With clojure:

clojure -Spath

Both Leiningen and clojure have more commands for dependencies; you can read more about them at Dep Expansion, Deps and CLI, and lein deps.