Date: 2026-03-14
Kiln is a ClojureScript project that targets Bun for execution, but its current shadow-cljs REPL workflow is effectively Node-oriented. This matters because Bun-specific APIs such as Bun.Glob are not reliably available through the current interactive workflow, which blocks exploratory debugging of Bun-backed code paths while preserving the existing clj-nrepl-eval + (shadow/repl ...) workflow.
The goal is to design a general solution in shadow-cljs, not a Kiln-only workaround.
Provide a Bun-backed interactive shadow-cljs REPL workflow for Node-family builds while preserving the current user contract:
clj-nrepl-eval(shadow/repl :build-id)Add Bun as a new runtime type beside the existing Node runtime, with its own explicit client/runtime path.
Pros:
Cons:
Add a general JS runtime selector for Node-style targets and REPL launch paths. Start by reusing the existing Node client/runtime code and swapping the launched executable from node to bun.
Pros:
Cons:
Add a Bun-executed exploratory script/build workflow in Kiln without changing shadow-cljs.
Pros:
Cons:
clj-nrepl-eval + (shadow/repl ...)Use approach 2 first.
The source code shows that shadow-cljs already has a strong seam for this approach:
shadow.cljs.devtools.server.repl-impl/node-repl* already launches an external JS process via configurable node-command and node-argsThat means the most pragmatic phase-1 design is:
If Bun fails that compatibility test, phase 2 becomes introducing a dedicated Bun client namespace.
Treat Bun as a selectable JS host for the existing Node-family runtime path.
The user-facing workflow remains unchanged:
clj-nrepl-eval(shadow/repl :build-id)The change is internal:
shadow-cljs currently launches node, it can launch bunnode, they can autorun with bunAdd an opt-in runtime selector for Node-family builds and REPL launch paths:
{:target :node-test
:js-runtime :bun
...}
Potential API support:
(shadow/node-repl {:js-runtime :bun})
Default remains Node when unspecified.
Phase 1 deliberately keeps these pieces unchanged:
shadow.cljs.devtools.client.nodeshadow.cljs.devtools.client.node-replshadow.cljs.devtools.client.node-esmshadow/repl user semanticsThis limits the first implementation to launch-path selection and shared runtime configuration.
shadow.cljs.devtools.server.repl-impl/node-repl*Relevant because it already exposes:
node-commandnode-argsThis is the clearest place to generalize from a Node-only launcher to a Node-family runtime launcher.
shadow.build.targets.node-test/autorun-testCurrently hardcodes node when executing the built test bundle. Bun-backed builds must honor the same runtime selector here or the interactive and runner workflows will diverge.
shadow.build.targets.node-scriptShould honor the same runtime selector for consistency across Node-family targets.
shadow.build.targets.sharedBest place to:
:js-runtimeshadow.cljs.devtools.client.nodeshadow.cljs.devtools.client.node-replshadow.cljs.devtools.client.node-esmThe existing client namespaces describe themselves as Node clients and may depend on Node behavior Bun only partially emulates.
Mitigation:
The source inspection shows a clean seam for node-repl*, but watched Node-family builds may have different runtime-launch paths than the standalone node-repl.
Mitigation:
:node-test may remain a poor interactive targetEven with Bun selection, :node-test may still behave more like a compile-and-run target than a persistent interactive runtime for some workflows.
Mitigation:
(shadow/repl :build-id)” as the phase-1 success gate:node-test remains awkward, solve that explicitly rather than hiding itBun may expose differences around import behavior, preload sequencing, or runtime evaluation semantics compared to Node.
Mitigation:
shadow-cljsPhase 1 is successful when all of the following are true:
:js-runtime :bunshadow-cljs watch <build> plus (shadow/repl <build>) yields a connected CLJS runtime hosted by Bunjs/BunBun.GlobMove to a first-class Bun client/runtime namespace only if phase 1 reveals concrete incompatibilities in:
Until then, a runtime-selection layer is the right technical bar.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |