vscode-extension-builder
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 registrationtree-view-sample/- Custom tree viewscompletions-sample/- Code completionwebview-sample/- Custom UI panelscustom-editor-sample/- Custom file editors
Quick Reference
Essential APIs
vscode.commands.registerCommand()- Register commandsvscode.window.createWebviewPanel()- Create webviewsvscode.window.createTreeView()- Create tree viewsvscode.languages.registerCompletionItemProvider()- Add completionsvscode.workspace.getConfiguration()- Read settingsvscode.window.createStatusBarItem()- Status bar items
Common Contribution Points
contributes.commands- Register commandscontributes.views- Add view containerscontributes.configuration- Add settingscontributes.languages- Define new languagescontributes.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.