Gloat Q2 Grant Halfway Report
We are halfway through the Q2 2026 Clojurists Together funding cycle, so this is a good time to report what has been done for Gloat and Glojure.
The grant officially started on May 1, but since I had learned that it was accepted a couple weeks earlier, I got too excited and decided to start working on it immediately. I was able to quickly get Glojure to pass the entire Clojure Compatibility Test Suite; except for 9 tests that are skipped as being not feasible. That gave Gloat a much stronger base to build on.
Since the start of the grant period, Gloat and Glojure have had over 20
releases, with Gloat moving from v0.1.26 to
v0.1.50.
The Glojure work was all being done on the long running fork
gloathub/glojure, but I'm thrilled to
announce that as of today, the work has been fully moved back to the upstream
glojurelang/glojure and will
continue to be maintained and released from there.
My overall ambition for Gloat is to have Clojure be as full featured and prominent to Go programming as it is to Java. The industry is crazy about Go. Let's get it crazy about Clojure.
Furthermore, given that Go cross-compiles to almost everywhere, I am bullish on Gloat being a serious alternative to GraalVM's native-image compiler. An alternative with fast compilation, expansive compilation targets (including WebAssembly) and completely open source licensing.
The Goals¶
In the funding announcement post I listed three main goals:
- Smaller, faster binaries.
- Pass the Clojure Compatibility Test Suite (CCTS).
- Tutorial docs.
The CCTS goal landed early, just before the official grant start. That did not mean compatibility was finished, but it meant the core language was good enough to shift attention toward real-world use: interop, REPLs, dependencies, docs, examples, and the missing pieces that appear when you stop testing toy programs and start trying to use the system.
The short version: the first half of the grant has been mostly about making Gloat usable and explainable.
Glojure Passed the Compatibility Test Suite¶
The most important foundation work happened in April: the Gloat/Glojure stack got to the point where Glojure passed Jank's Clojure compatibility test suite.
For Gloat, that matters because Gloat is not trying to invent a new language. The point is to take normal Clojure source, route it through Glojure and Go, and end up with Go source, native binaries, Wasm modules, or shared libraries. Every compatibility test that passes is one less place where user code can surprise us later.
After that milestone, I added a report page to the Gloat site so the compatibility state is easier to see for yourself.
The REPL Became a Real Tool¶
The most visible work this period was the REPL.
At the beginning of the cycle, Gloat was mostly an ahead-of-time compiler. You pointed it at source code and got output. That is still the center of the project, but a serious language tool needs an interactive story too.
The Glojure glj binary already had a working CLI REPL, but I really wanted
to push Gloat's CLI REPL beyond anything I'd seen to date (in any language).
gloat --repl now starts a REPL CLI with:
- Syntax highlighting w/ rainbow parens
- Multiline editing and history
- Auto-indent
- Namespace-aware tab completion
- Toggle vi/emacs readline behavior
- Persistent history with multiline selection
- Inline help
- Better startup information
- nREPL support
- Socket REPL support
- Editor integration
I also added client modes so Gloat can connect to other Clojure-family REPLs.
For example, gloat --repl=+bb, gloat --repl=+clj, and
gloat --repl=+let-go all use the same general idea: install the requested
tool if needed, start it in repl server mode and connect with Gloat's fancy UX.
You can also connect to any existing Clojure REPL with gloat --repl=12345 or
gloat --repl=.port-file.
This work was partly for Gloat itself and partly for comparison. When you are building a Clojure implementation, it is extremely useful to be able to jump between Clojure, Babashka, Glojure, let-go, and other dialects quickly.
I'm super proud of how far this CLI REPL has come so far. I hope you take some time to kick the tires and take it for a test drive. Let me know what you think!
Browser REPL¶
The REPL work also produced a browser REPL.
The Gloat website now has a Glojure REPL page backed by a WebAssembly build of Glojure. It has syntax highlighting, multiline input handling, toolbar controls, rainbow brackets, and shareable sessions.
That matters for two reasons.
First, it makes the project easier to try. People can evaluate Glojure in the browser without installing Go, Glojure, Gloat, Java, or anything else.
Second, it proves out one of the promises of the stack: Clojure code can travel through Glojure and Go into Wasm. The demo is not just a toy on the side; it exercises the same direction the compiler is trying to make practical.
My favorite part is sharable stateful URLs. Try this one!
JVM Interop Compatibility¶
The biggest compatibility expansion was JVM-style interop.
Glojure is hosted on Go, not Java, but most real Clojure code assumes at least
some java.lang behavior exists.
Even simple programs use things like Math/sqrt, System/getenv, strings,
regexes, UUIDs, numeric wrappers, and time classes.
During this period I added docs, demos, and tests around a growing Go-native Java compatibility layer, gojava. The current Java class set is:
java.lang.Mathjava.lang.Systemjava.lang.Integerjava.lang.Longjava.lang.Stringjava.lang.Doublejava.lang.Booleanjava.lang.Characterjava.util.regex.Patternjava.util.UUIDjava.lang.Thread/sleepjava.time.Instant
The goal is not to make Glojure secretly become a JVM. The goal is to make normal Clojure source behave correctly when it uses common JVM interop forms.
For example, (Math/floorDiv -7 2) should return the JVM result, not the Go
integer-division result.
(System/getenv "PATH") should feel like Clojure.
Fully-qualified java.lang.Math/abs and bare Math/abs should both resolve in
the expected way.
Fresh namespaces should have host-class imports populated in a way that matches
what Clojure programmers expect.
This is the kind of work that makes unmodified Clojure code more likely to run.
Go Interop and gljdeps.edn¶
The other side of the interop story is Go.
Glojure already has Go interop, but Gloat needed clearer Go interop docs, runnable demos, and an explicit way for Gloat programs to declare third-party Go packages.
I added a full Go interop guide covering:
- Calling Go package functions
- Calling methods
- Reading and setting struct fields
- Constructors
- Passing Glojure functions into Go higher-order functions
- Wrapping handlers
- Handling multiple return values
- Byte slices
- Reflection escape hatches
I also added runnable demo files for each of those cases.
The more important practical change is gljdeps.edn
support in AOT compilation.
Gloat now resolves deps from --deps=, GLOAT_GLJDEPS, or a local
./gljdeps.edn, passes that file through to the Glojure compile workspace, and
injects the declared modules into the generated go.mod.
For example, a Glojure program can declare a dependency on a Go module, compile through Gloat, and end up with a generated Go module or native binary linked against that Go package. That moves Gloat closer to the original promise: Clojure syntax and semantics, with access to the Go ecosystem and Go's build targets.
There is still more work needed here.
For public modules, AOT builds can sometimes succeed without gljdeps.edn
because go mod tidy can discover missing imports through the Go module proxy.
The deps file is still the reproducible path: it pins versions, supports
private/offline builds, and is required for REPL use where there is no final
go build discovery step.
Some dependency declaration and interop edges are still rough.
But the basic path exists now, and it has docs and demos behind it.
Upstream Glojure¶
Another important milestone: Gloat has moved back to upstream Glojure.
At the end of May I met with James Hamlin, the original author and owner of Glojure. He gave me full permission to maintain the project.
That is a big deal for Gloat. Since the beginning of the Gloat project I had been working on a fork of Glojure, because I needed to make a lot of changes quickly: compiler changes, runtime changes, REPL work, Java compatibility, AOT support, packaging, and release mechanics. A fork was the practical way to move fast, but it was never the ideal long-term shape.
As of today, Glojure is unforked. Gloat is using and releasing from the original upstream Glojure repository again.
One of the important things I had added on the fork was prebuilt binaries for
Linux and macOS.
That made Gloat and Glojure (glj) installs much faster, because users did not
need to build the Glojure toolchain from source on first run.
That prebuilt-binary release flow now works upstream too with the just released
Glojure v0.6.5
version.
That is the first upstream Glojure release since
v0.6.4, which
came out last October.
It means the work is no longer living off to the side in a Gloat-specific fork.
It is going back into the main Glojure project where it belongs.
The surrounding Gloat work also tightened release/development workflow around Glojure versions, local overrides, Go module replacement behavior, and local worktrees. Those details matter because Gloat, Glojure, gojava, go-readline, and the YAMLScript stdlib package all move together during development.
Documentation and Examples¶
I added a lot of documentation this period.
New or heavily expanded docs include:
The generated man pages and website docs were refreshed too.
The demos matter as much as the prose. There are now runnable examples for Go interop, Java interop, and third-party Go dependencies. Docs that only explain an idea are easy to get wrong. Docs that point to runnable files are much harder to fake.
Clojure.cc and the Wider Dialect Story¶
One unexpected side project was Clojure.cc.
I built it because Gloat and Glojure make more sense when people can see the larger Clojure dialect landscape. The site catalogs Clojure-family languages and lets people compare hosts, status, release activity, tags, and project links.
It includes Gloat, Glojure, let-go, Babashka, ClojureScript, Jank, Basilisp, Phel, Fennel, Janet, and many others. It also has instant command launchers:
$(make -f <(curl -sL clojure.cc/cmd.mk) glj)
$(make -f <(curl -sL clojure.cc/cmd.mk) gloat) --repl
$(make -f <(curl -sL clojure.cc/cmd.mk) lg) -e '(apply + (range 3 10))'
This is not the core Gloat compiler work, but it supports the same goal: make these dialects easier to discover, try, and compare. It also gave me another place to exercise the Glojure browser REPL and the multi-dialect REPL launcher work.
let-go Collaboration¶
The REPL comparison work also pulled in let-go, another Go-hosted Clojure-like language.
Gloat can now launch/connect to let-go as one of the supported external REPL targets, and Clojure.cc includes it in both the dialect catalog and the instant launcher.
The more interesting part is that the two projects are starting to challenge and inspire each other. Gloat/Glojure has been pushing hard on AOT compilation, Go interop, and Clojure compatibility. let-go, meanwhile, has a very promising performance story. It compiles to bytecode today, and the let-go team is now exploring AOT compilation by turning that bytecode into Go code.
I have been talking with let-go's author, Marcin Gasperowicz (@nooga), and with Norman Nunley, one of the main contributors working on performance. Norman and I knew each other about twenty years ago in the Perl world, so this is also a fun reconnection across language communities.
There is a real chance for collaboration here. One direction I have been thinking about is making Gloat an abstraction over both Glojure and let-go: same user-facing tool, potentially different Clojure- on-Go engines underneath. It is too early to promise that shape, but the overlap is obvious enough that it is worth exploring seriously.
What Still Needs Work¶
The original grant goal of smaller and faster binaries still needs more direct attention over the final 6 weeks of this grant.
Some groundwork is already there, especially the earlier -Xprune work for
dropping unused clojure.core code, but I have not spent enough of this cycle
yet on output size and runtime speed.
The first half pulled me toward compatibility, REPLs, dependencies, and docs,
because those were the things blocking real use and feedback.
For the second half, the main areas are:
- Continue reducing binary size
- Improve runtime performance
- Run more real Clojure programs through Gloat
- Keep expanding JVM compatibility where real code needs it
- Smooth out
gljdeps.ednand Go interop edges - Keep the docs tied to runnable examples
Thanks¶
Thanks to Clojurists Together and everyone who funds it. This kind of work needs long stretches of focused time, and the funding makes that possible.
Thanks also to the people building and maintaining the surrounding Clojure dialect ecosystem. Gloat sits in that larger context, and the project is better when it can learn from Clojure, ClojureScript, Babashka, Glojure, let-go, Jank, Basilisp, and the rest of the family.
Halfway through the grant, Gloat is much easier to try, much better documented, more compatible with ordinary Clojure code, and more connected to the Go ecosystem than it was on May 1.
Now back to making the binaries smaller and faster.