babashka 2026-09-10

Alex Miller (Clojure team) 2026-09-10T14:28:22.490279Z

@borkdude I'm not sure if you're aware of the aether.connector.userAgent system property - it's used by the Maven libs to identify the calling agent. tools.deps sets it as a default, the Clojure CLI extends it with CLI info. it might be useful for you to pop something in there too in the cases where you are the deps downloader. that agent string shows up in Maven stats and clojars probably can use it too to see traffic sources

👍 2
🙏 1
Alex Miller (Clojure team) 2026-09-10T14:31:58.803139Z

you can stack multiple things in the agent string, seems like the first is the top-level but I do something like "ClojureCLI/1.12.6.13 tools.deps/0.31.99"

ok, will do this:

babashka/ tools.deps/

Alex Miller (Clojure team) 2026-09-10T14:54:31.079299Z

in Sonatype (for Maven Central) they have a Scarf integration (limited for free, paid for more data) that can report the User Agent stats. Here's Clojure downloads for the past week for example

Alex Miller (Clojure team) 2026-09-10T14:55:49.822639Z

Aether is the default in the Maven resolver if you don't set it (I wasn't doing that until recently in the CLI)

for which library are these stats?

Alex Miller (Clojure team) 2026-09-10T14:56:20.641179Z

clojure

that's cool

Alex Miller (Clojure team) 2026-09-10T14:57:49.696629Z

lein includes JVM version which doesn't roll up very nicely

Alex Miller (Clojure team) 2026-09-10T14:58:37.479039Z

I don't know if clojars provides these stats, but they could

Alex Miller (Clojure team) 2026-09-10T15:01:34.640219Z

I think Maven Central is now looking at this stuff to identify scrapers too, so having this stuff set I think makes us less prone to getting banned

Alex Miller (Clojure team) 2026-09-10T15:01:51.333769Z

now that you can download so fast :)

Clojars doesn't collect user-agents currently, but could certainly start doing so. I have logic to do it now, developed in prep for my conj talk. I'll create an issue to think about collecting and sharing them.

😎 1
Alex Miller (Clojure team) 2026-09-14T17:29:06.357759Z

as a tool maker, I certainly find those stats super useful to get an idea of the age of the tools people are using in practice

👍 2

In HoneySQL's bb.edn file, I conditionally build a snapshot or a regular JAR, based on command line args: https://github.com/seancorfield/honeysql/blob/develop/bb.edn#L67-L75 If I switch to using bb to run the build/jar task, I could use :exec-fn build/jar but what would be the equivalent for (run '-snapshot) there to pass :snapshot true (or nothing). :exec-args does not eval its value, right, so I couldn't just say :exec-args (run '-snapshot) and change -snapshot to return a map?

You can just make --snapshot an option of your exec-fn

bb jar --snapshot 

Right now, jar gets a hash map of opts. How would --snapshot be passed?

as {:snapshot true}

Oh, from --opt to :opt true?

Yes. You can also explicitly specify this with metadata:

{:org.babashka/cli {:spec {:snapshot {:coerce :boolean}}}}
as fn metadata. if you do that, then you will also get auto-completions

and automatic help: bb jar --help

for autocomplete to work you do need to execute this somewhere in your zsh setup:

source <(bb org.babashka.cli/completions snippet --shell zsh)
You can read the details in the babashka cli readme

(other shells supported too of course, even powershell)

Maybe I'm holding it wrong... I have

ci {:doc "Run the CI pipeline of tests and build the JAR."
      :depends [test:bb eastwood doc-test:all test:all]
      :task build/jar}
and run bb ci --snapshot but the build/jar function seems to be passed a string?

Oh, exec-fn

and a nice bonus feature: if your :depends contains other :exec-fn, the specs get merged, so you'll also get auto-completions for that now

Okay, I have this now:

ci {:doc "Run the CI pipeline of tests and build the JAR."
      :depends [test:bb eastwood doc-test:all test:all]
      :exec-fn build/jar}

  ci:deploy {:doc "Deploy the JAR we just built to Clojars."
             :depends [ci]
             :exec-fn build/deploy}
but bb ci:deploy --snapshot does not pass :snapshot true to build/jar, only to build/deploy

I expected the opt to be available for all the :depends tasks based on your comment...

I think it might have to be explicitly defined in the depends case

since the specs are merged. but if both don't have a spec... I don't think I have tested that

Nothing has a spec (yet).

perhaps it should just pass all the things in that case

darn. what if bb could derive this from :keys and :keys! automatically ;)

the reason it doesn't just pass things here is that some fns may throw on unexpected keys

I'll write a note about this to investigate.

So I need this, yes?

(defn ^{:org.babashka/cli {:spec {:snapshot {:coerce :boolean}}}}
  jar "Build the JAR." [opts]
(and the same on deploy)

just write

(defn jar
 "Docstring"
 {:org.babashka/cli ...}
 [opts] ...)
but yeah both should work

Yup, that works:

Building target/com.github.seancorfield/honeysql-2.7.9999-SNAPSHOT.jar ...

Version: 2.7.9999-SNAPSHOT
{:installer :remote, :artifact #object[java.io.File 0x1b784319 ./target/com.github.seancorfield/honeysql-2.7.9999-SNAPSHOT.jar], :pom-file ./target/classes/META-INF/maven/com.github.seancorfield/honeysql/pom.xml}

Awesome! Can't wait for the non-dev release with this 🙂

I'm curious about Rich's new talk at the conj, perhaps more stuff will be added which could be useful for both kondo and cli...

Okay, one more weirdness I don't understand...

test:bb {:extra-paths ["test"]
           :extra-deps  {io.github.cognitect-labs/test-runner
                         {:git/tag "v0.5.1" :git/sha "dfb30dd"}}
           :task (exec 'cognitect.test-runner.api/test)
           :exec-args {:patterns ["^(?!(honey.cache|honey.sql-alphanumeric)).*-test$"]}}
This runs the tests via Babashka and skips two nses. I expected to be able to change this to;
test:bb {:extra-paths ["test"]
           :extra-deps  {io.github.cognitect-labs/test-runner
                         {:git/tag "v0.5.1" :git/sha "dfb30dd"}}
           :exec-fn cognitect.test-runner.api/test
           :exec-args {:patterns ["^(?!(honey.cache|honey.sql-alphanumeric)).*-test$"]}}
But this doesn't pass the exec args?

(the test run fails because honey.sql-alphanumeric depends on test.check which is not provided in the deps in this case)

have you checked that it doesn't pass the arg by e.g. printing it?

try :exec-fn clojure.core/prn

I get this:

$ bb test:bb --dude
{:patterns ["^(?!(honey.cache|honey.sql-alphanumeric)).*-test$"], :dude true}

maybe the regex is off because this is written in EDN?

bb test:bb works. bb ci does not.

All of the individual :depends tasks run.

you can leave out io.github.clojure/tools.build {:mvn/version "0.10.14"} now, I had to bundle tools.build myself for the uberjar task

it's always good to lines go away :) 17 additions and 32 deletions do you still have your bug?

I just found out about this bug: https://github.com/babashka/babashka/issues/2103 I think you're hitting that one

Will fix ASAP

Ah, that sounds like it! Thank you.

Whoa! bb includes tools.build? That's amazing.

tools.deps is basically the layer I build on to fetch the deps in bb and tools.build on top was easy and I could finally replace depstar with it, so it's a good reason to have it built-in. it's bundled as source files so it's mostly interpreted

but still fast enough

This will allow us to do a lot of cleanup at work too. Our build.clj file is very "heavy" but this will allow us (me) to move more pieces to bb.edn.

😍 1

A really nice bonus of being able to run build.clj via bb is that bb.edn can be cleaned up and utility functions moved to build.clj, so it becomes a lot more self-contained: no need for scripts/util.clj etc!

💡 1

The task deps exec-fn bug is now solved in the now available dev build

This is why there's a dev build. It's good to find these bugs before release, thanks for testing!

Confirmed fixed! Thank you!

🎉 1

Heya @borkdude, I tried out your new https://github.com/babashka/babashka.esbuild for cljdoc. Pretty neat!

🤩 1

https://github.com/cljdoc/cljdoc/pull/1206 has some notes:

Some notes:
1. It is certainly much quicker than spawning out to esbuild via npx.

2. I had to modify some cljs regexes to escape some chars. I expect this is due to compiling from bb squint rather than node squint.

3. Cljdoc uses preact. There is support in squint for preact via `:jsx-runtime {:import-source "preact"}`, but this did not work for me.

4. I switched to handling preact at bundle-time via `:jsx :automatic` and some react->preact `:alias` config. I think this is effectively what I was doing before switching to the wrapper, but because I was using squint at higher level, I didn't understand these details.

5. Cljdoc uses cache busting hashes in its filenames for most of its assets. Esbuild supports this, but the esbuild wrapper does not (yet) expose this functionality. I implemented my own hashing which was simple, but this meant a bit of fixup after files were generated by esbuild.

6. I find esbuild's analyze feature a nice way to see what contributes to my bundle size. This is not yet exposed by the esbuild wrapper.

7. My cljs tests previously required `cljs.test`, but this no longer worked for me. Switching to requiring `clojure.test` fixed the issue.

Thanks for the feedback

If you want, can you make separate issues out of these, either for squint or the esbuild wrapper? So I won't forget