leanest

Docs

Reference for the leanest CLI.

Install

Requires Bun. The CLI runs the TypeScript source directly; there is no build step.

bun add -D leanest

Configuration

leanest loads .env from the current directory. Environment variables:

Variable Description Default
LEANEST_PROVIDER Judge provider to use: classifier-dev, jev, or laya. classifier-dev
TYPESAFE_API_KEY API key for the jev provider. Unused by classifier-dev and laya. (none)
TYPESAFE_API_BASE Base URL for the jev provider. https://api.typesafe.ai/v1
TYPESAFE_MODEL Model name for the jev provider. jev-latest

Commands

leanest playwright Select, then actually run Playwright on the selection.
leanest vitest Select, then actually run Vitest on the selection.
leanest select playwright Show the selection only, run nothing.
leanest inspect playwright Rank every test by relevance, for debugging.

Flags

--base <ref> Base branch to diff against. Default main.
--dir <path> Target directory. Default the current one.
--changed Diff the working tree instead of a branch.
--json Machine-readable output.
--shadow Run the full suite, but log what would have been skipped.
--full Skip selection, run everything.

Judge providers

Set with LEANEST_PROVIDER.

Name Description Key required
classifier-dev (default) classifier.dev, a free zero-shot classifier none
jev TypeSafe's Jev, over HTTP TYPESAFE_API_KEY
laya Laya, self-hosted, runs in-process via ONNX Runtime none
LEANEST_PROVIDER=jev npx leanest playwright

CI integration

GitHub Actions:

.github/workflows/test.yml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0

- uses: baronunread/leanest@v1
  with:
    framework: playwright
    # defaults to classifier-dev: free, no key needed

typesafe-api-key is only needed when provider is set to jev. Any other CI system: install and run the CLI directly.

bun add -g leanest
leanest playwright --base origin/main

Behavior

  • Fail open. A missing or invalid provider key, an API timeout, or a malformed response runs the full suite and prints why, instead of silently skipping coverage.
  • Deterministic overrides. A test always runs, regardless of the judge's answer, if: its own file changed, it statically imports a changed file, or it navigates a route a changed file's path names (e.g. page.goto("/admin/users") against a changed routes/admin/users.tsx).
  • No changes detected. When the diff is empty (e.g. a pure CI or config change with no application code), every test is evaluated conservatively rather than skipped outright.
  • No server. The CLI calls the selected provider directly with your credentials, if any. Nothing routes through leanest's own infrastructure, because there isn't any.