VSCode Extension Expert
A comprehensive guide for developing Visual Studio Code extensions using TypeScript/JavaScript. This skill is built directly from the official VSCode extension samples repository and covers everything from basic extension creation to advanced language features, custom editors, and publishing workflows.
🎯 Getting Started with Official Generator
The best way to create a new VS Code extension is by using the official Yeoman generator tool.
Prerequisites
Ensure you have Node.js and Git installed.
Creating a New Extension
Option 1: One-time use (recommended)
npx --package yo --package generator-code -- yo code
Option 2: Global installation
npm install --global yo generator-code yo code
After Creation
- •Open the extension folder in VS Code
- •Navigate to
src/extension.ts - •Press F5 to launch Extension Development Host
- •Test from Command Palette (Ctrl+Shift+P)
🛠️ How to Use This Skill
Starting a New Extension
"I want to create a new VS Code extension" "Help me set up a VS Code extension project"
During Development
"How do I add a new command?" "My extension isn't loading, can you help me debug?" "I want to create a webview panel"
Working with Generated Projects
I'll respect your choices:
- •Package manager: npm, yarn, pnpm, or bun
- •Bundler: webpack, esbuild, or unbundled
- •Language: TypeScript or JavaScript
- •Extension type: commands, themes, language support, etc.
Core Concepts
Extension Anatomy
Basic package.json
{
"name": "my-extension",
"displayName": "My Extension",
"version": "0.0.1",
"engines": { "vscode": "^1.85.0" },
"categories": ["Other"],
"activationEvents": ["onCommand:extension.helloWorld"],
"main": "./out/extension.js",
"contributes": {
"commands": [{
"command": "extension.helloWorld",
"title": "Hello World"
}]
}
}
Extension Entry Point
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
console.log('Extension "my-extension" is now active!');
const disposable = vscode.commands.registerCommand('extension.helloWorld', () => {
vscode.window.showInformationMessage('Hello World!');
});
context.subscriptions.push(disposable);
}
export function deactivate() {}
Common Patterns
Command Registration
const commands = [
vscode.commands.registerCommand('extension.doSomething', () => {
// Implementation
}),
vscode.commands.registerCommand('extension.doSomethingElse', () => {
// Another command
})
];
context.subscriptions.push(...commands);
Status Bar Integration
const statusBarItem = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Right,
100
);
statusBarItem.text = '$(gear) My Extension';
statusBarItem.tooltip = 'My Extension Status';
statusBarItem.command = 'extension.toggleFeature';
statusBarItem.show();
context.subscriptions.push(statusBarItem);
Webview Development
Basic Webview
export function createWebviewPanel(context: vscode.ExtensionContext) {
const panel = vscode.window.createWebviewPanel(
'myWebview',
'My Webview',
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true
}
);
panel.webview.html = getWebviewContent(context.extensionUri);
panel.webview.onDidReceiveMessage(
message => {
switch (message.command) {
case 'alert':
vscode.window.showInformationMessage(message.text);
return;
}
},
undefined,
context.subscriptions
);
return panel;
}
Tree View Provider
export class TreeDataProvider implements vscode.TreeDataProvider<TreeItem> {
private _onDidChangeTreeData: vscode.EventEmitter<TreeItem | undefined | null | void> = new vscode.EventEmitter<TreeItem | undefined | null | void>();
readonly onDidChangeTreeData: vscode.Event<TreeItem | undefined | null | void> = this._onDidChangeTreeData.event;
private treeItems: TreeItem[] = [];
refresh(): void {
this._onDidChangeTreeData.fire();
}
getTreeItem(element: TreeItem): vscode.TreeItem {
return element;
}
getChildren(element?: TreeItem): Thenable<TreeItem[]> {
if (!element) {
return Promise.resolve(this.treeItems);
}
return Promise.resolve([]);
}
}
Language Features
Code Completion
export class CompletionItemProvider implements vscode.CompletionItemProvider {
provideCompletionItems(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken,
context: vscode.CompletionContext
): vscode.CompletionItem[] {
return [
new vscode.CompletionItem('console.log', vscode.CompletionItemKind.Method),
new vscode.CompletionItem('console.error', vscode.CompletionItemKind.Method)
];
}
}
vscode.languages.registerCompletionItemProvider(
'javascript',
new CompletionItemProvider(),
'.'
);
Configuration
Reading Settings
const config = vscode.workspace.getConfiguration('myExtension');
const enabled = config.get<boolean>('enabled', true);
const apiKey = config.get<string>('apiKey', '');
Configuration Schema (package.json)
{
"contributes": {
"configuration": {
"title": "My Extension",
"properties": {
"myExtension.enabled": {
"type": "boolean",
"default": true,
"description": "Enable/disable the extension"
}
}
}
}
}
Testing
Unit Tests
import * as assert from 'assert';
import * as vscode from 'vscode';
suite('Extension Test Suite', () => {
test('Extension should be present', () => {
assert.ok(vscode.extensions.getExtension('publisher.my-extension'));
});
test('Should register commands', async () => {
const commands = await vscode.commands.getCommands();
assert.ok(commands.includes('extension.helloWorld'));
});
});
Publishing
# Install vsce npm install -g @vscode/vsce # Create publisher vsce create-publisher your-publisher-name # Package and publish vsce package vsce publish
📚 Official Resources
Primary API Documentation (Authoritative)
Complete VS Code API: @source/vscode-docs/api/ - FIRST REFERENCE
Core References:
- •Extension API:
@source/vscode-docs/api/references/vscode-api.md - •Extension Manifest:
@source/vscode-docs/api/references/extension-manifest.md - •Contribution Points:
@source/vscode-docs/api/references/contribution-points.md
Development Guides:
- •Getting Started:
@source/vscode-docs/api/get-started/ - •Extension Guides:
@source/vscode-docs/api/extension-guides/ - •UX Guidelines:
@source/vscode-docs/api/ux-guidelines/
Code Examples
Core Features (@source/vscode-extension-samples/):
- •
command-sample/- Command registration - •
tree-view-sample/- Custom tree views - •
completions-sample/- Code completion - •
webview-sample/- Custom UI panels - •
custom-editor-sample/- Custom file editors
Quick Reference
Essential APIs
- •
vscode.commands.registerCommand()- Register commands - •
vscode.window.createWebviewPanel()- Create webviews - •
vscode.window.createTreeView()- Create tree views - •
vscode.languages.registerCompletionItemProvider()- Add completions - •
vscode.workspace.getConfiguration()- Read settings - •
vscode.window.createStatusBarItem()- Status bar items
Common Contribution Points
- •
contributes.commands- Register commands - •
contributes.views- Add view containers - •
contributes.configuration- Add settings - •
contributes.languages- Define new languages - •
contributes.themes- Custom themes
Essential Commands
npx --package yo --package generator-code -- yo code npm run compile # Compile TypeScript npm run watch # Watch for changes npm test # Run tests npm run package # Package extension vsce publish # Publish to marketplace
Troubleshooting
Common Issues:
- •Extension not loading: Check
engines.vscodeversion - •Commands not registering: Verify command IDs match in package.json
- •Activation issues: Check activationEvents
Debug Techniques:
- •Use
console.log()(Developer Tools console) - •Help > Toggle Developer Tools
- •View > Output > Extension Host
See references/ADVANCED.md for advanced topics like file system providers, terminal integration, and performance optimization. See references/EXAMPLES.md for complete extension templates and detailed implementation examples.