aspect run builds a target and runs the resulting binary, as bazel run does, inside the Aspect task lifecycle: health checks, status reporting and task hooks, the same as aspect build.
-- go to the binary unchanged. The binary runs with the args and env attributes of its target, the way bazel run runs it.
Flag passthrough
Type Bazel flags directly. A flag thataspect run doesn’t define itself is forwarded to Bazel, in the slot you typed it in:
Both spellings of a value work,
--jobs=8 and --jobs 8, as do short forms such as -c opt. Changing startup options restarts the Bazel server.
The rule is the same for every task that runs Bazel. A flag the task does define is the task’s, so when a Bazel flag has the same name as one of the task’s own, pass it with --bazel-flag (or --bazel-startup-flag for a startup option):
Options
Set
--run-in for a binary that resolves file arguments against its working directory instead of $BUILD_WORKSPACE_DIRECTORY, such as a bare Go binary with no shell wrapper.
Watch mode
Pass--watch to keep the binary current while you edit. The task watches the Bazel workspace and rebuilds the target after each settled batch of file changes:
- Successful rebuild that changes the target’s runfiles: unless the binary uses the ibazel protocol or the Incremental Build Protocol, the task terminates the running process tree and starts the new executable with the same arguments.
- Successful rebuild with unchanged runfiles: the current process keeps running, and the task reports the target as unchanged. An edit that doesn’t affect the binary or its runfiles, such as a change to an unrelated package, doesn’t restart it.
- Failed rebuild: the current process keeps running, and the task waits for the next change.
- Target exits on its own: the task reports the exit code and keeps watching. The next successful rebuild starts it again.
ibazel_notify_changestag: the task uses the ibazel protocol and notifies the target on stdin.- Otherwise: the task offers the Incremental Build Protocol. The
supports_incremental_build_protocoltag makes the connection required. - No protocol in use: the task restarts the target when its runfiles change.
.git, .jj and Bazel’s convenience symlinks (bazel-bin, bazel-out and so on) don’t trigger a rebuild. Stop the task with Ctrl-C.
On Linux and macOS the task starts the target in its own process group and terminates the whole group on restart, so child processes the binary spawned stop too. On Windows it terminates only the immediate child process, so processes that the binary starts can outlive a restart.
Without --watch, aspect run builds and runs the target once.
ibazel protocol
aspect run --watch speaks the live-reload protocol of ibazel (bazel-watcher). Targets written for ibazel run, such as dev servers that reload when they read a notification on stdin, work with aspect run --watch without changes.
To opt a target in, add the ibazel_notify_changes tag:
- Sets
IBAZEL_NOTIFY_CHANGES=yin the target’s environment and connects a pipe to its stdin. - Writes
IBAZEL_BUILD_STARTEDto stdin when a rebuild starts. - Writes
IBAZEL_BUILD_COMPLETED SUCCESSorIBAZEL_BUILD_COMPLETED FAILUREto stdin when the rebuild finishes, including after failed builds. - Keeps the process running after the notification. The target decides how to reload.
supports_incremental_build_protocol. The ibazel protocol works on every platform, including Windows.
Incremental Build Protocol
A binary that implements the Incremental Build Protocol (IBP) can apply changes in place instead of being restarted. Dev servers and bundlers with hot reload use this to keep their state across rebuilds. In watch mode, the task opens a Unix socket and passes its path to the binary in theIBP_WATCH_SOCKET_FILE environment variable. The task also sets ABAZEL_WATCH_SOCKET_FILE to the same path for older clients. When the binary connects, the two sides negotiate a protocol version and a change scope. After each build, the task sends the changed files to the running process as a cycle message rather than killing it.
To require the protocol for a target, add the supports_incremental_build_protocol tag:
- Tagged targets: the task waits for the binary to connect. If it doesn’t connect within the timeout, or negotiation fails,
aspect runstops the target and fails. - Untagged targets: the socket variables are still set. If the binary connects, the task uses the protocol. If negotiation fails, the task warns and falls back to process restarts for the rest of the session.
If the client requests both, the task uses
sources.
The task still restarts the process when a restart is required: when the target’s executable or entrypoint changes, when it can’t determine the change set (for example after a full rescan), or when sending an update fails. A build with no changes in the negotiated scope leaves the process running unchanged.
Set ASPECT_WATCH_CONNECTION_TIMEOUT_MS to change how long the task waits for a tagged binary to connect. The default is 10000 (10 seconds). The value must be a positive integer:
When to use aspect run
- Local development: the same lifecycle and output as
aspect buildandaspect test. - CI steps: running a binary as a pipeline step reports like a build or test step.
- One-off tools: run a binary built from source without a wrapper script.
- Iterating on a service:
--watchrebuilds and restarts or reloads it as you edit, including targets built for ibazel.
aspect run waits for the binary to exit, so start long-running services in CI some other way.

