# Babashka: a native Clojure interpreter for shell-adjacent scripting

> Babashka runs a subset of Clojure from a self-contained binary with no JVM, aimed at scripts that have outgrown bash but do not justify a full Clojure project. The trade-off is interpretation speed and an incomplete language surface.

**babashka/babashka** — Native, fast starting Clojure interpreter for scripting

- Repository: https://github.com/babashka/babashka
- Website: https://babashka.org
- Stars: 4,615 · Forks: 281
- Language: Clojure
- License: EPL-1.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/babashka-babashka

## The gap Babashka occupies between bash and a Clojure project

The README quotes a user describing the target case: things that are too complicated to be simple in bash, but too simple to be worth writing a clj/s script for. That is the whole pitch. A shell script that starts parsing JSON, walking a directory tree, or handling command-line flags quickly becomes unreadable, while spinning up a Leiningen project and a JVM for the same job costs seconds of startup on every invocation.

Babashka is for people who already write Clojure and want that vocabulary available in short-lived command-line tools. The stated goals are fast startup, a self-contained binary with no JVM, familiarity for JVM Clojure users, and cross-platform support for linux, macOS and Windows. The stated non-goals matter just as much: it is not a mixed Clojure/Bash DSL, and it does not try to replace bash. It is meant to be called from inside an existing shell.

If your team has never seen Clojure, the calculus changes. You would be trading bash's ubiquity for a language your colleagues cannot review, and the README offers no argument that this is worth it.

## How the interpreter works, and why startup is the design centre

Babashka uses SCI, the small Clojure interpreter, to evaluate Clojure source. The README is explicit that SCI implements a substantial subset of Clojure, not all of it. Because the code is interpreted rather than compiled, the README also states plainly that interpreting is in general not as performant as executing compiled code, and that a script taking more than a few seconds or containing lots of loops may be better served by Clojure on the JVM, where runtime performance outweighs the startup penalty.

That is an unusually direct piece of documentation, and it defines the architecture's boundary. The binary is built with GraalVM: the repository's Dockerfile pins GRAALVM_VERSION to 25.0.4 and selects a GraalVM architecture based on TARGETARCH, mapping amd64 to x64 and arm64 to aarch64. Build-time arguments such as BABASHKA_FEATURE_CSV, BABASHKA_FEATURE_JAVA_NIO, BABASHKA_FEATURE_TRANSIT, BABASHKA_FEATURE_XML and BABASHKA_FEATURE_YAML let a builder choose which feature sets are compiled in, which is how the project produces both a full binary and a leaner one.

The repository layout reflects the same idea. Directories named feature-csv, feature-yaml, feature-transit, feature-jdbc, feature-httpkit-server and others sit alongside src/ and sci/, and the bundled capabilities the README calls batteries included (tools.cli, cheshire) are part of that compiled-in set rather than fetched at runtime. The practical consequence: what you can require is decided when the binary is built, not when your script runs.

## Installing babashka and running a first script

The README offers a quick install path through bash. It pipes a script from the repository's master branch into a shell, which downloads and places the binary for you.

```bash
bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install)
```

Alternatively you can download a binary from the GitHub releases page and put it anywhere on your PATH. On Linux and macOS, Homebrew is also supported:

```bash
brew install borkdude/brew/babashka
```

The README notes that if you installed babashka before Homebrew introduced tap trust, you may see a warning reading Skipping babashka: tap formula is not trusted, and that running brew trust borkdude/brew fixes it. Nix users can install from nixpkgs-unstable:

```bash
nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs-unstable
nix-channel --update
nix-env -iA nixpkgs-unstable.babashka
```

On Alpine the README recommends downloading the static linux binary from GitHub Releases manually rather than using a package manager. Arch users can install babashka-bin from the AUR.

Once bb is on your PATH, the README's first example evaluates an expression directly from the command line, listing directories and normalising the first three paths:

```bash
bb -e '(->> (fs/list-dir ".") (filter fs/directory?) (map fs/normalize) (map str) (take 3))'
```

The README shows output like (".build" "feature-lanterna" ".repl") and a timing of roughly 0.017 seconds for the whole invocation. Note the fs/ namespace: Babashka/fs is bundled, so directory operations do not need an extra dependency. That is the shape of a typical babashka script, a short Clojure expression or a file ending in .clj run through bb.

## Where babashka stops: interpretation cost and an incomplete language surface

The most honest limitation is in the project's own words. SCI implements a substantial subset of Clojure. Substantial is not complete, and the README points readers to a differences-with-Clojure section rather than claiming parity. Code that leans on a macro, a class or a library outside that subset will not run, and the failure appears at runtime, not at install time.

The second limitation is throughput. Interpreting code is slower than executing compiled code, so a script that grows from a one-shot command into a loop over a large dataset can cross from comfortable to unusable without any change in how it is invoked. The README's suggested escape hatch is to move to JVM Clojure, which means the script stops being a single binary and picks up a JVM dependency again.

There is a third, quieter constraint: because features are compiled into the binary, a lean build may lack capabilities a full build has. If you build babashka yourself with the repository's Dockerfile and leave BABASHKA_FEATURE_YAML or BABASHKA_FEATURE_TRANSIT unset, you get a binary that behaves differently from the released one. That is a real source of confusion when a script works on a colleague's machine and not yours.

## Babashka versus JVM Clojure, and versus staying in bash

The natural alternative is JVM Clojure, and the difference is not stylistic. JVM Clojure compiles and runs your code with the full language and the entire Maven ecosystem available; babashka interprets a subset with whatever was compiled into the binary. JVM Clojure pays a startup cost on every run; babashka does not. The README frames the choice in exactly these terms, recommending the JVM when a script takes more than a few seconds or has lots of loops.

A second alternative is to keep writing bash. Babashka does not position itself against that. The README's non-goals say it is a tool you use inside existing shells and that it does not aim to replace them. If your script is a dozen lines of pipes and conditionals, bash is already the right answer and adding an interpreter is overhead.

Between those two poles, the decision is mostly about the shape of the script. Short, invocation-heavy, structurally complex: babashka. Long-running, computationally heavy, dependency-hungry: JVM Clojure. Genuinely simple: bash.

## Upgrades, licensing and what the release cadence implies

Babashka is licensed under EPL-1.0, the Eclipse Public License 1.0. That is a permissive, file-level copyleft licence, and it is the same licence family used across much of the Clojure ecosystem. Nothing here is legal advice; if you redistribute a modified babashka binary, read the licence text and your organisation's policy rather than assuming.

On maintenance: the repository is not archived, and the last push was on 2026-09-22. Releases are frequent and closely spaced, with v1.13.221, v1.13.222 and v1.13.223 all published in September 2026. For a scripting tool that is a mixed blessing. You get fixes quickly, and you also get a moving target if you pin nothing.

The README addresses this directly. It says functionality regarding clojure.core and java.lang can be considered stable and is unlikely to change, that changes may happen in other parts of babashka, and that you should always check the release notes or CHANGELOG.md before upgrading. The upgrade cost therefore depends on which surface your scripts touch. A script built on core functions and java.time is close to inert. A script leaning on a bundled library or a pod is the one that will break on a minor bump, so pin the version in your install script and read the changelog before moving.

## Conclusion

Babashka fits engineers who already know Clojure and keep hitting the ceiling of bash, and anyone who wants a single binary for glue scripts on linux, macOS or Windows. It is the wrong tool for long-running CPU-bound programs, for code that needs the full JVM classpath, or for teams with no Clojure background who would pay more in language learning than they save in startup time. Before adopting it, run your own script under bb -e and time it, check whether every library you need is already bundled or available as a pod, and read CHANGELOG.md for the release you are about to install, because the README states that changes may happen outside clojure.core and java.lang.

## FAQ

### What is babashka?

It is a native Clojure interpreter for scripting with fast startup, distributed as a self-contained binary that needs no JVM. Its stated goal is to bring Clojure to places where you would otherwise use bash.

### How do I install babashka?

The README gives a bash one-liner that pipes the repository's install script into a shell, and also documents Homebrew via brew install borkdude/brew/babashka and Nix via nixpkgs-unstable. You can also download a binary from GitHub Releases and place it on your PATH.

### How does babashka compare to Clojure on the JVM?

Babashka interprets a subset of Clojure through SCI, so it starts fast but runs interpreted code more slowly. The README states that if a script takes more than a few seconds or has lots of loops, JVM Clojure may be the better fit.

### What does the name babashka mean?

The README does not explain the origin of the name, so there is nothing in the project's own documentation to confirm it.

## Sources

- [babashka/babashka on GitHub](https://github.com/babashka/babashka)
- [License: EPL-1.0](https://github.com/babashka/babashka/blob/master/LICENSE)
- [Project website](https://babashka.org)
- [README](https://github.com/babashka/babashka/blob/master/README.md)
- [Releases](https://github.com/babashka/babashka/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/babashka-babashka
