announcements 2026-04-14

clj-xref 0.1.0 — LLM-friendly cross-reference database for Clojure code https://github.com/danlentz/clj-xref Instead of feeding your entire source tree to an AI coding assistant, clj-xref lets it query the dependency neighborhood of the function it's working on — just the relevant code, in far fewer tokens. Built on clj-kondo static analysis, it generates a queryable xref database with *lein xref * or c`lj -T:xref generate`, then answers questions from the REPL: (xref/who-calls db 'myapp.orders/process-payment) (xref/calls-who db 'myapp.web/handler) (xref/who-implements db 'myapp.protocols/Billable) (xref/unused-vars db) (xref/call-graph db 'myapp.core/main {:depth 3}) Returns plain maps and vectors — compose with filter, map, group-by, or anything else. How much context does it save? Well, that is still an experiment, but Measured on clj-xref's own source:

┌────────────────────────────-┬────────────────────┬────────────────────┬───────────┐ 
 │      Target                │   Whole-tree   │  Xref-guided   │ Reduction │                  
 ├────────────────────────────┼────────────────────┼────────────────────┼───────────┤                   
 │ core/index                 │ 8 files, 32K chars │ 1 file, 6K chars  │ 80%    │
 ├────────────────────────────┼────────────────────┼────────────────────┼───────────┤                   
 │ analyze/transform-analysis │ 8 files, 32K chars │ 1 file, 7K chars  │ 78%    │                  
 ├────────────────────────────┼────────────────────┼────────────────────┼───────────┤                   
 │ leiningen.xref/xref        │ 8 files, 32K chars │ 3 files, 11K chars │ 66%    │                  
 ├────────────────────────────┼────────────────────┼────────────────────┼───────────┤                   
 │ analyze/classify-kind      │ 8 files, 32K chars │ 1 file, 7K chars  │ 78%    │                  
 └────────────────────────────┴────────────────────┴────────────────────┴───────────┘                  
Also useful for: dead code detection, codebase visualization (DOT/Graphviz output), impact analysis in CI, and REPL-driven exploration of unfamiliar code. Query API: who-calls, calls-who, who-references, who-macroexpands, who-implements, who-dispatches, unused-vars, call-graph, apropos, ns-deps, ns-dependents. Inspired by SBCL's sb-introspect and Smalltalk's senders/implementors. Built entirely on clj-kondo — please consider sponsoring @borkdude: https://github.com/sponsors/borkdude

3
🔥 8
🎉 1

Will give this a go. This might be useful when e.g. refactoring existing code (“who’s calling this function”)

👍 1

clj-xref 0.1.1 — AI coding assistant integration is the headline. "robustness against clj-kondo edge cases" is the subtitle Check the readme for setup/AI assistant integration docs. Since 0.1.0: - New CLI: clj -M:xref who-calls ns/fn, unused, graph ns/fn, etc. - Claude Code /xref slash command (drop-in at .claude/commands/xref.md) - CLAUDE.md project guidance snippet — teaches Claude to reach for xref proactively before signature changes, deletions, or refactors instead of falling back to grep - Also: derived queries (unused-vars, call-graph, apropos), DOT/Graphviz output, incremental analysis (:only), and best-effort generation so clj-kondo errors no longer abort the build https://github.com/danlentz/clj-xref Detailed Info in Release notes: https://github.com/danlentz/clj-xref/releases/tag/0.1.1 I have some interesting ideas for next steps on this. Thanks everyone for having a look!

👍 2

sorry this will happen soon its a good improvement. just trying to balance this with work

Say, if, in addition to xref/graph analysis the LLM were easily able to instrument a function to see inside its lexical scope? I always see Claude spinning up all of these mini sessions to debug / work out issues. Making that more efficient seems like it might save significant context

just spitballing, but there seem like good libraries for the scope capture bit

and clj-kondo, while great, is ever only going to be an 80% solution. BUT...

The interesting hybrid                                                                                                  
                                                                                                                        
  The real power would be combining tiers:                                                                                
   
  ┌───────────────────────┬───────────────┬────────────────┬─────────┬──────────────────┬────────────────┐                
  │        Source         │ Pre-expansion │ Post-expansion │ Runtime │ Source locations │ No eval needed │              
  ├───────────────────────┼───────────────┼────────────────┼─────────┼──────────────────┼────────────────┤                
  │ clj-kondo (current)   │ yes           │ no             │ no      │ yes              │ yes            │              
  ├───────────────────────┼───────────────┼────────────────┼─────────┼──────────────────┼────────────────┤
  │ fdeps (Tier 1)        │ no            │ partial        │ yes     │ no               │ no             │                
  ├───────────────────────┼───────────────┼────────────────┼─────────┼──────────────────┼────────────────┤                
  │ ASM bytecode (Tier 2) │ no            │ yes            │ no      │ partial          │ partial        │                
  ├───────────────────────┼───────────────┼────────────────┼─────────┼──────────────────┼────────────────┤                
  │ Java agent (Tier 3)   │ no            │ yes            │ yes     │ partial          │ no             │              
  ├───────────────────────┼───────────────┼────────────────┼─────────┼──────────────────┼────────────────┤                
  │ Compiler AST (Tier 4) │ no            │ yes            │ no      │ yes              │ no             │              
  └───────────────────────┴───────────────┴────────────────┴─────────┴──────────────────┴────────────────┘  

