| Crates.io | codegraph |
| lib.rs | codegraph |
| version | 0.1.1 |
| created_at | 2025-11-03 00:48:28.279692+00 |
| updated_at | 2025-11-03 00:48:28.279692+00 |
| description | A fast, reliable, and flexible graph database optimized for storing and querying code relationships |
| homepage | |
| repository | https://github.com/anvanster/codegraph |
| max_upload_size | |
| id | 1913749 |
| size | 430,814 |
A fast, reliable, and flexible graph database optimized for storing and querying code relationships.
codegraph provides a fast, reliable, and flexible graph database optimized for storing and querying code relationships, enabling tool builders to focus on analysis logic rather than infrastructure.
"Bring your own parser, we'll handle the graph."
codegraph does NOT include built-in language parsers. You integrate your own parsers (tree-sitter, syn, swc, etc.), and we provide the storage and query infrastructure.
"Sub-100ms queries or it didn't happen."
"If it's not tested, it's broken."
"Explicit over implicit, always."
"Graphs outlive processes."
Add to your Cargo.toml:
[dependencies]
codegraph = "0.1"
use codegraph::{CodeGraph, Node, NodeType, Edge, EdgeType};
use std::path::Path;
// Create a persistent graph
let mut graph = CodeGraph::open(Path::new("./my_project.graph"))?;
// Add a file node (explicit, no magic)
let file_id = graph.add_file(Path::new("src/main.rs"), "rust")?;
// Add a function node
let mut func_node = Node::new(NodeType::Function);
func_node.set_property("name", serde_json::json!("main"));
func_node.set_property("line", serde_json::json!(10));
let func_id = graph.add_node(func_node)?;
// Create a relationship (file contains function)
let edge = Edge::new(file_id, func_id, EdgeType::Contains);
graph.add_edge(edge)?;
// Query the graph
let neighbors = graph.get_neighbors(&file_id)?;
println!("File contains {} entities", neighbors.len());
// Example with tree-sitter (you provide the parser)
use tree_sitter::{Parser, Language};
extern "C" { fn tree_sitter_rust() -> Language; }
let mut parser = Parser::new();
parser.set_language(unsafe { tree_sitter_rust() }).unwrap();
let source_code = std::fs::read_to_string("src/main.rs")?;
let tree = parser.parse(&source_code, None).unwrap();
// You extract entities from the AST
// codegraph stores the relationships
let mut graph = CodeGraph::open("./project.graph")?;
let file_id = graph.add_file("src/main.rs", "rust")?;
// Walk the tree and add nodes/edges as you see fit
codegraph is organized in clear layers:
User Tools (parsers, analysis)
โ
Code Helpers (convenience API)
โ
Query Builder (fluent interface)
โ
Core Graph (nodes, edges, algorithms)
โ
Storage Backend (RocksDB, memory)
Each layer:
| Operation | Target | Actual |
|---|---|---|
| Node lookup | <1ms | โ ~7ns (1000x better!) |
| Neighbor query | <10ms | โ ~410ns - 40ยตs |
| BFS traversal (depth=5) | <50ms | โ ~5ms |
| Batch insert (10K nodes) | <500ms | โ ~7ms |
| 100K node + 500K edge load | <5s | โ ~3.3s |
cargo build --release
cargo test
cargo doc --open
# Format code
cargo fmt
# Lint with clippy
cargo clippy -- -D warnings
# Check test coverage
cargo tarpaulin
# Run all CI checks locally (recommended before pushing)
./scripts/ci-checks.sh
See the examples/ directory for complete examples:
basic_usage.rs - Creating and querying a simple graphcall_graph.rs - Function call analysis with syn integrationdependency_tree.rs - File dependency and circular dependency analysisimpact_analysis.rs - Complex query patterns for impact analysisvisualize.rs - Exporting graphs to DOT, JSON, CSV, and RDF formats// Node operations
let node_id = graph.add_node(NodeType::Function, properties)?;
let node = graph.get_node(node_id)?;
graph.delete_node(node_id)?;
// Edge operations
let edge_id = graph.add_edge(source, target, EdgeType::Calls, properties)?;
let neighbors = graph.get_neighbors(node_id, Direction::Outgoing)?;
// Batch operations
graph.add_nodes_batch(nodes)?;
graph.add_edges_batch(edges)?;
use codegraph::helpers;
// Code-specific operations
let file_id = helpers::add_file(&mut graph, "main.rs", "rust")?;
let func_id = helpers::add_function(&mut graph, file_id, "main", 10, 20)?;
helpers::add_call(&mut graph, func1_id, func2_id, Some(15))?;
// Relationship queries
let callers = helpers::get_callers(&graph, func_id)?;
let deps = helpers::get_file_dependencies(&graph, file_id)?;
// Fluent query interface
let results = graph.query()
.node_type(NodeType::Function)
.in_file("src/main.rs")
.property("visibility", "public")
.name_contains("test")
.execute()?;
// Transitive analysis
let all_deps = helpers::transitive_dependencies(&graph, file_id, Some(5))?;
let all_dependents = helpers::transitive_dependents(&graph, file_id, None)?;
// Call chains
let paths = helpers::call_chain(&graph, from_func, to_func, Some(10))?;
// Circular dependencies
let cycles = helpers::circular_deps(&graph)?;
use codegraph::export;
// Graphviz DOT
export::export_dot(&graph, &mut output)?;
// D3.js JSON
export::export_json(&graph, &mut output)?;
// CSV (nodes and edges)
export::export_csv_nodes(&graph, &mut output)?;
export::export_csv_edges(&graph, &mut output)?;
// RDF N-Triples
export::export_triples(&graph, &mut output)?;
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Before contributing, please:
cargo fmt and cargo clippycodegraph is licensed under the Apache License 2.0, which means:
โ You can:
โ You must:
โ You can't:
This is a truly open license. There's no "gotcha" later where we switch to GPL or a commercial model. Apache-2.0 is forever.
This project adheres to the Rust Code of Conduct. See CODE_OF_CONDUCT.md.
This project follows Semantic Versioning:
Current version: 0.1.1 (Initial release + formatting fixes)
This project draws inspiration from:
Built with โค๏ธ in Rust