aspect gazelle runs Gazelle (or aspect_gazelle_prebuilt, for Starlark-defined extensions) to generate and synchronize your repository’s BUILD files. In CI it detects whether BUILD files are out of sync with source code and fails the step if so — preventing drift before it accumulates into a bigger cleanup.
Running aspect gazelle locally applies fixes in place. Same command, different behavior based on context — --check-only defaults to true on CI and false locally.
Setup: choosing a gazelle binary
aspect gazelle drives a Gazelle binary that you point it at with --gazelle-target (default //tools/gazelle:gazelle). There are two ways to provide that binary, and aspect gazelle supports both.
Prebuilt binary (recommended)
aspect_gazelle_prebuilt fetches a precompiled Gazelle binary from the aspect-gazelle releases. No Go toolchain and no compile step are required, and it is the only binary that can run Starlark/AXL extensions.
MODULE.bazel
tools/gazelle/BUILD.bazel
- No Go toolchain download, and no first-run compile of the gazelle binary — developers fetch a cached prebuilt artifact instead.
- Runs Starlark/AXL extensions, so you can write generators without the Go extension API.
- Exposes prebuilt-only flags like
-progressand-cache(see Additional Gazelle flags). - Avoids the bootstrapping trap where a broken
BUILDfile referenced by your gazelle binary’sloadstatements prevents gazelle from compiling — and therefore from fixing that file.
Building from source
Build Gazelle with the upstreamgazelle_binary macro from bazel-contrib/bazel-gazelle, composing whatever language extensions you need (including custom first-party Go extensions). This requires a Go toolchain.
tools/gazelle/BUILD.bazel
- Full control: compose any language extension and write custom generators against Gazelle’s Go
Languageinterface. - No dependency on which extensions ship in the prebuilt binary.
Incremental mode: only touch changed directories
For large repos, running Gazelle over the entire tree on every PR is slow.--scope=changed (available when --scope-all-on-change patterns aren’t matched) restricts Gazelle to directories containing changed files:
BUILD.bazel or MODULE.bazel escalate to --scope=all because those files can affect dependency resolution across the entire repo. Configure which patterns trigger escalation:
.aspect/config.axl
How drift detection works
aspect gazelle runs Gazelle with -mode=diff internally regardless of other flags. This is the key:
- Gazelle runs once with
-mode=diff— it produces a unified diff without writing any files - The task parses the diff to determine if BUILD files are out of sync (exit code from Gazelle isn’t reliable — the task uses stdout content)
- On CI (
--check-only=true): if the diff is non-empty, the task exits 1 - Locally (
--check-only=false): the task applies the diff viagit apply -p0
Configuration
Gazelle target
.aspect/config.axl
//tools/gazelle:gazelle.
Reacting to drift
Additional Gazelle flags
Pass extra flags to the Gazelle binary (any-mode flag is stripped internally since the task controls that):
-index=lazy pairs well with --scope=changed for the best incremental performance: Gazelle only indexes the packages it visits rather than the whole repo.
Patch upload
.aspect/config.axl
gazelle.patch when drift is detected, so developers can apply it locally.

