Babashka tasks meets babashka CLI

In a previous blog post (link) I introduced babashka CLI. It offers you similar benefits as clojure -X but with a more Unixy command line interface.

In version 0.9.160 of babashka, babashka CLI was integrated. It is available as a built-in library so you don't need to declare it anymore in :deps in bb.edn unless you want to use a newer version than the built-in one.


For invoking functions from the command line, you can use the new -x flag (a pun to Clojure's -X of course!):

bb -x clojure.core/identity --hello there
{:hello "there"}

What we see in the above snippet is that a map {:hello "there"} is constructed by babashka CLI and then fed to the identity function. After that the result is printed to the console.

What if we want to influence how things are parsed by babashka CLI and provide some defaults? This can be done using metadata. Let's create a bb.edn and make a file available on the classpath:


{:paths ["."]}


(ns tasks
  {:org.babashka/cli {:exec-args {:ns-data 1}}})

(defn my-function
  {:org.babashka/cli {:exec-args {:fn-data 1}
                      :coerce {:num [:int]}
                      :alias {:n :num}}}

Now let's invoke:

$ bb -x tasks/my-function -n 1 2
{:ns-data 1, :fn-data 1, :num [1 2]}

As you can see, the namespace options are merged with the function options. Defaults can be provided with :exec-args, like you're used to from the clojure CLI.


What about task integration? Let's adapt our bb.edn:

{:paths ["."]
 :tasks {doit {:task (let [x (exec 'tasks/my-function)]
                       (prn :x x))
               :exec-args {:task-data 1234}}

and invoke the task:

$ bb doit --cli-option :yeah -n 1 2 3
:x {:ns-data 1, :fn-data 1, :task-data 1234, :cli-option :yeah, :num [1 2 3]}

As you can see it works similar to -x, but you can provide another set of defaults on the task level with :exec-args. Executing a function through babashka CLI is done using the babashka.task/exec function, available by default in tasks.

Hope you will enjoy this!