VS

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.zip

Installs 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.
396 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Advanced

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

You give it
Request to develop, debug, or optimize a VS Code extension
You get back
VS Code extension code, architectural design, or performance improvements

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:

EventUse CaseExample
onLanguage:<lang>Language-specific featuresonLanguage:python
onCommand:<command>Command-driven extensionsonCommand:ext.showPanel
onView:<viewId>Sidebar view expansiononView:myTreeView
workspaceContains:<glob>Project-specific featuresworkspaceContains:**/.eslintrc*
onFileSystem:<scheme>Custom file systemsonFileSystem:sftp
onStartupFinishedBackground 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)

  1. 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>`;
}
  1. Input Sanitization - Always sanitize user input
  2. HTTPS Only - External resources must use HTTPS
  3. 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.

SkillInstallsUpdatedSafetyDifficulty
vscode-extension-expert (this skill)06moReviewAdvanced
vscode-ext-commands27moNo flagsBeginner
agent-implementer-sparc-coder16moReviewIntermediate
ai-sdk-model-manager14moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry