GraphView — Dependency Map
VS Code extension that reads your project's imports — in any of 12+ languages —
and draws the dependency map in three modes: an interactive force-directed
graph, a rotating 3D sphere, and a navigable tree in the style of
Flutter's widget tree, with search, filters and cycle detection.
Key Features
1. Dependency Graph (canvas + d3)
- Layered layout: every file is pulled toward its category anchor (api,
services, data, ui, hooks, state…), so the project's architecture shows up as
distinct spatial clusters.
- Edge highlighting: hovering a node lights up its edges — orange for what it
imports, green for what imports it — and works on top of an existing
selection, so you can compare two files without losing your place.
- Direct navigation: click to select, double-click to open the file, drag to
reposition a node, scroll to zoom.
- Side panel: lists both dependency directions with counts; clicking any
entry jumps to that file.
2. Sphere View (3D)
- Files are laid out on the surface of a sphere, each category occupying its
own "continent" — the most connected files sit at the center of each cap.
- Drag to rotate, scroll to zoom, and a
spin toggle for slow auto-rotation
(it pauses automatically while you have a file selected).
- Real perspective projection with depth cues: nodes and edges on the far
side of the sphere fade out, and everything is painter-sorted back to front.
- Same interactions as the graph — hover to highlight, click to select,
double-click to open.
- Hierarchy with indent guides, child counts and a per-category color dot.
- Roots = entrypoints (files nobody imports). The direction is reversible:
imports ↓ or imported by ↑.
- Cycles are flagged with ↻ and recursion stops there, so circular
dependencies neither hang nor blow up the tree.
- "Use as root" pins any file at the top to inspect just its subtree.
4. Native Activity Bar Panel
- GraphView icon → Dependencies panel, a native VS Code
TreeView showing
the real file icons from your active icon theme.
- Single click opens in preview (italic tab); double-click pins the tab.
- Title bar actions: open the full map, flip the direction, and reload.
5. Search & Filters (apply to every mode)
- Search by name or path, with a result count;
Enter jumps to the next
match (Shift+Enter goes back) and the graph zooms to it.
- Project filter: point GraphView at a folder holding dozens of repos and it
detects each project by its manifest, letting you isolate one at a time.
- Role in the graph: entrypoints, leaves, hubs (top decile by connections),
in a cycle (strongly connected components via Tarjan) and weakly connected.
- Folder filter by text and minimum connections slider.
- Clickable legend: hide entire categories to isolate a single layer.
Supported Languages
| Language |
Extensions |
What is followed |
| JavaScript / TypeScript |
.js .jsx .mjs .cjs .ts .tsx .vue .svelte .astro |
import / require / dynamic import() |
| Python |
.py .pyi |
import a.b, from .rel import x, package __init__ |
| Dart |
.dart |
import/export/part, including package: URIs |
| Go |
.go |
import blocks, resolved against the go.mod module path |
| Rust |
.rs |
mod x; and use crate::a::b |
| Java / Kotlin / Scala / Groovy |
.java .kt .kts .scala .groovy |
import com.foo.Bar |
| C# |
.cs |
using X.Y; |
| Ruby |
.rb .rake |
require / require_relative |
| PHP |
.php |
require/include and use App\Foo |
| C / C++ / Obj-C |
.c .h .cc .cpp .hpp .m .mm |
#include "..." and <...> |
| Swift |
.swift |
import Module (when it maps to a file) |
| Elixir |
.ex .exs |
import / alias / use |
How It Works
scan.js walks the workspace folder, extracts each file's imports with a
per-language parser, and resolves them to other scanned files. Relative paths are
resolved directly; package-style names (a.b.c, crate::a::b, com.foo.Bar,
package:app/x.dart) are matched against a path-suffix index, trying
progressively shorter prefixes so use crate::a::b::Symbol still finds a/b.rs.
Two rules keep the edges honest:
- Ambiguous targets are dropped. If a name could match two files, GraphView
draws no edge rather than guessing wrong.
- Resolution is scoped to a project. Each file belongs to the nearest folder
holding a manifest (
package.json, go.mod, pubspec.yaml, Cargo.toml,
pyproject.toml, pom.xml, …), and package-style imports only resolve inside
it — so scanning a folder with 40 repos never links one repo to another.
Files with no connections at all are left out. Each file's category comes from
the first path segment matching the table in scan.js (controllers/routes →
api, components/widgets → ui, models/repositories → data, and so on).
For a sense of scale: a folder with 41 projects — 7,700 files across JS, Python,
Dart and C — is scanned in about 2 seconds.
Commands
graphview.show: GraphView: dependency map — opens the graph/sphere/tree
in an editor tab.
graphview.refresh: GraphView: reload map — re-reads the files from disk.
graphview.toggleDirection: GraphView: flip tree direction — toggles
between "imports" and "imported by" in the side panel.
Configuration
| Setting |
Default |
What it does |
graphview.include |
[] (all supported languages) |
Restrict to specific extensions, e.g. [".py"]. |
graphview.exclude |
node_modules, dist*, build, .venv, .dart_tool, … |
Directories skipped. |
graphview.maxFiles |
4000 |
Cap on how many files are scanned. |
graphview.exclude matches directory names and accepts wildcards: dist*
covers dist, dist-electron-web and dist-ssr. Generated and bundled files
(*.min.js, *.g.dart, *_pb2.py, *.pb.go, …) are skipped everywhere.
License
MIT
| |