Development Guide
See structure for the full directory map.
Installation
Install bazelisk as your bazel
binary:
wget -O ~/tools/bazel https://github.com/bazelbuild/bazelisk/releases/download/v1.18.0/bazelisk-linux-amd64
chmod +x ~/tools/bazel
# Add ~/tools to PATH
Build and Test
bazel build //... # build everything
bazel test //... # run all tests
bazel test //path/to:target # run a single test
bazel test //... --test_output=all # show test output
bazel coverage //... --combined_report=lcov # generate coverage
Linting and Formatting
./lint.sh --mode check # check formatting (CI runs this)
./lint.sh --mode format # auto-format code
CI
GitHub Actions:
.github/workflows/Bazel remote caching via BuildBuddy (requires API key in
user.bazelrc)Disk caching via GitHub’s cache action
Remote caching also available via nativelink
Language FAQs
Each language answers: how to lint/format, build, test, run, add dependencies, package, and release.
Bazel
# Regenerate BUILD files
bazel run //:gazelle
# Completely clean
bazel clean --expunge
# Avoid networked backends / remote caches (helpful on slow networks)
bazel build //... --config local
References: Bazel query language, bzlmod migration
Python
Style: 79-char line length (black + isort via pyproject.toml)
# Create virtualenv with all dependencies
bazel run //:create_venv
Adding / modifying external dependencies:
Update
requirements.inbazel run //:requirements.update— updatesrequirements_lock.txtbazel run //:gazelle_python_manifest.update— updatesgazelle_python.yaml
Tests enforce that both update commands have been run after any change to
requirements.in.
Excluding lines from coverage: # pragma: no cover
(docs)
Rust
# Update cargo dependencies
CARGO_BAZEL_REPIN=1 bazel sync --only=crate_index
C++
Style: C++23, clang-format (.clang-format)
Use cc_test (from //bzl:cc.bzl) for all tests — see
cpp_testing for details.
# Run buildozer / buildifier manually
bazel run //tools/buildozer -- <args>
bazel run //tools/buildifier -- <args>
ThreadSanitizer on Ubuntu 24.04:
sudo sysctl vm.mmap_rnd_bits=30
JavaScript / Node
bazel run -- @pnpm//:pnpm --dir $PWD install --lockfile-only
Git LFS
Large binary files (firmware images, photos, archives) are tracked via
Git LFS. The patterns are configured in
.gitattributes.
The git-lfs binary is managed via
rules_multitool and can be run
directly from the repo root:
tools/git-lfs <args>
# or via bazel
bazel run @multitool//tools/git-lfs -- <args>
First-time setup
tools/git-lfs install # installs LFS hooks into .git/
Common operations
tools/git-lfs track "*.bin" # start tracking a new pattern (updates .gitattributes)
tools/git-lfs ls-files # list LFS-tracked files in the current commit
tools/git-lfs status # show LFS file status
tools/git-lfs pull # download LFS files after a clone/fetch
Adding a new file type
Add a pattern to
.gitattributes(or usetools/git-lfs track "*.ext")Commit the updated
.gitattributesMigrate any existing files:
tools/git-lfs migrate import --include="*.ext"