https://github.com/clj-kondo/clj-kondo: static analyzer and linter for Clojure code that sparks joy ✨
2026.05.25
This is a pretty huge release with a new feature to run macros from source, something which I've been mulling over for a long time.
Also it has ClojureScript async/await support + additional linters for it (correct :async metadata placement)
And a couple of new other linters along with the usual enhancements and bugfixes.
• Macros from source: a`defmacro`(and any supporting`defn`/`defn-`/`def`) tagged with`{:clj-kondo/macroexpand-hook true}`is automatically extracted into`.clj-kondo/`and registered as a`:macroexpand`hook on the next run. Seehttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md#macros-from-source
• https://github.com/clj-kondo/clj-kondo/issues/2822: NEW linter:`:alias-same-as-ns`which warns when an alias (`:as`) is the same as the namespace it's aliasing. Defaults to`:off`(https://github.com/tomdl89)
• https://github.com/clj-kondo/clj-kondo/issues/2807: NEW linter:`:conditional-build-up`which warns inside`let`when the same local map is rebound via successive`(if pred (assoc m ...) m)`patterns, suggesting`cond->`instead (default level:`:off`) (https://github.com/walber-araujo)
• https://github.com/clj-kondo/clj-kondo/issues/2062: NEW linter:`:if-x-x-y`which suggests`(or x y)`instead of`(if x x y)`when the condition is a simple symbol (default level:`:off`) (https://github.com/jramosg)
• Bump built-in ClojureScript analysis to 1.12.145, recognize`cljs.core/await`
• NEW linter:`:await-without-async-fn`which warns when`cljs.core/await`is used outside a function with`^:async`metadata
• NEW linter:`:misplaced-async-metadata`which warns when`^:async`metadata is placed on a function's argument vector or on the whole`(fn ...)`form, where ClojureScript ignores it; it must go on the function name
• Docs: update`doc/config.md`optional-linters section to include linters that are`:off`by default (https://github.com/jramosg)
• https://github.com/clj-kondo/clj-kondo/issues/2811: report correct location for`:missing-map-value`when the malformed map is nested in a set or in map-key position, and no longer suppress subsequent lint errors in the file
• https://github.com/clj-kondo/clj-kondo/issues/2813: fix false positive`:unused-excluded-var`when a core var is excluded to make room for a`:refer`with`:rename`(https://github.com/jramosg)
• https://github.com/clj-kondo/clj-kondo/issues/2814: fix false positive`:protocol-method-arity-mismatch`when a`definterface`declares the same method name with multiple arities (https://github.com/jramosg)
• https://github.com/clj-kondo/clj-kondo/issues/2818: do not fire`:redefined-var`across files when the same namespace is declared via`(ns ...)`in multiple files
• https://github.com/clj-kondo/clj-kondo/issues/2817: warn on`recur`inside a vector, map or set literal,`recur`is never in tail position there
• https://github.com/clj-kondo/clj-kondo/issues/2821: do not omit findings when`cljcfeatures`specified (https://github.com/lread)
• Deprecation: this is the last release to include the clj-kondo LSP server and the https://marketplace.visualstudio.com/items?itemName=borkdude.clj-kondo. For LSP-based editor integration, usehttps://clojure-lsp.io/, which embeds clj-kondo.
🚀 Old project, revived: Clojure 1.13 now runs on Android!
I ported Clojure 1.13 to run on Android (Dalvik / ART) — and not just loading
it: it supports on-device dynamic eval (JVM bytecode → d8 → DEX, compiled at
runtime). So you get a real REPL-style "evaluate Clojure live" experience right
on the phone 😄
Why it's neat
• Tracks the latest Clojure (1.13) — not stuck on the old 1.7 branch
• The changes are fully transparent and zero-overhead on the JVM — the Android
path only kicks in when java.vm.name == "Dalvik"
• Verified on an Android API 36 emulator: boot → AOT calls → on-device eval, all green
Two repos
• Patched Clojure 👉 https://github.com/xlisp/clojure-android
• Runnable Android demo 👉 https://github.com/xlisp/clojure-android-demo
OK, Thanks @neumann I'll get things organized and put together a demo video—specifically, a tutorial on Android development using hot reloading, where I build my own app from scratch.
clojure 1.13? does the core team know about this release? 😉
has there been any conversation with the core team about potentially getting this upstream?
I must say I'm very happy to see this, I played around with the android fork a few years ago. Even though pragmatically ClojureDart or even any of the cljs webview based solutions will often be a better solution, there are cases where having the full dynamic runtime is really valuable
The LLM-written announcement makes me not want to check this out. Just a data point, though.
What they don't know—since it's not quite ready yet—is that I'm planning to rewrite a Clojure Android development framework, similar to Neko. 😄 For the time being, the UI is still being written like this: https://github.com/xlisp/clojure-android-demo/blob/main/app/src/main/clojure/demo/ui.clj @nbtheduke
That's a great idea! 👍 I just need to refine it a bit—it's not quite perfect yet. 😄 https://github.com/xlisp/clojure-android @plexus
Yes, your intuition is correct. I primarily utilize a REPL server; I am currently integrating an MCP server into this project, which will enable me to use AI to invoke any capability across the entire Android system. @plexus
It doesn't matter whether the code was written by a large language model; what matters is whether you truly understand the underlying mechanisms of running Clojure on Android. Otherwise, even with the aid of an LLM, you won't be able to implement this functionality. @dj942
I used Clojure to develop for Android several years ago; I am intimately familiar with its underlying architecture, so I can accomplish this task without the aid of AI. https://github.com/xlisp/clojure-android-tensorflow-repl-server @dj942
That does make the question moot, as LLM code will not be accepted upstream.
I have reached out to the core team, and they are currently considering adding this feature so that the latest version of Clojure can be used for Android development. @plexus
(it's really not necessary to @-mention people on every reply, I'll be notified regardless cause I'm active in this thread)
good to hear that there's interest!
If Android development could be done using the latest version of Clojure, it would be a great boon for promoting the language. For years, I have never given up on applying Clojure to an ever-expanding range of domains. For instance, shadow-cljs is an excellent tool that has brought front-end development with ClojureScript to a high level of maturity—as demonstrated by a project I created: https://github.com/hulunote/hulunote
is startup time an issue?
Yes, the RT issue is a major obstacle hindering Clojure's development for Android.
@stevechan I'm glad @alexmiller is talking with you about adding the necessary changes in Clojure to support Android. Also be aware that, as @plexus mentioned, the Clojure team can't accept LLM-generated code. See: https://clojure.org/dev/contributor_agreement