Skip to main content
A build tool for Java, Kotlin & Scala

Your build is data.
Not a program.

One YAML file. Native performance. IDE imports over BSP (Build Server Protocol; what IntelliJ and Metals already speak), agent tool calls via MCP (Model Context Protocol; what Claude Code already speaks) — both open standards, both first-class.

Cold start10 msGraalVM native image
IDE import1 secIntelliJ · Metals · BSP
Build format1 filereadable, diffable YAML
Code in your build0 linesscripts live elsewhere
The refusal

Things we will not tolerate.

Build tools have spent twenty years getting more clever and more opaque. Bleep is the build tool that says no for you, on principle, before someone proposes a Maven enforcer plugin in your standup.

Refusal01

No build-as-program.

Your build should be readable by somebody who has never opened the project. Turing-complete build files import complexity in exchange for flexibility most teams will never use — and the complexity stays whether the flexibility gets used or not.

Refusal02

No scopes.

Dependencies are a flat list. compile,provided, runtime, Test/test/it/Compilegraft a second axis on top. Different context? Different project. Flat is enough.

Refusal03

No plugin acrobatics.

No preCompile mutators, no autoplugins, no requires graphs, no Plugin<Project> registration, no plugins fighting at runtime over which Guava is the real one. If you want custom build logic, write a regular Java, Kotlin, or Scala program. It compiles. It debugs. It has a main.

Refusal04

No 30-second imports.

We will not negotiate with a Gradle or sbt import that needs a coffee break to figure out which Scala version your project uses, or which Kotlin compiler plugins it wants. Bleep imports through BSP in about one second.

Refusal05

No whole-module rebuilds.

Change one file in a 200-class Maven module and Maven recompiles all 200. Bleep uses Zinc with file-level incremental tracking — one file changed, one (or two) recompiled. Your CI minute count is not a place to economise on engineering effort.

The tenets

What we propose instead.

A small list. We can recite it from memory at standup, in code review, and during the inevitable argument about whether to add a build plugin.

Tenet01

Builds are data.

A build is a description of projects and dependencies, not a program that produces one. Data is greppable, diffable, generable, machine-rewritable. Code is none of those things without a parser you usually don't have.

Tenet02

Round-trip, always.

Bleep reads its build, transforms it, and writes it back. That’s how update-deps, project-rename, andtemplates-reapply work; that’s how your scripts can do the same. The model on disk and the model in memory are the same model.

Tenet03

Open standards.

Bleep speaks BSP — the Build Server Protocol. Any editor that speaks BSP talks to bleep on day one: IntelliJ, Metals, VS Code via Metals. We didn’t invent a private wire format. We didn’t ship our own IDE plugin. The ecosystem already agreed on the protocol.

Tenet04

Debuggable end to end.

Bleep is a normal program; scripts are normal programs. You can attach a debugger to the build tool itself, to the BSP server, to your scripts. There is no privileged layer of magic dust.

Tenet05

Repeatable, on purpose.

bleep.yaml pins what turns YAML into bytecode — bleep itself, the JVM, and (for Scala.js) Node — and downloads the right versions on first run. Two checkouts of the same commit produce the same build, no matter what’s installed on the host. No .tool-versions, no nvmrc, no “works on my machine.”

Tenet06

Simplicity, on purpose.

We will refuse features that buy 5% flexibility for 50% complexity. We will pick the boring answer. We will not invent a fourth way to declare a dependency.

Tenet07

Native, by default.

Bleep is GraalVM native-image. The CLI starts in roughly the time it takes for your terminal to render the prompt. That is not a feature; that is the floor.

Tenet08

Performance — bleeping performance.

Instant CLI. One-second imports. Fast incremental compiles via Zinc, javac, and kotlinc, in a single BSP server we wrote for the job. We do not compete with build tools that are "fast enough." We are not.

What about plugins?

Anything a plugin does.

Anyone arriving from sbt or Gradle gets the same uneasy thought looking at the YAML — where does my codegen go? the publish step? the thing that signs my JARs? Bleep has two places for that work, and both are real programs.

Before compile01

Generate code from what the build can see.

A schema, a protobuf descriptor, a build version, an OpenAPI spec. You inspect the build, you generate the source, the build keeps compiling. Sourcegen is a first-class field in bleep.yaml — bleep runs your generator, hashes inputs, recompiles when needed, and never leaves stale generated code behind on failure.

After compile02

Run a program against the artifacts.

Publish them, sign them, ship them, package them, post a release note. Scripts are regular Java, Kotlin, or Scala programs registered in bleep.yaml. They have a main. You debug them with breakpoints. They get a typed handle on the resolved build model. There is no privileged layer of magic dust between you and the JVM.

