Skip to main content
GraphBuilder is a stateful builder class that accumulates nodes and edges from file analysis results and produces a complete KnowledgeGraph with a single call to build().
import { GraphBuilder } from '@understand-anything/core';

Constructor

constructor(projectName: string, gitHash: string)
projectName
string
required
Human-readable name for the project. Written into KnowledgeGraph.project.name.
gitHash
string
required
Git commit SHA at the time of analysis. Written into KnowledgeGraph.project.gitCommitHash.

Methods

addFile()

addFile(filePath: string, meta: FileMeta): void
Adds a single file node without deep structural analysis. Use this when only high-level metadata is available (e.g. from a lightweight scan pass). The node id is set to file:<filePath>. The name is derived from the last path segment. Language detection is performed automatically from the file extension and the detected language is added to the internal language set.
filePath
string
required
Relative file path (e.g. src/server/index.ts). Used as part of the node id and stored on the node.
meta
FileMeta
required
Metadata for the file node.

addFileWithAnalysis()

addFileWithAnalysis(
  filePath: string,
  analysis: StructuralAnalysis,
  meta: FileAnalysisMeta,
): void
Adds a file node along with child function and class nodes extracted from a full structural analysis. For each function and class, a contains edge is automatically created from the file node. This method is used by the agent pipeline when deep per-file analysis has been performed. Node IDs assigned:
  • File: file:<filePath>
  • Function: func:<filePath>:<functionName>
  • Class: class:<filePath>:<className>
filePath
string
required
Relative path to the source file.
analysis
StructuralAnalysis
required
Structural analysis result from a parser or tree-sitter plugin.
meta
FileAnalysisMeta
required
Extended metadata including per-symbol summaries.

addImportEdge()

addImportEdge(fromFile: string, toFile: string): void
Adds an imports edge between two file nodes with a default weight of 0.7.
fromFile
string
required
Relative path of the importing file. The source node ID will be file:<fromFile>.
toFile
string
required
Relative path of the imported file. The target node ID will be file:<toFile>.

addCallEdge()

addCallEdge(
  callerFile: string,
  callerFunc: string,
  calleeFile: string,
  calleeFunc: string,
): void
Adds a calls edge between two function nodes with a default weight of 0.8.
callerFile
string
required
Relative path of the file containing the calling function.
callerFunc
string
required
Name of the calling function. The source node ID will be func:<callerFile>:<callerFunc>.
calleeFile
string
required
Relative path of the file containing the called function.
calleeFunc
string
required
Name of the called function. The target node ID will be func:<calleeFile>:<calleeFunc>.

build()

build(): KnowledgeGraph
Assembles all accumulated nodes and edges into a complete KnowledgeGraph and returns it. Does not mutate the builder — you can continue calling addFile* methods and call build() again. What build() sets automatically:
  • version: always "1.0.0"
  • project.languages: sorted array of all detected languages
  • project.frameworks: [] (not populated by GraphBuilder)
  • project.description: "" (not populated by GraphBuilder)
  • project.analyzedAt: new Date().toISOString() at call time
  • layers: [] (populated separately by detectLayers)
  • tour: [] (populated separately by tour generation)
Returns KnowledgeGraph

Language detection

GraphBuilder automatically detects the programming language from the file extension and tracks it internally. The languages array on the built graph contains only languages actually seen in the added files. Supported extension mappings:
ExtensionsLanguage
.ts, .tsxtypescript
.js, .jsx, .mjs, .cjsjavascript
.pypython
.rbruby
.gogo
.rsrust
.javajava
.ktkotlin
.swiftswift
.c, .hc
.cpp, .hppcpp
.cscsharp
.phpphp
.lualua
.sh, .bash, .zshshell
.jsonjson
.yaml, .ymlyaml
.tomltoml
.xmlxml
.htmlhtml
.csscss
.scssscss
.lessless
.mdmarkdown
.sqlsql
Files with unrecognized extensions are still added but do not contribute to the languages list.

Usage example

import { GraphBuilder } from '@understand-anything/core';
import type { StructuralAnalysis } from '@understand-anything/core';

const builder = new GraphBuilder('my-project', 'abc1234');

// Add a file with structural analysis
const analysis: StructuralAnalysis = {
  functions: [
    { name: 'validateToken', lineRange: [12, 34], params: ['token'], returnType: 'boolean' },
  ],
  classes: [],
  imports: [{ source: 'jsonwebtoken', specifiers: ['verify'], lineNumber: 1 }],
  exports: [{ name: 'validateToken', lineNumber: 12 }],
};

builder.addFileWithAnalysis('src/auth.ts', analysis, {
  fileSummary: 'Handles JWT authentication.',
  summaries: {
    validateToken: 'Verifies a JWT token and returns whether it is valid.',
  },
  tags: ['auth', 'jwt', 'security'],
  complexity: 'simple',
});

// Add a lightweight file node
builder.addFile('src/config.ts', {
  summary: 'Application configuration constants.',
  tags: ['config'],
  complexity: 'simple',
});

// Add import relationship
builder.addImportEdge('src/server.ts', 'src/auth.ts');

// Add call relationship
builder.addCallEdge('src/routes/login.ts', 'handleLogin', 'src/auth.ts', 'validateToken');

// Build the final graph
const graph = builder.build();
// graph.nodes.length === 3  (file:src/auth.ts, func:src/auth.ts:validateToken, file:src/config.ts)
// graph.edges.length === 3  (contains, imports, calls)
// graph.project.languages  === ['typescript']

Persistence utilities

The core package also exports utility functions for saving and loading graphs to/from disk. These write to and read from .understand-anything/knowledge-graph.json in the given project root directory.
import { saveGraph, loadGraph, saveMeta, loadMeta } from '@understand-anything/core';

saveGraph()

saveGraph(projectRoot: string, graph: KnowledgeGraph): void
Writes graph as pretty-printed JSON to <projectRoot>/.understand-anything/knowledge-graph.json. Creates the .understand-anything/ directory if it does not exist.

loadGraph()

loadGraph(
  projectRoot: string,
  options?: { validate?: boolean },
): KnowledgeGraph | null
Reads and parses the knowledge graph from <projectRoot>/.understand-anything/knowledge-graph.json. Returns null if the file does not exist. By default (validate not set or true), the loaded data is validated against KnowledgeGraphSchema. Throws an Error with a descriptive message if validation fails. Pass { validate: false } to skip validation and return the raw parsed object.
// Load with validation (default)
const graph = loadGraph(process.cwd());
if (!graph) throw new Error("No knowledge graph found — run /understand first.");

// Load without validation
const raw = loadGraph(process.cwd(), { validate: false });

saveMeta()

saveMeta(projectRoot: string, meta: AnalysisMeta): void
Writes meta as JSON to <projectRoot>/.understand-anything/meta.json. Used by the pipeline to persist staleness-check data.

loadMeta()

loadMeta(projectRoot: string): AnalysisMeta | null
Reads and parses <projectRoot>/.understand-anything/meta.json. Returns null if the file does not exist.

Build docs developers (and LLMs) love