babashka

Oliver Marks 2025-07-21T09:11:34.640039Z

Any recommendations on how to run this, eval $(minikube docker-env) using shell eval is not available, the command basically gives you 4 export commands to run, so I could grab the content of "minikube docker-env" and run it another way but the main goal is to get the exports run before running a docker command, so it all needs to be inside the same context

borkdude 2025-07-21T09:14:01.090409Z

If you want to evaluate some bash/zsh/whatever you need to do it in the context of a bash/zsh/whatever shell. e.g.:

(shell "bash" "-c" "eval $(minikube docker-env); whatever-else")

Oliver Marks 2025-07-21T09:19:33.905039Z

okay thanks I did consider that, but was equally curious if there was a way to run a series of command inside a context which you have setup

borkdude 2025-07-21T09:20:30.634049Z

I have no idea what you have in mind

borkdude 2025-07-21T09:21:08.117309Z

you could possibly open a bash shell and iteratively feed it with more input I guess

Oliver Marks 2025-07-21T09:22:00.775129Z

yeah, it was more a question if you could create a perhaps bash shell keep the state and send additional commands after each had completed

Oliver Marks 2025-07-21T09:22:23.366329Z

I will go with the bash -c option, as its a quick script

borkdude 2025-07-21T09:24:33.510529Z

(require '[babashka.process :as p])
(def bash-process (p/process {:out :inherit} "bash"))
(def input (io/writer (:in bash-process)))

(binding [*out* input]
  (println "export FOO=BAR"))

(Thread/sleep 1000)

(binding [*out* input]
  (println "echo $FOO"))

teodorlu 2025-07-21T09:32:45.988319Z

Another alternative is to let Babashka communicate shell commands that should be evaluated back to the bash process. I did that for a Babashka script that can change the current directory. Details here: https://github.com/teodorlu/shed/tree/429e7d8c9d1ea19588f27e116a3bedf60aa314d9/contrib/clonecd

teodorlu 2025-07-21T09:35:22.322579Z

with_shelleval is a bash function that runs something. If that something puts !SHELLEVAL echo haha on stdout, you'll see haha printed. You can also change directories, set environment variables, etc.

borkdude 2025-07-21T09:39:32.380139Z

I've done a similar thing here once: https://stackoverflow.com/a/64804398/6264

👀 1
Oliver Marks 2025-07-21T09:43:10.559499Z

okay thanks both for the options, give me some things to try 🙂

sheluchin 2025-07-21T18:17:53.008559Z

I need to run a simple babashka script as an AWS Lambda. Is holy-lambda the recommended approach these days?

borkdude 2025-07-21T18:19:59.833099Z

there's also #blambda - https://github.com/jmglov/blambda

borkdude 2025-07-21T18:22:14.061299Z

it's also relatively easy to use nbb (or squint, or whatever JS thing) for lambda: https://github.com/babashka/nbb/blob/main/doc/aws_lambda.md

sheluchin 2025-07-21T18:27:38.934279Z

Thanks for the pointers. Will check out those options. Blambda looks like a turnkey solution.

seancorfield 2025-07-21T18:42:48.520279Z

Following up from a thread elsewhere: @borkdude Re: bb -- do you use build.clj as well? Or would you just use bb tasks?

borkdude 2025-07-21T18:43:04.945069Z

@seancorfield re: https://clojurians.slack.com/archives/C03RZGPG3/p1753123313702819?thread_ts=1753122112.128639&cid=C03RZGPG3 yes, I definitely use build.clj but just for what it says it does: building stuff. I often have a bb task called deploy that deploys stuff by invoking clj -T:build deploy for example

seancorfield 2025-07-21T18:45:17.538529Z

I'm kinda curious where you draw that line? At work, our build.clj is about 400 lines as I recall and does a lot of stuff, including running various tasks as subprocesses, and our "usual" way to work with it is to start a REPL with -M -i build.clj -r essentially, so we don't pay the startup cost for every task.

borkdude 2025-07-21T18:46:12.336039Z

I don't invoke clj -T:build for REPL stuff, I just start a REPL by what I usually call bb dev

borkdude 2025-07-21T18:46:58.462289Z

for example, here is the bb dev task for clerk: https://github.com/nextjournal/clerk/blob/149c4e5aeaaefb18ddaeae381595a3b5f7918481/bb.edn#L174

seancorfield 2025-07-21T18:48:20.821779Z

Okay, so I guess your bb dev is our dev.sh build at work, which in turn is:

cd $folder && clj $force -M:allow-attach-self:build -i bases/build/src/ws/build.clj -e "(in-ns 'ws.build)" -r
🙂

borkdude 2025-07-21T18:50:50.549219Z

yes, bb dev could also just be (shell "script/dev.sh") ;)

borkdude 2025-07-21T18:51:39.483369Z

invoking scripts in a certain directory is also a fine solution which comes close to a task runner. but sometimes it can be confusing which scripts are intended for that or not, for newcomers. bb tasks just gives you an overview of the most important things you'd invoke you in your project.