The liberating part isn’t the syntax. It’s that you stop forcing every random thing into the build. Compile. Follow the graph. Then say what you want in code.

The specimen

What declarative actually looks like.

A real bleep.yaml. Not pseudocode. Not a marketing render. Anyone on your team can read this and tell you exactly what the build does — without launching anything.

your-first-kotlin-project
$schema: https://raw.githubusercontent.com/oyvindberg/bleep/master/schema.json
$version: 1.0.0-M9
jvm:
name: graalvm-community:25.0.1
projects:
myapp:
extends: template-common
platform:
mainClass: com.example.MainKt
myapp-test:
dependencies:
- io.kotest:kotest-runner-junit5-jvm:5.8.0
- org.junit.jupiter:junit-jupiter:5.10.1
dependsOn: myapp
extends: template-common
isTestProject: true
templates:
template-common:
kotlin:
jvmTarget: '25'
version: 2.3.0
platform:
name: jvm
Two projects. One template. Plain text.An app (myapp) and its tests (myapp-test), both extending template-common. Tens of lines, no plugins, no build.gradle.kts.
Tests are projects.myapp-test is just another project. It depends onmyapp, picks up the template defaults, and flipsisTestProject: true. No Test/test/itTest/Compilescope dance. No second build file.
Bump Kotlin in one line.Move 2.3.0 to 2.4.0 in template-common and every project that extends it follows. Code review tells you exactly what changed — in plain text, with no graph viewer.
This is a real test fixture.The YAML on the left is loaded fromdocs-snippets-from-tests/your-first-kotlin-project/bleep.yaml— a workspace bleep’s own integration tests build, compile, and run end-to-end on every commit. Not a brochure.
Round-trip

Read it. Change it. Write it back.

Because bleep.yaml is data, the build tool can do to it what any other tool can do to a file: read, transform, write. No DSL to interpret. No plugin lifecycle to mutate. Just the file and a small library of commands that round-trip cleanly through the same model bleep itself uses.

Inspectshow · diff · invalidated · evicted
Tests

A test runner that shows its work.

You don’t watch a build tool think about tests for two minutes and get a fifty-thousand-line transcript dumped at the end. You watch suites compile, watch them run, see failures the second they happen, and walk away with a precise summary you can act on.

Massively parallel

Test suites run in forked JVMs across every available CPU. Each test project gets its own classpath, its own JVM, its own lifecycle. The bottleneck is your hardware, not the build tool.

Live TUI

The terminal shows which suites are compiling, which are running, which finished, which failed. Failures land the instant they happen, not at the end of the run. Pass --no-tui for plain CI logs.

Precise summary

When the run ends, you get exact suite and test names, pass/fail counts per project, and the diff against the previous run — not a wall of stdout you have to grep through. JUnit XML is one flag away (--junit-report).

Tooling for the future

Built for the agents next to you.

Claude Code, Cursor, and the next generation of dev tools talk to bleep through MCP — the Model Context Protocol. One command (bleep setup-mcp-server) and an agent can compile, test, run, and inspect your build through 18 structured tool calls. The design assumptions are blunt: more than one agent will be running at once, tokens are scarce, and any tool that takes seconds blocks every agent attached to it.

Performance

Four parallel agents on the same build mean four parallel tool calls. If the build tool is slow, every one of them stalls — aggregate latency multiplies. Bleep’s MCP server runs in-process against the BSP daemon. Every call is sub-second after warmup, sub-100ms once warm.

Ease

bleep setup-mcp-server writes.mcp.json in your build root. Any MCP client picks it up automatically. No adapter to configure, no protocol to translate — bleep speaks MCP natively.

Structured output

Every tool returns a compact JSON summary by default — error counts, failure suites, the diff against the previous run. Full diagnostics are one extra call away. Per-project errors stream as MCP notifications the instant a project finishes, not at the end. Latency floor for surfacing a real problem: milliseconds.

We don’t want a build tool that lets you do anything. We want a build tool that lets you do the obvious thing, in a file that anyone on the team can read.

By the numbers

Small numbers, on purpose.

Cold start10msNative CLI. No JVM warmup, no daemon to wake, no Gradle daemon to forget about.
IDE import~1secIntelliJ and Metals over BSP. You hit import, you start typing.
Build files1One bleep.yaml. Not a tree of build.sbt,plugins.sbt, project/, and a Dependencies.scala.
Lines of build code0Custom logic lives in scripts: real programs, with a main and a debugger.
Stop fighting your build

One line. One file. Get on with your day.

Bleep is open source under Apache 2.0. Java, Kotlin, and Scala on the JVM. Cross-build to JS and Native if you want. Or don’t.

$curl -fsSL https://bleep.build/install | sh