This is the VS Code extension for PowerShell — an LSP client that communicates with PowerShellEditorServices (PSES), the LSP server. The extension manages the PSES process lifecycle, provides UI features, and handles debugging.
npm install --include=optional # Install all deps (lint/test tools are in optionalDependencies)
npm run compile # Build with esbuild (outputs to dist/)
npm run lint # ESLint (strict TypeScript-aware rules)
npm run format # Prettier check (with organize-imports plugin)
npm test # Integration tests via @vscode/test-cliAfter any code change, always run npm run compile, npm run lint, and npm run format. Tests run inside a VS Code Insiders instance — there is no way to run a
single test from the command line. Tests live in test/ mirroring src/ structure and use
Mocha BDD (describe/it).
activate() in src/extension.ts creates the Logger, SessionManager, and two groups of
features:
- Standalone features — commands that don't need the LSP client (e.g.
PesterTestsFeature) - LanguageClientConsumers — features extending
LanguageClientConsumerthat depend on the LSP client and overrideonLanguageClientSet()to register their handlers
SessionManager (src/session.ts) owns the full lifecycle: finding a PowerShell executable
(src/platform.ts), spawning PSES (src/process.ts), connecting the LanguageClient, and
restarting on critical setting changes.
Each feature in src/features/ exports one vscode.Disposable class. Custom LSP message
types are defined as RequestType/NotificationType constants in the same file.
IPowerShellExtensionClient in src/features/ExternalApi.ts is the public API for other
extensions.
The modules/ folder contains the PSES, PSReadLine, and PSScriptAnalyzer PowerShell modules. In development the whole
folder is a symlink to ../PowerShellEditorServices/module — PowerShellEditorServices must be
cloned as a sibling and built before npm run compile will succeed. For cross-repo work, use pwsh-extension-dev.code-workspace.
Cross-repo dev/test cycle. Because modules/ is a symlink into the sibling PSES checkout's
module/ directory, building PSES deploys its DLLs straight into the path the extension loads from —
there is no copy step:
- Edit PSES C# (server) → rebuild PSES (e.g.
dotnet build src/PowerShellEditorServices/PowerShellEditorServices.csproj, orInvoke-Build Buildfor a full build). The build deploys intomodule/PowerShellEditorServices/bin, which the symlinkedmodules/exposes to the extension automatically. The extension (and its tests) then load the new DLL — no copy, but you must rebuild PSES, since the extension does not. - Edit extension TypeScript (client) →
npm run compile. - Verify end-to-end →
npm test. This launches a real VS Code Extension Host with PSES connected and runs the Mocha suite, exercising the locally-built PSES through the symlink. Prefer this over only eyeballing the Extension Development Host: it is the way to confirm cross-repo (client + server) changes actually work, and to catch regressions. After changing a setting's default or any shared behavior, run the full suite — e.g. ISE-compatibility tests assert against setting defaults.
- VS Code best practices: Follow the Extension Guidelines and UX Guidelines. Use VS Code's APIs idiomatically and prefer disposable patterns for lifecycle management.
- Logging: Use
ILogger(notconsole.log). Tests useTestLoggerfromtest/utils.ts. - Settings: Defined in
package.jsonundercontributes.configuration, read viavscode.workspace.getConfiguration("powershell")at point of use. Helpers insrc/settings.ts. - TypeScript: Strict mode, ESNext,
verbatimModuleSyntax.explicit-function-return-typeenforced. Unused vars prefixed_. Formatting via Prettier with theorganize-importsplugin. Useimport x = require("x")for Node/VS Code built-ins. - File headers: Every source file starts with
// Copyright (c) Microsoft Corporation.and// Licensed under the MIT License.