@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 npx command — 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 node container; first run hydrates the cache.
  • No system changes: JAVA_HOME/PATH are scoped to the spawned bb only.
  • Project bootstrap: BB_EDN_REPO turns any GitHub repo with a bb.edn into 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:

  1. Resolve the host OS/CPU to babashka + Adoptium asset names.
  2. Babashka: download & cache if the pinned version is missing.
  3. JDK: download & cache Temurin if missing.
  4. Git (Linux only): install via the system package manager if git is not on PATH.
  5. bb.edn bootstrap: if BB_EDN_REPO is set and the cwd has no bb.edn, fetch and adapt one.
  6. Run: spawn bb with your args, cwd = process cwd, JAVA_HOME/PATH pointing at the cached JDK and cached bb. stdio is inherited; the exit code and SIGINT/SIGTERM are 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.

PlatformAsset
macOS arm64babashka-<ver>-macos-aarch64.tar.gz
macOS x64babashka-<ver>-macos-amd64.tar.gz
Linux x64babashka-<ver>-linux-amd64.tar.gz (glibc)
Linux arm64babashka-<ver>-linux-aarch64-static.tar.gz (static)
Windows x64babashka-<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 git is already present.
  • No-op on macOS/Windows.
  • Fatal, with an actionable message, if not root and sudo is 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>"}
  1. GET /repos/{owner}/{project}/commits?per_page=1 → the default-branch HEAD commit (the pinned :git/sha).
  2. GET /repos/{owner}/{project}/contents/bb.edn?ref=<sha> with Accept: application/vnd.github.raw → the file.
  3. The dep is injected with borkdude/rewrite-edn (run through the just-installed bb), 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/root alternative 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 #

VariableDefaultEffect
BB_VERSION1.12.196babashka release to install
JDK_VERSION21Temurin feature version (e.g. 17, 21, 25)
REWRITE_EDN_VERSION0.5.9borkdude/rewrite-edn version used to edit bb.edn
BB_EDN_REPOunsetowner/project to bootstrap a bb.edn from
GITHUB_TOKENunsetBearer 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:

PlatformBase
macOS / Linux$XDG_CACHE_HOME or ~/.cachebigconfig-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 bb verbatim.
  • bb runs in the current working directory, so it picks up the local bb.edn.
  • stdio is inherited; bb's exit code is forwarded; SIGINT/SIGTERM are 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.

TaskPurpose
bb buildBuild the Docker image with host UID/GID and Node major version build args.
bb shellBuild (unless --skip-build), prepare the generated home, and run an interactive container.
bb configPrint the resolved image, workspace, command, and option values.
bb optionsPrint all supported flags and environment variables.
bb homesList generated homes under the configured prefix.
bb clean --allDelete all generated homes; pass --project-subdir PATH to delete one explicit directory.

Common options

Option / envDefaultEffect
--image / IMAGEnpm-bbDocker image name
--tag / TAGdevDocker image tag
--node-major / NODE_MAJOR24Node.js major version build arg
--no-cachefalsePass --no-cache to docker build
--workdir / WORKDIR/home/developerContainer working directory
--name / DOCKER_STYLE_RANDOM_NAMErandomContainer hostname and generated home name
--project-subdir / PROJECT_SUBDIRhomes/<name>Host directory mounted into the container
--docker-run-arg ARGnoneExtra docker run argument; repeat as needed
--dry-runfalsePrint 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 tar for extraction (PowerShell fallback on Windows).
  • Linux without git: a supported package manager and sudo (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.edn using tagged literals can fail rewrite-edn's sexpr — it fails loudly with a clear error, no silent corruption.
  • Symbol-invalid names: an owner/project with characters invalid in a Clojure symbol (used in io.github.<owner>/<project>) is a documented limitation.
  • First-run weight: babashka + JDK ≈ 190 MB; the first bb.edn bootstrap 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.edn helper tasks.
  • Moved the development workflow from Makefile targets to babashka tasks.
  • Added bb build --no-cache support 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_TOKEN support).
  • Repo injected as io.github.<owner>/<project> {:git/sha …} using comment-preserving borkdude/rewrite-edn.
  • :local/root deps stripped from :deps and 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 git via 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/project symbol the URL is inferred.
:local/root
A dependency resolved from a local filesystem path — invalid once a bb.edn is 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.