@bigconfig/bb
An npx launcher that bootstraps babashka, a Temurin JDK, git (on
Linux), and an optional bb.edn on first use — then forwards every
argument to bb. Zero install:
npx @bigconfig/bb@latest tasks becomes bb tasks.
Overview #
@bigconfig/bb is a tiny, single-file Node CLI. It resolves the
host OS/CPU, downloads pinned, known-good binaries into a shared user cache
on first run, optionally bootstraps a bb.edn from GitHub, and
then execs bb with your arguments. Nothing is changed
system-wide; subsequent runs reuse the cache and start immediately.
Babashka
Downloaded from babashka's GitHub releases for the host platform.
JDK
Eclipse Temurin via the Adoptium API; wired into the bb subprocess only.
Git (Linux)
Installed via the system package manager if missing; no-op elsewhere.
bb.edn bootstrap
Optionally fetch a project's bb.edn from a GitHub repo.
:local/root strip
Invalid local-path deps removed; the repo added as a pinned git dep.
Cached & lazy
One shared cache, race-safe atomic installs, reused across projects.
Why @bigconfig/bb #
- Zero install: one
npxcommand — no manual babashka/JDK setup. - Reproducible: babashka, JDK and rewrite-edn versions are pinned and overridable via env.
- CI / Docker friendly: works in a bare
nodecontainer; first run hydrates the cache. - No system changes:
JAVA_HOME/PATHare scoped to the spawnedbbonly. - Project bootstrap:
BB_EDN_REPOturns any GitHub repo with abb.edninto a runnable task set.
Installation & usage #
There is nothing to install. Invoke it through npx; every argument is forwarded verbatim to bb, run in the current directory.
npx @bigconfig/bb@latest tasks # -> bb tasks
npx @bigconfig/bb@latest <args...> # -> bb <args...>
Requires Node.js >= 18. The package is @bigconfig/bb (scoped) with a single bb bin.
Quick start #
List the tasks of a GitHub bb project without cloning anything:
BB_EDN_REPO=bigconfig-ai/once npx @bigconfig/bb@latest tasks
Or fully sandboxed in Docker:
docker run -it --rm -u node -w /home/node node:24 npx @bigconfig/bb@latest tasks
See the Examples for the full set.
How it works #
Each invocation runs the following pipeline; every step is skipped when its result is already present:
- Resolve the host OS/CPU to babashka + Adoptium asset names.
- Babashka: download & cache if the pinned version is missing.
- JDK: download & cache Temurin if missing.
- Git (Linux only): install via the system package manager if
gitis not onPATH. - bb.edn bootstrap: if
BB_EDN_REPOis set and the cwd has nobb.edn, fetch and adapt one. - Run: spawn
bbwith your args, cwd = process cwd,JAVA_HOME/PATHpointing at the cached JDK and cachedbb. stdio is inherited; the exit code andSIGINT/SIGTERMare forwarded.
Downloads are lazy (first run only), not done at npm install time.
Babashka install #
The platform-specific archive is downloaded directly from
github.com/babashka/babashka/releases (no curl/bash/brew
dependency) and extracted into the cache. Extraction uses the system
tar (present on macOS, Linux, and Windows 10+); Windows falls
back to PowerShell Expand-Archive for .zip if
tar is unavailable.
| Platform | Asset |
|---|---|
| macOS arm64 | babashka-<ver>-macos-aarch64.tar.gz |
| macOS x64 | babashka-<ver>-macos-amd64.tar.gz |
| Linux x64 | babashka-<ver>-linux-amd64.tar.gz (glibc) |
| Linux arm64 | babashka-<ver>-linux-aarch64-static.tar.gz (static) |
| Windows x64 | babashka-<ver>-windows-amd64.zip |
Pinned to 1.12.196; override with BB_VERSION. Babashka has no prebuilt Windows arm64 binary.
JDK install #
An Eclipse Temurin JDK is fetched from the Adoptium v3 API:
https://api.adoptium.net/v3/binary/latest/<feature>/ga/<mac|linux|windows>/<aarch64|x64>/jdk/hotspot/normal/eclipse
Pinned to feature version 21 (LTS); override with
JDK_VERSION. After extraction the real JAVA_HOME is
located (macOS nests it under Contents/Home) and recorded. When
bb runs, JAVA_HOME and PATH are set for
that subprocess only; PATH also includes the cached
bb so nested bb calls work. Nothing system-wide is touched.
babashka itself is a native binary and does not need a JVM; the JDK is bundled for tasks that shell out to java or use JVM-based tooling. It roughly doubles the first-run download (~190 MB).
Git (Linux) #
On Linux only, if git is not on PATH
it is installed via the system package manager — first match of
apt-get, dnf, yum, zypper,
pacman, apk — using sudo when not
running as root. apt-get update failures are tolerated;
DEBIAN_FRONTEND=noninteractive is set.
- Skipped if
gitis already present. - No-op on macOS/Windows.
- Fatal, with an actionable message, if not root and
sudois missing, or no supported package manager is found.
Unlike the other steps this modifies the system and may prompt for a sudo password; pre-install git to skip it entirely.
bb.edn bootstrap #
When the current directory has no bb.edn and
BB_EDN_REPO=owner/project is set, that repo's
bb.edn is downloaded and the repo itself is added to
:deps as a pinned git dependency:
io.github.<owner>/<project> {:git/sha "<sha>"}
GET /repos/{owner}/{project}/commits?per_page=1→ the default-branch HEAD commit (the pinned:git/sha).GET /repos/{owner}/{project}/contents/bb.edn?ref=<sha>withAccept: application/vnd.github.raw→ the file.- The dep is injected with
borkdude/rewrite-edn(run through the just-installedbb), so existing comments and formatting are preserved.
If GITHUB_TOKEN is set it is sent as a bearer token — enabling
private repos and lifting GitHub's 60 req/hr unauthenticated limit. A missing
or inaccessible repo, or one without a bb.edn, is a fatal error.
Skipped entirely if BB_EDN_REPO is unset or a bb.edn
already exists.
The first bootstrap also downloads the Clojure tools (~/.deps.clj/…) plus rewrite-edn (pinned 0.5.9, override via REWRITE_EDN_VERSION); both are cached afterward.
:local/root stripping #
A downloaded bb.edn often references sibling projects via
:local/root paths that don't exist on your machine. Before the
git dep is injected, every dependency whose effective coordinate is
a map containing :local/root is removed — from the top-level
:deps and every task's :extra-deps.
- The whole entry (key + coord) is dropped.
- Detection uses the effective value (rewrite-edn
sexpr), so a#_-discarded:local/rootalternative is correctly ignored and the active git/maven coord is kept. - Valid Maven and git deps are preserved.
For example bigconfig-ai/once downloads as:
{:deps {io.github.amiorin/once {:local/root "."}}
:tasks {:requires ([io.github.amiorin.once.describe :as describe] ...) ...}}
and is rewritten (with BB_EDN_REPO=bigconfig-ai/once) to:
{:deps {io.github.bigconfig-ai/once {:git/sha "<sha>"}}
:tasks {:requires ([io.github.amiorin.once.describe :as describe] ...) ...}}
Environment variables #
| Variable | Default | Effect |
|---|---|---|
BB_VERSION | 1.12.196 | babashka release to install |
JDK_VERSION | 21 | Temurin feature version (e.g. 17, 21, 25) |
REWRITE_EDN_VERSION | 0.5.9 | borkdude/rewrite-edn version used to edit bb.edn |
BB_EDN_REPO | unset | owner/project to bootstrap a bb.edn from |
GITHUB_TOKEN | unset | Bearer token for BB_EDN_REPO (private repos / rate limit) |
Supported platforms #
macOS arm64, macOS x64, Linux x64, Linux arm64, Windows x64.
- Linux x64 uses babashka's glibc build (may not run on musl distros such as Alpine).
- Linux arm64 uses babashka's static build, which runs on both glibc and musl.
- Windows arm64 is unsupported (no prebuilt babashka binary).
- Extraction needs the system
tar(or PowerShell on Windows for.zip).
Cache layout #
A single shared directory, reused across all projects:
| Platform | Base |
|---|---|
| macOS / Linux | $XDG_CACHE_HOME or ~/.cache → bigconfig-bb/ |
| Windows | %LOCALAPPDATA% → bigconfig-bb/ |
bigconfig-bb/
├── bb/<version>/bb # babashka binary
└── jdk/<feature>/ # extracted Temurin JDK
└── .javahome # recorded JAVA_HOME (relative)
Installs are atomic: each artifact is unpacked into a private .tmp-* dir and renamed into place, so concurrent first-runs never leave a half-written cache. Delete the directory to force a clean reinstall.
Passthrough & exit codes #
- All arguments (including flags) are passed to
bbverbatim. bbruns in the current working directory, so it picks up the localbb.edn.- stdio is inherited;
bb's exit code is forwarded;SIGINT/SIGTERMare forwarded to the child. - No arguments →
bb's normal behavior (reads stdin / REPL).
Example — local bootstrap #
Run the tasks of bigconfig-ai/once with nothing installed and no clone:
BB_EDN_REPO=bigconfig-ai/once npx @bigconfig/bb@latest tasks
First run: downloads babashka + Temurin JDK, fetches the repo's
bb.edn pinned to its latest commit, strips the
:local/root self-dep, injects
io.github.bigconfig-ai/once {:git/sha "…"}, writes
./bb.edn, then runs bb tasks.
Example — Docker #
Fully sandboxed in a stock Node 24 image, as the unprivileged node user:
docker run -it --rm -u node -w /home/node node:24 npx @bigconfig/bb@latest tasks
-u node runs as the non-root node user and
-w /home/node is its writable home — so the cache lands in
/home/node/.cache/bigconfig-bb. With no BB_EDN_REPO
and no bb.edn present, bb tasks simply reports no
tasks.
Example — Docker + repo + task #
Same container, but bootstrap bigconfig-ai/once and run its
validate task — pass the env var with -e:
docker run -it --rm -u node -w /home/node \
-e BB_EDN_REPO=bigconfig-ai/once \
node:24 npx @bigconfig/bb@latest validate
The launcher writes /home/node/bb.edn (bootstrapped + cleaned),
then runs bb validate against it. Add
-e GITHUB_TOKEN=… for a private repo or to avoid GitHub API
rate limits.
Example — BB_EDN_REPO explained #
BB_EDN_REPO is the bootstrap switch. When set (and the cwd has
no bb.edn) it makes any GitHub repo that ships a
bb.edn directly runnable: the file is downloaded pinned to the
repo's default-branch HEAD, :local/root deps are stripped, and
the repo is added back as a reproducible git dependency.
Local
BB_EDN_REPO=bigconfig-ai/once npx @bigconfig/bb@latest validate
Docker
docker run -it --rm -u node -w /home/node \
-e BB_EDN_REPO=bigconfig-ai/once \
node:24 npx @bigconfig/bb@latest tasks
Unset it (or run where a bb.edn already exists) and this step is skipped — bb runs against the local project as usual.
Development Docker image #
This repository also ships a Dockerfile and bb.edn
helper tasks for a throwaway development shell. The image is based on Ubuntu
24.04 and installs Node.js, the pi coding agent, Claude, ripgrep,
fd, and sudo. Requires Docker. The former Makefile
workflow now lives in bb.edn; run bb tasks or
bb options to inspect it. If bb is not on
PATH, use node bin/bb.js <task> to exercise the
local launcher instead. When bootstrapped into an empty directory with
BB_EDN_REPO=bigconfig-ai/npm-bb, task config downloads a missing
Dockerfile from the same pinned GitHub SHA.
bb tasks # list repository tasks
bb build # build npm-bb:dev
bb build --no-cache # rebuild without Docker layer cache
bb shell # build, create a generated home, then open bash
bb shell --skip-build # reuse the existing image
bb shell creates a writable host directory under
homes/<random-name> and mounts it at
/home/developer in the container. Before starting Docker it
copies ~/.pi/agent/auth.json and
~/.pi/agent/settings.json into that generated home when those
files exist; missing files are skipped. Use --project-subdir PATH
to mount a specific host directory instead.
| Task | Purpose |
|---|---|
bb build | Build the Docker image with host UID/GID and Node major version build args. |
bb shell | Build (unless --skip-build), prepare the generated home, and run an interactive container. |
bb config | Print the resolved image, workspace, command, and option values. |
bb options | Print all supported flags and environment variables. |
bb homes | List generated homes under the configured prefix. |
bb clean --all | Delete all generated homes; pass --project-subdir PATH to delete one explicit directory. |
Common options
| Option / env | Default | Effect |
|---|---|---|
--image / IMAGE | npm-bb | Docker image name |
--tag / TAG | dev | Docker image tag |
--node-major / NODE_MAJOR | 24 | Node.js major version build arg |
--no-cache | false | Pass --no-cache to docker build |
--workdir / WORKDIR | /home/developer | Container working directory |
--name / DOCKER_STYLE_RANDOM_NAME | random | Container hostname and generated home name |
--project-subdir / PROJECT_SUBDIR | homes/<name> | Host directory mounted into the container |
--docker-run-arg ARG | none | Extra docker run argument; repeat as needed |
--dry-run | false | Print commands without executing them |
Use bb shell --docker-run-arg=-p --docker-run-arg=3000:3000 to publish ports, or bb shell -- COMMAND ... to run a command other than bash.
Requirements #
- Node.js >= 18.
- Network access on first run (cached afterward).
- System
tarfor extraction (PowerShell fallback on Windows). - Linux without
git: a supported package manager andsudo(or root).
Caveats / what to avoid #
- Alpine / musl + x64: the Linux x64 babashka build is glibc-based and may not run; Linux arm64 (static) is fine.
- Exotic EDN: a
bb.ednusing tagged literals can failrewrite-edn'ssexpr— it fails loudly with a clear error, no silent corruption. - Symbol-invalid names: an
owner/projectwith characters invalid in a Clojure symbol (used inio.github.<owner>/<project>) is a documented limitation. - First-run weight: babashka + JDK ≈ 190 MB; the first
bb.ednbootstrap also pulls the Clojure tools. - Tested surface: exercised live on macOS arm64; the Linux arm64 asset URL is verified, other platforms are mapped but not yet run end-to-end.
Changelog #
Unreleased — 2026-05-18
- Documented the repository development Docker image and
bb.ednhelper tasks. - Moved the development workflow from Makefile targets to babashka tasks.
- Added
bb build --no-cachesupport for Docker cache-busting rebuilds.
0.2.0 — 2026-05-17
- bb.edn bootstrap from a GitHub repo via
BB_EDN_REPO(pinned to default-branch HEAD;GITHUB_TOKENsupport). - Repo injected as
io.github.<owner>/<project> {:git/sha …}using comment-preservingborkdude/rewrite-edn. :local/rootdeps stripped from:depsand task:extra-deps.
0.1.0 — 2026-05-17
- npx launcher: bootstraps babashka and a Temurin JDK on first use, forwards args to
bb. - Linux: installs
gitvia the system package manager when missing. - Shared, race-safe cache; pinned versions overridable via env.
Glossary #
- babashka (bb)
- A fast-starting Clojure scripting runtime, compiled with GraalVM
native-image(no JVM required). - bb.edn
- Babashka's project file:
:paths,:deps, and:tasks. - deps coordinate
- The value mapping a dependency symbol to its source — e.g.
{:mvn/version …},{:git/sha …}, or{:local/root …}. - :git/sha
- A git dependency pinned to an exact commit; with the
io.github.owner/projectsymbol the URL is inferred. - :local/root
- A dependency resolved from a local filesystem path — invalid once a
bb.ednis downloaded, hence stripped. - rewrite-edn
borkdude/rewrite-edn: edits EDN while preserving whitespace and comments.- Temurin
- Eclipse Adoptium's OpenJDK distribution, fetched here via the Adoptium v3 API.
- GraalVM native-image
- Ahead-of-time compiler producing the standalone babashka binary.