Bazelrc

The Bazelrc language surface implements upstream Bazel 8.7.0. It is separate from Starlark: Bazelrc files are never parsed, formatted or linted by buildifier.

Behavior inventory

Reviewed against upstream Bazel 8.7.0. Each entry states the language server's exact behavior and boundary.

Version and files

Capability Exact behavior
Upstream Bazelrc language Pinned to upstream Bazel 8.7.0.
Native flag catalog Only a configured executable reporting numeric major 8 and minor 7.
Structural editing with another Bazel version The 8.7 parser remains active; compatibility with another release is not claimed.
Nearest-version or bundled catalog fallback No catalog loads unless the executable reports numeric 8.7; no nearest or bundled fallback is used.
Vendor-only grammar and configuration semantics A vendor-suffixed numeric 8.7 executable supplies its flags; grammar and configuration semantics remain upstream 8.7.
.bazelrc and *.bazelrc classification The filename must be exact or end in .bazelrc.
Arbitrary imported filenames A regular file becomes Bazelrc when reached from the workspace import graph.
Unrelated open files such as bazel.rc Not classified as Bazelrc without a .bazelrc suffix or published import-graph membership.
Starlark parsing, buildifier formatting, or lint Bazelrc remains an independent native-client language and is never sent to buildifier.

Logical grammar

Capability Exact behavior
LF and CRLF continuation deletion Deleted globally before line splitting, including in quotes and comments.
Native whitespace delimiters Space, TAB, CR, and LF delimit; logical-line edges also strip vertical TAB and form feed.
Mid-token comments An unescaped, unquoted # ends the logical line.
Single/double quotes and fragment concatenation Quote bytes are removed; adjacent fragments form one token.
Backslash byte escaping Inside and outside quotes; no shell expansion is performed.
Unclosed quotes and dangling backslashes Accepted as Bazel's native tokenizer accepts them.
Empty quoted tokens Discarded rather than retained as empty arguments.
Physical ranges across continuations Editor ranges map logical tokens back to the original UTF-8 bytes.
Argless ordinary entries Bazel 8.7 discards them; they declare no empty configuration.

Imports and discovery

Capability Exact behavior
import PATH Exact arity; read failures are errors.
try-import PATH Exact arity; read failures are quiet.
try-import-if-bazel-version CONDITION PATH Bazel 8.7 SemVer grammar, evaluated against baseline 8.7.0.
Configured vendor label in conditional imports Conditions do not use suffixes such as 8.7.0-imc2.
Depth-first textual import expansion No later-version import-depth cap.
Diamond import replay Entries replay and the repeated import receives a warning.
Active import cycle detection Reported as an error.
Exact %workspace%/ substitution Other %workspace% spellings are literal paths.
Absolute and workspace-root-relative paths The server models the Bazel client working directory as the workspace root.
Per-invocation subdirectory working directory Relative imports resolve from the workspace root; Bazel launched below it may resolve the same spelling differently.
Live refresh for imports outside the workspace They load into snapshots, but external edits require manual reindexing.
Containing-file-relative imports Relative imports resolve from the workspace root, never from the containing file.
Environment-variable or tilde expansion $VAR, ${VAR}, and ~ remain literal.
Workspace .bazelrc graph The sole graph root; all reachable imports are indexed.
System, home, and explicit --bazelrc layers Not reconstructed by the language server.
Bazel 9.0 BAZELRC environment list Not read because it is outside the 8.7 contract.
New unsaved import targets Open graph members may reuse published targets; a new target loads after save and refresh.

Commands and configs

Capability Exact behavior
Bazel 8.7 commands and rc scopes Static exact list, including always, common, and startup.
Command inheritance Build/test/coverage and other 8.7 inheritance is transitive.
Unknown command sections Warned; excluded from config indexing and flag completion/checks. Native hover may still identify a spelling.
Named configuration declarations Recognized, non-startup base plus at least one option.
startup:name configurations Not indexed as named configurations because startup parsing cannot consume command --config.
Top-level --config=name and --config name Both spellings create configuration references.
Nested --config=name Included in completion, navigation, and absence diagnostics.
Bazel's recursive --config prefix quirk Named bodies expand any token beginning --config through its first =, before native parsing.
Nested split --config name Bazel 8.7 rejects it; the server reports an error.
Applicable configuration completion Follows command inheritance and all declarations in the graph.
Open-buffer declaration overlays An open file replaces declarations from its saved path.
Configuration go-to-definition Returns every applicable saved or open declaration.
Effective option/config expansion Graph analysis is supported; a final option sequence is not rendered.
Configuration expansion-cycle diagnostics Branch-local active-chain cycles are errors.
Repeated/deep expansion warnings Every occurrence is traversed; chains of ten or more configurations warn.
Automatic platform configuration selection Does not evaluate --enable_platform_specific_config.

Native flags

