4.3 Starlark Development Tools
You change a macro, run bazel build //app:all, and the failure points at a generated genrule you did not write by hand. Or you add print(ctx.attr.deps) to a rule implementation and see nothing the second time. Or review gets stuck on BUILD-file formatting until someone finally runs Buildifier. Starlark development feels confusing when every symptom is treated as one generic "debugging" problem.
This section is a routing guide. Before choosing a tool, write the question in one sentence. "What did this macro generate?" is not the same question as "what value did this rule see?" or "is this .bzl file mechanically clean?" The right tool is usually the one that can observe the smallest layer that contains the answer.
The Diagnostic Ladder
At the bottom is a temporary probe. 4.3.1 Print Debugging answers "what value did this macro or rule implementation see while Bazel was loading or analyzing Starlark?" It is fast and narrow: good for ctx.attr, ctx.files, provider values, labels, and branch flow. Wrong for action stdout, sandbox paths, generated file contents, or final tool behavior.
The next layer is loaded target shape. 4.3.2 Macro Expansion Inspection answers "what target did this macro actually leave behind?" Legacy macros disappear after loading, so the BUILD file shows the call site while the loaded graph contains ordinary rule targets. bazel query --output=build //pkg:target gives the BUILD-like view, and generator metadata helps find all targets produced by one macro function.
Then comes source text. 4.3.3 Buildifier — Formatting & Linting is not a provider debugger or configured-graph inspector. It keeps BUILD, WORKSPACE, and .bzl files in canonical shape, applies Starlark lint checks, and makes later tooling more reliable. For many repositories, the right move before review is simply buildifier -r ., with editor and CI integration so formatting stops being a conversation.
The daily loop sits above that. 4.3.4 LSP / IDE Integration brings Buildifier, Starpls or editor-native Starlark support, pinned project tool paths, and Bazel commands into the editor. The IDE should help you navigate, format, and see lightweight diagnostics. Bazel remains the authority for package loading, macro expansion, configured targets, and registered actions.
Use interactive tools after the cheap lenses have narrowed the question. 4.3.5 Starlark Debugger lets you attach to a Bazel invocation, set breakpoints, step through loading or analysis logic, and inspect Starlark state. Reach for it after print(), macro expansion inspection, and editor feedback leave the actual path through the .bzl code unclear. 4.3.6 Starlark REPL / Playground is the scratchpad for pure Starlark questions: helper functions, list and dict behavior, equality, ordering, or Python habits that may not hold. Do not use it as proof for label resolution, select(), ctx, providers, toolchains, or actions. Neither replaces query, cquery, aquery, sandbox debugging, analysis tests, or integration tests.
Stop When The Question Leaves The Layer
Most Starlark tooling mistakes keep using the first tool after the question has moved. A macro problem is not automatically a rule problem. A rule implementation value is not action execution output. A formatted .bzl file is not necessarily a well-designed public API. A language server warning is useful, but it is not the same thing as Bazel successfully analyzing the requested target.
If the question grows from one macro-produced target into graph structure, move from 4.3.2 Macro Expansion Inspection toward 5.2.1 bazel query — Static Graph Analysis. If the question is about selected select() branches, configured providers, or action registration, leave this section for 5.2.2 bazel cquery — Configured Graph, 5.2.3 bazel aquery — Action Graph, and 5.2.4 bazel config — Configuration Inspection. Layer discipline keeps each tool sharp instead of turning every failure into a full archaeology session.
Keep the tools small on purpose. print() is a temporary probe, not a logging framework. Buildifier is the mechanical first reviewer, not a judge of rule design. The IDE is a fast local assistant, not the source of truth. The debugger is worth its setup cost only when stepping through evaluated Starlark logic will answer the question.
Use It By Situation
For active macro or rule debugging, start with 4.3.1 Print Debugging and 4.3.2 Macro Expansion Inspection. For repository hygiene, read 4.3.3 Buildifier — Formatting & Linting and 4.3.4 LSP / IDE Integration as one operational pair connected to 3.5 Developer Experience & Local Tooling. Treat 4.3.5 Starlark Debugger and 4.3.6 Starlark REPL / Playground as specialist tools whose value comes from staying in a narrow lane.
Classify: Match each question to the narrowest useful feedback tool: What value did this rule see? What target did this macro generate? Is this file mechanically clean? Where is this symbol defined? Which branch did this code take? Does this pure helper behave as expected?
Reveal
Use a temporary print() for an observed Starlark value, macro-expansion tooling for generated declarations, Buildifier for mechanical formatting and lint, and the language server for symbol navigation. Use the Starlark debugger when control flow requires stepping, and the REPL for isolated pure-language experiments. If the question moves into configured providers or registered actions, switch to cquery or aquery instead of stretching these tools beyond their layer.
Starlark development tools are lenses over different layers of Bazel work: source text, loading, analysis, editor navigation, interactive stepping, and pure language experimentation. Choose the smallest lens that matches the layer you are investigating, then switch tools as soon as the question crosses a phase boundary.
Sections in this chapter · 6
Using print() to inspect values during the loading and analysis phases
Seeing what rules a macro actually generates with bazel query --output=build
De facto standard tool for formatting and linting BUILD and .bzl files
Language server and editor plugin options for Starlark development
Stepping through .bzl files with breakpoints via the DAP protocol
Interactive Starlark environments for quick syntax experiments