Shadow Workspace: Iteratively Improving Code in the Background
Key point
Cursor uses a hidden workspace so AI doesn't interfere with the user's work.
Details
For AI to fix code well, it needs to be able to iterate directly within the development environment, beyond simply reading fragments of files. However, touching the user's files directly causes editing conflicts, lint errors, and execution mismatches, so Cursor designed a separated shadow workspace to address this.
The primary goal is LSP-usability. The AI needs to be able to lint its own edits, jump to definitions, and leverage the language server protocol broadly. On the other hand, the requirements are clear.
- Independence: The user's coding experience must not change.
- Privacy: Code must stay local only.
- Concurrency: Multiple AIs must be able to work at the same time.
- Universality: It must work across all languages and workspaces.
- Maintainability: It should be implemented with as little and as separated code as possible.
- Speed: There must be no minutes-long delays, and it must handle many branches.
The simplest approach is to copy the original TextModel and show it only to the AI. This is good for maintainability, but since the copy becomes known to the same language server, reference results get mixed up, and for languages like Go that use a global namespace, duplicate declaration issues arise, while for languages like Rust that rely on disk-based imports, the expected lint doesn't appear at all. Ultimately, the key judgment was that harming independence would lead users to stop using the feature.
The current implementation launches an additional hidden Electron window. When the AI wants to see lint results, it opens the same workspace in a hidden window separate from the main window, and iterates edits and lint checks within it. Direct communication between renderer processes is avoided; instead, existing VS Code message port paths are combined with separate IPC, and gRPC and buf are used for internal communication to avoid the fragility of JSON serialization.
This approach satisfies the following:
- Independence, being fully separated from the user's window
- Privacy, operating only within the local environment
- An operational approach that reuses windows and automatically terminates after 15 minutes of inactivity to ease memory burden
- Concurrency, handling multiple AI requests by interleaving them within a single shadow window
However, it's not complete. In particular, rust-analyzer relies on code actually written to the file system to produce lint results, so the current approach does not sufficiently provide LSP-usability for Rust. As an exception, using the deprecated RLS is possible.
The next step, runnability, is even harder. Running code requires saving it to disk, and side effects like build caches and logs must also be separated, so the same folder cannot be shared. The simplest cp -r approach is too slow due to massive directories like node_modules, venv, and target, so better cloning methods and file-system-level isolation will be needed going forward.
This summary was generated automatically by AI. Check the original for the author's claims and context. Copyright belongs to the original author.
Our guide explains how the AI works. Report summary errors, attribution issues, or removal requests via Contact.