Query the cross-reference database for the current Clojure project. Built on clj-kondo static analysis.
/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
Generate the xref database:
JENV_VERSION=21 clj -T:xref generateThis uses the global :xref alias from ~/.clojure/deps.edn and produces .clj-xref/xref.edn.
Ensure .clj-xref/ is in .gitignore (the database is generated, not committed).
If .clj-xref/xref.edn doesn't exist when a query is requested, run init automatically first.
For all query commands, run via the global :xref alias:
JENV_VERSION=21 clojure -M:xref -e '
(require (quote [clj-xref.core :as xref]))
(def db (xref/load-db))
;; ... query here ...
'(doseq [r (xref/who-calls db (quote <fully-qualified-sym>))]
(println (format " %s (%s:%d)" (:from r) (:file r) (:line r))))Report each caller with its file and line number.
(doseq [r (xref/calls-who db (quote <fully-qualified-sym>))]
(println (format " %s (%s:%d)" (:to r) (:file r) (:line r))))(xref/unused-vars db)Report unused vars. Note: defrecord constructors (->Foo, map->Foo), -main, and test functions will show as "unused" because they're entry points called externally — filter these out when reporting.
(xref/ns-deps db (quote <ns-sym>))
(xref/ns-dependents db (quote <ns-sym>))(xref/apropos db #"<pattern>")(xref/call-graph db (quote <fully-qualified-sym>) {:depth 3 :direction :outgoing})Report as a set of [from to] edges.
When working on code changes in this session, use xref proactively:
- Before changing a function signature: run
who-callsto find all callers that need updating - Before understanding unfamiliar code: run
calls-whoto see dependencies - After refactoring: regenerate with
clj -T:xref generate :only '["path/to/changed/file.clj"]'for incremental update
After significant code changes, regenerate the database:
JENV_VERSION=21 clj -T:xref generateOr incrementally for specific files:
JENV_VERSION=21 clj -T:xref generate :only '["src/path/to/file.clj"]'