Skip to main content
Bazel is famously extensible, and almost all of that extensibility points inward, at defining new rules. The part of your build that engineers actually touch every day sits outside Bazel: the CLI they type, the scripts that wrap it, the BUILD files somebody has to write, and the CI plumbing that decides what they see when it breaks. That layer is usually Bash, Make, and YAML, and every monorepo grows its own. AXL, the Aspect Extension Language, is a Starlark dialect built into the open-source Aspect CLI. It’s how you program that outside layer: custom subcommands, BUILD generators, and the reporting that comes back from CI. Same language as your .bzl files. No Go plugin to compile, no new YAML schema to learn.

What you’ll build

By the end of this course you’ll have written, and run, all of the following against a real Bazel repository:
  • A custom aspect subcommand with typed arguments, phases, and a proper exit code.
  • A task that drives Bazel and reads its Build Event Stream live, target by target.
  • Repository-wide policy in .aspect/config.axl: flags, task defaults, pre- and post-task hooks, and rewritten repro commands.
  • A BUILD file generator in Starlark that encodes your repo’s conventions, including cross-package dependency resolution.
  • A CI integration that posts lint findings as inline comments on a pull request, plus a status surface of your own, written in about twenty lines.

Who it’s for

Bazel users of all experience levels. Newcomers curious about Starlark will be fine; platform and developer-experience teams looking to standardize how their engineers interact with Bazel are the people this was written for. Comfort with BUILD files and labels helps. Prior Starlark experience is not required, and we’ll flag the places where AXL differs from the Starlark you already know.

Prerequisites

  • Git and a terminal.
  • Bazelisk, so .bazelversion is honored. See installing Bazel.
  • The Aspect CLI. One line, no account needed:
    See How to install the Aspect CLI for Homebrew, npm, and the tools/bazel wrapper.
  • Roughly 2 GB of disk for the Bazel output base, and a network connection for the first build.
Everything in this course is free and open source. An Aspect account unlocks the CI integrations in the last two modules, and it’s also free. We cover that when we get there.

Course contents

Why AXL

The glue layer every monorepo grows, why it’s always Bash, and what changes when the outside of Bazel gets an extension language.

Set up the lab

Clone a starter repo, pin the CLI version, and run the built-in tasks so you know what “working” looks like.

Your first task

Write a task, give it typed arguments, run a subprocess, read the environment, and return a verdict.

Driving Bazel

Query the graph, build and test targets, and consume the Build Event Stream as it arrives.

Configuring the CLI

config.axl: flags, task defaults, aliases, traits, features, lifecycle hooks, and tips.

BUILD file generation

Teach Gazelle your conventions in Starlark, including resolving imports to labels across packages.

Reporting into CI

Status checks, a live PR summary, inline lint findings with one-click fixes, and a surface of your own.

Connect an account

What an Aspect account turns on: the VCS integrations, a remote cache, the Build and Test UI, and build results over MCP.

Where to go next

Shipping AXL to other repos, the reference docs, and how to get help.

Running this as a 90-minute workshop

The nine modules are sized for a single session, with the three headline exercises (a subcommand, a generator, a CI integration) weighted heaviest: Every module ends with the complete file, so anyone who falls behind can paste and catch up at the next section boundary.
Run the setup module before the session if you can. The first Bazel build downloads a toolchain, a prebuilt Gazelle, and ShellCheck, which is the one part of this course that conference WiFi can make miserable.