Local engine / The code graph
The code graph
Understand what Arbor extracts, how relationships become useful, and where static analysis stops.
On this page
From source to relationships
Arbor parses source code into symbols and relationships. Functions, classes, and modules become nodes. Resolved references connect them, allowing queries to follow dependencies across files.
The parser and graph engine provide structured context without an embedding service. A graph describes relationships recognized in source; it does not execute your program or observe production traffic.
Symbol- A named element of the code, associated with a file and source location.
Call edge- A resolved relationship from a caller to a callee.
Blast radius- Nodes the analysis reaches from changed or selected code, within its traversal rules and depth.
Centrality- A ranking derived from graph structure. Useful for orientation; not a measure of runtime usage or business importance.
Resolution and confidence
A written import or a same-file definition gives the resolver stronger evidence than a name match elsewhere. Arbor records confidence for relationships so that a direct resolution and a heuristic match need not be treated as equivalent.
File imports and the caller's language family help choose between definitions that share a name, and Rust paths such as crate::jobs::enqueue() resolve through the module tree. Since v3.0.4, a Rust method call resolves through its receiver's type where the code states it, so draft.run_started() reaches that type's method instead of being dropped as ambiguous; when the type is uncertain, Arbor falls back to matching the name. Since v3.0.5, each Jest, Vitest or Mocha test in TypeScript or JavaScript is a function named after its title, such as it: accepts two, so tests show up as callers. Ambiguous names and incomplete type information can still produce missing or incorrect edges. When a name has one definition and no callers, arbor callers says which kinds of call the graph cannot follow.
Confidence describes the evidence used by the analyzer. It is not a calibrated probability that a change will break a caller.
Language coverage
The public repository lists dedicated parsers for these languages:
- Rust
- TypeScript / JavaScript
- Python
- Go
- Java
- C / C++
- C#
- Dart
Kotlin, Swift, Ruby, PHP and Shell use a line-based fallback parser instead. It records declarations but not the calls inside them, so callers, callees and impact for those files are mostly empty. Coverage also varies within the languages above: a language appearing in the list does not mean every construct resolves.
Known limits in the public release
The public release notes, and checks against the v3.0.3 binary, identify limitations that still apply in v3.0.5 and matter when interpreting results:
- Inheritance is only partly followed. Since v3.0.3, Arbor records class inheritance, so changing a base class reports downstream impact. Python method calls are still matched by their written text:
self.run()inside a subclass is listed among the callers ofBase.run, butChild().run()anditem.run()on a local variable are not. - Dynamic imports can be invisible. Runtime imports and reflection, including
importlib,__import__, and dynamic JavaScript imports, may not resolve. - Impact can overcount. Some smaller targets in the published fixture have more reported downstream nodes than the ground truth.
Turn a result into a review
- Check that the intended project and files were indexed.
- Confirm the selected symbol's file and source location.
- Inspect reported relationships and uncertain resolutions.
- Read the code and run tests for the behavior being changed.
The recorded example on this site illustrates a review workflow. Its provenance identifies the engine used for that capture; it should not be read as a guarantee that every public release returns identical results.