# Native code graph

> Build, query and store code graphs of Rust, TypeScript, JavaScript and Markdown sources with bun:graph

`bun:graph-native` extracts a code graph from source files and runs graph algorithms on it in a worker thread. `bun:graph` stores graphs, runs and artifacts in a SQLite registry and queries them.

## Build and query a graph

`executeGraph()` takes one request and resolves with its result. Each request has a `scope` (a `graph:`-prefixed source name and a profile) and an `op`.

```ts graph.ts icon="/icons/typescript.svg"
import { executeGraph } from "bun:graph-native";

const scope = { source: "graph:demo", profile: "bun" } as const;

const built = await executeGraph({
  op: "build",
  scope,
  files: [{ path: "a.ts", content: "export function a() { return b(); }\nfunction b() { return 1; }\n" }],
});

console.log(built.result.graph.nodes.length, built.result.stats.calls);

const path = await executeGraph({ op: "path", scope, graph: built.result.graph, from: "a", to: "b" });
console.log(path.result.hops);
```

`build` extracts nodes and links from Rust (`.rs`), JavaScript and TypeScript (`.js`, `.jsx`, `.mjs`, `.cjs`, `.ts`, `.tsx`, `.mts`, `.cts`) and Markdown (`.md`, `.mdx`) files. Its result has the graph, call resolution statistics and the files that failed to parse.

| `op`      | Input                                           | Result                                                  |
| --------- | ----------------------------------------------- | ------------------------------------------------------- |
| `build`   | `files` (`{ path, content }`), `packages?`      | `graph`, `stats`, `parse_errors`                        |
| `query`   | `graph`, `question`, `depth?`, `budget_tokens?` | The best-matching nodes and their neighbourhood as text |
| `path`    | `graph`, `from`, `to`, `directed?`              | The hops of the shortest path, or `null`                |
| `explain` | `graph`, `node`                                 | The node with its incoming and outgoing connections     |
| `analyze` | `graph`, `top?`                                 | Communities, modularity and the most connected nodes    |
| `export`  | `graph`                                         | The normalized graph                                    |

`limits` bounds a request: `max_files`, `max_file_bytes`, `max_source_bytes`, `max_nodes`, `max_edges`, `max_ast_depth` and `max_output_bytes`. Pass an `AbortSignal` as `{ signal }` to cancel a request. At most four requests run at once; further requests reject until one finishes.

## Store graphs

`BunPython` (also exported as `PyJS`) opens a SQLite registry. With no argument it uses `bun_python.sqlite` in the current directory (`registryPath`).

```ts registry.ts icon="/icons/typescript.svg"
import { BunPython } from "bun:graph";
import { executeGraph } from "bun:graph-native";

using registry = new BunPython("graph.sqlite");
const repository = registry.repository("my-app", "git", process.cwd());

const { result } = await executeGraph({
  op: "build",
  scope: { source: "graph:my-app", profile: "bun" },
  files: [{ path: "a.ts", content: "export function a() {}\n" }],
});

const hash = new Bun.CryptoHasher("sha256").update(JSON.stringify(result.graph)).digest("hex");
await registry.importGraph(repository, result.graph, hash);

console.log(registry.queryNodes({ repositoryId: repository, search: "a" }));
console.log(registry.counts());
```

A registry holds repositories, files, nodes, edges, graph snapshots, runs, samples, fixes, events and artifacts. Its main methods:

| Method                                                 | Description                                                 |
| ------------------------------------------------------ | ----------------------------------------------------------- |
| `repository(name, kind, root, revision?)`              | Create or update a repository and return its id             |
| `importGraph(repositoryId, graph, sha256)`             | Import a graph as a new snapshot                            |
| `queryNodes({ repositoryId, kind?, label?, search? })` | Find nodes, paginated with `limit` and `offset`             |
| `neighbors(id)`, `incoming(id)`, `outgoing(id)`        | Adjacent nodes with their edges                             |
| `traverse(id, { direction?, maxDepth? })`              | Walk the graph from a node, with node and work limits       |
| `snapshots(repositoryId)`, `getSnapshot(repositoryId)` | Snapshots of a repository                                   |
| `coverage({ repositoryId, snapshotId? })`              | Node and edge counts by provenance, and unresolved nodes    |
| `startRun()`, `finishRun()`, `sample()`, `event()`     | Record command runs, benchmark samples and events           |
| `export(path?)`                                        | Write the registry as JSON, next to the database by default |

`bun:graphx` adds a Valkey/Redis result cache (`GraphRedisCache`) and helpers that render a registry as Markdown or HTML and stream bounded JSON. `packages/bun-types/graph.d.ts` declares every type.

The [`bun mcp`](https://bun.aphrody.app/docs/runtime/mcp) graph tools and [`bun lsp`](https://bun.aphrody.app/docs/runtime/lsp) use the same extraction to answer questions about a workspace.
