clojure 2026-06-26

I’m getting a strange behavior when I try to start a clj script.

clj -Sdeps '{:deps {org.clojure/data.csv  {:mvn/version "1.0.1"} org.clojure/data.json {:mvn/version "2.5.0"} org.apache.poi/poi-ooxml {:mvn/version "5.2.5"}}}' -M compute_grades.clj
Please install rlwrap for command editing or use "clojure" instead.
I don’t want command editing inside this stand-alone script. any ideas?

❯ clj
Please install rlwrap for command editing or use "clojure" instead.
I just got this today. I’m not sure how this happened to me. Quite strange

i’ve got tons of clj usage in my zsh_history. It’s gone. I’m not sure what’s up. And brew doesn’t keep uninstall logs apparently

Homebrew is currently ignoring formulae, casks and commands from these taps because tap trust is required.
Prefer trusting only the specific formulae, casks or commands you need.
Trust installed formulae from these taps with:
  brew trust --formula babashka/brew/neil
  brew trust --formula borkdude/brew/babashka borkdude/brew/clj-kondo borkdude/brew/jet
  brew trust --formula clojure/tools/clojure
ahh. This might be a new security posture

OK, i just did a brew install rlwrap and clj is happy.

use clj (which uses rlwrap)or clojure which doesn’t

➕ 1

❯ cat $(which clj)
#!/usr/bin/env bash

bin_dir=/opt/homebrew/Cellar/clojure/1.12.1.1561/bin

if type -p rlwrap >/dev/null 2>&1; then
  exec rlwrap -m -r -q '\"' -b "(){}[],^%#@\";:'" "$bin_dir/clojure" "$@"
else
  echo "Please install rlwrap for command editing or use \"clojure\" instead."
  exit 1
fi

if you squint, clj is just exec rlwrap clojure $@

but with the runes of the ancients mixed in

maybe i did some sort of brew update all recently?

i wonder if you had it prune unused stuff, it saw rlwrap was transitively brought in, no longer had an official consumer so removed it for you?

Alex Miller (Clojure team) 2026-06-26T16:53:39.051229Z

The intent of that message you first got "Please install rlwrap for command editing or use "clojure" instead." was to suggest using clojure instead of clj in this case - I'm wondering how that read for you and if some alternate wording would have made it clearer?

Maybe a tiny change would help?: ... or use "clojure" instead of "clj".

i don’t understand what “command editing” means there to be honest

maybe: interactive command editing?

that makes more sense. the niceties you would expect with interacting with it as a prompt

Alex Miller (Clojure team) 2026-06-26T18:11:06.648709Z

I'll wait to hear from Jim, but that makes sense

Maybe: rlwrap not found: "clj" uses rlwrap to support interactive command editing in the REPL. Consider using "clojure" for launching scripts and apps.

A bit wordy, but kinda explains why you would use one over the other.

why do prn calls sometimes go to my terminal window and sometimes go to the output of my connected repl? is there a way to force all prn calls to go to my repl, no matter which thread or whatever?

I've hit this several times. I rolled my own nrepl middleware to deal with it. It's a hack but it's effective.

do a quick experiment: eval (prn "from top level") and (future (prn "from a thread"))

oh i should note that this is happening in tests and we use a lot of core.async stuff

both of those go to my repl

ah ok. was wondering if it was nrepl issues

👍 1

Future very specially captured the value of *out* and carries it to the new thread

👍 1
☝️ 1

Nrepl relies on a specific binding of *out* to send stuff back

oh right. obvious in hindsight

So for example if you are creating http handler function that gets called on some random thread the http server owns it will have the default binding for *out*

core.async's go macro also captures and copies around the dynamic var environment, but I am not sure if futurama is as careful about it

good catch, i don't know

is there a way for me to do that myself?

like, capture *out* in a test so it's conveyed?

bound-fn or bound-fn*

The test out is a pain in socket repls too.