Single-page reference. Use the minimap to jump between sections.
Code Canvas is an infinite canvas for exploring and reviewing codebases visually.
Files are arranged as a folder-aware dependency graph: each file still sits inside its real folder structure, but the layout also accounts for how files import and depend on each other. That combination turns the canvas into a map of the codebase's actual architecture.
Use it to:
Full dependency analysis and LSP integration
and more coming later
You can ask the AI questions about these docs by connecting Code Canvas's MCP.
In the app, press Cmd+K to open the command palette and find any feature.
You can also open these docs inside the app from the help menu in the bottom-left sidebar. UI links highlight the relevant panel directly in the application's interface when clicked.
Code Canvas runs in three forms: a browser app, a VSCode extension, and a desktop app.
The following features require the local Node.js server running on your local machine:
Start the server with:
npx code-canvas-serverThe local server runs on your computer, and it's required only when using the browser version.
code --install-extension alex-c.code-canvas-appcursor --install-extension alex-c.code-canvas-app)The extension mirrors the active editor into the canvas: the cursor position, selection, and word under the caret all drive canvas highlights and navigation in real time, so opening a function in VS Code or Cursor jumps the canvas to it. The reframe behavior (keep zoom, smooth transition, include references, zoom level) is set in Navigation Settings.
Option+Click any file on the canvas to open it in an editor column beside the canvas. Click directly on a line of code and the editor scrolls to that line; click on the filename label to open the file at the top.
codeCanvas.startOnStartup → open Code Canvas automatically when the editor starts with a workspace (off by default)codeCanvas.showStatusBarItem → show or hide the Code Canvas status bar itemConnect a public GitHub repo without signing in for instant read-only browsing with language servers, search, diffs, and MCP. Point Code Canvas at a local folder when you need private code or live file watching.
owner/repogithub.com with v2.codecanvas.app in any GitHub repo URL to open it directly, e.g. v2.codecanvas.app/facebook/reactnpx code-canvas-server to enable the local connectionDependency edges show where exports are imported: each edge runs from an export site to the import site that resolves to it.
Each edge connects an importer to the imported export
Files are arranged left to right by dependency and folder structure
Toggle edge visibility from Dependency Edge Visibility in the Dependency Edges panel
When All is off, edges filter by category. Combine them as needed:
Selected → only edges touching a selected file
Changes → only edges touching a file changed in the active diff
Backwards → only cycle / layering edges, useful for spotting architectural violations
Internal → edges that stay inside the same folder
External → edges that cross folders, with a nesting-depth range slider that controls how far up the folder tree the edge has to cross to count
For very large codebases, turn All off and combine these filters to keep rendering responsive. If too many edges are visible at once, Code Canvas can also auto-trim them and notify you.
| Language | What's tracked |
|---|---|
| JavaScript / TypeScript / JSX / TSX | static import statements (default, named, namespace, side-effect, type-only); dynamic import(); require(); destructured forms; exports and re-exports |
Other languages still parse with tree-sitter for syntax highlighting and CST visualization, but no dependency edges yet.
An index file (index.ts, index.tsx, index.js, index.jsx, index.mjs, index.cjs, index.mts, index.cts) often re-exports things from sibling files → a "barrel"
Two display modes live in Barrel and Re-export settings inside the Dependency Edges panel:
Re-export edges → direct shortcut from importer to the original source export, skipping the barrel
Barrel edges → split into two hops: importer to the barrel re-export row, then re-export row to the source
Each can be independently shown or highlighted
TypeScript path aliases → read from tsconfig.json
Vite aliases → read from vite.config.{ts,js,mjs,cjs}
Index file fallback → ./foo resolves to ./foo/index.ts (or other resolvable extensions)
@/ shorthand falls back to src/
External (npm) modules are tagged external and don't draw edges
The goal of the layout is to reveal architecture. The files are arranged left to right based on dependency and folder structure.
The algorithm starts at leaf folders, laying out all the files inside the folder based on dependency, then moves up one level in the folder hierarchy, treating the sorted child folders as single nodes at that level. The process repeats until it reaches the root folder.
By combining the folder structure and dependencies, the layout of the files on the canvas reveals the architecture of the codebase.
Because files are laid out left to right, an edge that runs backwards from a file on the left to a file on the right usually signals a circular dependency or layering problem somewhere in the import chain. It is not always a direct file-to-file cycle; it can be a cycle between modules or folders. You can highlight these from Dependency Edge Visibility, where backwards edges render in red.
Open the Layout panel to apply layout, toggle auto layout, change horizontal and vertical alignment, adjust file and folder spacing, set folder padding, change sort behavior, and tune rank breaking. Hover a control label in the panel for a short description of what that control changes.
The Break slider controls rank breaking, letting you change the aspect ratio of the graph while preserving its edge relationships. Each file on the canvas is much taller than it is wide, just by the nature of how code files are written, so rank breaking is there to produce a more cohesive layout that fits the screen better.
Language servers add semantic information on top of the canvas. Hover a function and Code Canvas highlights its definition, references, callers, callees, and implementations across every open file.
Open the LSP panel
Use the LSP menu to open Language servers, then load or connect the server you need. TypeScript ships bundled.
References in light amber
Definitions in pink
Type definitions in pink with a stroke
Implementations in green
Incoming calls (who calls this) in light purple
Outgoing calls (what this calls) in orange
Click a symbol to pin its graph; Shift+Click to pin multiple.
The File nodes panel gains three actions that act on the currently-selected file node(s):
Open Importers → pulls every file that imports the selection onto the canvas. Resolved by asking the language service for references to each export, so it works for files that aren't on the canvas yet.
Open Imports → pulls every file the selection imports onto the canvas. Derived from the dependency graph, so the imported file must already have been analyzed.
Highlight Top-Level Symbols → in the Symbols section, pins a symbol graph for every top-level symbol in the selection, one after another. Skip imports is on by default so the highlights cover declarations rather than the imports the file brings in; toggle it off to include import statements as well.
All three are also available from the command palette (Cmd+K).
LSP settings include:
Query On Hover → auto-query as you hover; with it off, click a symbol to query
Auto Open Matches → automatically open files that contain matches, up to the Max files limit
Keep Zoom → keep the current zoom when navigating to a result
Smooth Transition → animate the viewport instead of jumping
Out-of-view target labels → when a symbol's target file scrolls off the canvas, a sticky label appears at the canvas edge pointing toward it, so you don't lose the connection. Toggle it from LSP Symbol Edge Settings.
Mirror IDE editor → in the VS Code / Cursor extension, the active editor's cursor and selection mirror into canvas highlights. Reframe behavior lives in Navigation Settings.
Use Clear Symbols (Shift+C) to remove every pinned symbol at once.
CST stands for concrete syntax tree. Code Canvas tints code regions by their syntactic role (functions, classes, conditionals, loops) so you can read structure at a glance, especially when zoomed out where individual characters disappear. Think of it as a smarter minimap baked into the canvas itself.
Per-type colors are editable from the CST panel
Pick a custom color, fill mode (solid or gradient), opacity, and border width / sides for any node type
Hide types you don't want to see
For large CST regions, such as function bodies or statement blocks, you do not always have to place the cursor directly over the name token. Symbol Mapping chooses a meaningful token inside that region instead, so hovering or clicking anywhere inside the construct can still highlight the related connections on the canvas.
See code changes in the context of the whole codebase. Local working changes update in real time as you edit; pull requests load from GitHub. Reviewing a change on the canvas shows you not just what changed but where it sits in the architecture and what it connects to.
Local changes → your working tree, refreshes when files change
Pull requests → pick from the GitHub PR list (sign-in required for private repos)
Local changes are the default source. Selecting a PR replaces them on the canvas with that PR's changes; closing the PR returns the canvas to your local changes.
Changes → the file as it is now, with added and modified lines marked and a marker where lines were deleted. Like an editor window in an IDE: deleted lines are not rendered, just signposted.
Unified → old and new in a single column
Split → old and new side by side
Cycle modes with D; reverse with Shift+D
The language server highlights work on both versions of a diff (old and new) separately, so you can trace references, definitions, and calls in either side independently.
The File nodes and Folders panels gain extra buttons during a diff session, each with a keyboard shortcut:
Shift+O → Open Changed Files: open every changed file in the active diff onto the canvas
Option+O → Close Files Without Changes: remove canvas files whose own path has no changes
Close Folders Without Changes: remove files whose entire folder has no changes (unchanged files inside a folder that has at least one change are kept)
Open All Folders With Changes: open every file in any folder that contains at least one changed file, so unchanged neighbors come along for context
Diffs above the per-file scan limit are skipped to keep the canvas responsive. When that happens, the File nodes panel shows an amber Large Diffs card with a one-click action to load just the open canvas files that were skipped, without raising the global limit.
Open Diff settings from the settings gear next to the diff mode toggle.
Context → number of unchanged lines kept above and below each change when collapsed
Character diff → Word, Char, or Off for fine-grained highlighting inside modified lines
Show deleted chars → render character-level deletion markers on modified lines
Similarity threshold → minimum similarity required to pair an added line with a removed line for character diffing; higher values pair only near-identical lines
Collapse / expand unchanged → toggle with C
git status for the current local sessionConnect AI agents to Code Canvas through MCP and they can drop annotated cards onto the canvas while they explain code. Each note's links resolve to specific files, folders, or symbols. Clicking one navigates the canvas and highlights the target. Reading an explanation while seeing the actual code is much more useful than reading text in isolation.
A title and a markdown body, both written by the agent
Links use the cc:// scheme and target one of:
a file: cc://file/path/to/file.ts
a folder: cc://folder/path/to/dir
a symbol: cc://symbol/path/to/file.ts:LINE:CHAR
a range: cc://range/path/to/file.ts:SL:SC-EL:EC
Clicking a link navigates the canvas and highlights the target
Hovering a link previews the highlight without navigating
Connect the MCP and ask the AI to explain a feature using agent_notes. The description appears in the Agent Notes panel as a navigable note instead of plain chat text.
Find code, files, or folders across the entire workspace, highlight matches, and jump straight to results on the canvas. Off-canvas matches stay listed alongside on-canvas ones, so a single search shows both what you can already see and what you'd need to open.
Code → full-text search across file contents
Files & folders → search by filename and folder path
Tab toggles modes from the search input
.* → regex
Aa → case sensitive
Word → whole word
Ignored → include gitignored files (local repos only)
Canvas → only files currently open on the canvas
Grouped into On Canvas and Off Canvas sections
Click an on-canvas result to focus it on the canvas
Click an off-canvas result to open the file and focus the match
ArrowUp / ArrowDown to navigate, ArrowLeft / ArrowRight to collapse / expand, Enter to open
Keep Zoom and Smooth Transition toggles control how navigation behaves
The Settings panel covers app-wide preferences. Feature-specific controls live in their own right-sidebar panels: Layout, Dependency Edges, Folders, File nodes, LSP, CST, and Agent notes.
Viewport → Smooth Zoom, Viewport Details, Activity Indicator
UI → Controls Bar and Minimap (with position/size reset)
Performance → Auto-hide edges for large graphs, Diff Scan Limits
Repository → dot-prefixed folders in the local folder picker
VS Code / Cursor → start Code Canvas automatically when the editor starts and toggle the status bar item, shown only in the extension
Reset → reset all settings or clear individual stored groups such as repository connection, UI settings, editor tabs, agent notes, server/auth/MCP, shortcut overrides, and dismissed toasts
Each right-sidebar panel has a header menu (the ⋮ button next to the panel title) with a Reset settings action for that panel only. Layout, Dependency Edges, Folders, File nodes, LSP, CST, and Agent notes all have one. Use it to clear a single feature's settings without touching anything else.
Hover a setting label for a description of what it does.
Code Canvas exposes an MCP server so AI agents can read the canvas, search the workspace, query the language server, post agent notes, and read these docs. Connect once and the agent works inside the same view you do.
Add this to your .mcp.json or Claude Code config:
{
"mcpServers": {
"code-canvas": {
"command": "npx",
"args": ["-y", "-p", "code-canvas-server", "code-canvas-mcp"]
}
}
}
In the VSCode extension, MCP connects through the extension backend; no separate npx code-canvas-server process is required.
In the browser app, start the local server first with npx code-canvas-server.
Toggle MCP Connections on in the Local Server panel; connected agents appear with a status dot.
list_commands → discover canvas and UI commands
use_command → run a command such as canvas:openFiles, layout:apply, viewport:fitNodes, folder:collapseAll, or agentNotes:push
query → read canvas state, nodes, folders, backwards edges, layout config, and registered state stores
search → search code, file paths, file contents, or language-server data
lsp_servers → detect, start, reload, stop, and inspect language servers
read_docs → read this guide, a section, or the section list
Once connected, ask "explain this codebase using agent_notes" and the agent will open files, lay them out, and post navigable agent notes describing what it finds.
The command palette is one searchable list of everything Code Canvas can do, from opening panels and toggling settings to running canvas actions. Instead of hunting through the interface for the right control, you type what you want and run it.
Start typing to filter actions by name; matches rank as you type
ArrowUp / ArrowDown to move through results, Enter to run the highlighted one
Selecting an action runs it immediately and closes the palette
Some actions also live somewhere in the interface, such as a panel, a toggle, or a button. Hover an option in the palette and a Go to UI button appears on its left side. Clicking it doesn't run the action; it highlights where that control sits in the app, so you can find it and learn where it lives instead of just triggering it blind.
Use Enter when you just want the action done, and Go to UI when you want to see where it lives for next time.