OSS updates July and August 2026
In this post I&aposll give updates about open source I worked on during July and August 2026.
To see previous OSS updates, go here.
Sponsors
I&aposd like to thank all the sponsors and contributors who make this work possible. Without you, the projects below would not be as mature or would not exist or be maintained at all! So a sincere thank you to everyone who contributes to the sustainability of these projects.

Current top tier sponsors:
Open the details section for more info about sponsoring.
If you want to ensure that the projects I work on are sustainably maintained, you can sponsor this work in the following ways. If you work for a company that uses my OSS, please ask your employer, that would be even better. Thank you!
- GitHub Sponsors
- The Babashka or Clj-kondo OpenCollective
- Ko-fi
- Patreon
- Clojurists Together
Updates
In the past two months it was summertime in Europe. Due to a couple of heatwaves, it was the perfect time to spend inside and enjoy my new air conditioning, while coding ;-).
The first half of July was mostly spent on improving performance and compatibility of SCI on CLJS. SCI now JIT-compiles interpreted function bodies to JavaScript at runtime, which closes a lot of the gap with compiled ClojureScript: a tight numeric loop went from ~175ms to ~7ms, over 20 times faster than the interpreter. Implementing core protocols on custom types now also works. There&aposs hardly anything you can&apost do in SCI that you can do in compiled CLJS. I released new versions of scittle and nbb that take full advantage of this.
Also in the middle of July, clj-kondo got a pretty cool enhancement. It infers types of function arguments from how they are used. E.g. when you write (defn foo [x] (inc x)) we can infer that foo is a function that takes a number. I took this principle as far as I could while preventing false positives. Of course, clj-kondo supports the latest Clojure 1.13 destructuring changes too.
In the second half of July I spent significant time on improving babashka tasks with automatic help and completions, backed by babashka.cli. You can read all about that in this blog post: Babashka tasks with automatic help and completions
In August I had the pleasure of giving a talk about Reagami at Func Prog Sweden. In the talk I gave an interactive demo of how to use Reagami in a Squint project through a REPL. I also went into detail on the algorithm that powers the fast DOM diffing. While preparing for the talk, I added SSR to Reagami too. You can view the talk on YouTube:
The last few weeks of August I created babashka.ffi, a new namespace in babashka to call C libraries. See my previous blog post: Babashka 1.13.220 gets FFI. To validate the design I wrote four libraries with it: babashka.sqlite, babashka.duckdb, babashka.postgres and filewatcher. Each one exercised a different corner of the API, along with some examples based on raylib. PacMan is particularly cool:

