Skip to content

Rust Library

The Cargo package is brokk-bifrost, and the Rust crate name is brokk_bifrost. It exports the analyzer core, project abstractions, searchtools service, and common result types from src/lib.rs.

Add the released crate with Cargo:

Terminal window
cargo add brokk-bifrost

That produces a dependency like:

[dependencies]
brokk-bifrost = "0.11.0"

For local development against a checkout, use a path dependency:

Terminal window
cargo add brokk-bifrost --path /path/to/bifrost

The package name uses a hyphen, but Rust imports use the crate name with an underscore:

use brokk_bifrost::{AnalyzerConfig, FilesystemProject, WorkspaceAnalyzer};

brokk-bifrost is the supported default dependency. It is the compatibility facade: it re-exports the analyzer and service API, and Cargo resolves the analysis, language-adapter, runtime, MCP, and LSP implementation crates automatically. Most applications should depend on this package alone.

Each language family is now a separate published adapter crate. This split keeps language-specific parser and resolver code separate from the shared analysis engine.

Source languageCargo packageRust crate
C and C++brokk-bifrost-cppbrokk_bifrost_cpp
C#brokk-bifrost-csharpbrokk_bifrost_csharp
Gobrokk-bifrost-gobrokk_bifrost_go
JavaScript and TypeScriptbrokk-bifrost-js-tsbrokk_bifrost_js_ts
Java, Kotlin, and Scalabrokk-bifrost-jvmbrokk_bifrost_jvm
PHPbrokk-bifrost-phpbrokk_bifrost_php
Pythonbrokk-bifrost-pythonbrokk_bifrost_python
Rubybrokk-bifrost-rubybrokk_bifrost_ruby
Rustbrokk-bifrost-rustbrokk_bifrost_rust

brokk-bifrost and brokk-bifrost-analysis currently depend on all of these adapters. Adding one adapter directly does not limit the languages that WorkspaceAnalyzer loads or reduce the facade dependency set.

Use a direct adapter dependency only when you own a focused host or an adapter integration. Keep every direct Bifrost dependency on the same release version. The adapter APIs are internal and can change between releases.

For an application that only hosts Bifrost over the Language Server Protocol, depend directly on the focused LSP host instead:

Terminal window
cargo add brokk-bifrost-lsp@0.8

Start its stdio server with a deterministic fallback workspace root:

use std::path::PathBuf;
fn main() -> Result<(), String> {
brokk_bifrost_lsp::run_lsp_stdio_server(PathBuf::from("/path/to/project"))
}

The LSP client can replace that fallback with its advertised workspace folders during initialization. Reserve the process’s standard input and output for LSP messages, and follow the LSP server guide for protocol configuration.

brokk-bifrost-core, the language adapters above, brokk-bifrost-analysis, brokk-bifrost-policy, brokk-bifrost-runtime, and brokk-bifrost-mcp are lower-level workspace components. They are published so focused hosts can compose them, but they are not necessary for ordinary library consumers. Prefer the facade unless you own one of those boundaries.

brokk-bifrost’s exported surface is the supported tier. While the project is pre-1.0 nothing is contractually frozen, but that surface is curated item by item, and we do not break it gratuitously: changes to it are deliberate, and release notes call them out.

Everything beneath the facade may change in any release, including in a patch. The lower-level packages listed above exist so that a host owning one of those protocol boundaries can compose them, not as a general-purpose API; their types, traits, module paths, and crate boundaries move whenever the internal design calls for it. Each of them carries the same note on its crates.io and docs.rs page. brokk-bifrost-lsp is the one documented exception: its stdio server entry point above is a supported way to host Bifrost over LSP.

There is no sealing and no #[doc(hidden)] sweep enforcing this. Depending directly on an internal package compiles and works; it just means you are tracking our internals, and an upgrade may require source changes.

use std::sync::Arc;
use brokk_bifrost::{AnalyzerConfig, FilesystemProject, WorkspaceAnalyzer};
fn main() -> Result<(), String> {
let project = Arc::new(FilesystemProject::new(".")?);
let workspace = WorkspaceAnalyzer::build_ephemeral(project, AnalyzerConfig::default())
.expect("ephemeral workspace should build");
let analyzer = workspace.analyzer();
println!("languages: {:?}", analyzer.languages());
println!("files: {}", analyzer.get_analyzed_files().len());
println!("declarations: {}", analyzer.get_all_declarations().len());
Ok(())
}

The top-level crate re-exports the public analyzer and service types most callers need:

ExportUse
WorkspaceAnalyzerBuild a workspace-backed analyzer with default multi-language routing.
MultiAnalyzerRoute analysis across multiple language analyzers.
IAnalyzerTrait for common analyzer operations.
FilesystemProject, FileSetProject, OverlayProject, MultiRootProjectProject backends for different file-source shapes.
ProjectFile, CodeUnit, DeclarationInfo, Language, RangeCore source and symbol model types.
SearchToolsService, ToolOutputIn-process access to the same tool implementations exposed over MCP.
CodeQuery, CodeQueryExecutionMode, CodeQueryResponseParse a canonical JSON/RQL query and select ordinary results, planning-only explain, or an opt-in profile.
CodeQueryExplain, CodeQueryProfileStable versioned public report models; internal benchmark/profiler structs are not exposed.
ImportAnalysisProvider, TypeHierarchyProvider, TypeAliasProvider, TestDetectionProviderOptional analyzer capability traits.
RustAnalyzerConfig, RustDependencyApiEvidence, RustSelectedTarget, RustPackageApiArtifactDescribe passive, exact Cargo and rustdoc evidence supplied by a host.
resolve_rust_semantic_pack_dependencies, RustDependencyPackAdapterValidate exact Rust dependency selections and prepare reusable semantic-model packs without invoking build tools.
RubyAnalyzerConfig, RubyDependencyApiEvidence, RubyGemApiArtifactDescribe passive, exact Bundler and local gem archive evidence supplied by a host.
resolve_ruby_semantic_pack_dependencies, RubyDependencyPackAdapterValidate exact Ruby dependency selections and prepare reusable RBS/RBI/source semantic-model packs without invoking Ruby tools.

For most embedded code-intelligence workflows, prefer SearchToolsService over manually composing individual analyzer calls. It keeps the tool argument and rendering behavior aligned with MCP and the Python client.

Library Integration is the executable walkthrough: it runs one canonical query through SearchToolsService::query_code_result(...) against a checked-in fixture, shows the typed result consumption, states when to use the lower-level execute_request API instead, and runs the same query through the Python client so the two stay in step.

analyzer::structural::execute always returns ordinary rows for embedders that own execution policy. Use the top-level execute_request to honor the query’s root execution_mode; its untagged CodeQueryResponse::Results variant preserves the existing serialized result shape. Explain performs logical lowering and physical selection without reading analyzer data during that phase, while profile nests the exact ordinary result. Cancellable embedders can call execute_request_with_cancellation with a top-level CancellationToken and receive the versioned profile, including cancellation observations and a cancellation-safe partial result. See Explain and Profile CodeQuery for the stable wire contract and measurement caveats.

The default Rust build has no optional features enabled.

python enables the PyO3 extension module used by the Python package. Maturin turns this on automatically through pyproject.toml; ordinary CLI and library builds do not need it.