Deploy to Clojars with Clojure CLI tool?

Can we bypass Boot and Lein and send code to Clojars by running clj?

Quick Result

at last(2020-04) I switched to deps-library, very handy:


I’d be interested to bypass lein and boot just to build uberjars with clj which is one step before clojars I believe

1 Like

This should definitely be possible. I suggest you take a look at how jar building is implemented in Lein/Boot and see if their basic approach can be copied — maybe turn it into a simple library even :slight_smile:

@swlkr FWIW most of the jars uploaded to Clojars are not uberjars (= jars that also bundle all their dependencies).

1 Like

:laughing: I didn’t know uberjars before.

AFAIK tools.deps.alpha is not intended as a build tool.


I want to remove boot from my workflow, however deploying code to Clojars still requires Boot(or Lein). I think I need some guides before really doing that. >.<

1 Like

pack from juxt can build uberjars and it works nicely with tools.deps.


It looks nice. I need to look into how it builds jars and how to send that jar into Clojars…

A fantastic guide:

updates… that post above illustrated deps.edn behaviors quite well, but for real use, please check out:


Hah, I came here intending to link my post and you beat me to it :smiley: I hope it helps!

(side note, I tweeted a slightly wrong link, so is technically the correct one - I added a redirect though)


Oh! Is it a really bad idea to publish an uberjar with Clojure bundled in? Should I just be publishing my core jar that can’t run on it’s own?

Yes, when people want your library they just want it, not the whole environment you used when you published. They may want a different version of Clojure etc. Uberjars are usually for complete apps you want to run directly from the java command-line, like java -jar .... Unless I’m completely mistaken (not a JVM specialist).

Sounds totally correct to me. So in my post, which I now need to update, make pack is really just for standalone jars that you deploy and run. I’ll need to update my build steps so that make deploy actually runs mvn package first I guess.

I’m also wondering what happens with AOT compilation. You won’t want to AOT if you publishing a library (I guess?) but if you’re publishing a JAR somewhere to run, you probably do want that AOT compiled. No idea how that works… I’ll have to update my post with all of this ASAP.

Why is everyone trying to get rid of Lein and Boot? What are the parts of these tools that are putting you off them? Which you are hoping a tools.deps based workflow would not suffer from?

Personally, I like less magic, less code to execute which means less opportunity for bugs. Also the possibility to use any commit of CLJ/CLJS without waiting for the corresponding lein/boot wrapper to make a release. I also like the possibility to use directly the CLJS compiler.

Doesn’t mean I don’t like Boot (never really used Lein), I do enjoy the composability of tasks and the virtual immutable fileset. But boot is imperative while Lein is declarative. Specifying dependencies should be declarative (think package.json, pom.xml) and build steps/project-level tasks should be imperative.

Deps give us the 1st half. And any combination of Makefiles/mach/Boot/Clojure scripts can fill the rest.

For me, because of ClojureScript. With shadow-cljs I barely need Boot or Lein, however I still need a build.boot for deploying. Feeling strange. Why do I have to install a bunch of libraries when I’m just trying to publish a package to Clojars. Aren’t importing and sharing package core features of a programming language?

1 Like

That does sound like a good rule of thumb. That said, didn’t Java start with Ant, and then Maven came around, complecting dependency management and build/deployment into one, and everyone stopped using Ant and moved to Maven?

In my experience, no. Most languages I’ve learned or used did not offer this as a core feature, but I do think it would be neat for these to be accessible as default.

Well, isn’t it really just 1 package, you need Lein or Boot? I mean, imagine the Clojure distribution was Lein. Then you’d say, oh cool, Clojure comes with a dependency manager and a build tool and a fancy CLI. But then wouldn’t you quickly complain about why the Clojure install comes with all this bloat?

I would complain “why Clojure is so slow and so much slow to startup. Node has a REPL and a npm binary after installation. Clojure is way slower than Node.js during startup, why?”.

Clojure’s slow startup is a mystery mostly. There doesn’t seem to be one single reason, its more lots of small things. Once started, its pretty fast, faster then node or python or ruby.

Node is to JavaScript what Lein is to Clojure/Script. If you want to code in Clojure, you just need to install Lein, and you’ll get a repl, a dependency manager, the clojure runtime and compiler, a build tool and a deployment packager.

But like with Javascript, you have other options. Boot is a full bundled alternative. Or you can mix and match, tools.deps + ant + clojure + clj repl for example.

I think the options Clojure gives can be confusing, but Lein is a good default. Yea, I understand startup of it is slow, clojure main repl is much faster to start, maybe lein can do something about this.

1 Like