Right now I&aposm looking forward to giving a babashka workshop at the Clojure/conj together with Rahul Dé. We&aposre still polishing the workshop material behind the scenes and I&aposm excited to see how it&aposs turning out. I&aposm sure it&aposll be a lot of fun and hope to catch many of you there.
In between all of this, I also worked on squint. It now supports the core protocols, so you can plug in your own collections and use them with core functions. E.g. you can use Immutable.js with Squint. I&aposm thinking about lightweight immutable persistent data structures for squint, but so far I haven&apost had much need for them, outside of Advent of Code puzzles.
The above was all about making existing projects better. But I also had a few new creative ideas:
- Choq: Cherry hosted on QuickJS, nREPL included.
- Buzz: a cross client-server framework that lets you write web-apps on the JVM or babashka without any JS tooling, while still having full JS expressivity via Squint. I wrote tube-pod and multi-snake with it.
- Cljbang.el: A Clojure-like language that runs as Emacs Lisp
Here are some highlights per project. See each project&aposs CHANGELOG.md for the full list.
Babashka: native, fast-starting Clojure interpreter for scripting.
- 1.13.220: Add experimental
babashka.ffi: call C functions in shared libraries straight from babashka and JVM Clojure! See the guide - 1.13.220: On Linux, the install script installs the dynamic binary by default. It installs the static binary on musl systems and on systems with glibc older than 2.17. The
--staticand--dynamicoptions override the automatic selection - 1.13.220:
:exec-argscan sit directly on a task, not only under:cli, the way(exec ...)already reads it. Before, it was ignored on an:exec-fnor:cmdtask - 1.13.220: A task&aposs
:clispec adds to the runner-level:tasks {:cli {:spec ...}}instead of replacing it. An option from the runner level keeps its coercion and default, and--helplists it underInherited options - 1.13.220: A task with
:exec-fnruns when another task:dependson it. Before, it did nothing - 1.13.220: Options declared by an
:exec-fntask named in:dependsalso parse for the CLI task that runs, with their coercion and default.--helplists them underInherited options - 1.13.220:
:cmdcan be a symbol naming a var that holds the command tree, like:cli. Its namespace loads on demand - 1.13.220: Shell completion offers inherited options (via
:depends) too - 1.13.220: SCI: call site caching for instance and static methods, constructors and fields. Interop calls are up to 5x faster
- 1.13.219: Tasks get automatic
--helpand shell completions, through the new:exec-fnand:cmdkeys. See the blog post! These task keys should be considered experimental and may change in a future version of babashka, depending on feedback from the community - 1.13.219: Clojure 1.13 map destructuring:
:keys!,:syms!,:strs!,&inside a directive,:select,:alland:defaults. Addsreq!andsome-valstoclojure.core - #1321: support implementing the
clojure.core/Instprotocol on records, types and reify, and withextend-protocolandextend-type - #2054: a
proxyofjava.io.Writersupports the one-argumentwriteandappend, so binding*out*to it works - #1918: fall back to
$HOMEwhen the OS does not supply a home directory, e.g. for LDAP users in the static binary - #1994: fix
:evaland:printoptions ofclojure.main/replbeing ignored in the interactive REPL (@jeroenvandijk) - Bump jline to 4.4.0: security hardening, a rewritten signal path for the FFM terminal, Kitty keyboard protocol
- #2021: bump http-kit to 2.9.0-beta4, which fixes four security advisories
- Class additions by @weavejester (#1985, #1986, #1987, #1988), @paintparty (#1982) and @christoph-frick (#2003)
- Full changelog
- 1.13.220: Add experimental
babashka.ffi: call C functions in shared libraries from Clojure. New library, also usable from JVM Clojure. See the guide and the examples. The API is experimental
babashka.sqlite: SQLite for babashka through
babashka.ffi- Uses the SQLite shared library that macOS, Linux and Windows already ship with, so there is nothing to install
with-conn, queries, aggregates, transactions,last-insert-rowid, interrupt, andcreate-function!for defining a Clojure function callable from SQL- CI green on three operating systems
babashka.duckdb: DuckDB for babashka through
babashka.ffi- Query CSV files directly with SQL, results as Clojure data
- HoneySQL support, thread safety, prepared statement cleanup
babashka.postgres: PostgreSQL for babashka through
babashka.ffiand libpqconnect,close!,with-conn,query,execute!,with-transaction,in-transaction?,cancel!,json,jsonb,version,server-version- Vectors map to arrays in both directions, maps map to JSON. Bring your own JSON library through
:read-jsonand:write-json - clj-kondo export with a
with-connhook, CI on three operating systems
filewatcher: watch files and directories from babashka
- Built on
babashka.ffi: FSEvents on macOS, inotify on Linux,ReadDirectoryChangesWon Windows, and polling everywhere - The same event types on all three platforms, modeled after chokidar
- A watcher keeps the process alive until
close
- Built on
SCI: Configurable Clojure/Script interpreter suitable for scripting
- ClojureScript JIT compilation. SCI on CLJS compiles interpreted function bodies to JavaScript at runtime via
js/Function. This is enabled by default and needs no configuration. When JIT is enabled, loops and numerical computations become much faster (and, in unrestricted contexts, JS interop too) - When
evalis unavailable (e.g. under a Content Security Policy) SCI falls back to the interpreter. Results, error messages and error locations should be identical. And of course, it works under:advancedcompilation - You can turn JIT off at runtime with
js/globalThis.SCI_DISABLE_JIT = truebefore loading SCI, or in your Google Closure compile settings with:closure-defines {sci.core/disable-jit true} - More CLJS JIT performance improvements. Up to 20x on arithmetic-dense code for >2 arity. Keyword lookups,
instance?and js globals no longer fall back to the interpreter - ClojureScript: native protocol support (#639). SCI code can implement CLJS protocols on
deftype,defrecordandreify, and host code calling protocol methods on such instances dispatches into the sci implementations. Works under:advancedcompilation - #1063: CLJS:
deftypeanddefrecordfields are JS accessors on the type&aposs prototype:(.-field x)works on instances,(set! (.-field x) v)mutates deftype fields - New
:unrestrictedoption oninitandeval-string: whentrue, evaluated code may mutate built-in vars and CLJS instance interop skips:classeschecks. The option applies only to the context it was passed to - BREAKING:
enable-unrestricted-access!now throws. Use the:unrestrictedoption instead. The old function set a process-global flag that leaked into nested contexts - Support async functions by adding
:async truein the attr map ofdefn - Caches resolved JVM instance methods per call site for performance
- Fix babashka#2030:
aseton a primitive array was reflective and 170x slower thanaset-double - Errors thrown inside a
loopnow report a located stack frame for theloopform instead of a frame without location (all platforms, including babashka) - Full changelog
- ClojureScript JIT compilation. SCI on CLJS compiles interpreted function bodies to JavaScript at runtime via
clj-kondo: static analyzer and linter for Clojure code that sparks joy.
- Type checker: infer the type of a function param from how it is used in the body. E.g.
(defn f [s] (subs s 1)) (f 42)will warn, since the evidence(subs s 1)tells us thatsshould be a string. - Type checker: infer the value type of a destructured map key from how it is used in the body. E.g.
(defn f [{:keys [x]}] (inc x)) (f {:x "foo"})will warn. A key whose use rejects nil and that has no:ordefault is required. - Type checker: a destructured binding gets the value type of its key when the map&aposs type is known, including through function return maps. E.g.
(defn cfg [] {:port "8080"}) (let [{:keys [port]} (cfg)] (inc port))will warn. - Type checker: a key missing from a map literal is provably nil, also through destructuring, keyword access chains and function return maps. E.g.
(inc (:y {}))will warn. - Type checker: narrow the type of a local in the then-branch of
ifor the body ofwhenwhen it is guarded by a known predicate. E.g.(if (string? x) (inc x) ...)will warn. - Built-in analysis now uses Clojure 1.13.0-alpha4. Param type inference over the core sources grows the arg type coverage of
clojure.corefrom 23 to 150 vars. E.g.(interleave 1 [2])and(mod "a" 2)will warn. - #721: NEW linter:
:constant-condition: warn on a condition whose truthiness is the same on every run. On by default. Replaces:condition-always-true, whose config and ignores still apply to always-true conditions, and takes over thecondcatch-all warning from:unreachable-code - Clojure 1.13 CLJ-2961: infer required keys from
:keys!,:syms!and:strs!and report them at call sites - #2874: Clojure 1.13 CLJ-2964: support
:selectin map destructuring. The bound map&aposs keys are known to the type checker - Clojure 1.13 CLJ-2966: support
:defaultsin map destructuring, error when used without:or - #2943: Type checker: when an
:analyze-callhook rewrites a call, clj-kondo checks the arity of the original function but not its parameter types. - #2900:
:discouraged-var: new per-var:positionsoption (a set or vector of:calland/or:value) to limit the warning to call position or value position. A var passed to a higher-order function such asmapcounts as:value. - #2851: NEW linter:
:seq-rest: suggest using(next x)over(seq (rest x)). Defaults to:off(@tomdl89) - #1882: built-in support for
clojure.test.check.clojure-test/defspec - #2877: warn when
#_before an unmatched reader conditional discards the next form. E.g.[#_#?(:cljs 1) 2]reads as[]in:cljand will warn. - Vars defined in
commentforms no longer count for:shadowed-var,:unused-private-varand:inline-def. - Performance: use a record for var usages: 13.5% less allocation, ~5-10% faster linting. More performance work by @alexander-yakushev
- The minimum Clojure version to run clj-kondo on the JVM is now
1.11. - Full changelog
- Type checker: infer the type of a function param from how it is used in the body. E.g.
babashka CLI: Turn Clojure functions into CLIs!
- #197:
:positionalspec marker: positional args get their ownArguments:help section and may not be passed as options - #197:
:restrict-args: error on positional args not consumed by:args->opts - #219:
:cmd-aliaseson a table entry or tree node gives a command one or more alternative names. - A short option that declares a non-boolean
:coercetakes the rest of its token as its value, like getopt:-J-Dfoo=barbinds"-Dfoo=bar",-p80binds80. Flag letters may precede the valued option in a cluster: with:ba flag and:avalued,-ba xparses as-b -a x - #216: in a cluster of flags, where no letter takes a value, an interior hyphen is an error instead of silently ending option parsing.
- Help: show the dispatch-level
:specoptions underInherited options:. The parser always accepted these options, but help did not show them - Help:
format-command-helpaccepts:spec, the dispatch-level spec, so a standalone call shows the same options asdispatch dispatch: the command named on the command line wins over the:exec-argsof its ancestors. A value the user typed at an ancestor level still wins over both- Add ordered
:enumvalues for validation, help and completion - Support
:docand:epilogas a vector of lines, joined with newlines - #198:
:cmdmay be a vector of[name command]pairs, preserving command order without:cmd-order - #199: fix hang on variadic arguments that weren&apost "collected" (e.g.
(repeat :k)) - #203:
parse-opts*resolves:specso its:coerce/:collectentries steer parsing like inparse-opts - Completion: the fish snippet registers with
--keep-order, so fish offers options in the order they are emitted, long option before its short alias, rather than sorting short options first - zsh completion: offer a command&aposs options without typing a dash first, by opting the registered program names out of zsh&aposs
prefix-neededstyle - Thanks to @lread for continued documentation review and maintenance
- Full changelog
- #197:
Squint: CLJS syntax to JS compiler
- Preparatory release before adding immutable + persistent collections in
squint.immutable. Added a lot of protocols and made sure core functions work properly with them - Add the
ILookup,IAssociative,IMap,ICounted,IKVReduce,ICollection,IEmptyableCollectionandIEquivprotocols.get,assoc,contains?,find,dissoc,count,reduce-kv,conj,emptyand=dispatch to them on custom types. Plain objects and arrays keep their fast paths - Add the
IStack,IIndexed,IVector,IWriterandIPrintWithWriterprotocols,write-all, and anITransientVector-pop!slot;nth,peek,pop,pop!,subvec,vec,vector?,sequential?,set?,map?,seq,=and printing dispatch to custom collection types - Add
equiv,hash,hash-ordered-coll,hash-unordered-colland theIHashprotocol.hashfollowsequiv: plain mutable objects and arrays hash by reference - Add the
IMetaandIWithMetaprotocols;metaandwith-metadispatch through them and the internal meta symbol property is gone clojure.setdispatches through the collection protocols: results keep the input&aposs type, membership tests against a protocol set are value-based, andrename-keys/map-invertno longer mutate a record- Add
defrecord,record?and theIRecordmarker protocol. Records store their fields as own string-keyed properties and implement the map-facing protocols, so keyword lookup,keys,seq,assoc,conjand=work through the regular core functions.assockeeps the record type,dissocof a basis field gives a plain map, printing gives#TypeName{:a 1} - Clojure 1.13 destructuring:
:keys!/:syms!/:strs!for required keys,&inside them for keys required but not bound,:select,:all,:defaults, and:orby key - Fix #975:
& {:keys [...]}now destructures a map instead of the raw rest args, and a seq destructured as a map is read as kwargs - Fix #977:
recurinsidetryno longer emits an illegalcontinue - Support
:as-aliasinns:requirelike CLJS: no runtime import, only a compile-time alias so a namespaced keyword such as::alias/xresolves - Add
:require-globaland:refer-globaltons, binding globals loaded via a script tag to consts without emitting an import - Add
:squint/compile-timeopt-in mechanism for macro/compile-time namespaces. See doc/compile-time.md - A
defmacrois compile-time only: no longer emitted to the runtime module, and:refering a macro no longer emits a runtime import for it, matching CLJS - The CLI reports the file, line and column of a compile error and exits non-zero, instead of dumping the raw exception
- Fix #957: vite HMR: support
^:dev/after-load+^:dev/before-loadhooks similar to shadow-cljs .indexOfon a lazy seq now uses reference equality like a JS array, not value equality. This diverges from CLJS but keeps=out of any bundle that only builds lazy seqs, shrinking aconjbundle from 3801 to 2215 bytes- Use
Symbol.forfor protocol method dispatch, so pulling in multiple copies of squint.core (e.g. via http://esm.sh/) does not break protocol dispatch - Full changelog
- Preparatory release before adding immutable + persistent collections in
Cherry: Experimental ClojureScript to ES6 module compiler
- Add
cherry.testwithclojure.test-compatible testing API, requirable ascljs.testorclojure.test cherry.test/reportis a multimethod dispatching on[*current-reporter* type]like cljs.test, so reporting can be extended withdefmethod- Add a vite plugin with browser REPL over nREPL and
^:dev/after-load/^:dev/before-loadhot-reload hooks, sharing squint&aposs implementation:import cherry from &aposcherry-cljs/vite.js&apos - Add
reify,defmulti/defmethodand thevswap!macro.#&aposfooemits foo&aposs value, like squint - Dynamic vars compile to squint&aposs box scheme, so
set!andbindingwork across ESM modules. cljs.core dynamic vars are exported as accessor boxes proxying the real var defprotocol:extend-via-metadataimpls resolve under the fully qualified method symbol, so replicant&aposs mutation-log renderer works: replicant&aposs own test suite passes under cherry- Fix
deftypeimplementing cljs.core protocols such asInst,IIterableandIAtom: their marker properties were Closure-renamed in the precompiled core and missing from the emitter&aposs core protocol set. The externs list and the set are now generated from cljs.core&aposs protocols (bb gen-externs) and the build fails on drift - Fix #190: share
PROTOCOL_SENTINELwith coexisting CLJS runtimes in the same JS realm - Share the macro scan and macro lookup with squint. Namespaces flagged
{:squint/compile-time true}load only their compile-time part into the macro environment, like squint - CLI:
--help/-h, argument validation and error messages via babashka.cli&apossdispatch, like squint. Addswatchandnrepl-servercommands, shell tab completion, and reads options fromcherry.edninstead ofsquint.edn - Fix emitted import specifiers on Windows: backslashes are normalized via the path resolution now shared with squint
- Full changelog
- Add
Choq: a ~5 MB binary running the cherry compiler on embedded QuickJS
- New project. Runs cherry inside quickjs-ng via rquickjs
- No JIT, so hot code is slower than Node.js, Bun or Deno, but the binary is small, startup is fast and memory use stays low. A Hono app serves around 30k requests per second locally, using less memory than the same app on Node.js or Bun
- An install script for macOS, Linux and Windows, and dev release binaries
- Clojure git and Maven deps, a module table covering
urlandutil,@babashka/fs, and a test runner - Experimental
Buzz: write a web application with the JVM or babashka only
- New project. Server state is watched and updated from client code. The UI compiles through squint and renders with Reagami, so no ClojureScript toolchain and no Node.js
- Rendering is asynchronous by default and coalesces at 20ms, and a failing render is contained to its own connection
- Examples: a whiteboard, a tap viewer, and a Datalevin browser with a CodeMirror query editor
- Highly experimental, the API will change
tube-pod: turn YouTube videos into a private podcast
- New project, written with Buzz. Add a link in the browser, tube-pod downloads the audio with
yt-dlp, writes an RSS feed and serves both - Rsyncs the audio and the feed to a remote after each change, since a laptop is asleep when you want to listen
- New project, written with Buzz. Add a link in the browser, tube-pod downloads the audio with
multi-snake: snake for as many players as show up
- New project, written with Buzz. Everyone plays on one board, in one world, held in one atom on the server
- Runs at multi-snake.michielborkent.nl
Reagami: A minimal zero-deps Reagent-like for Squint and CLJS
- Add
reagami.ssrto render hiccup to an HTML string on the JVM, Babashka, Squint and CLJS. See Server-side rendering reagami.core/render(the regular render function) now hydrates a server-rendered page. It adopts the existing DOM instead of clearing the root- Add create-reagami-app. Run
npm create reagami-app my-appto create a Vite project with hot reload and a browser nREPL - Breaking:
:on-rendernow takes a map:(fn [{:keys [node lifecycle state save]}]). Callsavewith a value to keep it for the next call, and read it back asstate. In previous versions, the hook took three arguments and its return value became the state - Move reordered nodes with
moveBeforewhere the browser has it, so a moved subtree keeps its iframe state, animations, focus and selection (#54) - Set
value,checked,selectedanddisabledon a tag with a hyphen as attributes, not as JS properties. A custom element observes attributes, so a property never had any effect. Native elements still handle them as properties - Custom events, e.g.
:on-rated, now reach the element throughaddEventListener, because a browser only wires anon*property for standard events - Add web component example. A
<todo-list>custom element, used from Squint, from JavaScript with and without Reagami - Fix memory leak with
:on-rendernodes and other:on-renderimprovements - I gave a talk about Reagami at Func Prog Sweden
- Add
cljbang: a Clojure-like language that runs as Emacs Lisp
- Compiles Clojure forms to Emacs Lisp forms and evaluates them in the running Emacs. No subprocess and no transpiled text, following the same approach as squint
- Namespaces with per-namespace aliases, multiple arities in
fnanddefn,loop/recurwith a tail position check,try/throw/ex-info,case, atoms, syntax quote including nesting,&formand&envin macros, regex and set literals,#_,edn/read-string,slurpandspit el!for calling Emacs Lisp names that are not valid Clojure symbols
nbb: Scripting in Clojure on Node.js using SCI
- ClojureScript JIT compilation. Nbb now bundles a SCI that compiles interpreted function bodies to JavaScript at runtime via
js/Function. This is enabled by default. This makes loops, numerical computations and JS interop much faster - Nbb now ships babashka.fs as a built-in library. The full file system API (
glob,copy,move,create-dirs,delete-tree,with-temp-dir, path helpers and more) is available via(require &apos[babashka.fs :as fs]), matching Babashka - Support implementing CLJS protocols (e.g.
ILookup, etc) ondeftypeanddefrecord - Support editscript: CLJS
deftype/defrecordfield interop,set!on^:unsynchronized-mutablefields, addcljs.coretype classes likePersistentHashMap,write-allandgoog.math.Long - #416: Fix problem with
prnin nREPL - SCI now covers most CLJS capabilities, so nbb should run existing CLJS libraries unless they rely on very specific macros that require the JVM. If you have anything that does not run, please report it in #nbb!
- ClojureScript JIT compilation. Nbb now bundles a SCI that compiles interpreted function bodies to JavaScript at runtime via
Scittle: Execute Clojure(Script) directly from browser script tags via SCI
- ClojureScript JIT compilation. Scittle now bundles a SCI that compiles interpreted function bodies to JavaScript at runtime via
js/Function. This is enabled by default - Include helitorus demo to show improved JIT
- Bump
reagentto 1.2.0,re-frameto 1.4.7,replicantto 2026.06.2 andshadow-cljsto 3.4.11
- ClojureScript JIT compilation. Scittle now bundles a SCI that compiles interpreted function bodies to JavaScript at runtime via
squint-inline: write squint functions and inline expressions in a ClojureScript project
- New project. Squint operates on JavaScript objects and arrays, so
assoc,update-inandselect-keyswork on those withoutjs->cljandclj->js - Squint core is tree-shaken through
:js-provider :import, and each function&aposs tree-shaken size is recorded - Squint functions can call each other across namespaces, and JS module references work inside squint bodies
- New project. Squint operates on JavaScript objects and arrays, so
Edamame: configurable EDN and Clojure parser with location metadata and more
- Speed up parsing by holding parse context in record fields instead of the extmap: ~10% faster on JVM, ~4% on ClojureScript
- Respect
:refer+ rename in:auto-resolve-ns - With
:auto-resolve-ns, qualify syntax-quoted imported classes (e.g.`Datewith(:import [java.util Date])) with the full classname - With
:auto-resolve-ns, leave method, constructor and dotted syntax-quoted symbols (`.toString,`Bar.,`foo.bar) as-is, matching Clojure - Do not resolve function literal params in a syntax quote
- ClojureDart: fix parsing zero literals and make plain readers non-indexing, matching tools.reader (#144)
fs: file system utility library for Clojure
- Released 0.5.34, which ships the Node.js support mentioned in the previous update as the
@babashka/fsnpm package
- Released 0.5.34, which ships the Node.js support mentioned in the previous update as the
http-client: HTTP client for Clojure and babashka
http-server: serve static assets
- Range requests: inclusive
Content-Rangelast-pos per RFC 9110, suffix ranges (bytes=-N, previously a 500), clamping last-pos beyond EOF, reading the full range, and a test suite (@slagyr)
- Range requests: inclusive
Cream: Clojure + GraalVM Crema native binary
- Reduced the core.async virtual thread memory corruption I reported upstream to a pure Java repro. GraalVM 25.0.3-ea.04 fixes it, and the pipeline test is back on now that the compile NPE is gone too
- Enable the Ristretto JIT for runtime-loaded bytecode, and update the benchmarks for it
- Clojure code runs without a JDK present, with the boot class loader warning suppressed
- Pick up
pom.xmlwhen there is nodeps.edn, and recompile Java sources when a dependency changed
graaljs-cherry: a native-image cherry REPL on GraalJS
- New prototype. Compiles cherry expressions on the JVM and evaluates the resulting JS in an embedded GraalJS context
- Two variants: a default Truffle JIT build, and a 49MB
--smallbuild without it
clj-kondo-browser: a static Clojure source browser built from clj-kondo analysis
- New prototype. Renders a codebase as a static HTML page where every symbol links to its definition and usages, scope-aware, so a local is linked only within its scope
- Runs clj-kondo as a pod and gets the classpath from deps.clj
grasp: Grep Clojure code using clojure.spec regexes
- Babashka compatibility (#34)
deps.clj: a faithful port of the Clojure CLI Bash script to Clojure
- As always, catching up with the most recent Clojure CLI versions
lein-clj-kondo and clj-kondo-bb: released alongside each clj-kondo release
Other projects
These are some other projects I&aposm involved with, but little to no activity happened in the past two months.
- quickblog: lightweight static blog engine for Clojure and babashka
- quickdoc: Quick and minimal API doc generation for Clojure
- neil: A CLI to add common aliases and features to deps.edn-based projects
- pod-babashka-go-sqlite3: A babashka pod for interacting with sqlite3
- pod-babashka-gozxing: a babashka pod for QR code and barcode decoding/encoding
- unused-deps: Find unused deps in a clojure project
- pod-babashka-fswatcher: babashka filewatcher pod
- sci.nrepl: nREPL server for SCI projects that run in the browser
- babashka.nrepl-client
- sci.configs: A collection of ready-to-use SCI configs.
- rewrite-edn: Utility lib on top of rewrite-clj
- 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 command
- graal-build-time: initialize Clojure classes at build time for GraalVM native-image
- html: HTML generation library inspired by squint&aposs HTML tag
- qualify-methods: experimental tool to rewrite instance calls to use fully qualified methods (Clojure 1.12 only)
- 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.
- http-kit: Simple, high-performance event-driven HTTP client+server for Clojure.
- 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
- clj2el: transpile Clojure to elisp
- deflet: make let-expressions REPL-friendly!
- deps.add-lib: Clojure 1.12&aposs add-lib feature for leiningen and/or other environments without a specific version of the clojure CLI
- process: Clojure library for shelling out / spawning subprocesses
- parmezan: fixes unbalanced or unexpected parens or other delimiters in Clojure files

