SuperAPI AI Directory

vscode-extension-guide

General & other

View repository

Updated 10-15 16:47

About this skill

VS Code Extension Guide

Create, develop, and publish VS Code extensions.

For extensions with a management UI, default to a dedicated Activity Bar icon and sidebar unless another entry point is explicitly chosen. A Marketplace icon alone does not create that navigation; use the TreeView reference below.

For user-facing extensions, provide a clearly labeled bug-report/feature-request entry in the primary sidebar or management UI and a Command Palette fallback; a README or Marketplace link alone is insufficient. Preview minimal, non-sensitive metadata before opening a fixed feedback destination; leave submission to the user and never auto-attach prompts, raw logs, secrets or private paths.

When to Use

  • VS Code extension, extension development, vscode plugin
  • Creating a new VS Code extension from scratch
  • Adding commands, keybindings, or settings to an extension
  • Publishing to VS Code Marketplace

Quick Start

# Scaffold new extension (recommended)
npm install -g yo generator-code
yo code

# Or minimal manual setup
mkdir my-extension && cd my-extension
npm init -y && npm install -D typescript @types/vscode

Project Structure

my-extension/
├── package.json          # Extension manifest
├── src/extension.ts      # Entry point
├── out/                  # Compiled JS (gitignore)
├── artifacts/vsix/       # Keep local VSIX archives out of the repo root
├── images/icon.png       # 128x128 PNG for Marketplace
└── .vscodeignore         # Exclude files from VSIX

Building & Packaging

npm run compile      # Build once
npm run watch        # Watch mode (F5 to launch debug)
mkdir -p artifacts/vsix
npx @vscode/vsce package --out artifacts/vsix/my-extension-1.0.0.vsix

Keep local .vsix archives under artifacts/vsix/ instead of the repository root, and prune old local builds on a schedule so release artifacts do not pile up.

Done Criteria

  • The packaged VSIX installs and activates in an isolated profile; changed user-facing integrations complete their real workflow there
  • Primary sidebar entry and commands work; referenced icons are present in the VSIX
  • Package size < 5MB (use .vscodeignore)
  • README links and feedback UI reach the intended support destination; verify the UI-to-form path with synthetic data without submitting
  • Local VSIX artifacts stored outside the repo root and pruned regularly

Quick Troubleshooting

Symptom Fix
Extension not loading Check main/engines.vscode; contributed commands/views activate implicitly (1.74+), add activationEvents only for other triggers
Command not found Match command ID in package.json/code
Shortcut not working Remove when clause, check conflicts

Reference Map

Topic Reference
AI Customization references/ai-customization.md
Code Review Prompts references/code-review-prompts.md
Code Samples references/ai-customization.md and references/webview.md
TreeView references/treeview.md
Webview references/webview.md
Testing references/testing.md
Publishing references/publishing.md
Troubleshooting references/troubleshooting.md
Notifications references/notification-normalization.md

Best Practices

Extension Host boundary

  • Scanner / provider / TreeView running on the Extension Host should, when they can do the same thing, prefer the VS Code API over Node-specific path / Buffer / raw fs . This makes it easier to avoid environmental differences between Problems and the actual build.
  • For resources bundled with your own extension, do not guess the user's home directory or the VS Code installation location; resolve them from the extension context, such ascontext.extensionUri と vscode.Uri.joinPath .
  • When you need to read resources bundled with another installed extension, also prioritize the known roots ofresources/agents|skills|prompts|instructions|hooks|mcp and the chatAgents / chatPromptFiles declaration in the manifest. Treat them as read-only resources separate from built-in resources, and do not mix in uninstall or reinstall flows.
  • Do not scatter runtime diagnostic logs across console.log ; consolidate them into an Output Channel-based logger. Also provide a way for users to open the logs somewhere, such as a command, notification, or the README.
  • Do not synchronously parse or aggregate large inputs on the Extension Host thread. Pass bounded bytes to node:worker_threads , and on cancel / opt-out complete await worker.terminate() and listener removal, and update the cache / UI only with results whose generation ID matches.
  • Only transfer exclusively owned, non- SharedArrayBuffer data, and after transfer do not use the sender-side view (all views of the same backing store are detached).Buffer may share a pool, so for offset views or buffers with ambiguous ownership, copy only the necessary range into a separate buffer and pass that.
  • Do not cache or display results received from a worker or another process as-is. Perform allowed-key checks with Reflect.ownKeys, and check for the existence of required keys with Object.hasOwn (Object.keys misses non-enumerable own properties, whilein and plain property access let inherited values through).
  • Do not output the exception's Error.name や FileSystemError.code as-is to logs / UI. Normalize it to an allowlist of known codes, and map unknown ones to a single generic code. This prevents cases where paths or tokens get mixed into names.

Manifest / Docs / Localization

  • package.json When you change the commands, views, configuration, or menus of
  • For extensions that localize the Marketplace display or setting descriptions, updatepackage.nls.json and the target language's package.nls.*.json in the same change.
  • In markdownDescription, use native setting references such as `#editor.wordWrap#`, not [label](#editor.wordWrap#): the latter can leave a trailing hash in the Settings @id: filter. Guard each locale's syntax and verify the resolved target.
  • If you change the order or descriptions of settings, review the README settings table, the manifest consistency test, and whether release notes are needed, all together.

Language Model Tools

  • Extension-provided LM Tools need strong modelDescription intent phrases. Prefer Use when the user asks to ... plus natural-language verbs for create/update/delete/toggle paths, and add a manifest/doc guard so future wording changes do not silently weaken agent-mode tool selection.
  • For configuration from VS Code Chat, prefer native LM Tools when no external client is required; do not call them an external MCP server. Share validated domain operations with the GUI, expose only necessary actions, and use explicit enable/disable values rather than retry-sensitive toggles.
  • Keep prepareInvocation side-effect free and request confirmation for mutations or sensitive disclosure. Revalidate input, cancellation, trust and the queried revision inside the locked write after confirmation. Host approval UI/policies still apply; custom confirmation text is not a bypass. Never accept secret values through tool arguments or silently widen execution permissions.
  • Page query results and omit prompt, environment and raw-output payloads by default. Make sensitive detail retrieval explicit with disclosure confirmation; describe which metadata reaches the model and treat stored strings as data, not instructions.
  • Return typed outcomes from shared operations; a GUI handler that catches errors and returns nothing cannot prove a tool succeeded. Keep committed IDs/success when only presentation fails, return a sanitized warning and tell the caller to query rather than repeat the mutation. Configuration saved is not work executed.
  • Before publishing an extension with LM Tools, inspect the packaged VSIX rather than trusting source files: confirm extension/package.json has the intended version, expected contributes.languageModelTools count, and no src/, test payloads, or sourcemaps unless intentionally shipped.

Generated Sections

  • START / END Treat the generated section enclosed by markers as a single SSOT.
  • If you find duplicate marker pairs, do not keep both and append; merge the content and restore a single marker pair.

Naming consistency

Before publishing, unify the package name, setting keys, and command names:

Item Example
Package name copilot-scheduler
Setting key copilotScheduler.enabled
Command ID copilotScheduler.createTask
View ID copilotSchedulerTasks

Centralized notification management

Notifications are consolidated into a common helper, and configuration values are normalized to known enums at runtime. For duplicate suppression, separation from logging, actions, and security design, refer to Notification Normalization .