Claude Agent Skill · by Wshobson

Bazel Build Optimization

For teams running multi-language monorepos at scale, this handles the gnarly parts of Bazel configuration that usually take weeks to figure out. It covers remot

Install
Terminal · npx
$npx skills add https://github.com/wshobson/agents --skill bazel-build-optimization
Works with Paperclip

How Bazel Build Optimization fits into a Paperclip company.

Bazel Build Optimization drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md381 lines
Expand
---name: bazel-build-optimizationdescription: Optimize Bazel builds for large-scale monorepos. Use when configuring Bazel, implementing remote execution, or optimizing build performance for enterprise codebases.--- # Bazel Build Optimization 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 ```python# WORKSPACE.bazelworkspace(name = "myproject") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # Rules for JavaScript/TypeScripthttp_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 Pythonhttp_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 ```bash# .bazelrc # Build settingsbuild --enable_platform_specific_configbuild --incompatible_enable_cc_toolchain_resolutionbuild --experimental_strict_conflict_checks # Performancebuild --jobs=autobuild --local_cpu_resources=HOST_CPUS*.75build --local_ram_resources=HOST_RAM*.75 # Cachingbuild --disk_cache=~/.cache/bazel-diskbuild --repository_cache=~/.cache/bazel-repo # Remote caching (optional)build:remote-cache --remote_cache=grpcs://cache.example.combuild:remote-cache --remote_upload_local_results=truebuild:remote-cache --remote_timeout=3600 # Remote execution (optional)build:remote-exec --remote_executor=grpcs://remote.example.combuild:remote-exec --remote_instance_name=projects/myproject/instances/defaultbuild:remote-exec --jobs=500 # Platform configurationsbuild:linux --platforms=//platforms:linux_x86_64build:macos --platforms=//platforms:macos_arm64 # CI configurationbuild:ci --config=remote-cachebuild:ci --build_metadata=ROLE=CIbuild:ci --bes_results_url=https://results.example.com/invocation/build:ci --bes_backend=grpcs://bes.example.com # Test settingstest --test_output=errorstest --test_summary=detailed # Coveragecoverage --combined_report=lcovcoverage --instrumentation_filter="//..." # Convenience aliasesbuild:opt --compilation_mode=optbuild:dbg --compilation_mode=dbg # Import user settingstry-import %workspace%/user.bazelrc``` ### Template 3: TypeScript Library BUILD ```python# libs/utils/BUILD.bazelload("@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"],) # Testsload("@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 ```python# libs/ml/BUILD.bazelload("@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 ```python# tools/bazel/rules/docker.bzldef _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 ```bash# Find all dependencies of a targetbazel query "deps(//apps/web:web)" # Find reverse dependencies (what depends on this)bazel query "rdeps(//..., //libs/utils:utils)" # Find all targets in a packagebazel query "//libs/..." # Find changed targets since commitbazel query "rdeps(//..., set($(git diff --name-only HEAD~1 | sed 's/.*/"&"/' | tr '\n' ' ')))" # Generate dependency graphbazel query "deps(//apps/web:web)" --output=graph | dot -Tpng > deps.png # Find all test targetsbazel query "kind('.*_test', //...)" # Find targets with specific tagbazel query "attr(tags, 'integration', //...)" # Compute build graph sizebazel query "deps(//...)" --output=package | wc -l``` ### Template 7: Remote Execution Setup ```python# platforms/BUILD.bazelplatform(    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.bazeltoolchain(    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 ```bash# Profile buildbazel build //... --profile=profile.jsonbazel analyze-profile profile.json # Identify slow actionsbazel build //... --execution_log_json_file=exec_log.json # Memory profilingbazel build //... --memory_profile=memory.json # Skip analysis cachebazel 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