1.1 CLI Survival Kit
The command line is where Bazel stops being a repository you can read and becomes a tool you can operate. At first, this section can look like a bag of verbs and flags: build, test, run, query, info, clean, fetch, --keep_going. A more useful daily model is to choose the outcome you want, understand which Bazel state the command is reusing, and classify failures before you start changing files.
Start with the outcome, not the implementation. build, test, and run ask
Bazel to produce or execute a target. query asks about declared targets and
dependencies. info, shutdown, and clean inspect or change Bazel's own
state. You do not need every flag in memory. You need to know which kind of
answer you expect from the command you chose.
The Survival Loop
The section is ordered like a real operator loop: choose an outcome, understand the state behind it, shape the request when the repo gets large, then triage the result.
First come the everyday verbs. 1.1.1 Commands separates build, test, and run by outcome: artifacts, supervised test execution, or one launched process. 1.1.2 bazel run & Runfiles then slows down on the process case, because running a Bazel-built executable is not the same as manually executing a file under bazel-bin. Runfiles, program arguments, and working directory rules become part of the operator contract.
The next cluster is state. 1.1.3 Server/Client Architecture explains why the first command after startup often feels slow and the next command can feel fast. 1.1.4 Inspecting Server State is an optional observability layer that shows you which state lives on disk and which state lives only in the running server. 1.1.7 bazel info gives you the locator command for paths, server metadata, and output locations, while 1.1.6 bazel clean becomes much less tempting once you know exactly what state it removes.
After that, the section turns to command shaping. 1.1.5 --keep_going (-k) makes wide requests report more independent failures. 1.1.8 Basic Query inspects the graph before building it. 1.1.11 bazel fetch separates external dependency setup from the normal build or test loop.
Finally, the section gives you the first triage and ergonomics layer. 1.1.9 Exit Codes tells automation which result bucket the command landed in. 1.1.10 Common Error Messages teaches the human to classify the failing layer before editing files. 1.1.12 Shell Tab Completion is intentionally last and extra: useful once the basic loop is familiar, especially when query-backed label completion turns the graph into command-line assistance.
Read Each Command By Its Outcome
Level 0 taught the coordinate system: repository roots, packages, labels, target patterns, and BUILD-file declarations. Level 1 puts that coordinate system under your fingers. bazel build //app:server, bazel test //..., and bazel query 'deps(//app:runner)' all use the same naming world, but they ask different questions of it.
That is why target patterns from 0.2.3 Target Patterns matter before most flags do. //... selects Bazel targets rather than scripts in a folder. deps(...) follows declared dependency edges rather than searching the filesystem. bazel run resolves one runnable target and then launches it. State commands inspect or reset the server and its files without requesting a target result.
The same model keeps flags in proportion. --keep_going does not make a failed command successful. It asks Bazel to report more independent failures from the same broad request. --nofetch does not change which targets you requested. It controls whether missing external repos may be downloaded during the command. bazel clean does not repair build logic. It deletes specific local state and forces later commands to rebuild or reanalyze more work.
Why This Feels Strange At First
Most early surprises come from carrying habits from other tools into Bazel's CLI.
The first habit is assuming that a command runs in the directory where you typed it. 1.1.2 bazel run & Runfiles shows why that is not always true: a program launched with bazel run sees a runfiles-centered runtime environment. If the binary needs files, they belong in data, and portable lookup matters more than guessing a relative path.
The second habit is treating repeated commands as independent. 1.1.3 Server/Client Architecture breaks that assumption. Two commands can feel different because the second one reused a warm server and analysis cache, not because Bazel became inconsistent. The companion habit is overusing 1.1.6 bazel clean whenever something feels odd. In Bazel, routine cleaning is usually a smell, because it discards exactly the state that makes the operator loop fast.
The third habit is reacting to a long error message as if every line has equal weight. 1.1.10 Common Error Messages teaches the better first move: classify the layer. Is the package missing? Is the target missing inside a package? Did visibility reject an otherwise valid edge? Did Starlark evaluation throw a traceback? Did toolchain resolution fail? Once you know the layer, the next action is much less random.
How To Read The Section
If you are new to Bazel as a daily user, read 1.1.1 Commands and 1.1.2 bazel run & Runfiles first. Those two articles explain the basic outcome choices: produce an artifact, run tests, or launch one executable. Then read 1.1.3 Server/Client Architecture, 1.1.7 bazel info, and 1.1.6 bazel clean together. They form the state model: why commands get faster, where outputs and server state live, and what different reset commands remove.
If you are trying to make a repository-wide command useful, jump to 1.1.5 --keep_going (-k) and 1.1.8 Basic Query. They teach the first two ways to get more signal from a large repo: keep independent work moving after failures, and inspect the graph before building. If your failures mention external repositories, read 1.1.11 bazel fetch before debugging application code.
If you are wiring automation, read 1.1.9 Exit Codes before 1.1.10 Common Error Messages. Scripts need the numeric result first. Humans need the message shape next. If your immediate job is mostly testing, this section gives you the CLI base and then 1.2 Testing Strategy takes over with test-specific caching, tags, sizes, output, coverage, and golden-file patterns.
The CLI survival kit gives you an operating model for Bazel: build-facing invocations address targets, while state commands inspect or reset the server and its files. Once you can name the requested outcome, the state involved, and the failure class, the daily CLI becomes predictable enough to build real workflow on top.
Sections in this chapter · 12
The everyday build, test, and run commands and how their outcomes differ.
Running one target with program arguments, resolving runfiles, and handling Bazel's runtime working directory.
The short-lived client, the server keyed by output_base, and the cold-versus-warm command lifecycle.
Inspectable Bazel server state: what lives under output_base and what only lives in the running server.
Continuing past independent failures with --keep_going so one invocation reports more breakages.
Resetting local Bazel build state with clean, --expunge, and narrower alternatives.
Using bazel info to retrieve authoritative workspace, output, execution, and server paths.
Using basic bazel query to inventory declared targets and inspect deps() without building.
Classifying command outcomes by exit code before deciding whether automation should fail, retry, or report.
First-action triage with runnable reproductions for common loading, analysis, compilation, platform, and execution errors.
Prefetching external repositories with bazel fetch for CI, offline work, and dependency diagnosis.
Shell completion for Bazel commands, plus optional query-backed target-label completion.