babashka 2025-08-08

how can I spawn this command in bb.process and the the output?

git diff --staged && echo '---UNSTAGED BELOW---' && git diff

✅ 1

this is spawned by LLM so I don't have much control on how LLM will call, but would like to use bb.process in a generic shell call way that things like that would work

via bb.process/shell I get fatal: ambiguous argument '&&'

I think you could probably do that as an arg to bash -c. It's possible to run into quoting headaches with commands more generally, but outside of that I think it'd be ok.

Hum good suggestion, will try!

actually, it might also be possible to avoid most/all of the quoting headaches if you can get the command in question into a variable and use the vararg arity of shell, e.g.:

user=> (let [cmd "echo \"wacky ''quoted'' stuff\""]
  (t/shell "bash" "-c" cmd))

I tried that but it fails for the provided one I mentioned

not tried with bash -c yet

Yeah, I think the general thing is that shell isn't specifically invoking a shell; it's using java's processbuilder, so I feel like it's closer to a call to a system call. As such, bash syntax doesn't work unless bash is invoked.

Makes sense

So one bash trick I learned long ago: A single quoted string only requires single quotes to be escaped, all other special chars inside a single quoted string are not special.

So take your string, escape all single quotes, then put it into single quotes, and bash -c should take it with no problems.

This will just work:

(p/shell "bash -c" "git diff --staged && echo '---UNSTAGED BELOW---' && git diff")

👍 1

No need to escape the single quotes

That is inside a double quote, which allows single quotes without escaping.

if you get the command as a string in babashka at runtime, I don't see how you would need escaping. unless you are generating the p/shell call somehow

Actually that could go either way it would depend on what p/shell does to those clojure strings. If you talk just bash strings:

bash -c 'echo $PATH' => $PATH
bash -c "echo $PATH" => /bin:/usr/bin...

it does nothing to the string

Let me put it like this, if your problem looks like this:

(let [s ;; some LLM generated shell command]
  (shell/p "bash -c" s))
no escaping necessary.

Does it also work on Windows? no or it depends, so be aware that this is very highly OS or environment specific

https://clojurians.slack.com/archives/CLX41ASCS/p1754673963618919?thread_ts=1754670046.580449&cid=CLX41ASCS, thank you! Would be nice to support windows as well, so we would need to decouple from bash, but that's ok for now

@ericdallo does LLM generate bash commands?

you could ask it to generate babashka.process commands instead? only the && is bash specific

no, it just "know" it has the shell command tool available. Hum, good point, but not sure how good most LLMs would be with knowing how to spawn bash commands vs bb.process ones, which is way exclusive to clojure in LLM knowledge terms

it just "know" it has shell command tool available... ehhh, what about Windows then?

Even small models can create bash commands it's why I created ouroboros the bash only agent.

exactly @borkdude most tools are not supporting windows well

Is babashka.process/shell specifically broken on Windows? Otherwise, the official git installer for Windows does come with Bash bundled, and I don't see any reason why this command wouldn't run using that Bash. You may need some extra step to put it on %PATH%, but I believe the git installer does it, or at least has an option to do it for you.

It is not broken on Windows, but bash is not standard on Windows

Indeed, but if you have git, you probably have Bash with it too. (Though mostly "just Bash", not necessarily all the other tools a unix-enthusiast would assume like grep and awk and...)

@gaverhae are you running Windows?

Not right now, no. I'm a bit scared of the direction this is taking 😅

Hey I just noticed when I tried swapping out clojure.data.json for babashka.json

(json/read reader :key-fn keyword) ; works in data.json not babashka.json
Due to this: https://github.com/babashka/json/blob/99055022121d38b851d2602b035adb2b60317988/src/babashka/json.clj#L38-L45 Would you be open to changing it to https://github.com/clojure/data.json/blob/f3cc3bda6b6d9bdcde0034e60ba4ebcc3aefeed0/src/main/clojure/clojure/data/json.clj#L539 so that the trailing keyword args is supported when clojure 1.11+ (which added that feature) is used by the lib consumer? I believe the only change would be
(defn read ... ([reader opts])) => [reader & {:as opts}]
Though I could be missing something I can do a PR or issue if you'd like (have one locally that passes tests) Edit: I realized this applies to read-str as well.

✅ 1

babashka.json has the same function signature for all implementation, but it doesn't have the same signature AS the implementations as this would be impossible if there are differences in the implementations

as such babashka.json isn't a drop-in replacement for an implementation, it's just an implementation-agnostic way of doing JSON

that's fair, thanks

I'm using linuxbrew on aarch64 and the babashka formula seems to be installing the amd64 binary (it's not executable). I manually installed the aarch64 binary and it works fine. Could we add an arch check for linux here? https://github.com/borkdude/homebrew-brew/blob/d662c9f8029f7ac434b19e861aaaa00f81e2eca8/babashka.template#L8-L9

✅ 1

Ah yes, of course!

I'll take a shot at it

thanks, confirmed it works!

🎉 1