Skip to content
AgileLogics
6 min read

Scripting with Babashka

Prerequisites: Files and I/O

Babashka (bb) is a native Clojure interpreter for scripting. It's a single binary compiled with GraalVM that starts in milliseconds, so Clojure becomes a practical replacement for Bash and Python scripts. Many popular libraries are built in: clojure.java.shell, babashka.fs, babashka.process, babashka.http-client, cheshire (JSON), YAML, clojure.tools.cli, and core.async.

Installing and running

brew install borkdude/brew/babashka      # macOS/Linux
scoop install babashka                   # Windows (after adding its bucket)
bb -e '(+ 1 2)'
bb script.clj arg1 arg2

A script

;; illustrative — cleanup.clj, run with: bb cleanup.clj ./logs 7
#!/usr/bin/env bb
(require '[babashka.fs :as fs]
         '[clojure.string :as str])

(let [[dir days] *command-line-args*
      cutoff (- (System/currentTimeMillis) (* (parse-long (or days "7")) 24 60 60 1000))
      old (->> (fs/glob (or dir ".") "**.log")
               (filter #(< (.toMillis (fs/last-modified-time %)) cutoff)))]
  (doseq [f old]
    (println "deleting" (str f))
    (fs/delete f))
  (println (count old) "file(s) removed"))

Running processes and calling APIs

;; illustrative — needs git and network access
(require '[babashka.process :refer [shell process]]
         '[babashka.http-client :as http]
         '[cheshire.core :as json])

(shell "git" "status" "--short")                      ; inherit output
(def branch (-> (process {:out :string} "git rev-parse --abbrev-ref HEAD") deref :out str/trim))

(def repo (-> (http/get "https://api.github.com/repos/babashka/babashka")
              :body
              (json/parse-string true)))
(println branch (:stargazers_count repo))

Tasks: a Makefile in Clojure

;; illustrative — bb.edn
{:tasks
 {test  {:doc "Run tests" :task (shell "clj -X:test")}
  lint  {:doc "Lint sources" :task (shell "clj-kondo --lint src test")}
  ci    {:doc "Lint, then test" :depends [lint test]}
  clean {:task (babashka.fs/delete-tree "target")}}}
bb tasks      # list tasks with their docs
bb ci         # run lint, then test

bb.edn tasks are a popular replacement for Makefiles and npm scripts in Clojure projects — and in non-Clojure projects too.

Limits

Babashka runs an interpreter, so CPU-heavy code is slower than JVM Clojure, and it can only use the Java classes compiled into it (plus Babashka-compatible libraries, called pods for native extensions). For scripts, CI glue, and small tools, it's ideal.