Capability Exact behavior
help flags-as-proto acquisition Runs in the Bazel actor with all rc files ignored.
Bazel 8.7 proto fields 1–16 All reported documentation and semantic metadata are decoded.
Canonical long flag completion Filtered to the current command and visible catalog entries.
Negative and one-character abbreviation completion Includes Bazel's negative -x- spelling.
Old-name completion Old names resolve for hover/diagnostics but are not suggested.
common flag union Known in any reported non-startup command.
always safe flag intersection Known in every reported non-startup command.
Native flag hover Docs, spellings, type, default, enums, scopes, tags, and expansions.
Required-value and negative-boolean checks Only contradictions proven by the exact catalog are errors.
Scope, old-name, deprecation, and status checks Severity follows the strength of catalog evidence.
Starlark build-setting flag exemption --//, --@, --no//, and --no@ bypass native lookup.
Internal flags omitted by Bazel flags-as-proto does not expose INTERNAL options.
Flag aliases and external rc aliases Not resolved because they are outside the native catalog and workspace snapshot.
Enum value completion Only exact nonempty enum sets reported by the 8.7 catalog.
Enum membership validation ASCII-case-insensitive, matching Bazel's converter, and only for an exact reported enum set.
Other flag-value completion Returns no values because non-enum converters do not expose a finite set.
Converter-specific value validation The server does not execute Bazel option converters.

Language server

Capability Exact behavior
Command and directive completion Available without Bazel.
Import-path completion At most 512 eligible matches from a 131,072-path snapshot; ignored, metadata, output, symlink, non-regular, and non-UTF-8 paths are excluded.
Import document links Only active imports whose targets loaded successfully.
Import go-to-definition Only active imports whose targets loaded successfully.
Semantic tokens Directives/keys, conditions, paths, option tokens, and comments.
Separate flag-value semantic tokens A value token uses the same property category as its option.
Continuation and comment-run folding Catalog-independent structural ranges.
Token, logical-line, and file selection ranges Catalog-independent structural ranges.
Current-buffer syntax diagnostics Published on each document change.
Saved import-graph diagnostics Shown only while the open text still matches the indexed file.
Missing configuration warnings Qualified to the published workspace graph; never called invalid.
Command/config/import hover Structural facts are available without a flag catalog.
Document and workspace symbols for configurations Declarations use decoded names and exact name-only ranges.
Configuration references and highlights Case-sensitive decoded identity across saved and open graph files.
Rename Declared names only; nonempty bare fragments; collisions are refused.
Formatting Returns no edits because Bazel defines no canonical semantics-safe layout.
Implementation, code lens, and inlay hints Bazelrc handlers return no results.

The tracked Bazelrc 8.7 specification defines the implementation contract behind this inventory.

Files and imports

The server recognizes .bazelrc, every *.bazelrc file, and arbitrary filenames reached from the workspace import graph. It indexes the workspace .bazelrc, expanding reachable imports depth-first at their textual position.

Supported directives are import, try-import, and the Bazel 8.7 try-import-if-bazel-version. Required imports report read failures; missing optional imports do not. %workspace%/ is recognized exactly. Other relative paths resolve from the workspace root: the server models one Bazel invocation working directory, while a command launched from a workspace subdirectory may resolve the same spelling differently. Imports are never containing-file relative.

Import paths receive workspace-file completion, document links, structural hover, and go-to-definition. Completion returns at most 512 eligible matches from the bounded workspace snapshot and quotes paths whose bytes would otherwise be tokenized differently. Imports outside the workspace load, but changes to those external files require a manual reindex.

Commands and configurations

Completion covers the Bazel 8.7 commands and the startup, common, and always rc scopes. Configuration completion and go-to-definition follow all applicable declarations in the workspace import graph, with open buffers taking precedence over saved files.

Nested configurations use --config=name. Bazel rejects split --config name inside a named configuration body, and the server reports it as an error. The server also models Bazel 8.7’s source-level quirk that any nested token whose first eight bytes are --config is expanded through its first = before native option parsing. Configuration names absent from the published workspace graph are warnings, not invalid-name errors, because another rc layer may declare them.

The server reports branch-local expansion cycles, repeated configuration expansion, and chains of ten or more configurations. It does not render a final effective option sequence or automatically select a platform configuration.

Native flags

When the configured executable reports numeric release 8.7, the server reads that binary’s help flags-as-proto output with rc files disabled. The resulting catalog supplies:

common completion is the union of flags known to any non-startup command. always completion is the safe intersection across the binary’s reported non-startup commands.

A native-looking spelling absent from the catalog is reported only as “not recognized by the Bazel 8.7 native flag catalog.” The catalog omits internal flags, and Starlark settings, aliases, vendor behavior or external rc layers may still explain a spelling. Recognizable Starlark setting forms are exempt from native lookup.

Structural features

Semantic highlighting distinguishes directives and command keys, version conditions, import paths, option tokens and comments. Continued lines and comment runs fold, and selection ranges expand through tokens and logical lines. Commands, rc scopes, imports, and configurations have structural hover. Configuration names support references, document highlights, document and workspace symbols, and conservative workspace rename. These features do not require Bazel.

Formatting

Formatting intentionally returns no edits. Bazel 8.7 defines tokenization but no canonical rc-file layout, and whitespace changes around continuations, comments, quotes, and escapes can change the option stream. Bazelrc files are never sent to buildifier.

Boundaries

The inventory above is the exhaustive public record as of its review date.