bazel-build-optimization
Install this skill
npx skills add wshobson/agentsWorks across Claude Code, Cursor, Codex, Copilot & Antigravity
Bazel build optimization focuses on accelerating development cycles and deployment speeds in complex, multi-language monorepos. By defining build targets through granular BUILD files and configuring centralized caching, this approach minimizes redundant compilations. It shifts the burden from local hardware to remote execution clusters and storage, ensuring that only modified components trigger re-builds. The process requires careful orchestration of .bazelrc flags and dependency tracking across various runtimes like TypeScript and Python. Mastering this skill involves balancing local resource utilization with high-concurrency CI/CD requirements, resulting in predictable build artifacts and shorter feedback loops for engineering teams operating at scale. This methodology replaces traditional slow build pipelines with an incremental, dependency-aware graph that scales across large codebases without duplicating compute overhead.
When to Use This Skill
- β’Reducing build times in monorepos exceeding thousands of packages
- β’Standardizing build and test environments for distributed global teams
- β’Enforcing strict separation between source code and generated build artifacts
- β’Integrating multiple language ecosystems like Python and TypeScript under one build system
How to Invoke This Skill
Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:
- βOptimize my Bazel build times
- βSetup remote caching for Bazel in a monorepo
- βConfigure .bazelrc for CI performance
- βFix slow Bazel builds and high cache misses
- βDefine custom Bazel rules for my project
Pro Tips
- π‘**Leverage Bazel's Build Event Protocol (BEP)**: Actively use BEP to generate detailed reports and visualize your build graph. This data is crucial for identifying bottlenecks, unused dependencies, and inefficient rule configurations, guiding your optimization efforts strategically.
- π‘**Prioritize Hermeticity for Reproducibility**: Ensure all your Bazel rules and targets are fully hermetic by explicitly declaring all inputs and outputs. This guarantees reproducible builds across different environments and maximizes the effectiveness of remote caching and execution.
- π‘**Fine-Grained Dependencies for Incremental Builds**: Structure your BUILD files with the most granular dependencies possible. This allows Bazel's dependency graph to be highly optimized, leading to significantly faster incremental builds locally and reducing cache invalidations across the team.
What this skill does
- β’Configuring remote caching via gRPC to share artifacts across developer machines and CI
- β’Implementing strict toolchain resolution to ensure reproducible build environments
- β’Parallelizing build tasks across high-core count remote execution nodes
- β’Optimizing incremental compilation through precise dependency graphing
- β’Managing heterogeneous language dependencies within a single workspace
When not to use it
- βSmall projects or micro-repos where the maintenance overhead exceeds the build time savings
- βTeams lacking the DevOps capacity to manage persistent remote cache/execution infrastructure
Example workflow
- Analyze the current build graph to identify common bottlenecks and slow targets
- Configure .bazelrc with appropriate resource limits and remote cache endpoints
- Refactor BUILD files to ensure granular target visibility and dependency tracking
- Set up toolchain resolution for required languages like Python or Node.js
- Validate build performance via the Build Event Service (BES) monitoring
- Enable CI integration to leverage remote execution for test suites
Prerequisites
- βBazel installed locally
- βWorkspace-level build configuration files (.bazelrc, WORKSPACE.bazel)
- βExisting monorepo structure
Pitfalls & limitations
- !Over-bloating the workspace with unnecessary dependencies causing cache thrashing
- !Incorrectly defined BUILD file visibility causing circular dependency errors
- !Non-deterministic build results if toolchain versions are not explicitly pinned
FAQ
How it compares
Unlike manual scripts or generic CI steps that often rebuild the entire repository, this skill enforces a strict, cached graph that only processes modified sub-trees.
π Full skill instructions β original source: wshobson/agents
Production patterns for Bazel in large-scale monorepos.
## When to Use This Skill
- Setting up Bazel for monorepos
- Configuring remote caching/execution
- Optimizing build times
- Writing custom Bazel rules
- Debugging build issues
- Migrating to Bazel
## Core Concepts
### 1. Bazel Architecture
workspace/
βββ WORKSPACE.bazel # External dependencies
βββ .bazelrc # Build configurations
βββ .bazelversion # Bazel version
βββ BUILD.bazel # Root build file
βββ apps/
β βββ web/
β βββ BUILD.bazel
βββ libs/
β βββ utils/
β βββ BUILD.bazel
βββ tools/
βββ bazel/
βββ rules/### 2. Key Concepts
| Concept | Description |
| ----------- | -------------------------------------- |
| **Target** | Buildable unit (library, binary, test) |
| **Package** | Directory with BUILD file |
| **Label** | Target identifier
//path/to:target || **Rule** | Defines how to build a target |
| **Aspect** | Cross-cutting build behavior |
## Templates
### Template 1: WORKSPACE Configuration
# WORKSPACE.bazel
workspace(name = "myproject")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Rules for JavaScript/TypeScript
http_archive(
name = "aspect_rules_js",
sha256 = "...",
strip_prefix = "rules_js-1.34.0",
url = "https://github.com/aspect-build/rules_js/releases/download/v1.34.0/rules_js-v1.34.0.tar.gz",
)
load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies")
rules_js_dependencies()
load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
nodejs_register_toolchains(
name = "nodejs",
node_version = "20.9.0",
)
load("@aspect_rules_js//npm:repositories.bzl", "npm_translate_lock")
npm_translate_lock(
name = "npm",
pnpm_lock = "//:pnpm-lock.yaml",
verify_node_modules_ignored = "//:.bazelignore",
)
load("@npm//:repositories.bzl", "npm_repositories")
npm_repositories()
# Rules for Python
http_archive(
name = "rules_python",
sha256 = "...",
strip_prefix = "rules_python-0.27.0",
url = "https://github.com/bazelbuild/rules_python/releases/download/0.27.0/rules_python-0.27.0.tar.gz",
)
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()### Template 2: .bazelrc Configuration
# .bazelrc
# Build settings
build --enable_platform_specific_config
build --incompatible_enable_cc_toolchain_resolution
build --experimental_strict_conflict_checks
# Performance
build --jobs=auto
build --local_cpu_resources=HOST_CPUS*.75
build --local_ram_resources=HOST_RAM*.75
# Caching
build --disk_cache=~/.cache/bazel-disk
build --repository_cache=~/.cache/bazel-repo
# Remote caching (optional)
build:remote-cache --remote_cache=grpcs://cache.example.com
build:remote-cache --remote_upload_local_results=true
build:remote-cache --remote_timeout=3600
# Remote execution (optional)
build:remote-exec --remote_executor=grpcs://remote.example.com
build:remote-exec --remote_instance_name=projects/myproject/instances/default
build:remote-exec --jobs=500
# Platform configurations
build:linux --platforms=//platforms:linux_x86_64
build:macos --platforms=//platforms:macos_arm64
# CI configuration
build:ci --config=remote-cache
build:ci --build_metadata=ROLE=CI
build:ci --bes_results_url=https://results.example.com/invocation/
build:ci --bes_backend=grpcs://bes.example.com
# Test settings
test --test_output=errors
test --test_summary=detailed
# Coverage
coverage --combined_report=lcov
coverage --instrumentation_filter="//..."
# Convenience aliases
build:opt --compilation_mode=opt
build:dbg --compilation_mode=dbg
# Import user settings
try-import %workspace%/user.bazelrc### Template 3: TypeScript Library BUILD
# libs/utils/BUILD.bazel
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
load("@aspect_rules_js//js:defs.bzl", "js_library")
load("@npm//:defs.bzl", "npm_link_all_packages")
npm_link_all_packages(name = "node_modules")
ts_project(
name = "utils_ts",
srcs = glob(["src/**/*.ts"]),
declaration = True,
source_map = True,
tsconfig = "//:tsconfig.json",
deps = [
":node_modules/@types/node",
],
)
js_library(
name = "utils",
srcs = [":utils_ts"],
visibility = ["//visibility:public"],
)
# Tests
load("@aspect_rules_jest//jest:defs.bzl", "jest_test")
jest_test(
name = "utils_test",
config = "//:jest.config.js",
data = [
":utils",
"//:node_modules/jest",
],
node_modules = "//:node_modules",
)### Template 4: Python Library BUILD
# libs/ml/BUILD.bazel
load("@rules_python//python:defs.bzl", "py_library", "py_test", "py_binary")
load("@pip//:requirements.bzl", "requirement")
py_library(
name = "ml",
srcs = glob(["src/**/*.py"]),
deps = [
requirement("numpy"),
requirement("pandas"),
requirement("scikit-learn"),
"//libs/utils:utils_py",
],
visibility = ["//visibility:public"],
)
py_test(
name = "ml_test",
srcs = glob(["tests/**/*.py"]),
deps = [
":ml",
requirement("pytest"),
],
size = "medium",
timeout = "moderate",
)
py_binary(
name = "train",
srcs = ["train.py"],
deps = [":ml"],
data = ["//data:training_data"],
)### Template 5: Custom Rule for Docker
# tools/bazel/rules/docker.bzl
def _docker_image_impl(ctx):
dockerfile = ctx.file.dockerfile
base_image = ctx.attr.base_image
layers = ctx.files.layers
# Build the image
output = ctx.actions.declare_file(ctx.attr.name + ".tar")
args = ctx.actions.args()
args.add("--dockerfile", dockerfile)
args.add("--output", output)
args.add("--base", base_image)
args.add_all("--layer", layers)
ctx.actions.run(
inputs = [dockerfile] + layers,
outputs = [output],
executable = ctx.executable._builder,
arguments = [args],
mnemonic = "DockerBuild",
progress_message = "Building Docker image %s" % ctx.label,
)
return [DefaultInfo(files = depset([output]))]
docker_image = rule(
implementation = _docker_image_impl,
attrs = {
"dockerfile": attr.label(
allow_single_file = [".dockerfile", "Dockerfile"],
mandatory = True,
),
"base_image": attr.string(mandatory = True),
"layers": attr.label_list(allow_files = True),
"_builder": attr.label(
default = "//tools/docker:builder",
executable = True,
cfg = "exec",
),
},
)### Template 6: Query and Dependency Analysis
# Find all dependencies of a target
bazel query "deps(//apps/web:web)"
# Find reverse dependencies (what depends on this)
bazel query "rdeps(//..., //libs/utils:utils)"
# Find all targets in a package
bazel query "//libs/..."
# Find changed targets since commit
bazel query "rdeps(//..., set($(git diff --name-only HEAD~1 | sed 's/.*/"&"/' | tr '\n' ' ')))"
# Generate dependency graph
bazel query "deps(//apps/web:web)" --output=graph | dot -Tpng > deps.png
# Find all test targets
bazel query "kind('.*_test', //...)"
# Find targets with specific tag
bazel query "attr(tags, 'integration', //...)"
# Compute build graph size
bazel query "deps(//...)" --output=package | wc -l### Template 7: Remote Execution Setup
# platforms/BUILD.bazel
platform(
name = "linux_x86_64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
exec_properties = {
"container-image": "docker://gcr.io/myproject/bazel-worker:latest",
"OSFamily": "Linux",
},
)
platform(
name = "remote_linux",
parents = [":linux_x86_64"],
exec_properties = {
"Pool": "default",
"dockerNetwork": "standard",
},
)
# toolchains/BUILD.bazel
toolchain(
name = "cc_toolchain_linux",
exec_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
target_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
toolchain = "@remotejdk11_linux//:jdk",
toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
)## Performance Optimization
# Profile build
bazel build //... --profile=profile.json
bazel analyze-profile profile.json
# Identify slow actions
bazel build //... --execution_log_json_file=exec_log.json
# Memory profiling
bazel build //... --memory_profile=memory.json
# Skip analysis cache
bazel build //... --notrack_incremental_state## Best Practices
### Do's
- **Use fine-grained targets** - Better caching
- **Pin dependencies** - Reproducible builds
- **Enable remote caching** - Share build artifacts
- **Use visibility wisely** - Enforce architecture
- **Write BUILD files per directory** - Standard convention
### Don'ts
- **Don't use glob for deps** - Explicit is better
- **Don't commit bazel-\* dirs** - Add to .gitignore
- **Don't skip WORKSPACE setup** - Foundation of build
- **Don't ignore build warnings** - Technical debt
## Resources
- [Bazel Documentation](https://bazel.build/docs)
- [Bazel Remote Execution](https://bazel.build/docs/remote-execution)
- [rules_js](https://github.com/aspect-build/rules_js)
How to Use This Skill Unit
Option A: Project-Specific (Recommended)
- Click "Download" above
- In your project, create the directory:
.agent/skills/bazel-build-optimization/ - Save the file as
SKILL.md - The agent will automatically discover the skill based on its description.
Option B: Global Installation (All Agents)
Save the file to these locations to make it available across all projects:
- Claude Code:
~/.claude/skills/wshobson/agents/bazel-build-optimization/SKILL.md - Cursor:
~/.cursor/skills/wshobson/agents/bazel-build-optimization/SKILL.md - Antigravity:
~/.gemini/antigravity/skills/wshobson/agents/bazel-build-optimization/SKILL.md
π Install with CLI:npx skills add wshobson/agents