github.com/nooga/let-go
v1.12.2
#2400 most downloaded on Go modules
nooga/let-go
What this package is like to depend on
Last release 3 days ago
20 Aug 2026
Ships fairly regularly
a new release about every 2 weeks
Some releases are documented
notes for 10 of 28 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
95 releases · first in 2021
56 releases in the last 12 months
see the full history below
Release timeline
95 releases · Jun 2021 to Aug 2026Releases
latest 60 of 95-
v1.12.3-0.20260820193935-a6657612002b20 Aug 2026 pre-releaseNothing published for this version
-
v1.12.3-0.20260813013559-2fe51750045c13 Aug 2026 pre-releaseNothing published for this version
-
v1.12.3-0.20260812141234-23f3ab15b02f12 Aug 2026 pre-releaseNothing published for this version
-
v1.12.3-0.20260811171607-a9d0b230106511 Aug 2026 pre-releaseNothing published for this version
-
v1.12.3-0.20260811145021-f3ca5f9be1da11 Aug 2026 pre-releaseNothing published for this version
-
v1.12.3-0.20260720233129-14e1746d1b5d20 Jul 2026 pre-releaseNothing published for this version
-
v1.12.220 Jul 2026Release notes
Open source → -
v1.12.120 Jul 2026Release notes
Open source →let-go v1.12.1
First release since v1.11.1 (2026-06-29). 126 commits in about three weeks,
centered on one theme: running real Clojure libraries unchanged. Stock HoneySQL
now works out of the box, backed by a round of JVM host-compat and exception-
semantics work. Beyond that: a compiler-free runtime binary, a WASI build, TCP
networking, a clearer Go-interop story, substantial AOT progress, and another
round of runtime performance improvements. There are no breaking API removals;
see the upgrade notes for observable behavior changes.Run real Clojure libraries
The headline: stock HoneySQL runs on let-go unchanged (#494). Getting there
closed a long tail of JVM-compat gaps that benefit any library you try next:- Mutable
java.util.HashMapandArrayDeque(#512), static method calls
(#514), and the collection interfaces libraries expect (#510). - The
java.langexception hierarchy (#472), typed catch dispatch (#476), and
finallyblocks that run on every exit path (#474). fnsupports:pre/:postconditions (#458),defprotocolaccepts standard
options (#488), and regex match results have Clojure's shape (#456).- Top-level
(do ...)forms evaluate subform-by-subform (#470), and require
aliases are honored before thecore/*shortcut (#548).
Ahead-of-time compilation
let-go has always bundled to bytecode (
lg -c) and standalone binaries
(lg -b). This release hardens and extends that pipeline:lg-runtimeis a compiler-free binary that executes precompiled.lgb
bundles: compile on your machine, then ship only a runtime and bundle (#424).- Bundles built against a different opcode set are rejected clearly instead of
misbehaving (#443), and lowered output is deterministic (#446). - More language features lower to native Go, including lambda-lifted functions
(#479), multi-arity direct calls (#371), and fused sequence pipelines (#440). - Parameters annotated with
^doubleor^longcan use unboxed Go numerics in
the native lowering pipeline (#530, #536). - The refreshed benchmark suite compares the VM with both native-lowered and
runtime-backed AOT code, and documents why those two paths perform differently
(#552, #578, #582).
New targets round out where compiled output can run: a WASI (
wasip1)
module for any WASI host (#466), real terminal input on Plan 9 (#460, #461),
custom browser shell templates (#377), and an in-browser IR/bytecode/lowered-Go
inspector notebook (#379).Interop between let-go and Go
- Go to let-go (embedding):
api.NewLetGoplusDefhands Go values,
functions, structs, and channels to the VM. - let-go to Go (wrapping):
lginteropgenerates smart wrappers around Go
packages. The guide now walks throughdatabase/sqlend to end, and an e2e
test keeps the wrapper path honest (#537, #532, #543, #542). - Native primitives: the
//lg:nativeannotation lets Go functions back
let-go builtins directly, including standard-library hot paths (#438).
Start with
docs/guide/go-interop.md.Networking, language, and library additions
- A
netnamespace with TCP client support plusbencodeencoding and framing
(#526, #533). - Ring-style HTTP requests now expose
request-methodas a keyword (#527). update-keys,update-vals,ns-publics,find-var,get-method, and a real
PersistentQueue(#447, #384, #417, #419).- Base64 and base64url encoding, raw byte-array writes through
spit/write!,
streamingos/exec*, and function metadata (#368, #367, #371, #383). - core.async now matches Clojure for closed channels: puts return
falseand
takes returnnil(#391).
See
docs/guide/usage.md,docs/guide/net.md, and
docs/guide/clojure-compatibility.mdfor the newly expanded guidance (#550).Performance
- Dynamic var lookup is O(1) per var (#462).
- Keyword map lookup and protocol dispatch avoid boxing (#396, #568), while
vector indexing takes a direct fast path (#398). - Inferred types moved to a positional side table, making type writes roughly
100x faster in the measured lowering workload (#558). - Realized lazy-seq reads gained a lock-free path (#560);
Keyword/Int
equality and string conversion gained typed fast paths (#567, #569). - Transient maps use their growth reserve (#559), checked integer multiply
avoids division on its fast path (#571), and all timeouts share one timer
daemon instead of one goroutine each (#442).
Upgrade notes
No hard-breaking API changes, but a few things behave differently:
- Namespace cleanup: let-go-specific functions that lived in
clojure.core
moved tolet-go.coreandlet-go.types(#410). Update requires for code that
reached let-go-specific functions throughclojure.core. - Closed channels do not panic: core.async operations on closed channels now
returnfalse/nil, matching Clojure (#391). - Recompile old bundles:
.lgbbundles built by older opcode sets are
rejected at load. Rebuild them with v1.12.0 (#443). - CLI exit codes:
lgexits non-zero when a script or-eexpression fails
(#409). - Ring-style request methods:
request-methodis a keyword such as:get,
not a string (#527). - Tracing: the old
traceopcode is replaced by the dynamically scoped
*lg-trace*facility; recompile bundles and migrate direct trace usage (#407).
Full change and contributor attribution follows.
What's Changed
- fix(bench): per-goroutine sink in Parallel VarDeref benchmarks by @nnunley in #365
- examples: host-eval browser demo (client-owned shell) by @mparrett in #359
- [codex] Derive lg metadata from Go build info by @mparrett in #366
- perf(ratchet): machine-profile baseline + machine-independent alloc gate + interactive multi-machine dashboard by @nnunley in #362
- fix(json,transit): serialize Float32 instead of panicking by @mparrett in #364
- chore: remove accidentally-committed perf-page binary + gitignore it by @nnunley in #369
- fix(ir): chained-comparison lowering + ec/callErr name collision in gogen by @nooga in #374
- feat(rt): spit/write! accept a byte-array (write raw bytes) by @mparrett in #367
- feat(wasm): -w-shell accepts a custom HTML template by @nnunley in #377
- feat(vm): carry metadata on functions (with-meta/meta) by @abogoyavlensky in #383
- feat(rt): add ns-publics by @abogoyavlensky in #384
- fix(vm): resolve empty LazySeq to nil so reduce/some don't see a phantom nil by @nnunley in #388
- refactor(vm): drop now-dead EmptyList guards after empty-LazySeq→nil fix by @nnunley in #389
- docs(clojure-test-suite): document make jank-stress native-lowering coverage gate by @nnunley in #393
- feat(ir,build): lowering-coverage ratchet gate (ITER-0021) by @nnunley in #370
- ci(perf): arm64 timeline leg + auto-backfill of release tags by @nnunley in #363
- chore(git): recompute generated.sums on merge (dedicated 'sums' driver) by @nnunley in #375
- Multi-arity direct calls + self-host coalesce fix, os/exec* streaming, VM Box fast-path by @nnunley in #371
- feat(wasm): neutral #app host mount by @mparrett in #378
- feat(rt): base64-encode / base64-decode builtins by @mparrett in #368
- docs(perf): document the perf label / PR-time A/B workflow by @mparrett in #373
- perf(ci): wasm A/B benchmark gate (perf-wasm label) by @mparrett in #386
- feat(rt): zero-arg (read-line) reads current in by @mparrett in #406
- feat(ir): type math intrinsic call results as :float in typeinfer by @mparrett in #372
- fix(cli): exit nonzero when script or -e fails by @mparrett in #409
- async: core.async parity — buffer policies, closed-channel puts, thread, alts!! by @nnunley in #391
- fix(vm): explicit :refer shadows the clojure.core auto-refer baseline by @nnunley in #408
- chore(perf): re-baseline ir-stress corpus after upstream drift (2347 -> 2366) by @nnunley in #395
- perf(vm): box-free KeywordLookup fast path (-4% native suite allocs) by @nnunley in #396
- feat(wasm): browser-inspector notebook + in-browser IR/bytecode/lowered-Go inspector by @nnunley in #379
- fix(rt): accept padded base64url input by @mparrett in #405
- feat(vm): real clojure.lang.PersistentQueue by @abogoyavlensky in #419
- feat(rt): add find-var and get-method by @abogoyavlensky in #417
- feat(ir): lowering strategy pattern + unified ir.coverage by @nnunley in #387
- feat(ir): combinator inlining + closure devirtualization (opt-in via enable-inline) by @nnunley in #394
- perf(vm): chunked ArrayVectorSeq (growing-from-1) + orderless maps + alloc-free symbol parsing (-34.8% suite allocs) by @nnunley in #397
- perf(rt): ArrayVector direct-index fast paths — eliminate the seq-protocol tax (-19.7% suite allocs) by @nnunley in #398
- Various bug fixes by @ingydotnet in #400
- fix(compiler): allow an empty catch body with a qualified class name by @abogoyavlensky in #413
- fix(core): scope record fields in defrecord protocol-method bodies by @abogoyavlensky in #415
- feat(rt): compile-only Clojure-compat classpath-scan stubs by @abogoyavlensky in #421
- feat(ir): reach typed natives from runtime values by @ingydotnet in #432
- perf(rt/ir): stop (nth string i) allocating the rune slice; O(1) registry emptiness check (−13% lowering allocs) by @nnunley in #402
- perf(ir): transducer-fusion foundation — data-driven pass list + remove arity-1 + transduce≡lazy proof by @nnunley in #434
- perf(ir/typeinfer): worklist membership via in-place transient-map flags (−1GB cloneAndSet) by @nnunley in #403
- chore(perf): refresh ir-stress and benchmark baselines after upstream drift by @nnunley in #437
- docs(vm/allocattr): correct the single-goroutine attribution assumption by @nnunley in #439
- feat(lgbgen): self-hosting lowering — Go overrides + check-selfhost target by @nnunley in #435
- feat(gogen): math.NaN()/math.Inf() emission + go-ast read/COW import bindings by @nnunley in #430
- perf(ir): transient current-locals-flat + reduce-based every? (−270MB lowering) by @nnunley in #433
- feat(ir-stress): tool-maintained coverage baseline — make ir-stress-rebaseline by @nnunley in #404
- refactor(rt,core): purify clojure.core — let-go.core / let-go.types for lg-isms by @nnunley in #410
- fix(core): format time macro elapsed duration as msecs by @nooga in #444
- feat(bytecode): reject .lgb bundles compiled against a different opcode set by @mparrett in #443
- perf(rt): close timeout channels from one shared timer daemon by @mparrett in #442
- test(vm): stabilize BenchmarkVectorAccess — sink result + hoist key boxing by @nnunley in #454
- fix(compiler): parse empty catch bodies with simple class names by @abogoyavlensky in #449
- fix(rt): return Clojure-compatible regex match results by @abogoyavlensky in #456
- fix(core): support the partition padding arity by @abogoyavlensky in #453
- fix(rt): add compile-only Exception constructor stub by @abogoyavlensky in #451
- fix(core): support fn pre and post conditions by @abogoyavlensky in #458
- feat(rt): java.lang exception class hierarchy and constructors by @abogoyavlensky in #472
- fix(vm): run finally on abnormal exits and propagate the exception by @abogoyavlensky in #474
- Typed catch dispatch by @abogoyavlensky in #476
- fix(rt): expose key-pending? on plan9 by @mparrett in #460
- feat(rt): real Plan 9 terminal input (raw mode, read-key, key-pending?) by @mparrett in #461
- bench: YamlStar real-corpus parse benchmark + ITER-0035 gate (#352) by @nnunley in #495
- Build let-go as a WASI (
GOOS=wasip1) module by @mparrett in #466 - test(ir): build-stable op baseline for the fold-unroll pipeline tests by @nnunley in #505
- feat(core): add update-keys/update-vals by @nooga in #447
- feat(native-bridge): //lg native-primitive generation — drain hot trampolines (IRCompile −13.6% allocs) by @nnunley in #438
- chore(hooks): reject committing compiled executables (pre-commit/prek) by @nnunley in #465
- chore(ir-stress): exclude scripts/lginterop.lg from corpus — stale gogen/parse-stmts by @nnunley in #467
- fix(vm): ArrayVectorSeq.ChunkedFirst must not mutate the shared seq node (data race) by @nnunley in #463
- fix(compiler): evaluate top-level (do ...) subform-by-subform like Clojure by @nnunley in #470
- Runtime-only build: execute precompiled bytecode, no compiler linked by @mparrett in #424
- perf(vm): per-var root binding chains — O(1) bound deref (Phase 2, stacks on #459) by @nnunley in #462
- feat(ir): loop-fusion (deforestation) — pass, enabled, comp-chains + into by @nnunley in #440
- fix(ir): accept defn attr-map position in AOT lowering by @nnunley in #469
- feat(ir): legalize cross-block refs
Note truncated.
- Mutable
-
v1.12.1-0.20260720172919-c29b31152fc920 Jul 2026 pre-releaseNothing published for this version
-
v1.12.1-0.20260720164222-123ea91e9e6e20 Jul 2026 pre-releaseNothing published for this version
-
v1.12.020 Jul 2026Nothing published for this version
-
v1.11.2-0.20260706200442-cf195a67fd8a06 Jul 2026 pre-releaseNothing published for this version
-
v1.11.129 Jun 2026Release notes
Open source →Changelog
- d418eef Brew cask update for let-go version v1.11.0 (#350)
- cf9fcb6 ci(perf): track core-bundle decode (InitFromLGB) in the ratchet (#355)
- 079b9bb perf(bytecode): pre-size source-map / local-var slices on bundle decode (#354)
- 7aef577 perf(startup): exclude ir.* AOT pipeline from the bytecode bundle (#356)
-
v1.11.1-0.20260628234958-cf9fcb63b49b28 Jun 2026 pre-releaseNothing published for this version
-
v1.11.028 Jun 2026Release notes
Open source →let-go v1.11.0
First release since v1.10.0 (2026-06-08). 109 commits: a browser-runtime host-decoupling arc, native-Go IR lowering across most of the Clojure-compat surface (now emitting typed cross-namespace direct calls), terminal mouse input, and a round of VM and compiler performance work. No breaking changes.
Browser runtime and client-owned shell
The WASM host now talks to Go through typed seams instead of ad-hoc JS shims, and the embedding page can own the shell.
-w-shell nonelets the host page supply its own shell;lg-host.jsis split out so a client can drive the runtime directly (#245).-w-wasm externalships the payload as a separate streamingmain.wasmrather than inlining it (#246).- Typed host seams: output through a Go
HostWriterfor*out*/*err*(#231), aHostEmitterforjs/emit(#241), aKeySourceforterm/read-keyandkey-pending?(#244), and a host-bound storage seam (#315). js/url-paramreads a query parameter from the launch URL, so a WASM bundle can pick up configuration from the page it's loaded on (#339).- Native bundles bake a storage store id into the trailer (v3), binding a bundled app to its own storage namespace through the seam above (#336).
-w-host-evalexposesLetGoHost.eval, letting a JS host evaluate code in a live in-page image; it works in both main-thread and worker boot modes and is gated to host-eval bundles (#340).- WASM/mobile fixes: a newest-wins non-blocking key producer over a SharedArrayBuffer (#276, #279), viewport meta and
dvhheight (#291), and an overflow guard onhost.html(#277).
Language and runtime
*command-line-args*incore(#205).os/free-portreturns an OS-assigned TCP port (#209).str/replaceandreplace-firstaccept a function replacement, matching Clojure (#216).alts!takes a:defaultfor non-blocking select (#250).- Terminal SGR mouse input: enable/disable primitives and a decoder (#313).
set-rand-seed!reseeds the runtime RNG for reproduciblerand/rand-int/rand-nth/shuffle, backed by a mutex-guardedmath/rand/v2source (#341).- Profiling:
-cpuprofile/-memprofileflags, withLG_CPUPROFILE/LG_MEMPROFILEenv fallbacks for generated builds (#331).
Compiler: native-Go IR lowering
The self-AOT pipeline now lowers most of the language straight to Go.
- try/catch/finally (#222), deftype/defprotocol (#232), and set!/binding/var/quote (#249) lower to native Go.
- The jank Clojure-compat surface reaches 100% lowering coverage, gated in CI (#324, #327, #317).
- Typed direct calls: cross-namespace calls into
clojure.coreand lowered siblings now emit direct Go calls instead of dynamicInvokeValue, built on reified IR op-types and interface-category type classification (#310, #318, #320, #321, #322). The arc extends to hotclojure.corebuiltins viapkg/rt/builtins(#343), cross-package calls between lowered packages (#345), and a build-call that builds args once in callee-before-arguments order (#344). - Type-dispatched
defmulti/defmethodlower to native Go (#325). - Correctness fixes: loop bytecode lowering (#214), captured-name shadowing (#247), IIFE head expansion (#254), an O(n²) closure-info blowup that timed out AOT (#280), box-as-value in
:trylowering (#316), a fresh-regen nil inir.passes.purity(#309), and empty-list()lowering to the empty-list constant rather than invoke-nil (#342).
Performance
- Lock-free dynamic-var deref via a persistent frame-list binding stack (#220).
- O(1)-amortized
PersistentVector.pop, previously O(n) (#302). PersistentMap.Equalscompares in place instead of materializing a node seq (#300).- typeinfer runs on positional transient state rather than HAMT side tables (#301, #305, #306).
subsno longer materializes the whole string to runes (a124d2d).
Upgrade notes
No breaking changes. A few behavior changes are worth knowing if you embed the runtime:
print/pr/prn/printlnand theterm/*ANSI control ops now route through*out*, with error sites through*err*(#206, #223). Output and terminal control that previously went straight to stdout now follow whatever those vars are bound to.- New
WithStdout/WithStderroptions onNewLetGobind those streams at construction, scoped perRun(#207). - The WASM
fs.writeSyncoutput shim is retired in favor of theHostWriterseam (#231). - The source-paths transition warning and
LG_SUPPRESS_SOURCE_PATHS_WARNINGare removed (#230).
Full commit list below.
Changelog
- 8bbb572 Brew cask update for let-go version v1.10.0 (#202)
- 5acc45e feat(args): add core/command-line-args var (#205)
- 9aa5354 fix(vm): per-namespace RWMutex — make Namespace map access concurrency-safe (F-1) (#203)
- d6d0128 feat(rt): route print/pr/prn/println through out and error sites through err (#206)
- 8b6b545 feat(rt): add os/free-port — OS-assigned free TCP port (#209)
- acd4676 fix(lower-go): make gogen_ir lowering deterministic (4 axes) (#192)
- 531db14 perf(lower-go): exact-key registry resolution (resolve-then-get, no scan) (#193)
- a3572e3 feat(api): WithStdout/WithStderr constructor options (per-Run binding scope) (#207)
- 79196be build: cap Go heap (GOMEMLIMIT) for bootstrap/lowering targets, not just
make test(#215) - 1809ed0 feat(rt): str/replace + replace-first accept a function replacement (Clojure-compatible) (#216)
- c297975 build(lgbgen): single-pass --target=both — emit bundle + go tree from one compile (#212)
- 439b603 feat(vm,ir): ExecContext threading — explicit dynamic-binding + scope context, delete goid (#210)
- 02c9660 Publish Homebrew formula to shared tap (#218)
- 7beb0a4 fix(ir): correct ir-compile bytecode lowering of loops (4 defects) (#214)
- 7d37167 feat(ir): structured Go emission — CFG → if/for tree-walk (lg-dn6u) (#213)
- 45a9bdf Makefile fixes (#219)
- 605ccbd feat(build): content-based regen tracking for generated .lg artifacts (#217)
- db3c396 chore(pre-commit): add checkmake hook (#221)
- fa20c7b perf(vm): lock-free dynamic-var deref via persistent frame-list binding stack (#220)
- e314ded perf(vm): cut redundant value hashing on the lowering hot path (#224)
- 5dfa4c4 feat(lgbgen): CPU profiling for the self-AOT generation process (#227)
- 72a96a3 fix(vm): Indexed collection protocol — correct nth dispatch + chunked-seq/conj semantics (#228)
- ad8ff50 feat(resolver): LG_FORCE_SOURCE_NS for incremental .lg dev loop (#225)
- c8c7553 feat(rt): route term/* ANSI output through out (#223)
- eac88b9 feat(ir): lower try/catch/finally to native Go (gogen_ir self-AOT) (#222)
- c23bae5 chore(source-paths): remove transition warning and LG_SUPPRESS_SOURCE_PATHS_WARNING (#230)
- d4eb364 fix(nrepl): report OS-assigned port under -p 0 (#229)
- 41140ea feat(wasm): route out/err through a Go HostWriter, retire the fs.writeSync output shim (#231)
- 43ff528 docs(design): runtime I/O host-decoupling proposal (status: planning) (#233)
- 9f8df3a ci(perf-timeline): add workflow_dispatch for historical backfill (#236)
- 0d9bad4 ci(perf-timeline): resolve dispatch ref in a script step (support short SHAs) (#238)
- 49ba840 feat(ir): native Go lowering for deftype and defprotocol (#232)
- 6474580 fix(term): tolerate ENOTTY from flush Sync on a file-backed TTY (#237)
- 80683f0 build: keep the readline REPL out of GOOS=js builds (fixes #242) (#243)
- 4e3bbbd refactor(test): move e2e tests under test/e2e + pkg/bundle extraction + root-test guard (#234)
- ad24d9b perf(ir): thread typeinfer state + preserve [:dtype T]; complete numeric typing (#235)
- 9521ca4 feat(rt,wasm,api): typed HostEmitter seam — promote js/emit off the raw _lgEmit lookup (#241)
- 164e8cb feat(rt,api): typed KeySource seam — route term/read-key + key-pending? through a host capability (#244)
- 95aa9c5 feat(wasm): client-owned shell — split lg-host.js, add -w-shell none (#245)
- 7bf8f42 feat(wasm): -w-wasm external — ship the payload as a separate streaming main.wasm (#246)
- 0a87097 ci(gold-differential): pin the Clojure toolchain, drop the makeplus curl|make install (#248)
- e2aeace fix(ir): prefix closure-local arg names to prevent captured-name shadowing miscompile (#247)
- cbe5abf feat(async): alts! :default for non-blocking select (#250)
- e712fa6 docs(design): mark runtime-I/O decoupling shipped; refresh status (#261)
- 3d40e7e fix(generate): clean lowered-tree target dir before regen (hermetic generation) (#240)
- 9b844d3 fix(genmanifest): exclude generated Go from digest; gate before regen (#252)
- b9c3399 fix(ir): expand-all must expand fn-expression heads (IIFE) (#254)
- 6a0a8b4 fix(reader): read-string skips leading no-value forms (#253)
- d4c36cf fix(lang): def/declare forward-declaration promise semantics (#251)
- 23bfd87 feat(ir): native-Go lowering for set!/binding/var/quot + self-AOT diff harness; fix cluster-A engine divergence (#249)
- 83f650d fix(wasm): non-blocking SAB key producer — newest-wins, never block main thread (#276)
- 329743a fix(wasm): add min-height:0 to host.html #terminal so client content can't overflow the frame (#277)
- 6126423 perf-page: relative-% timeline charts (#278)
- d159b84 fix(wasm): drop SAB key when slot still pending, don't overwrite mid-consume (#279)
- 2a72e40 docs: focus the README, move feature how-to into docs/guide/ (slice 1) (#273)
- f7c91ee test(ir-stress): pre-declare deftype/defrecord/defprotocol generated names (#287)
- c6f65ef fix(ir): memoize closure-info* per-nid to kill O(n^2) AOT lowering timeout (#266) (#280)
- c9e6092 test(ir-stress): eval top-level (require ...) forms so deps load (#288)
- 8087f99 fix(wasm): host.html viewport meta + dvh height for mobile (#291)
- 2aa2e0c build(lgbgen): nest lowered-Go output to mirror namespace nesting (#297)
- e9bcdcd fix(ir-stress): close the (do ...) wrapper on its own line in read-all (#295)
- 5547d78 feat(gogen): elide callErr check for total keyword-callee calls (#294)
- 65882d6 feat(gogen): make the gogen macro layer usable by the IR lowering pipeline (#286)
- 1375e81 docs: reorganize docs/ — design consolidation, layout rule, pods split
- d67c739 fix(term): tokenize read-key so a key burst yields one event per key
- 46b1027 refactor(term): fold the key tokenizer into a single-pass scanner
- ba8488c perf(vm): O(1)-amortized PersistentVector.pop (was O(n) Unbox+rebuild) (#302)
- 64feeec fix(term): flush on piped stdout
- a124d2d perf(rt): subs without materializing the whole string to runes
- 5f06d34 perf-tooling(fanout): gate on lg->go expansion ratio + portable os/ls walk (#285)
- b67d684 feat(lg): add -cpuprofile and -memprofile flags
- 73ff475 feat(term): SGR mouse input — enable/disable primitives + decode (#313)
- 9665f5a perf(ir): source-infos in a positional side table, off the inst tuple (#306)
- e55bcd9 perf(ir/typeinfer): positional transient-vector state (Indexed-RPN), not HAMT side tables (#305)
- d646fdf perf(ir/typeinfer): build-deps via transients, not atom+swap!+assoc (#301)
- 1a04328 perf(vm): PersistentMap.Equals walks in place instead of materializing nodeSeq (#300)
- c3d0109 ci(pages): add workflow_dispatch trigger (#319)
- ff28da0 ci(codeql): bump CodeQL action v1→v3, checkout v2→v4, add permissions (#323)
- 892a25c feat(ir,scripts): jank lowering-coverage gate + canonical fn enumeration (#317)
- 5fc3d96 feat(rt,wasm,api): add host-bound storage seam (#315)
- 5dd810e feat(ir): lower the full jank Clojure-compat surface — coverage gate 65% → 100% (#327) (#324)
- c553565 ci(perf): same-runner A/B microbenchmark check on PRs (#328)
- 511a0bf perf-page: CPU-tier filter and selectable baseline; release-baseline recapture (#329)
- 4714b53 perf(bench-ratchet): add named -profile with a curated pr-fast profile (#330)
Note truncated.
-
v1.10.1-0.20260628062305-25ccf550558828 Jun 2026 pre-releaseNothing published for this version
-
v1.10.1-0.20260622231529-d67c7391ea3922 Jun 2026 pre-releaseNothing published for this version
-
v1.10.1-0.20260620233456-8087f9979f5120 Jun 2026 pre-releaseNothing published for this version
-
v1.10.1-0.20260609013047-9aa53549819709 Jun 2026 pre-releaseNothing published for this version
-
v1.10.008 Jun 2026Release notes
Open source →Changelog
- bdab027 Brew cask update for let-go version v1.9.0 (#139)
- 7f8d720 Minimal compatibility with
weavejester/medley(#157) - 9b7e7a1 Out-of-SSA Go lowering: lineage coalescing, dead-store elimination, const-param inlining, loop-closure capture (#142)
- ef13bac build: consolidate generated-artifact gates into
make check-generated(#162) - 60731cf build: coordinate the code-generation pipeline in scripts/generate.lg (#163)
- 2457fce build: fix + install the core_compiled.lgb merge driver; add a content freshness gate (#152)
- 6b69c99 docs(readme): document :lg reader-conditional portability convention (#132) (#161)
- 18aed18 feat(bytecode): carry local-variable names as debug info in the bundle (#131)
- c572516 feat(core): Comparable protocol + let-go.semver (versions, ranges, sha) (#160)
- 779bab8 feat(core): faithful print-method dispatch (#179)
- b27111c feat(core): hybrid ir-compile — fall back to bytecode for unlowerable defns (#191)
- af87844 feat(core): mutable deftype fields (^:mutable / ^:unsynchronized-mutable) (#135)
- a454199 feat(core): namespaced and :syms associative destructuring (#150)
- 7b0d457 feat(core): upstream clojure.core fns from the malli shim (#181)
- 2050fe8 feat(examples): revive the malli-on-let-go shim example (#172)
- 4af8cea feat(lower-go): cross-ns IFn dispatch via cached vars (rt.CachedVarFn) (#189)
- ef72a92 feat(lower-go): intra-namespace direct-call lowering (slice 1) (#168)
- 9e870fb feat(lower-go): registry-driven intra-namespace direct-call lowering (slice 2) (#188)
- fe6c6e2 feat(math): expose the math namespace as clojure.math too (#156)
- 098f55b feat(os): add os/exec* — run a command with inherited stdio (#154)
- de8d3ee feat(reader): don't require type-hint tags to resolve as vars (#141)
- d57d0cd feat(reader): match :bb reader-conditional feature (opt-in) (#136)
- 64f53fc feat(rt): 3-arg deref (blocking deref with timeout) for promises/futures (#140)
- 64501a2 feat(rt): bytecode bundle disassembler (lgb -> round-trippable EDN) (#184)
- cfb7654 feat(rt): compare-and-set! for atoms (#137)
- 6db26f2 feat(rt): lazy var roots, bound?, defonce; own-ns access to private vars (#147)
- ee129db feat(rt): pluggable host-method-dispatch seam (#138)
- 0e4e4cd feat(rt/term): wake read-key on SIGWINCH via BEL self-pipe (#165)
- 98a5d21 feat(semver): require-letgo (Layer 3) + npm/cargo range sugar (Layer 4) (#132) (#164)
- de92b59 feat(source-paths): explicit -source-paths/LG_SOURCE_PATHS fully define the search path (#199)
- fdacba3 feat(string): add clojure.string/replace-first (#153)
- 430b72d feat(tooling): fanout-ratchet — generated-code-size gate (#171)
- 7fcac88 feat(vm): make Protocol and deftype/reify instances metadata-aware (IMeta) (#187)
- 91be848 feat(vm): set-field! primitive for in-place deftype field mutation (#133)
- c71ba4d feat: Add io/resource with -resource-paths roots and -b binary embedding (#178)
- 5c5f434 feat: browser interop (js/emit + LetGoHost API) (#174)
- 664b13c feat: invokable (IFn) + derefable (IDeref) protocols (#158)
- f593010 fix(compiler): correct lexical binding resolution (#144)
- 1d906cd fix(core): binding must restore dynamic vars on non-local exit (#185)
- 81dcc4f fix(core): deftype/defrecord/reify/extend-protocol macro hygiene (#151)
- a9e35b4 fix(core): ns :require is load-only; run-tests runs each ns's tests in its home ns (#149)
- f9037fb fix(core): thread reader metadata through defmacro so ^:private works (#180)
- b0dd737 fix(lower-go): deterministic gensym naming so lowered Go is reproducible (#182)
- 9dcbdc7 fix(lower-go): unbox vm.Value -> primitive at branch-edge copies (#166)
- 79d26c8 fix(reader): fully skip non-matching reader-conditional branches (#145)
- 8734dde fix(rt): find returns a MapEntry; pop drops the first element of a one-item seq (#148)
- 873cb79 fix(vm): emit EDN-conformant string escapes from pr-str (#183)
- 7930fb1 fix(vm): type dispatch — Object default, instance? on protocols, deftype fields, re-pattern (#146)
- ab99a52 perf(timeline): perf-data branch, execution-only suite, 3 IR exec variants (#190)
- b8c37fc perf: add timeline page and main snapshots (#173)
- 74d4ec6 test(bench): fixed-workload program benchmark from benchmark/*.clj (#170)
-
v1.9.1-0.20260531082317-bdab0276bd9931 May 2026 pre-releaseNothing published for this version
-
v1.9.031 May 2026Release notes
Open source →Changelog
- 17ad803 Add term/key-pending? non-blocking input peek (#118)
- 0044979 Brew cask update for let-go version v1.8.0 (#74)
- 1738270 Fix HTTP response header string rendering (#102)
- dbb3403 Fix error output (#87)
- a34de76 Thread doc metadata through def forms (#100)
- 155b9b0 chore(pre-commit): bump golangci-lint to v2.12.2 to match v2 config (#93)
- d037132 compiler/reader: namespace-qualify bare symbols in syntax-quote (#91)
- 49dd47b docs(policy)+ci+devx: contribution policy + staleness gates + parity tooling (issue #97) (#117)
- 3987b28 feat(bytecode): LGB v2 format with per-tag versioning and batch decode (#80)
- 4b726d8 feat(core): graph ns (toposort, Tarjan SCC) + read-all-string + scripts/sort-defns.lg (#98)
- 896316d feat(ir): SSA IR + Lisp-side pass pipeline (#77)
- 8de2d04 feat(ir): band2 — variadic, tail-call, destructure, multi-arity, type-infer (with review fixes) (#94)
- d2d75d9 feat(ir+scripts): substrate observability + small ops + IR-stress harness (#114)
- 86e724f feat(perf): bench-ratchet system + v1.8.0 historical baseline (#119)
- 4fc5f34 feat(rt+vm): xxh3 namespace via lginterop + .lg wrapper (#108)
- 2154e3f feat(vm): Scope — hierarchical goroutine supervision tree (draft, depends on #120) (#123)
- 941cbe5 feat(vm): surface Go panic origin in crash reports (#127)
- 44d0ea4 feat(vm+rt): chunked seqs — substrate + chunk-aware map/reduce/filter/take/pmap (#109)
- f9565e8 feat(vm+rt/async): goroutine registry + cancellable, correct core.async primitives (#120)
- a58b323 feat/perf(ir): multi-arity closure captures + uses-cache infra + typeinfer overhaul + lower-go enhancements (#116)
- 4c40934 feat: support .clj namespace resolution + LG_READ_CLJ env var (#129)
- 5f7556c fix(compiler): in-ns compile-time hook must not trigger ns reload (#78)
- f754a37 fix(ir): build/lower minor bug fix bundle (#113)
- 60da8be fix(rt): identity short-circuit + hash fast-reject + visited-pair memoization in valueEquals (#111)
- 987c6f5 fix(rt+resolver+lgbgen): land the missing call-site switches for #110 (#115)
- efce979 fix(rt/term): guard syscall/js Value.Int() against undefined Atomics/SAB (#126)
- cbc22c8 fix(scripts): atomic gofmt write via .tmp + mv; trap cleanup (#92)
- 8d7dca2 fix(string): index-of / last-index-of return rune indices for UTF-8 safety (#89)
- d2b7474 fix(test): make os-cwd-test hermetic — assert string, not checkout path (#121)
- aa4bd55 fix(vm): Go-fn-call-boundary fixes + Closure as Fn interface (#112)
- 8bac483 lginterop: compact positional exports, generics/methods/fields metadata (#85)
- 3ed77c7 perf(bench-ratchet): default to fast jank-suite gate (bytecode + gogen_ir variants); -full for the micro-bench fleet (#125)
- 6035aa3 perf(gogen): lazy AddLine for synthetic positions (#95)
- 517d129 perf(rt): atomic gensym + pmapv (eager parallel map), and a design note (#124)
- a898a39 perf(vm): lock-free Var.Deref — atomic root/curr instead of global bindingsMu (#122)
- bc9b02c refactor(rt+resolver+lgbgen): reduce binding-add ceremony to a single drop (#110)
- 0051e63 repl: migrate from alimpfard/line to chzyer/readline for FreeBSD support (#90)
- ecc0584 resolver: deps.edn source path support + runtime deps-paths fn (#83)
- ba082de runtime: enforce ns load semantics for require and qualified lookup (#81)
- 06bd643 scripts: corpus-agnostic ir-stress harness (#96)
-
v1.8.1-0.20260522213931-e002e4f7ed8622 May 2026 pre-releaseNothing published for this version
-
v1.8.022 May 2026Release notes
Open source →Changelog
- ff2ec36 Brew formula update for let-go version v2.0.2 (#31)
- e2e5ffa Fix Homebrew formula PR merge branch (#32)
- d733e03 Migrate Homebrew release to casks
- 3dd9949 Some improvements to Makefile and report generator
- 5a63816 chore(tooling): git merge driver for core_compiled.lgb
- 5dc9ad8 ci: add prek-compatible pre-commit hooks mirroring CI
- a43d69d examples: ys-on-let-go — run yamlscript compiled output on let-go (#53)
- 7df8031 feat(core): add unchecked-add/-subtract/-multiply/-negate/-inc/-dec/-divide-int for Clojure parity
- de06636 feat(gogen): Clojure-to-Go AST codegen library
- 1abc5cb feat(gogen): add func-lit, switch, composite-lit
- 02b1b4f feat(reader): promote overflowing hex literals to BigInt — Clojure parity
- de4668a feat(rt): unchecked-* coercion family — long/int/short/byte/char/float/double
- fcdbdea feat(vm): warn on def shadowing clojure.core — Clojure JVM parity
- 96bebc6 feat(vm/string): add .getBytes interop — returns UTF-8 byte-array
- e3dcf11 feat: add check ns for property testing
- a1824d4 feat: add lazy-seq? predicate; throw on lazy-seq of non-seq value
- 693cd4d feat: add walk/keywordize-keys and walk/stringify-keys
- 9ef4cc2 feat: preserve laziness via vm.Iter + SeqToSlice + reflect bridge
- 18fc2da fix(compiler): allow multiple _ parameters in fn arg lists
- b8d0ff2 fix(compiler): recurCompiler must count slots, not distinct names — fixes loop+shadow stack overflow
- 1ca8567 fix(vm): warn-on-core-shadow only fires when name is referred in
- 2c97d2e fix: COI service worker passes through server headers, uses require-corp
- 711f2bc fix: RegisterNS auto-refers CoreNS so (in-ns 'foo) preserves core macros
- 33ee8e7 fix: bootstrap stdlib lgb generation from source
- fa6d96b fix: guard COI service worker against reload loops, unregister when redundant
- 6f1f276 fix: make lgbgen output bit-deterministic
- 8442bbc fix: make map and mapcat lazy
- 38011c6 fix: normalize empty Sequable in lazy-seq
- e32debd fix: support docstrings and attr-map on defmulti and defprotocol
- 325a73b fix: walk handles maps via map-entry? predicate
- d0c0d76 style: apply gofmt -s and golangci-lint fixes to existing files
-
v1.7.5-0.20260516175903-768ad291307116 May 2026 pre-releaseNothing published for this version
-
v1.7.5-0.20260513232729-20ca9f4860e613 May 2026 pre-releaseNothing published for this version
-
v1.7.413 May 2026 -
v1.7.313 May 2026Release notes
Open source →Changelog
- d8543c4 Add -source-paths flag and LG_SOURCE_PATHS env var
- 92fe5e2 Add JVM compatibility shim plan
- c01ee76 Add execution plan for Clojure compat work
- 5c71688 Correct JVM compat plan: dot-method dispatch already exists
- 1120fcb Fix ineffectual ch assignments in readMeta
- 430d531 Fix sort comparator compatibility
- 9a033b1 Fix typo in README
- af894a3 Improve real-world Clojure source compatibility
- 75fbcb6 Pre-flight cleanups for Clojure compat (P1-P5)
- 137b6d0 Refactor benchmarks and README for clarity and performance
- 1598930 Unskip clojure-test-suite files: ancestors, parents, add_watch, remove_watch
- 5a6b933 Update Homebrew formula to v1.7.2
- f448204 Update benchmark results: add gloab/glojure back
- a15aae9 Update website
-
v1.7.3-0.20260507142155-5a6b9334fb1d07 May 2026 pre-releaseNothing published for this version
-
v1.7.207 May 2026 -
v1.7.107 May 2026Nothing published for this version
-
v1.7.1-0.20260506235351-6f5b0e0e342806 May 2026 pre-releaseNothing published for this version
-
v1.7.005 May 2026Nothing published for this version
-
v1.6.1-0.20260430143738-2c62ee35b82730 Apr 2026 pre-releaseNothing published for this version
-
v1.6.030 Apr 2026Nothing published for this version
-
v1.5.1-0.20260419190631-aa901ed6555719 Apr 2026 pre-releaseNothing published for this version
-
v1.5.019 Apr 2026Nothing published for this version
-
v1.4.014 Apr 2026Nothing published for this version
-
v1.3.803 Apr 2026Nothing published for this version
-
v1.3.8-0.20260403111314-48eef675bdbd03 Apr 2026 pre-releaseNothing published for this version
-
v1.3.703 Apr 2026Nothing published for this version
-
v1.3.7-0.20260401200617-4d8087b594fe01 Apr 2026 pre-releaseNothing published for this version
-
v1.3.631 Mar 2026Nothing published for this version
-
v1.3.531 Mar 2026Nothing published for this version
-
v1.3.431 Mar 2026Nothing published for this version
-
v1.3.331 Mar 2026Nothing published for this version
-
v1.3.3-0.20260330194832-d552d24371e330 Mar 2026 pre-releaseNothing published for this version
-
v1.3.230 Mar 2026Nothing published for this version
-
v1.3.2-0.20260330122829-2036becd997630 Mar 2026 pre-releaseNothing published for this version
-
v1.3.130 Mar 2026Nothing published for this version
-
v1.3.1-0.20260329210313-be533ef5fb9e29 Mar 2026 pre-releaseNothing published for this version
-
v1.3.029 Mar 2026Nothing published for this version
-
v1.2.029 Mar 2026Nothing published for this version
-
v1.1.1-0.20260329022957-4961aa55bd8e29 Mar 2026 pre-releaseNothing published for this version
-
v1.1.029 Mar 2026Nothing published for this version
-
v1.0.028 Mar 2026Nothing published for this version
-
v0.0.0-20230325213609-73db05b2c31d25 Mar 2023 pre-releaseNothing published for this version
-
v0.0.0-20230321142457-7c066b8699ae21 Mar 2023 pre-releaseNothing published for this version
-
v0.0.0-20230204230207-7d846abf622304 Feb 2023 pre-releaseNothing published for this version
-
v0.0.0-20230127010213-620c62c75ec327 Jan 2023 pre-releaseNothing published for this version