# Copilot instructions — VS Code extension (TypeScript)

## Commands
`npm run compile` (or `npm run watch`) · `npm run lint` · `npm test` (`@vscode/test-cli` + `@vscode/test-electron`) · package: `npx @vscode/vsce package`. Never run `vsce publish` unless asked.

## Rules
- Respect `engines.vscode` in `package.json`; only use APIs available in that version. Don't use proposed APIs.
- Activate lazily: use specific `activationEvents` (`onCommand`, `onLanguage:x`, `workspaceContains:`) or rely on contribution-based activation. Never `*`.
- Everything registered in `activate(context)` is pushed to `context.subscriptions` (commands, listeners, providers, status bar items). No leaked disposables.
- Every command in code is declared in `contributes.commands` with a `category`, and settings in `contributes.configuration` with types, defaults and descriptions. Read settings via `vscode.workspace.getConfiguration('myExt')`.
- Keep `activate` fast; defer heavy work and show progress with `vscode.window.withProgress`.
- Use `vscode.Uri` and `vscode.workspace.fs` instead of Node `fs` and string paths so remote and virtual workspaces work.
- Webviews: set `enableScripts` only when needed, a strict Content-Security-Policy with a nonce, `localResourceRoots` limited to the extension's media folder, and load assets via `webview.asWebviewUri`. Validate every message from the webview.
- Secrets go in `context.secrets`, never in settings or globalState.
- Long-running language features belong in a language server (`vscode-languageclient`), not the extension host.
- User-facing strings via `vscode.l10n.t()`.

## Tests
Integration tests under `src/test/` with `@vscode/test-cli` (`.vscode-test.mjs`); unit-test pure logic without the `vscode` module.
