CLI tool
glojurelang/glojure avatar
glojurelang/glojure

Glojure runs Clojure on Go without giving up Go values

Clojure interpreter hosted on Go, with extensible interop support.

730 stars17 forksGoEPL-1.0

At a glance

What is it?
Glojure is a Clojure interpreter hosted on Go, so any Go value can be used as a Glojure value and the reverse. The project is explicit that it is in early development with no backwards compatibility promise before a v1 release, which defines who should try it.
Who is it for?
Adopt Glojure if you want Clojure syntax over Go libraries without a JVM, or if you want to script a Go service, and keep it out of production paths that depend on stable behaviour, because the project states that backwards compatibility is not guaranteed until a v1 release.
Can I use it commercially?
Yes, with conditions. EPL-1.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A hosted language means Go values and Clojure values are the same thing

The central design claim is on the first lines of the README. Glojure is an interpreter for Clojure, hosted on Go, and it provides easy access to Go libraries, similar to how Clojure provides easy access to Java frameworks.

The important qualifier is the word hosted, and the README is explicit about the difference. Unlike most other Go implementations of Clojure, Glojure is a hosted language, a term used to describe languages that are implemented in terms of a host language. This means that all Go values can be used as Glojure values and vice versa.

That is a genuinely different approach from the alternative. The usual way to run Clojure-like code on Go is to translate the semantics into Go and accept that the host's values have to be wrapped or reified at the boundary. A hosted implementation avoids the wrapper: a Go struct returned from a Go library can be handed straight to Clojure code, and a Clojure value can be passed into Go without conversion.

The price is stated just as plainly. Glojure is in early development, and the documentation says to expect bugs, missing features and limited performance. It is used successfully in hobby projects and runs a significant subset of the transformed core Clojure library. Significant subset is doing a lot of work in that sentence, and that is the honest framing for anyone evaluating it.

Installing glj requires Go 1.24 and produces one binary

Glojure is currently available from source for all platforms where Go can run, and the prerequisite is stated twice: Go version 1.24 or higher, and at least go 1.24 for the tool itself. The go.mod file confirms it with a go 1.24 directive.

Installation is a single go install invocation, which is the whole of it.

bash
$ go install github.com/glojurelang/glojure/cmd/glj@latest

That puts a glj command on your PATH, and starting it gives a familiar Clojure prompt.

bash
$ glj
user=> (println "Hello, world!")
Hello, world!
nil
user=>

The prompt is user=>, evaluation is immediate, and the result of println is nil, which matches standard Clojure behaviour. The REPL can also be opened in the browser, since the README links to a hosted instance at the glojurelang.github.io site.

Two other flags exist for one-off work. The help output is reachable through glj --help or glj -h, and the version flag prints a banner. Note that the README still shows glojure v0.3.0 as the version output, while the recent release tags are v0.7.24, v0.7.23 and v0.7.22. The documentation example is simply out of date, which is worth knowing before you treat the README as a reference for expected output.

The REPL is a readline front end with real editing features

The interactive REPL is more than a bare loop, and the README lists the features it implements. Editing modes include vi and emacs, with vi as the default and configuration through ~/.inputrc. Incomplete expressions continue on the next line with auto-indent, which is what makes multi-line forms usable.

Tab completion covers symbols, namespaces and aliases, with descriptive labels attached. Smart indentation is defined precisely: Tab inserts two spaces and Backspace removes a full indent level. History is persistent and saved to ~/.glj_history across sessions, so your previous definitions are still there tomorrow.

Three more behaviours are worth knowing about. Bracketed paste means pasting a block of code inserts it instantly rather than line by line. Job control is present, so Ctrl+Z suspends and fg resumes cleanly. Ctrl+C interrupts, cancelling input or stopping an evaluation in progress.

This front end is built on github.com/gloathub/go-readline, which appears as a direct dependency in go.mod. That dependency explains the vi and emacs modes, the readline config file and the line editing behaviour, and it also means the editing experience is not the one you get from a Java or Clojure jar-based REPL. If your muscle memory expects the clj style editing keybindings, they will not be identical.

glj -e and script files cover the non-interactive paths

A REPL is a poor fit for CI, so Glojure offers two ways to run code without a person at the keyboard. The -e flag evaluates an expression given on the command line.

bash
$ glj -e '(println "Hello, World!")'
Hello, World!
$ glj -e '(apply + (range 3 10))'
42
$ glj -e '
(defn factorial [n] (if (<= n 1) 1 (* n (factorial (dec n)))))
(factorial 5)'
120

The last example shows a multi-line form passed in a single quoted argument, which works because the reader keeps reading an incomplete expression until it is balanced.

The second path is a script file, and the file name convention is plain: a script named hello.glj.

clojure
;; hello.glj
(println "Hello," (first *command-line-args*))
bash
$ glj hello.glj World
Hello, World

Command line arguments arrive in the usual Clojure place, *command-line-args*. Nothing is compiled to a separate artefact, the script is interpreted at run time, so the file you pass is the file that runs.

The third path is a script that is meant to be executable in its own right, and the README shows a program that starts an HTTP server on port 8080 using the net:http namespace, with the namespace declared in an ns form.

require-deps pulls a Maven library without a JVM

The most surprising capability is dependency handling. Glojure embeds the ClojureStar dependency facade and the Grenadine resolver, which means a script can acquire a Maven library and import its namespace without a JVM anywhere in the picture.

clojure
(require '[clojurestar.deps :refer [require-deps]])

(require-deps
 ["mvn:dev.weavejester/[email protected]/medley.core" :as medley])

(println (medley/index-by :id [{:id 1} {:id 2}]))

The coordinate format is a string with an mvn: prefix, a group and artefact, a version and a namespace path. Literal libspec vectors do not need quoting, while quoted vectors remain supported. require-deps accepts Maven, Gist and GitHub source-file coordinates, with either :as or an explicit :refer list.

The resolver configuration is explicit and ordered. For Maven, the repository is chosen from an explicit :mvn/local-repo or :local-repo, then GLOJURE_MAVEN_REPOSITORY, then GRENADINE_MAVEN_REPOSITORY, and finally $HOME/.m2/repository. The Git, Gist and GitHub source cache root resolves from :gitlibs/dir or :gitlibs-dir, then GLOJURE_GITLIBS_DIR, GRENADINE_GITLIBS_DIR, GITLIBS, and finally $HOME/.gitlibs. Gist and GitHub sources live under gist/ and github/ in that root, and require-deps also accepts :cache-dir as a compatibility alias.

Two boundaries are stated. Glojure ships org.clojure/clojure and org.clojure/clojurescript itself, so those coordinates are terminal and their artifacts and transitive dependencies are not acquired. And a selected GitHub or Gist source file must be self-contained and begin with an ns form, because the resolver loads single files rather than repositories of namespace definitions.

Embedding the interpreter and cutting the binary down with glj_aot_runtime

Glojure can also be embedded within Go applications, and the README lists the use cases: scriptable configuration, letting users extend the application with Clojure plugins, mixing Go performance with Clojure expressiveness, and controlling the execution environment with custom I/O or sandboxing. The last of those is the one most specific to a hosted design, since the interpreter is running inside your process rather than in a sidecar.

There is a build tag for shipping a trimmed binary. Applications that ship precompiled namespace loaders can omit development-only runtime features.

sh
go build -trimpath -tags glj_aot_runtime -ldflags="-s -w" ./cmd/myapp

The trade-off is precise in the documentation. The glj_aot_runtime tag retains evaluation, clojure.core and file I/O support required by core functions such as slurp and spit. It omits the Go source generator, the broad default Go export registry, fallback standard library source, HTTP URL I/O, and precompiled loaders for optional namespaces.

Omitting the last item is the catch. Any optional standard-library namespace your executable needs has to be imported explicitly, with blank imports for the generated application loader and for each namespace.

go
import (
    _ "example.com/myapp/generated/example/app"
    _ "github.com/glojurelang/glojure/pkg/stdlib/clojure/math"
    _ "github.com/glojurelang/glojure/pkg/stdlib/clojure/set"
    _ "github.com/glojurelang/glojure/pkg/stdlib/clojure/string"
)

A namespace that is used but not imported is simply absent from the build, and the failure appears at run time rather than compile time.

Version 0.x with a moving target and an EPL licence

Maintenance activity is clear. The last push was on 2026-10-19, and three releases landed close together: v0.7.22 on 2026-10-13, v0.7.23 on 2026-10-19, and v0.7.24 on the same day as the last push. The default branch is main and the repository is not archived.

The version number is the thing to plan around. Everything is on 0.x, and the README states that backwards compatibility is not guaranteed until a v1 release. In practice that means a 0.7.x upgrade can change behaviour that your scripts depend on, and that the interpreter, the standard library namespace set and the dependency resolver are all still moving.

The build system also reaches outside the repository. The Makefile pulls in an external make toolkit from a separate repository on first use, and it builds the standard library from transformed Clojure sources under scripts/rewrite-core/originals, with CLOJURE-STDLIB-SOURCE-VERSION pinned at 1.12.4 in the Makefile. A list of ahead-of-time compiled namespaces is enumerated there too, including clojure.core.async, clojure.template, clojure.test, clojure.walk and clojure.uuid.

The licence is EPL-1.0, with a LICENSE.md file at the root of the repository. That is a weak copyleft licence, and for a language implementation it is the licence other Clojure-adjacent projects also use. The practical note is that a distribution bundling the interpreter carries obligations the MIT licensed tool would not, so an organisation with a policy on copyleft dependencies needs to read the licence text before shipping it.

Editorial conclusion

Adopt Glojure if you want Clojure syntax over Go libraries without a JVM, or if you want to script a Go service, and keep it out of production paths that depend on stable behaviour, because the project states that backwards compatibility is not guaranteed until a v1 release. Before committing, run glj --version against the release you pinned, since the README still shows glojure v0.3.0 while the recent tags are v0.7.24, and check that the go.mod requirement of Go 1.24 matches your build images.

Frequently asked questions

How do I install glojure and start the REPL?

Install it with go install github.com/glojurelang/glojure/cmd/glj@latest, which requires Go 1.24 or higher, then run glj to get the user=> prompt.

What does it mean that glojure is a hosted language?

It means the interpreter is implemented in terms of Go, so all Go values can be used as Glojure values and vice versa, unlike other Go implementations of Clojure that keep the two value worlds separate.

Can glojure load Maven libraries without a JVM?

Yes. Glojure embeds the ClojureStar dependency facade and the Grenadine resolver, so require-deps can acquire a Maven, Gist or GitHub source-file coordinate and import its namespace. org.clojure/clojure and org.clojure/clojurescript are shipped by Glojure itself and are terminal coordinates.

Is glojure stable enough for production use?

The README says Glojure is in early development and to expect bugs, missing features and limited performance, and that backwards compatibility is not guaranteed until a v1 release. It says the project is used successfully in hobby projects and runs a significant subset of the transformed core Clojure library.

What licence does glojure use?

The project is licensed under EPL-1.0, with the terms in the LICENSE.md file at the root of the repository.

Official sources

  1. glojurelang/glojure on GitHub
  2. Issues
  3. License: EPL-1.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/glojurelang-glojure.svg)](https://hysenlabs.com/projects/glojurelang-glojure)

Was this useful?