vscode-extension-expert
Provides architectural and API guidance for building and publishing VS Code extensions.
Install
mkdir -p .claude/skills/vscode-extension-expert && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12263" && unzip -o skill.zip -d .claude/skills/vscode-extension-expert && rm skill.zipInstalls to .claude/skills/vscode-extension-expert
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
This skill provides expert-level guidance for VS Code extension development. Use when implementing new extension features, debugging extension code, designing WebView UIs, implementing Language Server Protocol features, or optimizing extension performance. Covers activation events, contribution points, VS Code API patterns, security best practices, testing strategies, and publishing workflows.Key capabilities
- →Implement new VS Code extension features.
- →Design extension architecture and structure.
- →Create WebView-based UIs with security requirements.
- →Implement Language Server Protocol (LSP) features.
- →Debug extension activation or runtime issues.
- →Optimize extension performance and startup time.
How it works
The skill provides expert guidance on VS Code extension development, covering activation events, contribution points, API usage, security, testing, and publishing workflows.
Inputs & outputs
When to use vscode-extension-expert
- →Design extension architecture
- →Implement WebView UI
- →Debug extension activation
About this skill
VS Code Extension Expert
Overview
This skill enables expert-level VS Code extension development by providing comprehensive knowledge of the VS Code Extension API, architectural patterns, security requirements, and best practices. It should be used when creating new extensions, adding features to existing extensions, implementing WebViews, designing language support, or optimizing performance.
When to Use This Skill
- Implementing new VS Code extension features
- Designing extension architecture and structure
- Creating WebView-based UIs with proper security
- Implementing Language Server Protocol (LSP) features
- Debugging extension activation or runtime issues
- Optimizing extension performance and startup time
- Preparing extensions for Marketplace publication
Core Concepts
Extension Anatomy
Every VS Code extension requires:
extension-name/
├── .vscode/ # Debug configurations
│ ├── launch.json
│ └── tasks.json
├── src/
│ └── extension.ts # Main entry point
├── package.json # Extension manifest (critical)
├── tsconfig.json # TypeScript config
└── .vscodeignore # Exclude from package
Package.json Essential Fields
{
"name": "extension-name",
"publisher": "publisher-id",
"version": "0.0.1",
"engines": { "vscode": "^1.80.0" },
"main": "./out/extension.js",
"activationEvents": [],
"contributes": {
"commands": [],
"configuration": {},
"views": {}
},
"extensionKind": ["workspace"]
}
Extension Entry Point Pattern
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
// Register commands, providers, listeners
const disposable = vscode.commands.registerCommand('ext.command', () => {
// Command implementation
});
context.subscriptions.push(disposable);
}
export function deactivate() {
// Cleanup resources
}
Activation Events
Choose the most specific activation event to minimize startup impact:
| Event | Use Case | Example |
|---|---|---|
onLanguage:<lang> | Language-specific features | onLanguage:python |
onCommand:<command> | Command-driven extensions | onCommand:ext.showPanel |
onView:<viewId> | Sidebar view expansion | onView:myTreeView |
workspaceContains:<glob> | Project-specific features | workspaceContains:**/.eslintrc* |
onFileSystem:<scheme> | Custom file systems | onFileSystem:sftp |
onStartupFinished | Background tasks | (prefer over *) |
Critical: Avoid using * as it activates on every VS Code startup.
Contribution Points
Commands
{
"contributes": {
"commands": [{
"command": "ext.doSomething",
"title": "Do Something",
"category": "My Extension",
"icon": "$(symbol-method)"
}]
}
}
Configuration
{
"contributes": {
"configuration": {
"title": "My Extension",
"properties": {
"myExtension.enabled": {
"type": "boolean",
"default": true,
"description": "Enable the extension"
}
}
}
}
}
Views (Tree Views)
{
"contributes": {
"views": {
"explorer": [{
"id": "myTreeView",
"name": "My View"
}]
},
"viewsContainers": {
"activitybar": [{
"id": "myContainer",
"title": "My Extension",
"icon": "resources/icon.svg"
}]
}
}
}
VS Code API Namespaces
window API
// Show messages
vscode.window.showInformationMessage('Hello!');
vscode.window.showErrorMessage('Error occurred');
// Quick picks
const item = await vscode.window.showQuickPick(['Option 1', 'Option 2']);
// Input boxes
const input = await vscode.window.showInputBox({ prompt: 'Enter value' });
// Active editor
const editor = vscode.window.activeTextEditor;
workspace API
// Read configuration
const config = vscode.workspace.getConfiguration('myExtension');
const value = config.get<boolean>('enabled');
// Watch files
const watcher = vscode.workspace.createFileSystemWatcher('**/*.ts');
watcher.onDidChange(uri => { /* handle change */ });
// Open documents
const doc = await vscode.workspace.openTextDocument(uri);
commands API
// Register
const disposable = vscode.commands.registerCommand('ext.cmd', (arg) => {
// Implementation
});
// Execute
await vscode.commands.executeCommand('ext.cmd', argument);
WebView Development
Security Requirements (Critical)
- Content Security Policy (CSP) - Always implement strict CSP:
function getWebviewContent(webview: vscode.Webview): string {
const nonce = getNonce();
return `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="
default-src 'none';
style-src ${webview.cspSource} 'unsafe-inline';
script-src 'nonce-${nonce}';
img-src ${webview.cspSource} https:;
">
</head>
<body>
<script nonce="${nonce}">
const vscode = acquireVsCodeApi();
// Use vscode.postMessage() for communication
</script>
</body>
</html>`;
}
- Input Sanitization - Always sanitize user input
- HTTPS Only - External resources must use HTTPS
- Minimal Permissions - Limit
localResourceRoots
Message Passing Pattern
// Extension → WebView
panel.webview.postMessage({ type: 'update', data: payload });
// WebView → Extension
panel.webview.onDidReceiveMessage(message => {
switch (message.type) {
case 'action':
handleAction(message.data);
break;
}
});
// In WebView JavaScript
window.addEventListener('message', event => {
const message = event.data;
// Handle message
});
vscode.postMessage({ type: 'action', data: result });
State Persistence
// Simple state (survives webview hide/show)
const state = webview.getState() || { count: 0 };
webview.setState({ count: state.count + 1 });
// Full persistence (survives VS Code restart)
class MySerializer implements vscode.WebviewPanelSerializer {
async deserializeWebviewPanel(panel: vscode.WebviewPanel, state: any) {
panel.webview.html = getHtmlForWebview(panel.webview, state);
}
}
vscode.window.registerWebviewPanelSerializer('myWebview', new MySerializer());
Language Server Protocol (LSP)
Architecture
┌─────────────────────┐ ┌─────────────────────┐
│ Language Client │────│ Language Server │
│ (VS Code Extension)│ LSP │ (Separate Process) │
│ vscode-languageclient │ vscode-languageserver
└─────────────────────┘ └─────────────────────┘
Client Implementation
import { LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient/node';
const serverOptions: ServerOptions = {
run: { module: serverPath, transport: TransportKind.ipc },
debug: { module: serverPath, transport: TransportKind.ipc }
};
const clientOptions: LanguageClientOptions = {
documentSelector: [{ scheme: 'file', language: 'mylang' }],
synchronize: {
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.mylang')
}
};
const client = new LanguageClient('mylang', 'My Language', serverOptions, clientOptions);
client.start();
Server Implementation
import { createConnection, TextDocuments, ProposedFeatures } from 'vscode-languageserver/node';
import { TextDocument } from 'vscode-languageserver-textdocument';
const connection = createConnection(ProposedFeatures.all);
const documents = new TextDocuments(TextDocument);
connection.onInitialize((params) => {
return {
capabilities: {
textDocumentSync: TextDocumentSyncKind.Incremental,
completionProvider: { resolveProvider: true },
hoverProvider: true
}
};
});
connection.onCompletion((params) => {
return [
{ label: 'suggestion1', kind: CompletionItemKind.Text }
];
});
documents.listen(connection);
connection.listen();
Tree View Implementation
class MyTreeDataProvider implements vscode.TreeDataProvider<MyItem> {
private _onDidChangeTreeData = new vscode.EventEmitter<MyItem | undefined>();
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
refresh(): void {
this._onDidChangeTreeData.fire(undefined);
}
getTreeItem(element: MyItem): vscode.TreeItem {
return {
label: element.name,
collapsibleState: element.children ?
vscode.TreeItemCollapsibleState.Collapsed :
vscode.TreeItemCollapsibleState.None,
command: {
command: 'ext.selectItem',
title: 'Select',
arguments: [element]
}
};
}
getChildren(element?: MyItem): Thenable<MyItem[]> {
if (!element) {
return Promise.resolve(this.getRootItems());
}
return Promise.resolve(element.children || []);
}
}
// Register
const provider = new MyTreeDataProvider();
vscode.window.registerTreeDataProvider('myTreeView', provider);
Performance Best Practices
Lazy Loading
// Delay expensive imports
let heavyModule: typeof import('./heavyModule') | undefined;
async function getHeavyModule() {
if (!heavyModule) {
heavyModule = await import('./heavyModule');
}
return heavyModule;
}
Bundling (Required for VS Code Web)
Use esbuild for fast bundling:
// esbuild.config.js
const esbuild = require('esbuild');
esbuild.build({
entryPoints: ['./src/extension.ts'],
bundle: true,
outfile: './out/extension.js',
external: ['vscode'],
format: 'cjs',
platform: 'node',
minify: process.env.NODE_ENV === 'production',
sourcemap: true
});
Resource Cleanup
export function activate(context: vscode.ExtensionContext) {
// Always add to subscriptions for automatic cleanup
context.subscriptions.push(
vscode.commands.registerCommand(...),
vscode.window.registerTreeDataProv
---
*Content truncated.*
When not to use it
- →When developing applications outside of the VS Code extension ecosystem.
- →When the task does not involve VS Code API or contribution points.
- →When only basic JavaScript/TypeScript development is needed without extension-specific concerns.
Limitations
- →Requires adherence to VS Code Extension API.
- →Strict security requirements for WebViews, including CSP.
- →Activation events should be specific to minimize startup impact.
How it compares
This skill offers specialized knowledge for VS Code extension development, including specific API patterns and security requirements like Content Security Policy, which is distinct from general software development.
Compared to similar skills
vscode-extension-expert side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| vscode-extension-expert (this skill) | 0 | 6mo | Review | Advanced |
| vscode-ext-commands | 2 | 7mo | No flags | Beginner |
| agent-implementer-sparc-coder | 1 | 6mo | Review | Intermediate |
| ai-sdk-model-manager | 1 | 4mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by s-hiraoku
View all by s-hiraoku →You might also like
vscode-ext-commands
github
Guidelines for contributing commands in VS Code extensions. Indicates naming convention, visibility, localization and other relevant attributes, following VS Code extension development guidelines, libraries and good practices
agent-implementer-sparc-coder
ruvnet
Agent skill for implementer-sparc-coder - invoke with $agent-implementer-sparc-coder
ai-sdk-model-manager
tambo-ai
Manages AI SDK model configurations - updates packages, identifies missing models, adds new models with research, and updates documentation
update-codemaps
chenqin231
扫描代码结构并更新架构文档映射
tsx
javimosch
TSX namespace for Netsnek e.U. TypeScript component toolkit. React component scaffolding, type-safe props, Storybook integration, and component docs.
update-requirement
Tan90Qian
处理需求变更并同步 spec、类型和实现