OSS updates July and August 2025

In this post I'll give updates about open source I worked on during July and August 2025.

To see previous OSS updates, go here.

Sponsors

I'd like to thank all the sponsors and contributors that make this work possible. Without you the below projects would not be as mature or wouldn't exist or be maintained at all! So a sincere thank you to everyone who contributes to the sustainability of these projects.

gratitude

Current top tier sponsors:

Open the details section for more info about sponsoring.

Sponsor info

If you want to ensure that the projects I work on are sustainably maintained, you can sponsor this work in the following ways. Thank you!

Updates

Although summer hit Europe and I made a train trip to Switzerland for some hiking with my wife, OSS activity continued in the borkiverse. 20 projects saw updates. As usual, babashka, SCI and clj-kondo saw the most activity.

One of the big things I’m looking forward to is speaking at Clojure Conj 2025. At the risk of sounding a bit pretentious, the title of my talk is "Making Tools Developers Actually Use". Babashka started as a quirky interpreter "nobody had asked for" but now many Clojure developers don't want to live without it. Clj-kondo started out as a minimal proof-of-concept linter and now is widely used tool in Clojurian's every day toolset and available even in Cursive today. In the talk I want to reflect on what makes a tool something developers (like myself) actually want to use. I'm excited about this opportunity and about my first time visiting the Conj (don't ask me how I got the Clojure Conj cap on the photo above). Given the rest of the schedule, it's something I wouldn't want to miss.

For babashka, my main focus has been making it feel even more like regular Clojure. One example is the change in how non-daemon threads are handled. Previously, people had to sometimes add @(promise) to keep an httpkit server alive. Now babashka behaves like clojure -X in this regard: if you spawn non-daemon threads, the process waits for them. It’s looks like a small change, but it brings consistency with JVM Clojure, something I'm always aiming for more with babashka. If you want the old behavior, you can still use --force-exit. While implementing this I hit an interesting bug with GraalVM and also found out that clojure -X sometimes stalls when using agents. Maybe more on this next time.

Another change that was introduced is that when code is evaluated through load-string or Compiler/load (which is the same thing in bb), vars like *warn-on-reflection* are bound. This fixes a problem with loading code in non-main threads. E.g. @(future (load-string "(set! *warn-on-reflection* true)")) would fail in previous versions of babashka. You might wonder why you would ever want to do this. Well, a similar thing happens when you execute babashka tasks in parallel and that's where I ran into this problem.

SCI, the interpreter under the hood of babashka and several other projects, got some critical fixes as well. I detected one somewhat embarrasing bug when loading clojure+.hashp in babashka. It had code that looked like:

(def config {})
(let [config {}
      _ (alter-var-root #'config (constantly config))
     ]
  ...)

In the expression (alter-var-root #'config (constantly config)) the var #'config was mistaken for the local config since SCI's analyzer used a resolve-like function that also resolves locals. This fails horribly. In 6 years of SCI it's the first time I encountered this bug though. After fixing this problem, I noticed that babashka's CI acted up. On every commit, babashka CI tests dozens of Clojure libraries by running their test suites. I noticed that specter's tests were failing. It turned out that one test actually worked prior to fixing the above bug exactly because the SCI analyzer's resolve returned a node that evaluated to a local value. But there is no way I could just leave that bug in, so I had to make a pull request to specter as well to set this straight. A new specter version was released that works both with older version of babashka and the new version.

One other headscratcher in SCI was on the ClojureScript side of things and had to do with munging. In interop like (.-foo-bar #js {:foo-bar 1}) ClojureScript munges the field name in the interop form to foo_bar but in the object it stays "foo-bar". The munging of this name wasn't applied in SCI as an oversight. So in SCI (and thus in nbb, joyride, scittle, etc.) the above expression would return 1 whereas in ClojureScript it would return nil. In contrast, (.-foo-bar #js {:foo_bar 1}) would return nil in SCI but 1 in CLJS. Although fixing this could mean a breaking change in SCI-based scripting environments I decided to align it with CLJS anyway, as switching between SCI and CLJS should not introduce these kinds of surprises.

Other improvements in SCI were made in the area of better using type hints on instance method interop.

And then there’s clj-kondo, the linter that is supposed to spark joy ✨, as far as a linter is able to do that in a developer's life. Two new linters were added, including one that catches suspicious uses of locking. This linter was inspired by a similar rule in splint. Lots of smaller improvements were made like sorting findings and imported files such that they are consistent across multiple runs that use the --parallel option and across operating systems. And as usual bugfixes and preventing false positives.

One happy improvement to scittle is that referencing a library that was introduced by a <script> tag now was made a lot easier. You can find the docs about that here. The tl;dr of this is that when a library registers itself as a global, you can just use that global in :require now: (require '["JSConfetti" :as confetti]).

Of course, none of this happens in isolation. I’m deeply grateful to the community and the sponsors who make this work sustainable: Clojurists Together, Roam Research, Nextjournal, Nubank, and many other companies and individuals. Every bit of support means I can keep refining these tools, fixing edge cases, and thinking about the long-term direction.

Here are updates about the projects/libraries I've worked on in the last two months in detail.

  • babashka: native, fast starting Clojure interpreter for scripting.

    • Bump clojure to 1.12.2
    • #1843: BREAKING (potententially): non-daemon thread handling change. Similar to JVM clojure, babashka now waits for non-daemon threads to finish. This means you don't have to append @(promise) anymore when you spawn an httpkit server, for example. For futures and agents, bb uses a thread pool that spawns daemon threads, so that pool isn't preventing an exit. This behavior is similar to clojure -X. You can get back the old behavior where bb always forced an exit and ignored running non-daemon threads with --force-exit.
    • #1690: bind clojure.test/*test-out* to same print-writer as *out* in nREPL server
    • Add Compiler/demunge
    • Add clojure.lang.TaggedLiteral/create
    • Add java.util.TimeZone/setDefault
    • Add println-str
    • SCI: Var literal or special form gets confused with local of same name
    • #1852: (.getContextClassLoader (Thread/currentThread)) should be able to return results from babashka classpath
    • Bump deps.clj to 1.12.2.1565
    • Bind more vars like *warn-on-reflection* during load{string,reader} (same as JVM Clojure) so can load code in other than than the main thread
    • #1845: expose cheshire.generate/{add-encoder,encode-str}
    • Bump timbre to 6.8.0
    • Bump clojure.tools.logging to 1.3.0
    • Improve interop using type hints on qualified instance methods
    • Bump Jsoup to 1.21.2
    • Bump fs to 0.5.7
    • Bump cheshire to 6.1.0
    • Pods: no exception on destroy when there's still calls in progress
  • SCI: Configurable Clojure/Script interpreter suitable for scripting

    • Add println-str
    • Fix #997: Var is mistaken for local when used under the same name in a let body
    • Fix regression introduced in #987
    • Fix #963: respect :param-tags on qualified instance method
    • Add *suppress-read*
    • Add load-reader
    • Fix #872: *loaded-libs* is now the single source of truth about loaded libs
    • Fix #981: respect type hint on instance method callee
    • Add core dynamic vars like *warn-on-reflection* and bind them during load-string etc. such that set!-ing then in a future works.
    • Fix #984: support alternative set! syntax in CLJS
    • Fix #987: method or property name in interop should be munged
    • Fix #986: preserve error location for js static method
    • Fix #990: fix merge-opts with :bindings + deprecate :bindings (replaced by :namespaces {'user ...})
  • clj-kondo: static analyzer and linter for Clojure code that sparks joy.

    • Unreleased
    • #2588: false positive type mismatch about symbol accepting var
    • Require clojure 1.10.3 is the minimum clojure version
    • #2564: detect calling set with wrong number of arguments
    • #2257: support ignore hint on invalid symbol
    • Sort findings on filename, row, column and now additionally on message too
    • #2602: Sort auto-imported configs to avoid differences based on OS or file system
    • #2603: warn on :inline-def with nested deftest
    • #2606: make it easy for users to know how inline-config files should be version controlled (@lread)
    • #2610: ignores may show up unordered due to macros
    • #2615: emit inline-configs config.edn in a git-diff-friendly way (@lread)
    • 2025.07.28
    • #2580: false positive type mismatch with quoted value
    • Fix some :locking-suspicious-lock false positives
    • #2582: :condition-always-true false positives
    • 2025.07.26
    • #2560: NEW linter: :locking-suspicious-lock: report when locking is used on a single arg, interned value or local object
    • #2519: NEW linter: :unresolved-protocol-method. See docs (@emerson-matos)
    • #2555: false positive with clojure.string/replace and partial as replacement fn
    • #2566: Expand :condition-always-true check. (@NoahTheDuke)
    • #2350: support schema.core/defprotocol (@emerson-matos)
    • #2571: false positive unresolved symbol when ignoring expression that goes through macroexpansion hook
    • #2575: false positive type mismatch with nested keyword call and str
    • Bump SCI to 0.10.47
    • Drop memoization for hook fns and configuration, solves memory issue with Cursive + big projects like metabase
    • Optimizations to compensate for dropping caching, performance should be similar (or better depending on the size of your project)
    • #2568: support :deprecated-namespace for .cljc namespaces
  • clerk: Moldable Live Programming for Clojure

    • Upgrade to Reagent and fix unsafe HTML rendering
    • Add viewers for HTML markdown nodes
    • Support file watching in babashka
    • Support server side rendering of formulas using KaTeX
  • squint: CLJS syntax to JS compiler

    • v0.8.153 (2025-08-31)
    • Fix #704: while didn't compile correctly
    • Add clojure.string/includes?
    • Emit less code for varargs functions
    • Fix solidJS example
    • Documentation improvements (@lread)
    • Fix #697: ClassCastException in statement function when passed Code records
    • v0.8.152 (2025-07-18)
    • Fix #680: support import attributes using :with option in require, e.g. :with {:type :json}
    • v0.8.151 (2025-07-15)
    • Implement not= as function
    • Fix #684: JSX output
    • v0.8.150 (2025-07-09)
    • #678: Implement random-uuid (@rafaeldelboni)
    • Fix #681: support unsafe HTML via [:$ ...] tag
  • scittle: Execute Clojure(Script) directly from browser script tags via SCI

    • v0.7.27 (2025-08-21)
    • #95: support string requires of globalThis js deps (@chr15m). See docs.
    • Potentially breaking: (.-foo-bar {}) now behaves as {}.foo_bar, i.e. the property or method name is munged.
    • v0.7.26 (2025-08-20)
    • #121: add cjohansen/dataspex plugin (@jeroenvandijk)
    • #118: add goog.string/format (@jeroenvandijk)
    • Support alternative (set! #js {} -a 1) CLJS syntax (by bumping SCI)
    • Add source maps to distribution
    • Add dev versions of all modules in the dev folder of the distribution + a dev/scitte.cljs-devtools.js module
  • edamame: configurable EDN and Clojure parser with location metadata and more

    • Fix #132: Add counterpart to Clojure's *suppress-read*: :suppress-read
  • sci.configs: A collection of ready to be used SCI configs.

    • Add config for dataspex
  • nbb: Scripting in Clojure on Node.js using SCI

    • nREPL improvement for vim-fireplace
  • Nextjournal Markdown

    • Drop KaTeX dependency by inlining TeXMath lib
  • babashka.nrepl-client

    • Add :responses key with raw responses
  • fs - File system utility library for Clojure

    • Documentation improvements
    • Fix wrong typehint
  • cherry: Experimental ClojureScript to ES6 module compiler

    • not= is now a function
  • CLI: Turn Clojure functions into CLIs!

    • #122: introduce new :repeated-opts option to enforce repeating the option for accepting multiple values (e.g. --foo 1 --foo 2 rather than --foo 1 2)
  • deps.clj: A faithful port of the clojure CLI bash script to Clojure

    • Fixed Java download program that respects CLJ_JVM_OPTS for downloading tools jar.
    • Released several versions catching up with the clojure CLI
  • pod-babashka-fswatcher: babashka filewatcher pod

    • Pod protocol fix: don't send done with async messages
    • Robustness improvements
    • Bump fsnotify
  • sci.nrepl: nREPL server for SCI projects that run in the browser

    • Send current working directory in describe message (for tools like clojure-mcp)
    • Add "session-closed" to close op reply
  • pod-babashka-go-sqlite3: A babashka pod for interacting with sqlite3

    • JSON1 support
  • http-server: serve static assets

    • 0.1.15
    • #22: fix off-by-one error in range requests (@jyn514)
    • 0.1.14
    • #21: Add :not-found option for handling unfound files. The option is a function of the request and should return a map with :status and :body.
    • #19: Add text/html MIME types for asp and aspx file extensions (@respatialized)
    • 0.1.13
    • #16: support range requests (jmglov)
    • #13: add an ending slash to the dir link, and don't encode the slashes (@KDr2)
    • #12: Add headers to index page (rather than just file responses)

Contributions to third party projects:

  • specter: Clojure(Script)'s missing piece

    • Fix babashka support by removing optimizations that only worked due to SCI bug
  • clojure-test-suite: Dialect-independent tests for clojure.core, and others, focused on characterizing how Clojure JVM behaves so that other dialects to reach parity.

    • Added babashka to the test suite

Other projects

These are (some of the) other projects I'm involved with but little to no activity happened in the past month.

Click for more details
  • quickdoc: Quick and minimal API doc generation for Clojure
  • unused-deps: Find unused deps in a clojure project
  • http-client: babashka's http-client
  • quickblog: light-weight static blog engine for Clojure and babashka
  • process: Clojure library for shelling out / spawning sub-processes
  • html: Html generation library inspired by squint's html tag
  • instaparse-bb: Use instaparse from babashka
  • sql pods: babashka pods for SQL databases
  • rewrite-edn: Utility lib on top of
  • rewrite-clj: Rewrite Clojure code and edn
  • tools-deps-native and tools.bbuild: use tools.deps directly from babashka
  • bbin: Install any Babashka script or project with one comman
  • qualify-methods
    • Initial release of experimental tool to rewrite instance calls to use fully qualified methods (Clojure 1.12 only0
  • neil: A CLI to add common aliases and features to deps.edn-based projects.
  • tools: a set of bbin installable scripts
  • babashka.json: babashka JSON library/adapter
  • speculative
  • squint-macros: a couple of macros that stand-in for applied-science/js-interop and promesa to make CLJS projects compatible with squint and/or cherry.
  • grasp: Grep Clojure code using clojure.spec regexes
  • lein-clj-kondo: a leiningen plugin for clj-kondo
  • http-kit: Simple, high-performance event-driven HTTP client+server for Clojure.
  • babashka.nrepl: The nREPL server from babashka as a library, so it can be used from other SCI-based CLIs
  • jet: CLI to transform between JSON, EDN, YAML and Transit using Clojure
  • lein2deps: leiningen to deps.edn converter
  • cljs-showcase: Showcase CLJS libs using SCI
  • babashka.book: Babashka manual
  • pod-babashka-buddy: A pod around buddy core (Cryptographic Api for Clojure).
  • gh-release-artifact: Upload artifacts to Github releases idempotently
  • carve - Remove unused Clojure vars
  • 4ever-clojure - Pure CLJS version of 4clojure, meant to run forever!
  • pod-babashka-lanterna: Interact with clojure-lanterna from babashka
  • joyride: VSCode CLJS scripting and REPL (via SCI)
  • clj2el: transpile Clojure to elisp
  • deflet: make let-expressions REPL-friendly!
  • deps.add-lib: Clojure 1.12's add-lib feature for leiningen and/or other environments without a specific version of the clojure CLI

Published: 2025-08-05

Tagged: clojure oss updates

OSS updates May and June 2025

In this post I'll give updates about open source I worked on during May and June 2025.

To see previous OSS updates, go here.

Sponsors

I'd like to thank all the sponsors and contributors that make this work possible. Without you the below projects would not be as mature or wouldn't exist or be maintained at all! So a sincere thank you to everyone who contributes to the sustainability of these projects.

gratitude

Current top tier sponsors:

Open the details section for more info about sponsoring.

Sponsor info

If you want to ensure that the projects I work on are sustainably maintained, you can sponsor this work in the following ways. Thank you!

Updates

Here are updates about the projects/libraries I've worked on in the last two months, 19 in total!

  • babashka: native, fast starting Clojure interpreter for scripting.

    • Bump edamame (support old-style #^ metadata)
    • Bump SCI: fix satisfies? for protocol extended to nil
    • Bump rewrite-clj to 1.2.50
    • 1.12.204 (2025-06-24)
    • Compatibility with clerk's main branch
    • #1834: make taoensso/trove work in bb by exposing another timbre var
    • Bump timbre to 6.7.1
    • Protocol method should have :protocol meta
    • Add print-simple
    • Make bash install script work on Windows for GHA
    • Upgrade Jsoup to 1.21.1
    • 1.12.203 (2025-06-18)
    • Support with-redefs + intern (see SCI issue #973
    • #1832: support clojure.lang.Var/intern
    • Re-allow init as task name
    • 1.12.202 (2025-06-15)
    • Support clojure.lang.Var/{get,clone,reset}ThreadBindingFrame for JVM Clojure compatibility
    • #1741: fix taoensso.timbre/spy and include test
    • Add taoensso.timbre/set-ns-min-level! and taoensso.timbre/set-ns-min-level
    • 1.12.201 (2025-06-12)
    • #1825: Add Nextjournal Markdown as built-in Markdown library
    • Promesa compatibility (pending PR here)
    • Upgrade clojure to 1.12.1
    • #1818: wrong argument order in clojure.java.io/resource implementation
    • Add java.text.BreakIterator
    • Add classes for compatibility with promesa:
      • java.lang.Thread$Builder$OfPlatform
      • java.util.concurrent.ForkJoinPool
      • java.util.concurrent.ForkJoinPool$ForkJoinWorkerThreadFactory
      • java.util.concurrent.ForkJoinWorkerThread
      • java.util.concurrent.SynchronousQueue
    • Add taoensso.timbre/set-min-level!
    • Add taoensso.timbre/set-config!
    • Bump fs to 0.5.26
    • Bump jsoup to 1.20.1
    • Bump edamame to 1.4.30
    • Bump taoensso.timbre to 6.7.0
    • Bump pods: more graceful error handling when pod quits unexpectedly
    • #1815: Make install-script wget-compatible (@eval)
    • #1822: type should prioritize :type metadata
    • ns-name should work on symbols
    • :clojure.core/eval-file should affect *file* during eval
    • #1179: run :init in tasks only once
    • #1823: run :init in tasks before task specific requires
    • Fix resolve when *ns* is bound to symbol
    • Bump deps.clj to 1.12.1.1550
    • Bump http-client to 0.4.23
  • SCI: Configurable Clojure/Script interpreter suitable for scripting

    • 0.10.47 (2025-06-27)
    • Security issue: function recursion can be forced by returning internal keyword as return value
    • Fix #975: Protocol method should have :protocol var on metadata
    • Fix #971: fix satisfies? for protocol that is extended to nil
    • Fix #977: Can't analyze sci.impl.analyzer with splint
    • 0.10.46 (2025-06-18)
    • Fix #957: sci.async/eval-string+ should return promise with :val nil for ns form rather than :val <Promise>
    • Fix #959: Java interop improvement: instance method invocation now leverages type hints
    • Bump edamame to 1.4.30
    • Give metadata :type key priority in type implementation
    • Fix #967: ns-name should work on symbols
    • Fix #969: ^:clojure.core/eval-file metadata should affect binding of *file* during evaluation
    • Sync sci.impl.Reflector with changes in clojure.lang.Reflector in clojure 1.12.1
    • Fix :static-methods option for class with different name in host
    • Fix #973: support with-redefs on core vars, e.g. intern. The fix for this issue entailed quite a big refactor of internals which removes "magic" injection of ctx in core vars that need it.
    • Add unchecked-set and unchecked-get for CLJS compatibility
  • clerk: Moldable Live Programming for Clojure

    • Make clerk compatible with babashka
  • quickblog: light-weight static blog engine for Clojure and babashka

    • 0.4.7 (2025-06-12)
    • Switch to Nextjournal Markdown for markdown rendering The minimum babashka version to be used with quickblog is now v1.12.201 since it comes with Nextjournal Markdown built-in.
    • Link to previous and next posts; see "Linking to previous and next posts" in the README (@jmglov)
    • Fix flaky caching tests (@jmglov)
    • Fix argument passing in test runner (@jmglov)
    • Add --date to api/new. (@jmglov)
    • Support Selmer template for new posts in api/new
    • Add 'language-xxx' to pre/code blocks
    • Fix README.md with working version in quickstart example
    • Fix #104: fix caching with respect to previews
    • Fix #104: document :preview option
  • edamame: configurable EDN and Clojure parser with location metadata and more

    • 1.4.31 (2025-06-25)
    • Fix #124: add :imports to parse-ns-form
    • Fix #125: Support #^:foo deprecated metadata reader macro (@NoahTheDuke)
    • Fix #127: expose continue value that indicates continue-ing parsing (@NoahTheDuke)
    • Fix #122: let :auto-resolve-ns affect syntax-quote
    • 1.4.30
    • #120: fix :auto-resolve-ns failing case
  • squint: CLJS syntax to JS compiler

    • #678: Implement random-uuid (@rafaeldelboni)
    • v0.8.149 (2025-06-19)
    • #671: Implement trampoline (@rafaeldelboni)
    • Fix #673: remove experimental atom as promise option since it causes unexpected behavior
    • Fix #672: alias may contain dots
    • v0.8.148 (2025-05-25)
    • Fix #669: munge refer-ed + renamed var
    • v0.8.147 (2025-05-09)
    • Fix #661: support throw in expression position
    • Fix #662: Fix extending protocol from other namespace to nil
    • Better solution for multiple expressions in return context in combination with pragmas
  • clj-kondo: static analyzer and linter for Clojure code that sparks joy.

    • #2560: NEW linter: :locking-suspicious-lock: report when locking is used on a single arg, interned value or local object
    • #2555: false positive with clojure.string/replace and partial as replacement fn
    • 2025.06.05
    • #2541: NEW linter: :discouraged-java-method. See docs
    • #2522: support :config-in-ns on :missing-protocol-method
    • #2524: support :redundant-ignore on :missing-protocol-method
    • #2536: false positive with format and whitespace flag after percent
    • #2535: false positive :missing-protocol-method when using alias in method
    • #2534: make :redundant-ignore aware of .cljc
    • #2527: add test for using ns-group + config-in-ns for :missing-protocol-method linter
    • #2218: use ReentrantLock to coordinate writes to cache directory within same process
    • #2533: report inline def under fn and defmethod
    • #2521: support :langs option in :discouraged-var to narrow to specific language
    • #2529: add :ns to &env in :macroexpand-hook macros when executing in CLJS
    • #2547: make redundant-fn-wrapper report only for all cljc branches
    • #2531: add :name data to :unresolved-namespace finding for clojure-lsp
  • sci.configs: A collection of ready to be used SCI configs.

  • scittle: Execute Clojure(Script) directly from browser script tags via SCI

  • nbb: Scripting in Clojure on Node.js using SCI

    • 1.3.204 (2025-05-15)
    • #389: fix regression caused by #387
    • 1.3.203 (2025-05-13)
    • #387: bump import-meta-resolve to fix deprecation warnings on Node 22+
    • 1.3.202 (2025-05-12)
    • Fix nbb nrepl server for Deno
    • 1.3.201 (2025-05-08)
    • Deno improvements for loading jsr: and npm: deps, including react in combination with reagent
    • #382: prefix all node imports with node:
  • quickdoc: Quick and minimal API doc generation for Clojure

    • v0.2.5 (2025-05-01)
    • Fix #32: fix anchor links to take into account var names that differ only by case
    • v0.2.4 (2025-05-01)
    • Revert source link in var title and move back to <sub>
    • Specify clojure 1.11 as the minimal Clojure version in deps.edn
    • Fix macro information
    • Fix #39: fix link when var is named multiple times in docstring
    • Upgrade clj-kondo to 2025.04.07
    • Add explicit org.babashka/cli dependency
  • Nextjournal Markdown

    • 0.7.186
    • Make library more GraalVM native-image friendly
    • 0.7.184
    • Consolidate utils in nextjournal.markdown.utils
    • 0.7.181
    • Hiccup JVM compatibility for fragments (see #34)
    • Support HTML blocks (:html-block) and inline HTML (:html-inline) (see #7)
    • Bump commonmark to 0.24.0
    • Bump markdown-it to 14.1.0
    • Render :code according to spec into <pre> and <code> block with language class (see #39)
    • No longer depend on applied-science/js-interop
    • Accept parsed result in ->hiccup function
    • Expose nextjournal.markdown.transform through main nextjournal.markdown namespace
    • Stabilize API and no longer mark library alpha
  • babashka.nrepl-client

    • Add :responses key with raw responses
  • speculative

    • Add spec for even?
  • http-client: babashka's http-client

    • 0.4.23 (2025-06-06)
    • #75: override existing content type header in multipart request
    • Accept :request-method in addition to :request to align more with other clients
    • Accept :url in addition to :uri to align more with other clients
  • unused-deps: Find unused deps in a clojure project

    • This is a brand new project!
  • fs - File system utility library for Clojure

    • #147: fs/unzip should allow selective extraction of files (@sogaiu)
    • #145: fs/modified-since works only with ms precision but should support the precision of the filesystem
  • cherry: Experimental ClojureScript to ES6 module compiler

    • Fix cherry.embed which is used by malli
  • deps.clj: A faithful port of the clojure CLI bash script to Clojure

    • Released several versions catching up with the clojure CLI

Other projects

These are (some of the) other projects I'm involved with but little to no activity happened in the past month.

Click for more details - [CLI](https://github.com/babashka/cli): Turn Clojure functions into CLIs! - [process](https://github.com/babashka/process): Clojure library for shelling out / spawning sub-processes - [html](https://github.com/borkdude/html): Html generation library inspired by squint's html tag - [instaparse-bb](https://github.com/babashka/instaparse-bb): Use instaparse from babashka - [sql pods](https://github.com/babashka/babashka-sql-pods): babashka pods for SQL databases - [rewrite-edn](https://github.com/borkdude/rewrite-edn): Utility lib on top of - [rewrite-clj](https://github.com/clj-commons/rewrite-clj): Rewrite Clojure code and edn - [pod-babashka-go-sqlite3](https://github.com/babashka/pod-babashka-go-sqlite3): A babashka pod for interacting with sqlite3 - [tools-deps-native](https://github.com/babashka/tools-deps-native) and [tools.bbuild](https://github.com/babashka/tools.bbuild): use tools.deps directly from babashka - [http-server](https://github.com/babashka/http-server): serve static assets - [bbin](https://github.com/babashka/bbin): Install any Babashka script or project with one comman - [qualify-methods](https://github.com/borkdude/qualify-methods) - Initial release of experimental tool to rewrite instance calls to use fully qualified methods (Clojure 1.12 only0 - [neil](https://github.com/babashka/neil): A CLI to add common aliases and features to deps.edn-based projects.
- [tools](https://github.com/borkdude/tools): a set of [bbin](https://github.com/babashka/bbin/) installable scripts - [sci.nrepl](https://github.com/babashka/sci.nrepl): nREPL server for SCI projects that run in the browser - [babashka.json](https://github.com/babashka/json): babashka JSON library/adapter - [squint-macros](https://github.com/squint-cljs/squint-macros): a couple of macros that stand-in for [applied-science/js-interop](https://github.com/applied-science/js-interop) and [promesa](https://github.com/funcool/promesa) to make CLJS projects compatible with squint and/or cherry. - [grasp](https://github.com/borkdude/grasp): Grep Clojure code using clojure.spec regexes - [lein-clj-kondo](https://github.com/clj-kondo/lein-clj-kondo): a leiningen plugin for clj-kondo - [http-kit](https://github.com/http-kit/http-kit): Simple, high-performance event-driven HTTP client+server for Clojure. - [babashka.nrepl](https://github.com/babashka/babashka.nrepl): The nREPL server from babashka as a library, so it can be used from other SCI-based CLIs - [jet](https://github.com/borkdude/jet): CLI to transform between JSON, EDN, YAML and Transit using Clojure - [pod-babashka-fswatcher](https://github.com/babashka/pod-babashka-fswatcher): babashka filewatcher pod - [lein2deps](https://github.com/borkdude/lein2deps): leiningen to deps.edn converter - [cljs-showcase](https://github.com/borkdude/cljs-showcase): Showcase CLJS libs using SCI - [babashka.book](https://github.com/babashka/book): Babashka manual - [pod-babashka-buddy](https://github.com/babashka/pod-babashka-buddy): A pod around buddy core (Cryptographic Api for Clojure). - [gh-release-artifact](https://github.com/borkdude/gh-release-artifact): Upload artifacts to Github releases idempotently - [carve](https://github.com/borkdude/carve) - Remove unused Clojure vars - [4ever-clojure](https://github.com/oxalorg/4ever-clojure) - Pure CLJS version of 4clojure, meant to run forever! - [pod-babashka-lanterna](https://github.com/babashka/pod-babashka-lanterna): Interact with clojure-lanterna from babashka - [joyride](https://github.com/BetterThanTomorrow/joyride): VSCode CLJS scripting and REPL (via [SCI](https://github.com/babashka/sci)) - [clj2el](https://borkdude.github.io/clj2el/): transpile Clojure to elisp - [deflet](https://github.com/borkdude/deflet): make let-expressions REPL-friendly! - [deps.add-lib](https://github.com/borkdude/deps.add-lib): Clojure 1.12's add-lib feature for leiningen and/or other environments without a specific version of the clojure CLI

Published: 2025-07-01

Tagged: clojure oss updates

OSS updates March and April 2025

In this post I'll give updates about open source I worked on during March and April 2025.

To see previous OSS updates, go here.

Sponsors

I'd like to thank all the sponsors and contributors that make this work possible. Without you the below projects would not be as mature or wouldn't exist or be maintained at all! So a sincere thank you to everyone who contributes to the sustainability of these projects.

gratitude

Current top tier sponsors:

Open the details section for more info about sponsoring.

Sponsor info

If you want to ensure that the projects I work on are sustainably maintained, you can sponsor this work in the following ways. Thank you!

On to the projects that I've been working on!

Blog posts

I blogged about an important improvement in babashka regarding type hints here.

Interviews

Also I did an interview with Jiri from Clojure Corner by Flexiana, viewable here.

Updates

Here are updates about the projects/libraries I've worked on in the last two months.

  • babashka: native, fast starting Clojure interpreter for scripting.

    • Improve Java reflection based on provided type hints (read blog post here)
    • Add compatibility with the fusebox library
    • Fix virtual ThreadBuilder interop
    • Add java.util.concurrent.ThreadLocalRandom
    • Add java.util.concurrent.locks.ReentrantLock
    • Add classes:
      • java.time.chrono.ChronoLocalDate
      • java.time.temporal.TemporalUnit
      • java.time.chrono.ChronoLocalDateTime
      • java.time.chrono.ChronoZonedDateTime
      • java.time.chrono.Chronology
    • #1806: Add cheshire.factory namespace (@lread)
    • Bump GraalVM to 24
    • Bump SCI to 0.9.45
    • Bump edamame to 1.4.28
    • #1801: Add java.util.regex.PatternSyntaxException
    • Bump core.async to 1.8.735
    • Bump cheshire to 6.0.0
    • Bump babashka.cli to 0.8.65
  • clerk: Moldable Live Programming for Clojure

    • Replace tools.analyzer with a more light-weight analyzer which also adds support for Clojure 1.12
  • squint: CLJS syntax to JS compiler

    • #653: respect :context expr in compile-string
    • #657: respect :context expr in set! expression
    • #659: fix invalid code produced for REPL mode with respect to return
    • #651 Support :require + :rename + allow renamed value to be used in other :require clause
    • Fix #649: reset ns when compiling file and fix initial global object
    • Fix #647: emit explicit null when written in else branch of if
    • Fix #640: don't emit anonymous function if it is a statement (@jonasseglare)
    • Fix #643: Support lexicographic compare of arrays (@jonasseglare)
    • Fix #602: support hiccup-style shorthand for id and class attributes in #jsx and #html
    • Fix #635: range fixes
    • Fix #636: add run!
    • defclass: elide constructor when not provided
    • Fix #603: don't emit multiple returns
    • Drop constructor requirement for defclass
  • clj-kondo: static analyzer and linter for Clojure code that sparks joy.

    • #2522: support :config-in-ns on :missing-protocol-method
    • #2524: support :redundant-ignore on :missing-protocol-method
    • #1292: NEW linter: :missing-protocol-method. See docs
    • #2512: support vars ending with ., e.g. py. according to clojure analyzer
    • #2516: add new --repro flag to ignore home configuration
    • #2493: reduce image size of native image
    • #2496: Malformed deftype form results in NPE
    • #2499: Fix (alias) bug (@Noahtheduke)
    • #2492: Report unsupported escape characters in strings
    • #2502: add end locations to invalid symbol
    • #2511: fix multiple parse errors caused by incomplete forms
    • document var-usages location info edge cases (@sheluchin)
    • Upgrade to GraalVM 24
    • Bump datalog parser
    • Bump built-in cache
  • SCI: Configurable Clojure/Script interpreter suitable for scripting

    • Fix #957: sci.async/eval-string+ should return promise with :val nil for ns form rather than :val <Promise>
    • Fix #959: Java interop improvement: instance method invocation now leverages type hints
    • Fix #942: improve error location of invalid destructuring
    • Add volatile? to core vars
    • Fix #950: interop on local in CLJS
    • Bump edamame to 1.4.28
  • quickdoc: Quick and minimal API doc generation for Clojure

    • Fix #32: fix anchor links to take into account var names that differ only by case
    • Revert source link in var title and move back to <sub>
    • Specify clojure 1.11 as the minimal Clojure version in deps.edn
    • Fix macro information
    • Fix #39: fix link when var is named multiple times in docstring
    • Upgrade clj-kondo to 2025.04.07
    • Add explicit org.babashka/cli dependency
  • CLI: Turn Clojure functions into CLIs!

    • #119: format-table now formats multiline cells appropriately (@lread)
    • Remove pom.xml and project.clj for cljdoc
    • #116: Un-deprecate :collect option to support custom transformation of arguments to collections (@lread)
    • Support :collect in :spec
  • process: Clojure library for shelling out / spawning sub-processes

    • #163, #164: Program resolution strategy for exec and Windows now matches macOS/Linux/PowerShell (@lread)
    • Fix memory leak by executing shutdown hook when process finishes earlier than VM exit (@maxweber)
  • html: Html generation library inspired by squint's html tag

    • Fix #3: allow dynamic attribute value: (html [:a {:a (+ 1 2 3)}])
    • Fix #9: shortcuts for id and classes
  • cherry: Experimental ClojureScript to ES6 module compiler

    • Add cljs.pprint/pprint
    • Add add-tap
    • Bump squint compiler common which brings in new #html id and class shortcuts + additional features and optimizations, such as an optimization for aset
  • nbb: Scripting in Clojure on Node.js using SCI

    • Add better Deno + jsr: dependency support, stay tuned.
  • instaparse-bb: Use instaparse from babashka

  • edamame: Configurable EDN/Clojure parser with location metadata

    • #117: throw on triple colon keyword
  • fs - File system utility library for Clojure

    • #141: fs/match doesn't match when root dir contains glob or regex characters in path
    • #138: Fix fs/update-file to support paths (@rfhayashi)
  • sql pods: babashka pods for SQL databases

    • Upgrade to GraalVM 23, fixes encoding issue with Korean characters

Other projects

These are (some of the) other projects I'm involved with but little to no activity happened in the past month.

Click for more details - [rewrite-edn](https://github.com/borkdude/rewrite-edn): Utility lib on top of - [deps.clj](https://github.com/borkdude/deps.clj): A faithful port of the clojure CLI bash script to Clojure - [scittle](https://github.com/babashka/scittle): Execute Clojure(Script) directly from browser script tags via SCI - [rewrite-clj](https://github.com/clj-commons/rewrite-clj): Rewrite Clojure code and edn - [pod-babashka-go-sqlite3](https://github.com/babashka/pod-babashka-go-sqlite3): A babashka pod for interacting with sqlite3 - [tools-deps-native](https://github.com/babashka/tools-deps-native) and [tools.bbuild](https://github.com/babashka/tools.bbuild): use tools.deps directly from babashka - [http-client](https://github.com/babashka/http-client): babashka's http-client
- [http-server](https://github.com/babashka/http-server): serve static assets - [bbin](https://github.com/babashka/bbin): Install any Babashka script or project with one comman - [sci.configs](https://github.com/babashka/sci.configs): A collection of ready to be used SCI configs. - Added a configuration for `cljs.spec.alpha` and related namespaces - [qualify-methods](https://github.com/borkdude/qualify-methods) - Initial release of experimental tool to rewrite instance calls to use fully qualified methods (Clojure 1.12 only0 - [neil](https://github.com/babashka/neil): A CLI to add common aliases and features to deps.edn-based projects.
- [tools](https://github.com/borkdude/tools): a set of [bbin](https://github.com/babashka/bbin/) installable scripts - [sci.nrepl](https://github.com/babashka/sci.nrepl): nREPL server for SCI projects that run in the browser - [babashka.json](https://github.com/babashka/json): babashka JSON library/adapter - [squint-macros](https://github.com/squint-cljs/squint-macros): a couple of macros that stand-in for [applied-science/js-interop](https://github.com/applied-science/js-interop) and [promesa](https://github.com/funcool/promesa) to make CLJS projects compatible with squint and/or cherry. - [grasp](https://github.com/borkdude/grasp): Grep Clojure code using clojure.spec regexes - [lein-clj-kondo](https://github.com/clj-kondo/lein-clj-kondo): a leiningen plugin for clj-kondo - [http-kit](https://github.com/http-kit/http-kit): Simple, high-performance event-driven HTTP client+server for Clojure. - [babashka.nrepl](https://github.com/babashka/babashka.nrepl): The nREPL server from babashka as a library, so it can be used from other SCI-based CLIs - [jet](https://github.com/borkdude/jet): CLI to transform between JSON, EDN, YAML and Transit using Clojure - [pod-babashka-fswatcher](https://github.com/babashka/pod-babashka-fswatcher): babashka filewatcher pod - [lein2deps](https://github.com/borkdude/lein2deps): leiningen to deps.edn converter - [cljs-showcase](https://github.com/borkdude/cljs-showcase): Showcase CLJS libs using SCI - [babashka.book](https://github.com/babashka/book): Babashka manual - [pod-babashka-buddy](https://github.com/babashka/pod-babashka-buddy): A pod around buddy core (Cryptographic Api for Clojure). - [gh-release-artifact](https://github.com/borkdude/gh-release-artifact): Upload artifacts to Github releases idempotently - [carve](https://github.com/borkdude/carve) - Remove unused Clojure vars - [4ever-clojure](https://github.com/oxalorg/4ever-clojure) - Pure CLJS version of 4clojure, meant to run forever! - [pod-babashka-lanterna](https://github.com/babashka/pod-babashka-lanterna): Interact with clojure-lanterna from babashka - [joyride](https://github.com/BetterThanTomorrow/joyride): VSCode CLJS scripting and REPL (via [SCI](https://github.com/babashka/sci)) - [clj2el](https://borkdude.github.io/clj2el/): transpile Clojure to elisp - [deflet](https://github.com/borkdude/deflet): make let-expressions REPL-friendly! - [deps.add-lib](https://github.com/borkdude/deps.add-lib): Clojure 1.12's add-lib feature for leiningen and/or other environments without a specific version of the clojure CLI

Published: 2025-05-02

Tagged: clojure oss updates

Archive