seancorfield 2025-07-21T18:52:58.203559Z

Are the tasks that start with - some sort of "private" that isn't listed when you ask bb what tasks are available?

borkdude 2025-07-21T18:53:33.196049Z

yes. invoking bb tasks from the command line will give you a clean overview of all the important tasks, without the "helper" tasks which start with a -

👍🏻 1
seancorfield 2025-07-21T19:08:38.362669Z

In that clerk task file, several nses are required with an alias but not used, e.g., babashka.process :as p -- but shell (and clojure) are used without an alias. Is that require needed?

seancorfield 2025-07-21T19:09:57.111639Z

(as I'm reading this, I'm try to think about whether I could coalesce my testing scripts for next.jdbc since I have a bb script to run multi-version testing from the command line and similar code in my build.clj file for running tests as part of CI build & deploy).

seancorfield 2025-07-21T19:10:27.877559Z

I sort of expected babashka.process to have a clojure function...

borkdude 2025-07-21T19:11:44.056509Z

shell and clojure are the only automatically refer-ed things since you need them often. they come from a special namespace called babashka.tasks the rest of the stuff works like normal bb scripting. Most of this stuff should be documented here: https://book.babashka.org/#tasks I don't mean this as a RTFM, feel free to ask anything you want

seancorfield 2025-07-21T19:12:06.873579Z

Specifically, I'd like to be able to reuse the multi-version testing code between https://github.com/seancorfield/next-jdbc/blob/develop/run-tests.clj and https://github.com/seancorfield/next-jdbc/blob/develop/build.clj#L24-L38

seancorfield 2025-07-21T19:13:13.575769Z

(the latter uses tools.build for java process invocation but could happily shell out to clojure instead really)

borkdude 2025-07-21T19:14:04.877079Z

clojure uses the deps.clj clojure runner. if you prefer to run your system-installed clojure, all you need is shell basically

lread 2025-07-21T19:14:29.010939Z

I like the succinctness of bb tasks as a dev front end and have them abstract any clojure -T:build... invocations.

seancorfield 2025-07-21T19:18:14.773099Z

@lee Hmm, so instead of me thinking about trying to reuse code between bb and build.clj, turn it on its head and use bb as the "interface" and have it shell out to clojure -T:build as needed...? Might be an interesting exercise for me to try on next.jdbc...

borkdude 2025-07-21T19:19:25.487979Z

I sometimes (not always) share code between bb and build.clj if it's convenient to have some of the code run in both.

borkdude 2025-07-21T19:20:27.968309Z

but to get started, you could just use bb tasks as a simple "front-end" like lread suggested

borkdude 2025-07-21T19:22:57.068219Z

if you're going to be using bb tasks, make sure to install the completions, I find those very handy: https://book.babashka.org/#_terminal_tab_completion (more advanced completion scripts are on the wiki, I use the one in the book)

seancorfield 2025-07-21T19:26:24.943669Z

If you have a folder that matches a task name, that seems to offer the folder (with a trailing /) -- is that expected?

seancorfield 2025-07-21T19:26:31.462059Z

(for bash)

seancorfield 2025-07-21T19:26:53.732629Z

(!2006)-> bb tasks
The following tasks are available:

test Run the test suite.
ci   Run the CI pipeline of tests and build the JAR.

(2025-07-21.15:26:40)-(~/oss/next-jdbc)
(!2007)-> bb t
target/ test/   

borkdude 2025-07-21T19:27:32.871729Z

probably not. it does auto-complete files because you can invoke files with bb too, but directories should probably be filtered out

seancorfield 2025-07-21T19:28:15.359599Z

If I change my test task to tests then I get this:

(!2010)-> bb t
target/ test/   tests   

borkdude 2025-07-21T19:28:34.776799Z

weird. did you restart your shell, maybe that helps?

borkdude 2025-07-21T19:29:15.367299Z

ah yes, tests is what you should see, sorry I didn't catch that

borkdude 2025-07-21T19:30:20.092919Z

sometimes you have multiple test tasks. it's a convention in bb tasks to write those as test:cljs and test:clj for example. auto-completion is handy for those cases where you have typed bb test:

seancorfield 2025-07-21T19:30:41.029139Z

But if my task is test and I have a folder called test, I won't see the test task right now?

borkdude 2025-07-21T19:32:29.269149Z

http://claude.ai suggests these improvements: https://claude.ai/share/4bcb813e-6e56-436a-a075-4e889e1b40b5 if you can test either, happy to update the book 😆

seancorfield 2025-07-21T19:33:11.304759Z

zsh 😞

borkdude 2025-07-21T19:33:20.883029Z

you are using bash I guess?

seancorfield 2025-07-21T19:33:27.998019Z

Yup.

borkdude 2025-07-21T19:33:54.903569Z

