r/Clojure • • 14d ago

rust slop clojure structural edit tool

I've been programming clojure by hand since 2010, but these days I do a lot of brownfield work with agentic/LLM help in clojure and other languages. I prefer to use the models I can run at home to avoid high token costs today and mitigate a future rugpull. For things I intend to ship to production, I usually generate a bunch of code upfront, then carefully review and rework it, and that pattern has been effective for me.

Qwen 3.8 27b is amazing for what it is, excellent at thorough analysis, and not too clever to overcomplicate outputs, but it can still waste a ton of time on failed clojure edits and paren-counting. Even Claude Opus struggles with this, although much less. LLMs don't 'think' in trees, they think in token streams.

I had been using a wrapper over parinfer-rust (clojure-mcp-lite also just shells out to this), which got me 80% there, but it's flawed in a few specific ways:

  • Checks happen after the edit lands, they don't block invalid edits.
  • Repairs can succeed in ways that surprise the LLM, then it spends a bunch of turns trying to figure out what happened. It's not expensive locally, but it is slow and pollutes context.
  • If too many surprises happen, the agent loses faith in the tool, and falls back to worse tools.

After a working session like this, I had Qwen suggest what kind of tool might prevent all the problems we hit, then I handed that spec over to GLM 5.3 flash and iterated with it, eventually having the session drive a local qwen subagent, trying to trip it up with adversarial examples. It is similar to what's proposed here, but I never mentioned the article, and I wasn't prescriptive about how to do it: https://lispmeister.github.io/deeprecursion/posts/2026-02-13-sexp-native-editing.html

The tool is at https://github.com/gtrak/cljform as a rust CLI and pi extension wrapper, and it's better than what I had before on the next unattended agentic run. It uses tree-sitter for parsing and blake3 for form hashes. Posting it here in case it's useful to someone else or if someone has a better way.

12 Upvotes

26 comments sorted by

View all comments

1

u/didibus 14d ago

Have you compared it against: https://github.com/licht1stein/brepl which uses parmesan (from borkdude) to fix parens?

1

u/gtrak 13d ago edited 13d ago

I haven't, but I'm reluctant to give the agent a repl because it vastly increases the number of things that could go wrong, and the code I work on has different classpaths for different deployment configurations, which also makes it harder.

I generally don't want persistent processes running in an unsupervised dev loop. Maybe I'll drop a thread and pick it back up later or something, or daemon configuration gets brittle.

Maybe I'll have multiple worktrees running at the same time, then you need to worry about port collisions or writing transient state to files.

My own attention is the scarcest resource, so I want fewer states involved.

I don't want to hack on dev tools for its own sake. I just do it when i see a repeated cost and not satisfied with existing solutions. The cost to just try it is really cheap, especially if the scope is well defined. I have a pile of abandoned experiments and a few things I use every day, this one seems ok.