so a lot to think about for next steps.

give it that, the more efficient (scope capture) debugging tools, then just teach it wisdom

not all tiers most likely. but more than kondo

something at least to fix macros

i'll push a 0.1.1-SNAPSHOT tonight that addresses those two GH issues and does a better "best effort" when kondo fails.

👍 1

but then i think there are some cool directions to go with this

Ya absolutely

🙌 1

Thanks - 262k lines of code is a good stress test :).

have done so, thanks @dan.lentz!

That sounds like a reasonable fix

How long does the xref take on the 262k line project?

to generate, or to run a query?

i'll check! 😄

Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Clojure                        828          15418           3913         117983
ClojureScript                  714           8042           2104          95075
ClojureC                       510           6673           1698          50523
Markdown                         3             59              0            132
JavaScript                       2              4              0             34
-------------------------------------------------------------------------------
SUM:                          2057          30196           7715         263747

Wed Apr 15 14:21:48 CEST 2026
clj-xref: analyzing ["src" "test"]...
clj-xref: wrote 22057 vars, 254861 refs -> .clj-xref/xref.edn
Wed Apr 15 14:22:17 CEST 2026
around 30secs to generate!

i can't do any queries at the mo, because of the bug

Not too bad. I'll try to get an 0.1.1 release out and take care of that

appreciated. if you want to push a commit i can use a sha dependency to do a quick test, just lmk!

Y ok will do. Let me circle back to it this afternoon

cheers, will try it and report back!

i added new experimental hooks for Claude / style commands eg /xref ns-deps ns that seems like a nice interface

Claude Code integration clj-xref now ships an example /xrefhttps://github.com/danlentz/clj-xref/blob/0.1.1-refinements/doc/claude-slash-command.md for Claude. Copy it to .claude/commands/xref.md in your project to add cross-reference queries as Claude commands:

/xref init                          — generate/regenerate the xref database
/xref who-calls ns/fn               — who calls this function?
/xref calls-who ns/fn               — what does this function call?
/xref who-implements ns/Protocol     — who implements this protocol?
/xref unused                        — find dead code (defined but never referenced)
/xref ns-deps ns                    — what namespaces does this one depend on?
/xref ns-dependents ns              — what namespaces depend on this one?
/xref apropos pattern               — search for vars matching a name pattern
/xref graph ns/fn                   — show transitive call graph
The slash command wraps the same CLI, so Claude runs the queries directly in your terminal. The included prompt guidance tells Claude to use xref proactively — checking callers before changing a signature, checking dependencies before refactoring, and regenerating after edits. This works with any AI assistant that can run shell commands. The CLI is the interface; the slash command is just a convenience wrapper.

🎉 2

does this need to reanalyze the entire project after a code change or does it have support for incremental analysis?

it does currently support a limited form of incremental (limited to changed files) but that was more of an experiment. I'm not sure its generally useful You would have to know your changes only had local impact

i tried to talk more about "what it is" vs "what it isn't" in the README

love the 'interact with/look at code like a graph' ideas, will have to give this a shot gratitude

🙌 1

@dan.lentz what drove you to build this, and would you like to get on a quick call? I see a lot of intersections between clj-ref and pando (http://clojure.getpando.ai)

🙌 1

So I asked Claude what they thought of this, and were eager to try. We created a skill to /xref init and then /xref {verb} for actual use. Looking forward to trying this out in my next session! Thanks for sharing @dan.lentz!!!

👍 1

the one time claude didn't screw up. don't tell codex

that does sound useful

giving this a try! we have a large monorepo (263kloc), with a 60mb clj-xref edn db. we use shadow-cljs with requires like ["@tanstack/react-pacer/debouncer" :as debouncer] this causes this issue when using the query mode: "Execution error at clj-xref.emit/read-edn (emit.clj:56).\nInvalid leading character: @\n" i have a codex-generated assessment and suggested fix. would it be ok if i shared its full output with you via a GH issue, @dan.lentz?

👍 1

We built something deeply inspired by Clojure's homoiconicity. pando is a tool for coding agents that treats code as data and has first class support for structural (i.e. using the AST) Clojure code navigation and editing. It works in addition to your existing tools - just connect over MCP. I'd love your feedback on it - https://clojure.getpando.ai Thank you kindly and looking forward to hearing from you! p.s. it's free for personal use and not OSS.

🚀 3

so, not open source?

Not yet at least :-)