_bb_tasks() {
    COMPREPLY=( $(compgen -W "$(bb tasks |tail -n +3 |cut -f1 -d ' ')" -- ${COMP_WORDS[COMP_CWORD]}) );
}
# autocomplete filenames but not directories
complete -f -o filenames -F _bb_tasks bb

seancorfield 2025-07-21T19:34:18.562009Z

Thanks!

borkdude 2025-07-21T19:34:22.477809Z

does it work?

seancorfield 2025-07-21T19:35:18.028349Z

Nope.

seancorfield 2025-07-21T19:35:22.762919Z

Still get the folder.

borkdude 2025-07-21T19:36:37.153759Z

ok, I'll take a look at this when I have more time. thanks for reporting. I'll come back to this

👍🏻 1
seancorfield 2025-07-21T19:49:25.977879Z

For now I ended up with this, which at least doesn't put the / on folders (and doesn't add a space after a match):

_bb_tasks_and_filenames() {
    COMPREPLY=(
      $(
        compgen -W "$(bb tasks |tail -n +3 |cut -f1 -d ' ')" -- ${COMP_WORDS[COMP_CWORD]};
        compgen -f -- ${COMP_WORDS[COMP_CWORD]}
      )
    );
}
# autocomplete filenames as well
complete -o nospace -F _bb_tasks_and_filenames bb

borkdude 2025-07-21T20:08:53.430789Z

There's more stuff here: https://github.com/babashka/babashka/wiki/Shell-completion

borkdude 2025-07-21T20:09:33.774729Z

Maybe one reason for completing also directories was that there may be scripts in directories

borkdude 2025-07-21T20:09:45.591469Z

but good that you found your tweak

seancorfield 2025-07-21T20:36:57.321109Z

It won't auto-complete task names with : in for some reason but I'll circle back to that later.

seancorfield 2025-07-21T21:17:46.947249Z

next.jdbc PR to switch to using bb tasks -- build.clj only handles building & deploying the JAR now; bb.edn has the multi-version / JDK test logic (you have to tell it what JDK you are using, for now): https://github.com/seancorfield/next-jdbc/pull/305

👌 1
borkdude 2025-07-21T21:21:09.188699Z

Nice! If you don't like the big chunk of clojure code in your bb.edn you can still put it in a file and have the task be (load-file "whatever.clj") Or put it on the bb classpath with for example:

{:paths ["bb"]}
and execute it as a normal function in a task. All up to you of course

seancorfield 2025-07-21T21:22:08.062239Z

Well, I already had nearly all of that "big chunk of clojure code" in run-tests.clj 🙂

seancorfield 2025-07-21T21:23:09.361849Z

But run-tests.clj is gone now (moved to bb.edn essentially). The duplication of the env vars is gone (from the GH Actions files). The duplication of the multi-version testing is gone (from build.clj). So that's all a win.

🙌 1
seancorfield 2025-07-22T03:31:10.804449Z

Several back and forths with Claude 4 Sonnet on the : completion got me this:

# Remove any existing bb completion first
complete -r bb 2>/dev/null || true

_bb_complete() {
    local cur tasks

    # Extract what we're trying to complete (everything after 'bb ')
    cur="${COMP_LINE#*bb }"
    [[ "$cur" == "$COMP_LINE" ]] && cur=""  # Handle case with no space after bb

    # Get available tasks
    tasks=$(bb tasks 2>/dev/null | tail -n +3 | cut -f1 -d ' ')

    if [[ "$cur" == *:* ]]; then
        # For colon completions, return only the suffix after the colon
        local prefix="${cur%:*}:"
        COMPREPLY=($(compgen -W "$tasks" -- "$cur" | sed "s/^$prefix//"))
    else
        # Normal completion
        COMPREPLY=($(compgen -W "$tasks" -f -- "$cur"))
    fi
}

complete -o nospace -F _bb_complete bb

seancorfield 2025-07-22T03:34:25.683159Z

(the first "solution" was horrendously complex so this is Claude's "simpler" version -- and it seems to work perfectly)

👍 1
2025-07-21T18:53:14.663999Z

@borkdude you said in the just thread that bb can do tasks in parallel. that's cool. how does that work? what's the use-case? i don't do a lot of stuff that would benefit from parallel execution so i'm unfamiliar

borkdude 2025-07-21T18:54:17.938779Z

the use case is for example spinning up a shadow-cljs build along with a JVM Clojure REPL. bb dev can do both of those, so you can start "development"

2025-07-21T18:54:31.919589Z

that's clever!

2025-07-21T18:54:56.208539Z

how does it handle closing down both? i usually have two terminal windows split

borkdude 2025-07-21T18:55:08.342909Z

just press ctrl-c to close both

👀 1
lispyclouds 2025-07-21T19:01:46.892049Z

parallel tasks are very neat for monorepos for builds/compiling too: https://github.com/bob-cd/bob/blob/main/bb.edn#L47 has significant speedups

❤️ 1