microsoft/vscode
Visual Studio Code
Healthy across the board
- ✓Last commit today
- ✓5 active contributors
- ✓Distributed ownership (top contributor 48%)
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
- ⚠Small team — 5 top contributors
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Embed this verdict
[](https://repopilot.app/r/microsoft/vscode)Paste into your README — the badge live-updates from the latest cached analysis.
Onboarding doc
Onboarding: microsoft/vscode
Generated by RepoPilot · 2026-05-04 · Source
Verdict
GO — Healthy across the board
- Last commit today
- 5 active contributors
- Distributed ownership (top contributor 48%)
- MIT licensed
- CI configured
- Tests present
- ⚠ Small team — 5 top contributors
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
TL;DR
This is the open-source core of Visual Studio Code ('Code - OSS'), a cross-platform code editor built on Electron and TypeScript. It solves the problem of providing a lightweight yet feature-rich editing environment with IntelliSense, debugging, Git integration, and a rich extension API. The bulk of the codebase (~118M bytes of TypeScript) implements the editor engine, workbench UI, language services, and extension host runtime. The repo is a large monolith organized by layer and platform: src/vs/ contains all editor and workbench TypeScript source split into base/ (utilities), platform/ (injectable services), editor/ (Monaco core), workbench/ (UI shell), and code/ (Electron entry points). Custom ESLint plugins in .eslint-plugin-local/ enforce these layer boundaries at lint time.
Who it's for
Two audiences: (1) developers who contribute features/fixes to VS Code itself, working in TypeScript with deep knowledge of Electron, language servers (LSP), and extension APIs; (2) extension authors and platform integrators who fork or embed the editor. Microsoft engineers, open-source contributors, and IDE platform builders all actively work here.
Maturity & risk
Extremely mature and production-ready — VS Code is one of the most-starred repos on GitHub (50k+), has been in continuous development since 2015, ships monthly stable releases, and has extensive CI (GitHub Actions), integration tests, and a formal endgame/iteration planning process visible in the wiki. Commit activity is daily.
Very low risk as a dependency-of-reference: Microsoft maintains it with a large team, it has no single-maintainer risk, and the MIT license is permissive. The primary risk for contributors is the sheer scale — the codebase has strict layering rules enforced by custom ESLint plugins (e.g., .eslint-plugin-local/code-layering.ts, code-import-patterns.ts) that will block PRs if violated. The open issue backlog numbers in the tens of thousands.
Active areas of work
Based on the repo structure, active work includes: custom ESLint rules for observable/reactive patterns (code-no-observable-get-in-reactive-context.ts), a Rust component (Rust: 577664 bytes — likely the file watcher or ripgrep integration), AI/Copilot skill scaffolding (.agents/skills/launch/SKILL.md), and a tsgo typecheck script in package.json suggesting migration work toward the new TypeScript Go-based compiler (tsgo).
Get running
git clone https://github.com/microsoft/vscode.git cd vscode npm install # uses npm (no package-lock alternative visible) npm run typecheck # type-check only via tsgo
For full build and run:
./scripts/code.sh # macOS/Linux .\scripts\code.bat # Windows
See https://github.com/microsoft/vscode/wiki/How-to-Contribute for full build prereqs (Node 20, Python, C++ build tools)
Daily commands:
Full dev build (macOS/Linux):
./scripts/code.sh
Full dev build (Windows):
.\scripts\code.bat
Type-check only (no emit, uses tsgo):
npm run typecheck
Run unit tests:
./scripts/test.sh
See wiki for platform-specific prereqs
Map of the codebase
.github/copilot-instructions.md— Defines AI-assisted development guidelines and conventions that govern how contributors interact with Copilot across the entire repo..eslint-plugin-local/index.ts— Entry point for all custom ESLint rules enforced across the codebase; understanding these rules is mandatory before writing any new code..eslint-plugin-local/code-import-patterns.ts— Enforces the layered import architecture (browser/node/common) that is central to VS Code's cross-platform design..eslint-plugin-local/code-layering.ts— Enforces the strict architectural layering rules that prevent circular dependencies and cross-layer violations..github/CODEOWNERS— Maps every subsystem to its owning team, essential for knowing who to consult and who reviews PRs for any given area..devcontainer/devcontainer.json— Defines the canonical development environment; contributors must understand this to reproduce the expected build and runtime setup..eslint-plugin-local/code-no-unexternalized-strings.ts— Enforces i18n compliance by preventing hard-coded user-facing strings, a non-negotiable requirement for all UI contributions.
How to make changes
Add a new custom ESLint lint rule
- Create a new rule file following the existing naming convention (code-<rule-name>.ts) and implement the ESLint rule using the RuleCreator pattern found in adjacent files. (
.eslint-plugin-local/code-<your-rule-name>.ts) - Register the new rule in the plugin index by importing it and adding it to the rules export map. (
.eslint-plugin-local/index.ts) - Add test cases covering valid and invalid code patterns for the new rule. (
.eslint-plugin-local/tests/code-<your-rule-name>-test.ts)
Add a new Copilot/AI instruction for a subsystem
- Create a new markdown file in the instructions directory named after the subsystem with the .instructions.md suffix, following the format of existing instruction files. (
.github/instructions/<subsystem>.instructions.md) - If the subsystem has supporting diagrams or resources, add them to the resources subdirectory. (
.github/instructions/resources/<subsystem>/) - Reference the new instruction file from the top-level Copilot instructions if it should apply globally. (
.github/copilot-instructions.md)
Add a new GitHub Issue template
- Create a new markdown file in the ISSUE_TEMPLATE directory following the frontmatter format of existing templates (name, about, labels, assignees). (
.github/ISSUE_TEMPLATE/<template-name>.md) - Update the issue template chooser config to surface the new template in the GitHub UI. (
.github/ISSUE_TEMPLATE/config.yml)
Add a new CODEOWNER mapping for a subsystem
- Add a glob pattern mapping to the relevant GitHub team in CODEOWNERS, following the existing path-to-team format. Patterns are evaluated last-match-wins. (
.github/CODEOWNERS) - If more granular per-file notification is needed beyond CODEOWNERS, add a corresponding CODENOTIFY entry. (
.github/CODENOTIFY)
Why these technologies
- TypeScript — Provides static type safety across a massive multi-platform codebase, enabling safe refactoring and IDE intelligence essential for an editor product.
- tsgo (TypeScript Go port) — Used for fast type checking (typecheck script) — significantly faster than tsc for large codebases, reducing iteration time.
- Custom ESLint Plugin — Standard ESLint rules are insufficient to enforce VS Code's unique architectural constraints (platform layering, i18n, disposable patterns), necessitating a bespoke plugin.
- Dev Containers / GitHub Codespaces — Ensures all contributors have a reproducible, pre-configured environment regardless of host OS, critical for a cross-platform editor.
- GitHub Actions — Native CI integration with GitHub's PR workflow, supporting the open-source collaboration model where external contributors submit PRs.
Trade-offs already made
-
Custom ESLint plugin instead of shared npm rules
- Why: VS Code's architectural constraints are unique and highly specific to its layered platform model (common/browser/node/electron).
- Consequence: The plugin must be maintained in-repo and updated whenever new architectural patterns are introduced, adding maintenance overhead.
-
Strict platform layering (common/browser/node/electron)
- Why: VS Code runs in multiple environments (desktop Electron, browser, remote) and must prevent environment-specific code from leaking into shared layers.
- Consequence: Developers must be deeply familiar with the layer model; violations are caught at lint time but architectural mistakes can be subtle.
-
Dev Container as canonical environment
- Why: Eliminates 'works on my machine' issues across a globally distributed contributor base with varying OS setups.
- Consequence: Contributors without Docker or on resource-constrained machines may face friction; the container build adds initial setup time.
-
In-repo AI instructions (.github/
- Why: undefined
- Consequence: undefined
Traps & gotchas
tsgoin the typecheck script is the experimental TypeScript Go compiler — it may not be on PATH without separate installation from the TypeScript repo. 2) The custom ESLint plugin rules (especiallycode-no-dangerous-type-assertions,code-layering) will hard-fail CI on patterns that look totally fine in normal TypeScript projects. 3) Building from source requires Python, a C++ toolchain, and specific Node.js versions (check.nvmrcor wiki) — missing native build tools is the #1 stumbling block. 4) The Rust components need a Rust toolchain installed separately.
Architecture
Concepts to learn
- Dependency Injection (instantiation service) — VS Code's entire platform layer uses a custom DI container in
src/vs/platform/instantiation/— understanding service tokens and decorators is required to add or consume any platform service - Language Server Protocol (LSP) — All language features (completions, hover, go-to-definition) are implemented via LSP between the extension host and language server processes — understanding this is key to working on any language feature
- Debug Adapter Protocol (DAP) — VS Code's debugger UI communicates with debug adapters via DAP, a JSON-RPC protocol; required knowledge for any debugging feature work
- Tree-sitter incremental parsing — Used for fast, error-tolerant syntax highlighting and code structure analysis; the
.tsTree-sitter query files in the repo define grammar patterns for specific languages - Electron main/renderer process split — VS Code's architecture maps onto Electron's process model — some code runs in the privileged main process, other code in sandboxed renderer processes, and mixing these incorrectly causes security or runtime failures
- Observable / reactive pattern (RxJS-style but custom) — The workbench uses a custom observable/reactive event system with strict rules enforced by
code-no-observable-get-in-reactive-context.ts— reading an observable synchronously in a reactive context is a bug class the linter catches - AMD module layering (historical → ESM migration) — The codebase is mid-migration from AMD (RequireJS-style) modules to native ESM; the
code-amd-node-module.tslint rule and thetsgotypecheck script are artifacts of this transition, and mixing module styles causes subtle build failures
Related repos
microsoft/monaco-editor— The embeddable browser editor extracted from this repo — if you're working on src/vs/editor/, changes may need to be mirrored heremicrosoft/vscode-extension-samples— Companion repo with runnable extension API examples; essential for contributors working on the extension host APIsmicrosoft/vscode-docs— The documentation repo for VS Code; UI/feature changes in this repo usually require parallel doc updates thereVSCodium/vscodium— Community build of Code-OSS without Microsoft telemetry/branding — a close fork that tracks this repo's changeseclipse-theia/theia— Alternative open-source IDE platform solving the same problem (browser+desktop IDE) in a different architectural approach
PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for ESLint plugin rules in .eslint-plugin-local that lack test coverage
The .eslint-plugin-local directory contains 30+ custom ESLint rules (e.g., code-no-any-casts.ts, code-no-dangerous-type-assertions.ts, code-no-deep-import-of-internal.ts, code-no-icons-in-localized-strings.ts) but only two test files exist: code-no-observable-get-in-reactive-context-test.ts and code-no-reader-after-await-test.ts. The vast majority of custom lint rules have zero test coverage, making it risky to refactor or extend them. Adding tests for untested rules would meaningfully improve reliability of the entire codebase's lint enforcement.
- [ ] Examine .eslint-plugin-local/tests/ and identify all rules lacking test files (e.g. code-no-any-casts.ts, code-no-dangerous-type-assertions.ts, code-no-deep-import-of-internal.ts, code-no-icons-in-localized-strings.ts, code-no-telemetry-common-property.ts)
- [ ] Follow the pattern established in .eslint-plugin-local/tests/code-no-reader-after-await-test.ts to understand the test harness structure
- [ ] Create a new test file for each untested rule, e.g. .eslint-plugin-local/tests/code-no-any-casts-test.ts, covering both valid and invalid code cases
- [ ] Ensure the new tests are picked up by the existing test runner by checking .eslint-plugin-local/tsconfig.json and package.json for test script configuration
- [ ] Submit PR referencing specific rules covered and include a summary of edge cases tested per rule
Add a GitHub Actions workflow for ESLint plugin local type-checking and testing
The .eslint-plugin-local directory has its own tsconfig.json and package.json, indicating it is a self-contained TypeScript package with its own build and test lifecycle. However, examining the .github directory reveals no dedicated CI workflow that type-checks or runs tests specifically for this plugin package. The top-level package.json only has a 'typecheck' script using tsgo. A missing CI step means PRs that break the custom lint rules or their tests can go undetected until runtime.
- [ ] Inspect .github/ for any existing workflow files and confirm none target .eslint-plugin-local specifically
- [ ] Read .eslint-plugin-local/package.json and tsconfig.json to understand build/test commands available
- [ ] Create .github/workflows/eslint-plugin-local-ci.yml that triggers on pull_request for changes to .eslint-plugin-local/**
- [ ] Add steps: checkout, setup Node.js (matching version used in .devcontainer/Dockerfile), install dependencies in .eslint-plugin-local, run tsc type-check using the local tsconfig.json, run tests
- [ ] Validate the workflow passes on the current main branch before submitting the PR
Add missing SKILL.md documentation for all agent skills beyond 'launch'
The .agents/skills directory currently only contains a single skill subdirectory 'launch' with a SKILL.md file. If the agents framework supports multiple skills (which the plural 'skills' directory name implies), other skill types are undocumented or missing entirely. Additionally, the existing .agents/skills/launch/SKILL.md lacks any companion README at the .agents/ or .agents/skills/ level explaining the skills framework, how to add new skills, or how the agent system integrates with VS Code. This is a concrete documentation gap that new contributors and extension authors would benefit from.
- [ ] Read .agents/skills/launch/SKILL.md thoroughly to understand the schema and format used for skill definitions
- [ ] Create .agents/README.md documenting what the .agents directory is for, how the skills system works, and how it integrates with
Good first issues
- Add tests for
.eslint-plugin-local/code-no-observable-get-in-reactive-context.ts— there is a test file at.eslint-plugin-local/tests/code-no-observable-get-in-reactive-context-test.tsbut no equivalent test files exist for most other custom lint rules, leaving coverage gaps. 2) Add aREADME.mdto.eslint-plugin-local/that documents each rule with a concrete before/after TypeScript example — currently only a stub README exists. 3) Improve the.devcontainer/README.mdwith explicit troubleshooting steps for the Rust toolchain setup required by the native modules, which is currently undocumented in the devcontainer flow.
Top contributors
- @vritant24 — 29 commits
- @roblourens — 12 commits
- @hediet — 8 commits
- @benibenj — 8 commits
- @pwang347 — 4 commits
Recent commits
5c4d9a2— Add experimental alt prompt for Claude Opus 4.7 (#313916) (bhavyaus)4341e36— Update remote dependencies (#313923) (rebornix)4847e79— Pzhu/feature custom snooze time (#298934) (Pengkun-ZHU)10d2282— Update InlineChatZoneWidget screenshot baselines (hediet)8b69774— themes: fix match highlight contrast in focused quick pick rows (2026 themes) (#314117) (hawkticehurst)d72513b— fixes diff reporter (hediet)b4399be— Fixes (hediet)3a27114— Fixes screenshot diff report (hediet)bb81c9c— Improves screenshot experience for forks (hediet)1bb9a48— Disable flaky hover test (#314129) (pwang347)
Security observations
- Medium · Devcontainer Running as Root or Privileged User —
.devcontainer/Dockerfile, .devcontainer/devcontainer.json. The .devcontainer/Dockerfile and devcontainer.json may configure the development environment without explicitly enforcing a non-root user. Development containers that run as root can expose the host system to privilege escalation risks if the container is compromised or misconfigured. Fix: Explicitly define a non-root USER in the Dockerfile and set 'remoteUser' in devcontainer.json. Apply least-privilege principles to the devcontainer configuration. - Medium · Post-Create Script with Potentially Unvalidated Commands —
.devcontainer/post-create.sh, .devcontainer/install-vscode.sh. The .devcontainer/post-create.sh script runs automatically after container creation. If this script downloads or executes external resources without checksum verification or integrity checks, it could be vulnerable to supply chain attacks or man-in-the-middle injection. Fix: Ensure all downloads in shell scripts use HTTPS, validate checksums (SHA256) of downloaded artifacts, pin versions explicitly, and avoid piping untrusted remote scripts directly to a shell interpreter. - Medium · Minimal package.json with Unresolved Transitive Dependency Risk —
package.json. The provided package.json is minimal (private, type=module, only a typecheck script using 'tsgo'). The 'tsgo' tool is a relatively new/unofficial TypeScript compiler wrapper. Without a lockfile (package-lock.json or yarn.lock visible in this context) or pinned version, transitive dependencies could be silently updated to malicious versions. Fix: Pin the 'tsgo' dependency to a specific version. Ensure a lockfile is committed and integrity checks (npm ci) are used in CI/CD pipelines. Regularly audit dependencies with 'npm audit'. - Medium · XSS Risk via Extension API and WebView Integration —
Extension host / WebView infrastructure (general architecture). VSCode's extension architecture heavily uses WebViews, which render arbitrary HTML/JS content from extensions. Without strict Content Security Policy (CSP) enforcement on all WebViews, malicious or compromised extensions could execute cross-site scripting attacks within the Electron shell, potentially accessing local file system resources or Node.js APIs. Fix: Enforce strict CSP headers on all WebView panels (disallow inline scripts, restrict script-src). Validate and sanitize all data passed from the extension host to WebView contexts. Ensure WebViews run with contextIsolation enabled and nodeIntegration disabled. - Medium · Potential Injection Risk in ESLint Plugin Custom Rules —
.eslint-plugin-local/*.ts. The .eslint-plugin-local directory contains numerous custom ESLint rules that perform static analysis on source code. If any of these rules dynamically evaluate or construct code from analyzed AST nodes without proper sanitization, there could be a risk of code injection during the lint/build process. Fix: Audit all custom ESLint plugin rules to ensure AST node content is never passed to eval(), Function(), or dynamic import() without sanitization. Treat all analyzed code values as untrusted input. - Low · Sensitive Configuration Files Potentially Exposed in Repository —
.config/guardian/.gdnsuppress, .config/1espt/PipelineAutobaseliningConfig.yml. Files such as .config/guardian/.gdnsuppress, .config/1espt/PipelineAutobaseliningConfig.yml, and .github/classifier.json contain security policy suppressions and classification data. If suppression rules are overly broad, legitimate vulnerabilities may be silently ignored in automated scanning pipelines. Fix: Regularly audit .gdnsuppress entries to ensure suppressions are specific, time-bounded, and justified. Review PipelineAutobaseliningConfig.yml to prevent overly permissive baselining that masks real security issues. - Low · GitHub Actions and Workflow Supply Chain Risk —
.github/agents/, .github/commands/, .github/hooks/. The .github directory contains workflow configurations, agent definitions, and command files. GitHub Actions workflows that reference third-party actions without pinning to a specific commit SHA (using @vX.Y.Z or branch references instead) are vulnerable to supply chain attacks if upstream action repositories are compromised. Fix: Pin all third-party GitHub
LLM-derived; treat as a starting point, not a security audit.
Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.