Interactive force-directed graph visualizer for git diffs. Analyzes changed files between branches using ts-morph to extract TypeScript/JavaScript import relationships, then renders an interactive graph as a self-contained HTML file.
- Force-directed graph — nodes are files, edges are import relationships between changed files
- Search —
Cmd+K/Ctrl+Kto find any file, camera flies to the node - Filters — dropdown multiselect for file types (TS, JS, JSON, CSS...), groups/layers, and statuses (added, modified, deleted)
- Clustering — toggle to collapse groups into cluster nodes; click a cluster to expand it
- Diff viewer — click any node to see file details and the actual unified diff with colored lines
- Branch comparison — dropdown selectors to switch between branches/PRs and re-analyze live (requires
--servemode) - Self-contained HTML — output is a single file you can share, open offline, or commit to a PR
npm install --save-dev tsmorph-graphnpm install -g tsmorph-graphgit clone https://github.com/QusayNaserFHS/TSMorphGraph.git
cd TSMorphGraph
npm install# From within any git repo
npx tsmorph-graph --base main --branch HEAD --open
# Or specify a repo path
npx tsmorph-graph --repo /path/to/project --base main --branch feature/my-branch --opennpx tsmorph-graph --repo . --base main --branch HEAD --diff-content --opennpx tsmorph-graph --repo . --base main --branch HEAD --diff-content --serveThis starts a local server at http://localhost:3742. You can change branches from the dropdowns in the toolbar — the graph re-analyzes and updates without page refresh.
npm run analyze -- --repo /path/to/project --base main --branch HEAD --diff-content --open
npm run analyze -- --repo /path/to/project --base main --branch HEAD --diff-content --serve| Flag | Description | Default |
|---|---|---|
--repo <path> | Path to git repository | Current directory |
--base <branch> | Base branch for diff | main |
--branch <branch> | Compare branch | HEAD |
--diff-content | Include unified diff per file (opt-in) | Off |
--output <dir> | Output directory | ./output |
--open | Auto-open HTML in browser | Off |
--serve | Start live server with branch switching | Off |
--port <number> | Server port (with --serve) | 3742 |
--list-branches | Print available branches as JSON and exit | — |
import{analyze,generateHtml}from'tsmorph-graph';constdata=analyze({repo: '/path/to/project',base: 'main',branch: 'feature/xyz',diffContent: true,});consthtml=generateHtml(data);// data.nodes, data.links, data.meta are also available| Action | Effect |
|---|---|
Cmd+K / Ctrl+K | Open file search |
| Click node | Select node, open detail panel with diff |
| Click background | Deselect, close detail panel |
| Scroll | Zoom in/out |
| Drag | Pan the graph |
| Cluster toggle | Collapse/expand groups |
| Click cluster node | Expand that cluster |
| Filter dropdowns | Show/hide nodes by type, group, or status |
git diff base...branch
|
v
Parse --name-status + --numstat
|
v
ts-morph: analyze imports between changed .ts/.tsx/.js/.jsx files
|
v
Build nodes (files) + links (imports) + metadata
|
v
Inject JSON into self-contained HTML template (force-graph)
|
v
output/graph.html (open in browser)
{
"meta": { "branch": "...", "base": "...", "totalFiles": 30, "totalAdditions": 500, "totalDeletions": 120 },
"nodes": [
{ "id": "src/foo.ts", "name": "foo.ts", "filePath": "src/foo.ts", "additions": 42, "deletions": 10, "status": "modified", "fileType": "typescript", "group": "core", "diffContent": "..." }
],
"links": [
{ "source": "src/foo.ts", "target": "src/bar.ts" }
]
}- TypeScript (ESM) — all source code
- ts-morph — TypeScript AST analysis for import extraction
- force-graph — 2D canvas force-directed graph (loaded from CDN)
- Nx — workspace tooling (build, cache)
MIT
