Skip to main content
Bazel is famously extensible, and almost all of that extensibility points inward, at defining new rules. A large part of your build that engineers touch every day sits outside Bazel: the CLI they type, the scripts that wrap it, and the plumbing that decides what they see when it breaks. None of that is rules, and you don’t get to use Starlark for any of it. The wrappers are Bash and Make, the pipelines are YAML. One artifact that is Starlark — your BUILD files — is the one you don’t get to program: you write them out by hand, or you generate them from a Gazelle extension in Go. AXL, the Aspect Extension Language, is a Starlark dialect built into the open-source Aspect CLI. It’s how you program that outside layer. Same language as your .bzl files, with types, records and enums on top. No Go plugin to compile, no new YAML schema.

How this course works

You won’t type AXL from a tutorial. Each section starts with a git checkout, and the code arrives already written and already working. You read the diff, run the commands, change one thing, and watch what moves.
That’s deliberate. Transcribing Starlark from a web page teaches typing. Reading real code and then breaking it on purpose teaches the API. How much arrives varies a lot. The first command, .aspect/changed.axl, is 49 lines and you should read all of it. impact.axl is 294 lines, 93 of them docstrings explaining traps that are not obvious, and policy.axl is 222. observe.axl is 344 lines and arrives with five smaller snapshots beside it, which is how you should read it. Each section points you at the functions that matter rather than pretending you’ll read the whole file mid-workshop — the rest is there when you want it.

A theme worth naming

Bazel will write both of its richest streams to a file — --build_event_json_file for the Build Event Protocol, --execution_log_compact_file for the execution log. No service required, and no particular language. What they do need is a program to read them, and standing one up is enough friction that the work usually ends up somewhere else: a BES endpoint, a CI job, a future dashboard. AXL puts that processing in the tool that ran the build, on the machine that ran it, while it is still running. Logic that may otherwise be specific to your CI — or to a script you maintain by hand — is programmable in Starlark, and can be run locally or on CI with the same command. That shift left is what this course is about, and it matters more now that the other thing on that machine is an agent: anything you can compute locally, agents can use immediately.

What you’ll have built

  • aspect changed and aspect impact — what you’re touching, and which tests it could break, computed from your uncommitted working tree
  • aspect policy — an architecture rule that exits non-zero, modelled as a CI gate to land
  • A task that spawns Bazel and reads both of its structured streams — live, and both complete
  • The same analysis attached to aspect test without rewriting it
  • A Gazelle extension in Starlark that generates deployment targets from your own convention
  • A container image, pushed with a delivery command

Prerequisites

  • macOS or Linux. The Aspect CLI does not currently support Windows — contact us if you need it.
  • Git and a terminal.
  • Bazelisk, so .bazelversion is honored. See installing Bazelisk.
  • The Aspect CLI — the first section installs it. One line, no account.
  • Admin rights on the machine. The install script finishes with sudo mv into /usr/local/bin, and the first Bazel command writes to your home cache.
  • jq — required, not optional. brew install jq, or your package manager. Several steps use jq to compute the answer the prose quotes, not just to pretty-print it, so without it the transcripts don’t line up.
The very first bazel command in section 4 is a network event, not a compile: Bazelisk downloads Bazel 9.3.0 (about 70 MB, per .bazelversion) before anything else happens, then Bazel fetches rules_go, gazelle and the Go SDK 1.25.1 (about 58 MB) one after another. Start it early — that section tells you exactly when. Comfort with BUILD files and labels helps. Prior Starlark experience is not required, and the places AXL differs from Bazel’s dialect are flagged as they come up.

Course contents

Install the CLI

The launcher, the CLI it fetches, and pinning a version for a repository.

A project with one file

aspect describe against a repository with no Bazel workspace at all.

A repository with a build in it

Fast-forward to a Go monorepo with real dependency depth, and start it warming.

Your first command

Fifty lines of AXL, typed arguments, and which stream a command’s contract lives on.

What does my working tree affect?

Changed files to labels to reverse-dependency queries — and exactly where it stops working.

A rule you can actually enforce

Layering rules as data, typed query results, and a non-zero exit code.

Watch Bazel work

Spawn Bazel yourself and read both structured streams, live and complete.

You won't ship that

Attach the same analysis to the commands you already run, without rewriting them.

Generate it, then ship it

A Gazelle extension in Starlark for your own convention, and a container pushed with a delivery command.

Hand it to an agent

An agent discovers everything you wrote, with no manifest and no network.