babashka 2025-09-19

In my Dockerfile, I use Babashka like this:

RUN bb --config /my-project/bb.edn -x dev.livereload/inject
But I can’t find a way to set --config /my-project/bb.edn globally. I expected something like this to work:
ENV BABASHKA_CONFIG=/my-project/bb.edn
RUN bb -x dev.livereload/inject

Maybe set the working dir to the bb.edn project?

I haven’t figured out exactly how I want to do it yet, but the idea is that bb -x ... will be called in different contexts, including in the entrypoint. Setting the working directory, while it seems obvious, apparently isn’t suitable.

Another option. Make a babashka start script.clj and call babashka cli yourself. Then just call this script instead. It will default to the right config. You can also add this script to the PATH

Babashka also helpfully locates bb.edn files in parent directories to the current directory — so if all your stuff is in /app/..., you could do /app/bb.edn as the "global" bb.edn.

huh, that doesn't sound right to me

it doesn't do that

😅 I thought that was added a few years ago, but you're probably right, you made the thing!

never added that and I would be still against that

such a thing works with clj-kondo though and leiningen, perhaps you're confused with those

anyway so you script would be something like:

$project_root/myscript
#/!/usr/bin/env bb

(require '[babashka.cli :as cli] '[your.ns])

(def args (cli/parse-opts *command-line-args* ...))

(apply your.ns/your-fn args)

☝️ 1

and then can call /my/project/myscript from everywhere while it respects bb.edn

I was wrong. I thought tasks could be run from subdirectories, they cannot.

$ pwd
/Users/teodorlu/tmp/temp-2025-09-19/bbstuff
$ cat bb.edn
{:tasks
 {hello (println "Hello, Babashka!")}}
$ bb hello
Hello, Babashka!
$ mkdir -p some/sub/dir
$ cd some/sub/dir
$ pwd
/Users/teodorlu/tmp/temp-2025-09-19/bbstuff/some/sub/dir
$ bb hello
----- Error --------------------------------------------------------------------
Type:     java.lang.Exception
Message:  File does not exist: hello

Should this work on the jvm?

(ns user
  (:require [babashka.pods :as pods]))

(pods/load-pod 'org.babashka/fswatcher "0.0.7")
(require '[pod.babashka.fswatcher :as fw])
(def w (fw/watch "docs/"
                (fn [event]
                    (tap> [:WATCH event]))
                {:recursive true}))
The fw/watch call is hanging forever, and if I do cider-interrupt the stack trace is:
1. Caused by java.lang.InterruptedException
   (No message)
AbstractQueuedSynchronizer.java: 1139  java.util.concurrent.locks.AbstractQueuedSynchronizer/acquireSharedInterruptibly
       CountDownLatch.java:  230  java.util.concurrent.CountDownLatch/await
                  core.clj: 7257  clojure.core/promise/reify
                  core.clj: 2337  clojure.core/deref
                  core.clj: 2323  clojure.core/deref
                  impl.clj:  111  babashka.pods.impl/invoke
                  impl.clj:   93  babashka.pods.impl/invoke
                  impl.clj:  135  babashka.pods.impl/bencode->vars/fn/fn

✅ 1

let me check

do you have the deps.edn handy?

{:paths ["src"]
 :deps  {dev.weavejester/medley    {:mvn/version "1.9.0"}
         babashka/fs               {:mvn/version "0.5.27"}
         babashka/process          {:mvn/version "0.6.23"}
         hifi/error                {:local/root "../hifi-error"}
         org.clojure/tools.logging {:mvn/version "1.3.0"}
         com.nextjournal/beholder  {:mvn/version "1.0.3"}
         babashka/babashka.pods    {:mvn/version "0.2.0"}
         hifi/util                 {:local/root "../hifi-util"}
         hifi/html                 {:local/root "../hifi-html"}}}

I'm on nixos fwiw, but since the pod is statically built I don't see any classic nix library problems

just a moment

the script isn't hanging, it's the classic behavior in clojure that when you use futures, it waits for them to complete. the watcher is still running and then the script won't exit

e.g. when I run this:

(def w (fw/watch "docs/"
                 (fn [event]
                   (tap> [:WATCH event]))
                 {:recursive true}))
(prn :dude w)
I see it being printed

Adding this to the script will make it behave like clojure -X does:

(defn- set-daemon-agent-executor
  "Set Clojure's send-off agent executor (also affects futures). This is almost
  an exact rewrite of the Clojure's executor, but the Threads are created as
  daemons."
  []
  (let [thread-counter (atom 0)
        thread-factory (reify java.util.concurrent.ThreadFactory
                         (newThread [_ runnable]
                           (doto (Thread. runnable)
                             (.setDaemon true) ;; DIFFERENT
                             (.setName (format "CLI-agent-send-off-pool-%d"
                                               (first (swap-vals! thread-counter inc)))))))
        executor (java.util.concurrent.Executors/newCachedThreadPool thread-factory)]
    (set-agent-send-off-executor! executor)))

(set-daemon-agent-executor)

hmmm, for me, in my clj repl, i eval the def w form and it never returns

haven't tried the REPL, do you mean CIDER or just the bare clj REPL?

sorry, I can see how my initial message made it seem like I was running it as a script file. CIDER

$ clj
Clojure 1.12.1
(ns user
  (:require [babashka.pods :as pods]))
nil
(pods/load-pod 'org.babashka/fswatcher "0.0.7")
(require '[pod.babashka.fswatcher :as fw])
(def w (fw/watch "docs/"
                 (fn [event]
                   (tap> [:WATCH event]))
#:pod{:id "pod.babashka.fswatcher"}
user=> nil
user=>                  {:recursive true}))
#'user/w

can't reproduce with bare clj REPL. Will try CIDER now

works as expected:

Perhaps you're using the CIDER debugger or so?

clj working here too ...

let me restart the repl 😕

when the repl started i didn't have babashka.pods in the cp, i added it to the deps.edn later and evaled (clojure.repl.deps/sync-deps) in the repl to load it

and it's working 🤷

perhaps some sync-deps stuff, don't know

sorry for the noise 😞

nice to see that the pods are statically built now, i hadn't used pods in a long while because of the nixos situation

well, the fswatcher one is just a golang binary and those are static by nature

I try to make them static when possible