π οΈ CI and Coverage
- CI workflow:
.github/workflows/ci.yml- Runs format check, clippy (deny warnings), build, tests, docs.
- Coverage workflow:
.github/workflows/coverage.yml- Installs
cargo-tarpaulinand uploadslcov.info.
- Installs
Run coverage locally:
π rust-relations-explorer β Rust Knowledge Graph System
A fast, lightweight tool to parse Rust projects into a knowledge graph and run insightful queries over code structure. Generate DOT/SVG visualizations, persist graphs to JSON, and explore code relationships via a clean CLI. β¨
β¨ Features
- β
Graph builder from source (
KnowledgeGraph::build_from_directory) - β
Incremental builds with cache (reuse unchanged files;
--no-cache,--rebuild) - β Relationship analysis (imports, heuristics for calls)
- β JSON persistence (save/load)
- β DOT generation with styling (rankdir, splines, rounded, theme, clusters, legend)
- β SVG enhancement (interactive highlights, clickable nodes)
- β
CLI powered by
clap - β
Queries
connected-filesβ files related to a target fileitem-infoβ show item metadata, code, and relations by ItemIdfunction-usageβ callers/callees of a functioncyclesβ detect file-level cyclespathβ shortest path between two fileshubsβ top-N files by degree centrality (in/out/total)module-centralityβ top-N modules (directories) by degree centralitytrait-implsβ list types and files implementing a given trait
- π§ Pretty table output for terminal
- π§ Advanced analyses and config system
π§° Installation
Build from source:
# from repo root
Run checks and tests:
π Usage
Build a graph from a Rust project and export artifacts:
# Build and save artifacts (uses cache by default)
# Force parsing all files without using cache
# Rebuild cache from scratch (clears previous cache file)
# Apply options from a configuration file
# Bypass ignore rules (include files even if ignored)
Run queries (builds the graph on-the-fly unless --graph is provided):
# Connected files for a given file
# Show detailed info for an item by ItemId (text or JSON)
# Function usage: who calls `foo` (callers) or who does `foo` call (callees)
# Detect cycles
# Shortest path between files
# Hubs: top-N by degree centrality
# Module centrality: top-N modules by degree
# Trait implementations for Display
# Any query can also bypass ignore rules when building on-the-fly
Use a prebuilt graph for faster queries:
π Examples
Run the included examples to see the library API in action:
# Build all examples
# Basic graph build and stats
# Print connected files to a target (defaults to src/lib.rs if present)
Example sources:
examples/basic_build.rsexamples/query_connected.rs
π§ Typical Workflows
-
Build and save graph to JSON
-
Programmatic DOT/SVG generation
# Produces graph.dot and graph.svg- Requires Graphviz
dotexecutable on PATH. Install via your OS package manager. - Options like clusters, theme, rankdir, splines are in
visualization::DotOptionsandvisualization::SvgOptions.
- Requires Graphviz
-
Bypass ignore rules for one-off analyses
-
Save and load graph JSON
# Save # Query using saved graph (faster) -
Programmatic save/load JSON
use KnowledgeGraph; use CacheMode;Note:
KnowledgeGraphimplementsserde::Serialize/Deserialize.
π§© Mapping: CLI queries β API
query connected-filesβquery::ConnectedFilesQueryquery item-info --item-id IDβquery::ItemInfoQueryquery function-usage --direction callers|calleesβquery::FunctionUsageQuery::{callers,callees}query cyclesβquery::CycleDetectionQueryquery path --from A --to Bβquery::ShortestPathQuery::new(A,B)query hubs --metric in|out|totalβquery::HubsQuerywithCentralityMetricquery module-centralityβquery::ModuleCentralityQueryquery trait-impls --trait NAMEβquery::TraitImplsQuery::new(NAME)
π οΈ Troubleshooting
- Graphviz
dotnot found- Ensure Graphviz is installed and
dotis on PATH. Thegenerate_svgexample will print a hint on failure.
- Ensure Graphviz is installed and
- Empty graph
- Check ignore rules. Try
--no-ignoreto include ignored files. SeeIgnore Patternssection.
- Check ignore rules. Try
- Slow runs on large repos
- Use saved JSON and query with
--graph graph.json. Ensure cache (default) is enabled.
- Use saved JSON and query with
π§± Design Overview
- Graph model
- Nodes: items parsed from Rust files (functions, structs, enums, traits, impls, etc.). See
src/graph/mod.rs. - Edges: relationships between items (uses, implements, contains, extends, calls). Projectable to file-level.
- Nodes: items parsed from Rust files (functions, structs, enums, traits, impls, etc.). See
- File discovery & ignores
- File walking in
src/utils/mod.rshonors.gitignore, global ignores, nested ignores. Explicit override via--no-ignore.
- File walking in
- Visualization
- DOT via
visualization::DotGenerator; SVG viavisualization::SvgGeneratorusing Graphvizdot.
- DOT via
β FAQ
- How do item-level relationships map to files?
- Each relationship stores
from_item/to_item(item IDs). For file-level analyses (e.g., connected files), items are mapped to their defining file and deduplicated.
- Each relationship stores
- Does the CLI modify environment variables for ignores?
- No. Ignoring is controlled explicitly via flags. Legacy env is still read by the library for backwards compatibility but not set by the CLI.
πΊοΈ Roadmap
See plan-tasks.md for full project plan, phases, and task status.
- Core queries: β
- Centrality/hubs: β
- Table output: π§
- Config file and ignores: π§
- Performance (parallelism, caching, incremental): π§
π Benchmarks
-
Run all benches
-
Reports
- Criterion stores results under
target/criterion/. - With
html_reportsenabled, opentarget/criterion/report/index.htmlfor an overview.
- Criterion stores results under
-
Whatβs measured
- Build performance by cache mode:
benches/build_graph.rs. - Query performance (connected files, hubs, shortest path):
benches/queries.rs.
- Build performance by cache mode:
-
Notes
- Benches use
criterion0.5. Setup occurs outsideiterand results areblack_boxed.
- Benches use
π Sample Results (local, 2025-08-18)
-
Build graph (lower is better)
- rebuild: [6.86 ms, 6.98 ms, 7.11 ms]
- use_cache: [4.42 ms, 4.46 ms, 4.52 ms]
- ignore_cache: [7.06 ms, 7.20 ms, 7.35 ms]
-
Queries (lower is better)
- connected_files: [55.65 Β΅s, 57.48 Β΅s, 59.75 Β΅s]
- hubs (top10 total): [43.09 Β΅s, 44.77 Β΅s, 47.06 Β΅s]
- shortest_path (aβb): [42.73 Β΅s, 43.17 Β΅s, 43.64 Β΅s]
π¦ 10k synthetic project (release)
- Dataset: generated via
examples/generate_synthetic.rs(10,000 files) - Default (use cache), warm run: 0.29s elapsed, ~103 MB max RSS
- No-cache: 0.85s elapsed, ~100 MB max RSS
- Notes:
- First invocation via
cargo runincludes compilation overhead; use the built binary for timing. - Results are for a simple synthetic workload (flat modules, tiny files). Real projects will vary.
- First invocation via
Notes:
- These are Criterion min/mean/max for 100 samples on the current machine and can vary across runs and environments.
- Please record your machine specs (CPU model, cores, RAM, OS) alongside results for context.
π₯οΈ Machine specs (example, replace with yours)
- CPU: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (6 cores / 12 threads)
- RAM: 32 GB
- OS: Ubuntu 22.04 x86_64
- Rust: nightly toolchain (see
rust-toolchain.tomlorrustup show)
π¬ Validate 10k-file Performance (Phase 4)
Use the synthetic generator example to create a large project and measure performance.
- Generate N files (e.g., 10,000):
- Measure build time (Use cache by default):
# Build release binary once
# Use the built binary to avoid compile overhead
- Compare cache modes:
- Optional memory profiling:
# or use heaptrack if available
Record the elapsed wall time and peak memory, and confirm the 10k-in-30s target.
π§ͺ CLI Quick Examples
Build graph with DOT and SVG outputs:
Connected files for a target file (JSON):
Function usage: callers of function foo (JSON):
Shortest path between two files (JSON):
Top hubs by total degree (top 10):
Top modules (directories) by in-degree (top 5):
Types implementing a trait (e.g., Display):
π§ Caching Modes
- Default (Use) β reuse unchanged files from
.knowledge_cache.jsonand only reparse changed/added files. - --no-cache (Ignore) β do not reuse cache; parse all files, then write a fresh cache at end.
- --rebuild (Rebuild) β remove existing cache file first, then parse all files and write a new cache.
Cache file location: .knowledge_cache.json at the project root passed to --path.
ποΈ Ignore Patterns
- File discovery respects
.gitignoreand.ignorefiles. Parent directories are traversed, so nested ignore files apply. - Global git excludes are intentionally disabled for determinism.
- This affects which
.rsfiles are scanned and parsed bybuildand on-the-fly builds forquery.
Determinism: The CLI now passes ignore behavior explicitly to the file walker. This removes reliance on ambient environment state during normal operation.
Examples:
# src/.ignore (or .gitignore)
ignored.rs
# Nested ignore (src/a/.ignore)
skip.rs
# Negation pattern (src/.gitignore)
*.rs
!keep.rs
Bypass ignores (use with care):
# Preferred: CLI flag (explicit)
# Optional: environment variable (legacy/compat)
# Still supported, but not required since the CLI now passes the flag directly.
KNOWLEDGE_RS_NO_IGNORE=1
βοΈ Configuration
You can provide a TOML config with --config <path> for both build and all query subcommands.
- Precedence:
- CLI flags override binary defaults.
- Config values are applied on top of CLI defaults to provide convenient project-wide settings (as implemented, config values for DOT/SVG and query format will be applied even if CLI uses defaulted values).
Example rust-relations-explorer.toml:
[]
= true
= false
= "dark" # "light" | "dark"
= "TB" # "LR" | "TB"
= "ortho" # "curved" | "ortho" | "polyline"
= true
[]
= true
[]
= "json" # "text" | "json"
π References
- @web https://doc.rust-lang.org/
- @web https://graphviz.org/
- @web https://crates.io/crates/clap
- @web https://serde.rs/
- @web https://docs.rs/regex
π€ Contributing
Issues and PRs are welcome! Please run cargo fmt, cargo clippy, and cargo test before submitting.
π License
TBD