Skip to content

Why Bazelle?

The Problem

Setting up Gazelle with multiple languages is complex:

❌ Without Bazelle:
├── Configure rules_go
├── Configure gazelle
├── Find and add gazelle_cc
├── Find and add kotlin gazelle extension (which one?)
├── Find and add python gazelle extension (rules_python_gazelle_plugin?)
├── Wire up all extensions in WORKSPACE/MODULE.bazel
├── Create gazelle targets manually
├── Figure out directives for each language
└── Hope they all work together...

The Solution

Bazelle bundles everything into a single binary:

✅ With Bazelle:
├── bazelle init
├── bazelle update
└── Done.

Before & After

MODULE.bazel
# 50+ lines of boilerplate...
bazel_dep(name = "rules_go", version = "0.59.0")
bazel_dep(name = "gazelle", version = "0.47.0")
bazel_dep(name = "rules_kotlin", version = "2.2.2")
bazel_dep(name = "rules_python", version = "1.8.0")
bazel_dep(name = "rules_python_gazelle_plugin", version = "1.6.3")
# ... more deps, more configuration
# Then wire up extensions...
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
# ... more extension wiring
BUILD.bazel
load("@gazelle//:def.bzl", "gazelle")
load("@rules_python_gazelle_plugin//:def.bzl", "python_gazelle")
# ... more loads
gazelle(
name = "gazelle",
# ... lots of configuration
)

Feature Comparison

FeatureRaw GazelleBazelle
Go support✅ Built-in✅ Built-in
Proto support✅ Built-in✅ Built-in
Kotlin support⚠️ Find & configure plugin✅ Built-in, enable with directive
Python support⚠️ Multiple options, complex setup✅ Built-in, enable with directive
C/C++ support⚠️ Find gazelle_cc, configure✅ Built-in, enable with directive
Incremental updates❌ Full scan every time✅ Only changed directories
Watch mode❌ Not available✅ Built-in file watcher
Project init❌ Manual setupbazelle init
CI check mode⚠️ Manual diff setup--check flag
Single binary❌ Multiple dependencies✅ One binary, all extensions

How It Works

┌─────────────────────────────────────────────────────────────┐
│ Bazelle CLI │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ init │ │ update │ │ fix │ │ watch │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ └───────────┴───────────┴───────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Gazelle Runner │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────┐ ┌──────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │ Go │ │Proto │ │ Kotlin │ │ Python │ │ C/C++ │ │
│ │(core)│ │(core)│ │(gazelle- │ │(gazelle- │ │(gazelle│ │
│ │ │ │ │ │ kotlin) │ │ python) │ │ _cc) │ │
│ └──────┘ └──────┘ └──────────┘ └──────────┘ └────────┘ │
│ │
│ All extensions pre-configured │
└─────────────────────────────────────────────────────────────┘

Real-World Example

A typical monorepo with Go, Kotlin, and Python:

my-company/
├── MODULE.bazel
├── BUILD.bazel # gazelle:kotlin_enabled true
│ # gazelle:python_enabled true
├── services/
│ ├── api/ # Go service
│ │ ├── main.go
│ │ └── BUILD.bazel # ← generated: go_binary
│ └── auth/ # Kotlin service
│ └── src/main/kotlin/
│ └── Auth.kt
│ └── BUILD.bazel # ← generated: kt_jvm_library
├── libs/
│ └── ml/ # Python library
│ ├── model.py
│ └── BUILD.bazel # ← generated: py_library
└── proto/
└── api.proto
└── BUILD.bazel # ← generated: proto_library

One command updates all BUILD files:

Terminal window
bazelle update

Time Savings

TaskManual SetupWith Bazelle
Initial project setupHoursMinutes
Adding a new language30+ minutes1 directive
Updating BUILD filesRun gazelle, check configbazelle update
CI integrationCustom scriptsbazelle update --check
New developer onboardingRead docs, understand setupbazelle init && bazelle update

Get Started

Installation

Build from source or download.

Install →