Architecture Analysis · Apr 2026
35 seconds
to find one file.
VS Code is the most popular editor in history, backed by a trillion-dollar company. On a 4.47M-file drive, its Ctrl+P picker takes 35 seconds. This is not a bug. It's six architectural decisions that can never be undone.
Interlinked Files
Machine-wide · persistent index · native binary
VS Code Ctrl+P
Workspace-scoped · rebuilt every session · TypeScript walker
Six load-bearing decisions
Why it can't be fixed without rewriting the editor.
| Design decision | Implementation | Performance cost |
|---|---|---|
| Workspace scope | Only indexes folders open in the current window | Zero knowledge of files outside one project |
| No persistent index | File list rebuilt in memory per session | Cold start walks entire directory tree every launch |
| TypeScript + Electron | fs.readdir walkers, V8 garbage collector | 2-3 orders of magnitude slower than native |
| Extension host sandbox | Cannot access NTFS/MFT directly | Limited to Node's portable filesystem APIs |
| Fuzzy re-scoring per keystroke | fuzzyScorer.ts re-runs on every character | Scores tens of thousands of candidates per frame |
| Must stay cross-platform | One codebase for Windows, macOS, Linux | Cannot use OS-specific acceleration (MFT, Spotlight) |
Every row is load-bearing. Remove any one and you break something users depend on. Together they lock the file picker into its current order of magnitude.
Reason 1: The workspace model
Searches what's open, not what exists.
The fundamental unit of VS Code is a workspace: one or more folders open in the current window. File search is scoped to the workspace. When you open a new workspace, the file list starts from scratch. VS Code never builds a machine-wide index. It has no idea what files exist outside the currently open folder.
This is sensible for an editor: predictable memory, no file leaks between projects. But you cannot flip a switch and make it index the whole drive without rebuilding most of the editor.
VS Code scope
Must switch workspaces to search other projects
Interlinked scope
Every file on the entire machine, always indexed
Reason 2: No persistent index
The file list dies the moment you close the editor.
Every time you reopen VS Code, the editor walks the entire workspace directory tree from scratch. On a small repo this is invisible. On a monorepo with hundreds of thousands of files, the walk takes seconds. On a workspace opened at the root of C:, the walk would take minutes, which is why people have learned to keep workspaces small.
A persistent index would fix this. But the VS Code team has reasonably decided the editor shouldn't maintain a long-lived background index. That's a different product. Someone should ship it externally and let VS Code call into it.
The gap
The speed difference between a native persistent index reading NTFS directly and a TypeScript walker behind an extension sandbox calling fs.readdir.
Reasons 3 & 4: Language + Platform
TypeScript in Electron is not how you build a fast filesystem walker.
Every async call crosses the JavaScript/native boundary. Every promise allocation hits V8's garbage collector. The fuzzy scorer runs in JavaScript and re-scores the entire candidate list on every keystroke. For small repos, the overhead is tolerable. For hundreds of thousands of files, the scorer can't keep up with keystrokes and the UI starts to jank.
Platform constraint
VS Code cannot use Windows-specific acceleration without shipping two codebases. Interlinked trades portability for speed.
Measured performance
Every operation, side by side.
| Operation | VS Code | Interlinked Files | Speedup |
|---|---|---|---|
| Cold start (full drive) | 35,000 ms | 0.13 ms | 269,000× |
| Per-keystroke filter | 200-800 ms | 0.014 ms | ~36,000× |
| Reopen after close | Full rebuild | Instant | ∞ |
| File count scope | ~50K (1 repo) | 4,470,000 | 89× more files |
| Content search (grep) | Workspace only | 446K files indexed | Machine-wide |
Reasons 5 & 6
The scorer and the sandbox.
Every keystroke re-scores the entire candidate list. The extension host sandbox prevents direct filesystem access. Both are load-bearing.
| Constraint | What VS Code does | What Interlinked does |
|---|---|---|
| Fuzzy ranking | fuzzyScorer.ts rescores all candidates per keystroke in JavaScript | Pre-indexed trigrams, zero re-scoring, results in 14µs |
| Extension sandbox | Extensions run in isolated Node.js host, no raw disk access | Zig binary reads NTFS MFT directly at kernel speed |
| Cross-platform | One codebase for all platforms: portable APIs only | Windows-only (for now): uses every OS-specific path |
The fix is not inside the editor. The fix is a daemon every editor can query.
Install once. Every Ctrl+P on the machine becomes 412,000× faster.The shape of the answer
VS Code should stay exactly what it is.
Every one of the six reasons above is load-bearing. You can't remove them without turning VS Code into a different editor, and that editor would be worse than the one we have. VS Code is correct to stay slow at file search, because the right place for file search is not inside the editor.
The right place is a local daemon that every editor on the machine can query. Install it once, register it with VS Code (or Cursor, or Zed, or any other editor) as an external file-search backend, and the editor stops walking and starts asking. The editor's Ctrl+P picker becomes a thin UI over an external microservice, and the microservice is 412,000× faster than the walker it replaced.
VS Code can't fix this inside itself. But every VS Code user can install one tool that fixes it from outside. That's the shape of the answer.
Three approaches to file search
The right tool for the job.
#1: Best approach
Persistent index, machine-wide scope, native binary, every editor queries it. 14µs per lookup. Survives reboots. Invisible background service.
#2: The status quo
Workspace-scoped, rebuilt per session, TypeScript walker. Good enough for small repos. Breaks down at scale. 35 seconds on a full drive.
#3: OS file dialog
Navigate a tree by hand. Click through folders. No fuzzy matching, no filtering. The last resort when Ctrl+P gives up.