@zaidakbar/zgraph
v0.1.0
Published
Local-first interactive 3D codebase knowledge globe (AST-based, no embeddings).
Maintainers
Readme
ZGraph
An interactive 3D knowledge globe for your codebase. Local-first, AST-based, no embeddings.
z-graph parses your TypeScript/JavaScript project into a deterministic graph of files, functions, classes, methods, and the imports/calls/defines edges between them — then renders it as a live 3D globe in your browser. As you edit your code, the graph updates in real time.
npx zgraph devThat's the whole install. It runs in the current directory, picks a free port, opens your browser, and starts watching.
Why
Reading code linearly is slow. ZGraph turns "what calls this?", "what would I break if I rename this?", and "do we have circular imports?" into a glance.
Compared to traditional code-visualization tools:
| | ZGraph | Most others |
| --- | --- | --- |
| Setup | npx zgraph dev | config files, services |
| Updates | live, sub-second | manual rebuild |
| Render | 3D force-directed globe | 2D node-link |
| AI / embeddings | none — pure AST | often required |
| Storage | .zgraph/graph.json | external DB |
| Insights | cycles, dead code, hotspots, impact | usually none |
Install
npm i -D z-graph
# or one-shot:
npx zgraph devRequires Node 18+.
Commands
zgraph dev [path] # live 3D globe with file watcher (defaults to .)
zgraph build [path] # build graph.json without starting a server
zgraph stats [path] # print node/edge counts from cached graphdev flags:
-p, --port <n>preferred port (auto-finds a free one if taken; default 7777)--no-opendon't auto-open the browser--no-cacheignore the persisted graph and rebuild from scratch--editor <name>vscode | cursor | windsurf | zed | webstorm | idea | subl
Features
The globe
- 3D force-directed layout — nodes spread into a roughly spherical cloud
- Color-coded by node type (file, function, class, method, module)
- Hover any node for a live source-snippet preview
- Click to select; selection rings, neighbor highlighting, edge fade
- Animated particles flow along
callsedges - Pulse animation when nodes are added by the live watcher
Insights (press i)
- Cycles — Tarjan SCC over import edges, with one-click jump
- Dead code — exported symbols with zero callers
- Hotspots — files ranked by combined fan-in × fan-out
Power tools
- Command palette (
⌘K/Ctrl+K) — search nodes or run any action - Open in editor (
o) — VS Code / Cursor / WebStorm / Zed / Sublime / IntelliJ deep links - Path finding — pick any two nodes, see the shortest dependency path
- Impact view — click a node, "impact" → highlights everything that transitively depends on it
- Saved views — bookmark filter+selection state, restore in one click
- Shareable URL — every selection/filter/path lives in
location.hash; copy and send - PNG export (
⌘E) — drop the current view straight into a PR description - LOD rendering — symbol nodes hide automatically when zoomed out so big repos stay legible
Live updates
- Chokidar watches the repo and patches the graph in place — no full rebuild
- WebSocket pushes a minimal patch (
+nodes/-nodesonly) to the UI - Downstream importers are reparsed automatically when an upstream export changes
Graph engine (under the hood)
- Stable node identity:
filePath + symbolName(so re-renders preserve selection) - Cross-file
obj.method()resolution via localnew ClassName()bindings this.method()resolution via enclosing class- Re-export chains (
export { x } from "./y") followed - File-hash-based incremental builds (cached in
.zgraph/graph.json) - Monorepo-aware: detects npm/yarn/pnpm workspaces
Keyboard shortcuts
| Key | Action |
| --- | --- |
| ⌘K / Ctrl+K | Command palette |
| / | Focus search |
| f | Focus camera on selection |
| i | Open insights |
| o | Open selection in editor |
| ⌘E / Ctrl+E | Export PNG |
| Esc | Clear selection / close panel |
HTTP API
The dev server exposes a small REST + WebSocket API at http://localhost:<port>:
GET /api/info rootDir, workspaces, default editor
GET /api/graph full SerializedGraph
GET /api/stats node/edge counts
GET /api/node/:id selected node + neighbors
GET /api/search?q=… name/id search
GET /api/path?from=…&to=… shortest path
GET /api/dependencies/:id transitive imports
GET /api/impact/:id transitive importers ("what breaks if I change this")
GET /api/insights/cycles Tarjan SCCs over import edges
GET /api/insights/dead exported, uncalled symbols
GET /api/insights/hotspots fan-in × fan-out ranking
GET /api/source?file=…&start=&end= source snippet
POST /api/open {file, line, editor} open a file in your editor
WS /ws push: {type: "graph:full"|"graph:patch", payload}Programmatic use
import { buildGraph, QueryEngine } from "@zaidakbar/zgraph";
const { graph } = await buildGraph({ rootDir: "/path/to/repo" });
const q = new QueryEngine(graph);
console.log(q.findCycles());
console.log(q.findDeadCode());
console.log(q.findHotspots());
console.log(q.getImpact("file:src/auth/session.ts"));
console.log(q.findPath("file:src/index.ts", "func:src/db/conn.ts#open"));Storage layout
.zgraph/
graph.json # serialized graph + per-file content hashes (for incremental builds)Add .zgraph/ to your .gitignore.
Limitations
- TS/JS only in this version. Python/other languages planned via tree-sitter.
- Call resolution is AST-driven (not type-checker driven), so
obj.method()binds via localnewbindings,this, or imported names. Calls through abstract interfaces, generics, or dynamic property access aren't resolved. - Re-export aliases (
export { x as y }) follow the source target but the alias mapping isn't fully propagated.
License
MIT
