Repository navigation
Home
Code Canvas is a Visual Studio Code extension that turns your workspace into an interactive dependency graph. It indexes your JavaScript/TypeScript and Python files, resolves their imports, and renders the result as a canvas of folders and files connected by circuit-style wires.
The canvas is collapse-first: folders open as compact chips carrying the aggregate of everything inside them, and you expand only the parts you care about. That is what keeps a ten-thousand-file repository readable — and fast.
- Folder-level graph - a collapsed folder shows the union of its descendants' external imports, with in/out degree badges
- Expand on demand - open a folder to reveal its files and subfolders; edges re-anchor to the specific file
- Radial layout - connected nodes on concentric rings, unconnected files in the centre
- Circuit-style edges - orthogonal wires that route around nodes, not through them
- Symbols on hover - a wire tells you which functions, classes and types cross that boundary
- Automatic descriptions - every file and folder is described from its doc comment, exports and imports; your own text always wins
- Inline code previews - syntax-highlighted, scrollable, click a token to jump to its definition
- Git-aware - open changed files, live refresh on save
This project is provided as-is with many known and unknown bugs. I open-sourced it so the community can build on it and take it further. I don’t have time to actively maintain it. Use at your own risk; contributions are very welcome.
- Node.js 18+ (Vite 7 requires Node 18 or newer)
- VS Code 1.102+ (as per extension engine)
- Git (optional but recommended; used to detect changed files)
This repo uses npm workspaces with two packages:
-
extension/- the VS Code extension (TypeScript, bundled with tsup) -
webview/- the webview UI (React, Vite, React Flow, ELK)
- Install dependencies at the repository root (installs both workspaces):
npm install- Build the webview and the extension:
npm run buildThis produces the webview build into extension/media/ and the extension bundle into extension/dist/.
- Launch the extension for development in VS Code:
- Open the repository in VS Code
- Press F5 (Run and Debug → “Extension”) to launch a new Extension Development Host
- In the dev host, run “Code Canvas: Open” to show the canvas panel
Notes for rapid iteration:
- The default root watch script starts Vite’s dev server for the webview, which doesn’t feed the extension’s
extension/media/folder. For quickest feedback inside the extension, prefer a build‑watch for the webview:- Terminal A:
cd webview && npx vite build --watch - Terminal B:
npm -w extension run watch - Reload the Extension Development Host window to pick up changes if needed
- Terminal A:
Root scripts for convenience:
-
npm run build— buildwebviewthenextension -
npm run watch— runswebview devandextension watchin parallel (dev server for webview; see note above) -
npm run package— package the extension VSIX viavsce
Create a .vsix package:
npm run packageThis generates a file like extension/code-canvas-0.0.1.vsix.
Install the VSIX locally:
code --install-extension extension/code-canvas-0.0.1.vsixOr via VS Code: Extensions view → “…” menu → Install from VSIX…
Open the canvas:
- Command Palette → “Code Canvas: Open”
Toolbar (in the webview):
- Layout selector — Radial / ELK / Dagre / Force
- Relayout — recompute the current layout
- Expand (E) — grow the graph from the selected nodes
- Hide/Show Edges — toggle edge visibility
- Seed Folder… — build a view scoped to a specific folder
- Load More — raise the node cap
- Restore Hidden — bring back nodes removed with Delete
- Refs (R) — toggle the references panel
- Wrap/Unwrap — toggle code wrapping in previews
Interaction tips:
- Click the chevron on a folder (or double-click it) to expand or collapse
- Double-click a file header to open it in the editor
- Scroll inside a code card with the wheel; the canvas zooms everywhere else
- Hover an edge to see the symbols crossing that boundary
- Click an edge to scroll both code cards to the import site
- Click a token in code to jump to its definition and populate the references panel
- Press E to expand from the selection; Delete hides nodes (restorable)
- Zoom out far enough and code bodies become labels — a deliberate performance floor
Seeds and growth:
- The opening view is chosen automatically: folders expand just far enough to show a graph with actual edges
- Your expansion state, hidden set and layout choice persist across reloads
- "Seed Folder…" scopes the view to one folder
Contributed commands (Command Palette):
- Code Canvas: Open (
codeCanvas.open) - Code Canvas: Open Changed Files (
codeCanvas.openChanged) - Code Canvas: Layout – Radial (
codeCanvas.layout.radial) - Code Canvas: Layout – Dagre (
codeCanvas.layout.dagre) - Code Canvas: Layout – ELK (
codeCanvas.layout.elk) - Code Canvas: Layout – Force (
codeCanvas.layout.force) - Code Canvas: Toggle Refs (
codeCanvas.toggleRefs) - Code Canvas: Open Folder as Seed (
codeCanvas.seedFolder) - Code Canvas: Load 25 More (
codeCanvas.loadMore)
Default keybindings:
- ⇧O — Open Changed Files
- ⇧+ — Load 25 More
- ⇧1 / ⇧2 / ⇧3 / ⇧4 — Layout: Radial / Dagre / ELK / Force
- R — Toggle Refs
All four algorithms are implemented and switch at runtime. Radial is the default.
User/workspace settings under Code Canvas:
-
codeCanvas.initialCap(number, default: 400) — Files pulled in on first render. Folders open collapsed, so this can be generous; a small cap silently truncates whole parts of the tree. -
codeCanvas.maxNodes(number, default: 1000) — Ceiling for expansion and "Load more" -
codeCanvas.maxPreviewBytes(number, default: 100000) — Max bytes per file sent to the code preview -
codeCanvas.excludeGlobs(array) — Glob patterns excluded from indexing. Defaults covernode_modules,venv/.venv,site-packages,__pycache__,dist,build,out,.next,.expo,coverage,.cache,vendor,Pods,logsand more.⚠️ Setting this replaces the default list rather than adding to it.
Full documentation lives in __doc__/. In brief:
-
Indexing (extension host) —
fast-globfinds JS/TS/Python files, regex scanners extract import specifiers and their bindings, and relative specifiers resolve to absolute paths. One read per file also captures exported symbols and the leading doc comment. - Subgraph — a BFS from the seed files, then a top-up pass so disconnected parts of the workspace (a frontend that never imports the backend) still appear.
- Model & projection (webview) — the full tree is held as plain data. Only a projection of it reaches React Flow: each edge endpoint is mapped up to its nearest visible ancestor, so a collapsed folder carries the union of its descendants' external edges.
- Layout — one container-recursive pipeline, deepest-first, shared by all four engines. A group's size is final before its parent spaces it, so containers cannot overlap.
- Routing — orthogonal paths found by turn-aware A* over a Hanan grid built from node rectangles, computed off the render path and memoised by geometry hash.
- Descriptions — composed from doc comments, exports and resolved imports; stored separately from anything you write.
| Document | Covers |
|---|---|
| Architecture | Process model, message protocol, data flow |
| Indexing | Parsing, resolution, subgraph selection |
| Graph model | Collapse-first projection |
| Layout | Radial/ELK/Dagre/Force, non-overlap invariant |
| Edge routing | Hanan grid + A*, performance budgets |
| Descriptions | Generation and the override rule |
| UI reference | Commands, settings, interactions |
| Performance | The rules that keep it fast |
| Development | Build, package, debug, offline harnesses |
JavaScript, TypeScript (including JSX/TSX) and Python. Nothing else is indexed.
Only relative imports resolve — bare package specifiers are skipped by design, and TypeScript paths / bundler aliases (@/components/…) are not resolved yet.
- Changes don’t appear after installing: reload the VS Code window —
--install-extensiondoes not refresh an open one. Also make sure you rannpm run buildat the root, sincevscode:prepublishbuilds only the extension, not the webview. - Nothing shows up: make sure you opened a folder and have JS/TS or Python files that aren’t excluded by settings.
- Whole folders missing: raise
codeCanvas.initialCap, or checkexcludeGlobsisn’t too broad. - Very few edges: your imports probably go through TS
pathsor bundler aliases, which aren’t resolved yet. - Code cards won’t scroll: the wheel scrolls a card and zooms the canvas — make sure the pointer is over the code.
- Webview doesn’t update: If using watch mode, prefer
npx vite build --watchinstead ofvite devto feedextension/media/where the extension loads assets. - Node version errors: Ensure Node 18+.
- Changed files missing: Verify the Git extension is enabled; otherwise the extension falls back to parsing
git statusoutput. - Performance: Reduce
codeCanvas.maxNodesand/or widencodeCanvas.excludeGlobs. Large files are truncated tocodeCanvas.maxPreviewBytesfor preview.
Root package.json:
{
"scripts": {
"build": "npm -w webview run build && npm -w extension run build",
"watch": "npm -w webview run dev & npm -w extension run watch",
"package": "npm -w extension run package"
},
"workspaces": ["webview", "extension"]
}Webview package.json:
{
"scripts": {
"dev": "vite",
"build": "vite build"
}
}Extension package.json:
{
"scripts": {
"vscode:prepublish": "npm run build",
"build": "tsup src/extension.ts --format cjs --dts --out-dir dist --external vscode",
"watch": "tsup src/extension.ts --watch --format cjs --out-dir dist",
"package": "vsce package --no-dependencies"
}
}Tip: For a webview build watch, run npx vite build --watch inside webview/.
- Additional language parsers (Go, Rust, Java, C#)
- Resolve TypeScript
pathsand bundler aliases - Migrate to React Flow v12 (
@xyflow/react) and adoptNodeResizer - Model-generated descriptions as an opt-in alternative to the heuristics
- Named, saveable canvases and screenshot export
MIT - free to use, modify, and distribute. See the LICENSE file for details.
- React Flow for graph rendering
- ELK (Eclipse Layout Kernel) for layered layouts
- Highlight.js for syntax highlighting
- VS Code extension samples and APIs
First of all I give thanks to the original author waLLxAck. I have forked his source code for this extension and added support for VScode later versions. I have also optimized and added new features, while improving usability of the extension. You might see build files here. I have git committed them intentionally as a fallback. I have tested it extensively on VScode 1.129.1, extension engine 1.102+. Version lesser than this might not work with this extension. You can report any bug(s) or ask for new features. Even though the extension is under development and more features will be coming next month, the master is the stable release branch and you are welcome to try it!