Skip to main content
Most code review tools only see the diff — the lines that changed. BugViper goes further: before a single agent reads your code, it builds a structural map of your entire codebase and calculates how broadly each changed file affects everything else. This means agents don’t just know what changed; they know what depends on it, and they can focus their attention accordingly.
The call graph is built fresh in a clean E2B sandbox for every review run. There is no stale cached data — BugViper always works from the exact state of your repository at the PR’s head commit.

What Is a Call Graph?

A call graph is a directed graph that represents the relationships between pieces of code in your repository.
  • Nodes represent functions, classes, and modules.
  • Edges represent relationships between them: a function call, an import, or a class inheritance.
When file A imports a function from file B and calls it, the call graph contains an edge from A to B. When file C also imports from B, there’s an edge from C to B as well. BugViper traverses the entire repository to build this graph before any review begins. The call graph is constructed by parsing your source files into Abstract Syntax Trees (ASTs) using tree-sitter — a fast, incremental parser that works across a wide range of languages without requiring your code to compile or run.

Supported Languages

BugViper’s AST parser supports 17+ languages: If your repository mixes languages — for example, a Go backend with a TypeScript frontend — BugViper parses all of them and builds a unified call graph across the full codebase.

Blast Radius Scoring

Once the call graph is built, BugViper calculates a blast radius score for every file in the PR diff. A file’s blast radius is determined by how many other files depend on it — directly or through a chain of imports and calls. The more downstream dependents a file has, the higher its blast radius score. Example:
  • utils/auth.py is imported by 45 other modules → high blast radius
  • scripts/seed_data.py imports from other files but nothing imports it → low blast radius
A change to utils/auth.py could silently break 45 call sites. A change to seed_data.py is self-contained. BugViper surfaces this distinction so agents allocate more scrutiny to high-blast-radius changes. Blast radius scores also influence batching: files with overlapping call graph neighborhoods are grouped together using Louvain community detection, so the agent reviewing a high-impact file also sees the files that directly call it.

Why This Matters

A bug in a utility function called by 50 other modules is categorically more dangerous than a bug in a leaf module that nothing else touches. Traditional diff-only review can’t make that distinction — both bugs look equally small in the diff. BugViper’s call graph makes the structural risk visible. When an agent reviews a change, it knows:
  • Which files in the PR call the modified function
  • How many total downstream dependents exist
  • Whether the changed code sits at the core or the periphery of the codebase
This context shapes which findings the agent surfaces, how severely it scores them, and how the verifier evaluates whether an issue is worth posting. A minor type annotation inconsistency in a high-blast-radius module may warrant an inline comment; the same issue in an isolated script likely won’t.