Pre-built binary
We recommend that developers execute a pre-compiled binary.- You could create a custom workflow for your repository to build the binary when needed, for the right architectures, and then publish it somewhere that your developers use. Consider creating a
tools/gazelleredirect in the repo to make it easy to locate - see run tools installed by bazel - Much easier: use the
aspect gazelletask in the free Aspect CLI, which runs the pre-built aspect-gazelle binaries, no compilation required. See the aspect gazelle task for setup and the built-in language extensions. This includes the ability to write extensions in Starlark, which we’ll explore extensively.
Using aspect_gazelle_prebuilt
The prebuilt binary is distributed as a Bazel module, so wiring it up is two snippets. The aspect_gazelle_prebuilt README documents how to wire up the aspect_gazelle() macro and all its options. Add the dependency to MODULE.bazel:
//tools/gazelle, selecting the languages your repo uses:
languages entirely to get the default set (visibility_extension, proto, starlark, python, js). The valid language keys are buf, cc, go, js, kotlin, orion, proto, python, starlark, and visibility_extension.
That target is what aspect gazelle runs by default. Crucially, this is the binary that interprets the Starlark (.axl) extensions we write later in the course — building from source (below) cannot run them.
Enabling the go language requires some extra repo_config and go_deps wiring — see the aspect_gazelle_prebuilt README for the details.
Why prefer the prebuilt binary over building from source?
- No Go toolchain download and no first-run compile — developers fetch a cached artifact instead.
- It bundles all the common, well-written language extensions, including support for the orion Gazelle language for writing your own extensions in Starlark/AXL.
- It avoids the bootstrapping trap: a broken
BUILDfile referenced by your gazelle binary’sloadstatements can otherwise prevent gazelle from compiling, and therefore from fixing that file.
Building from source
Drawbacks of building from source
- Bootstrapping trap — broken
BUILDfiles referenced (even transitively) byloadstatements prevent Gazelle from compiling, so it can’t fix the very files it needs to run. - Slow cold starts — Bazel adds latency for analysis-cache rebuilds and external-repo fetches; a prebuilt artifact skips both.
- Rebuild on every extension change — any edit to a first-party Go extension forces all developers to recompile the binary.
- cgo portability — the Go toolchain is hermetic under Bazel but cgo is not (without extra work). Extensions that need it (such as rules_python) may not compile on all developer machines. See this PR.
- Unnecessary Go toolchain — repos without Go code still pull down the Go toolchain and all its complexity.
Checking on CI
CI steps should verify that the repository is “gazelle-clean” in case developers haven’t run the tool. Passwith_check = True to aspect_gazelle() to generate a companion <name>.check target that runs Gazelle in diff mode — it makes no changes, prints a diff of what would change, and exits non-zero if any BUILD file is stale:

