babashka

kuzmin_m 2025-09-19T11:28:31.917339Z

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

borkdude 2025-09-19T11:37:48.882759Z

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

kuzmin_m 2025-09-19T11:40:30.005299Z

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.

borkdude 2025-09-19T11:44:54.094909Z

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

teodorlu 2025-09-19T11:54:15.596889Z

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.

borkdude 2025-09-19T11:54:55.413809Z

huh, that doesn't sound right to me

borkdude 2025-09-19T11:55:07.903549Z

it doesn't do that

teodorlu 2025-09-19T11:58:14.532809Z

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

borkdude 2025-09-19T11:59:09.993169Z

never added that and I would be still against that

borkdude 2025-09-19T11:59:30.652649Z

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

borkdude 2025-09-19T12:06:25.197019Z

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
borkdude 2025-09-19T12:06:47.164089Z

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

teodorlu 2025-09-19T12:35:49.626549Z

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

Casey 2025-09-19T13:01:29.340409Z

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
borkdude 2025-09-19T13:24:39.778329Z

let me check

borkdude 2025-09-19T13:24:49.790389Z

do you have the deps.edn handy?

Casey 2025-09-19T13:26:02.091749Z

{: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"}}}

Casey 2025-09-19T13:26:45.564839Z

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

borkdude 2025-09-19T13:27:07.481589Z

just a moment

borkdude 2025-09-19T13:29:01.678419Z

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

borkdude 2025-09-19T13:29:15.497719Z

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

borkdude 2025-09-19T13:31:19.113899Z

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)

Casey 2025-09-19T13:31:32.402609Z

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

borkdude 2025-09-19T13:31:54.335479Z

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

Casey 2025-09-19T13:32:14.577609Z

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

borkdude 2025-09-19T13:32:21.255249Z

$ 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

borkdude 2025-09-19T13:32:34.165529Z

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

borkdude 2025-09-19T13:33:31.250239Z

works as expected:

borkdude 2025-09-19T13:33:38.594049Z

Perhaps you're using the CIDER debugger or so?

Casey 2025-09-19T13:34:28.851569Z

clj working here too ...

Casey 2025-09-19T13:34:35.818419Z

let me restart the repl 😕

Casey 2025-09-19T13:35:17.731259Z

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

Casey 2025-09-19T13:45:34.236429Z

and it's working 🤷

borkdude 2025-09-19T13:45:50.945419Z

ok great

borkdude 2025-09-19T13:45:58.534489Z

perhaps some sync-deps stuff, don't know

Casey 2025-09-19T13:45:59.106789Z

sorry for the noise 😞

borkdude 2025-09-19T13:46:02.933209Z

no problem

Casey 2025-09-19T13:46:27.227239Z

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

borkdude 2025-09-19T13:46:49.372629Z

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

borkdude 2025-09-19T13:47:01.707999Z

I try to make them static when possible