A small custom extension can automate a team-specific workflow that no marketplace extension covers.
Extensions are Node.js packages written in TypeScript or JavaScript. Scaffold one with the Yeoman generator: npx --package yo --package generator-code -- yo code. It creates:
package.jsonwith the manifest:engines.vscode(minimum version),main(entry file), and acontributessection declaring commands, settings, keybindings, menus and more. Contributed commands activate the extension automatically when invoked.src/extension.tsexportingactivate(context)and optionallydeactivate().
Inside activate, use the vscode API: vscode.commands.registerCommand, vscode.window.activeTextEditor, vscode.window.showInformationMessage, vscode.workspace.getConfiguration, and editing via editor.edit or WorkspaceEdit. Push every disposable (commands, listeners) into context.subscriptions so it is cleaned up on deactivation.
Press F5 to launch an Extension Development Host, a second VS Code window with your extension loaded; breakpoints in your code work immediately. The generator also sets up tests run with @vscode/test-cli.
To share it, package with npx @vscode/vsce package (creates a .vsix you can install with code --install-extension file.vsix) or publish to the Marketplace under a publisher account. Keep activation narrow and work asynchronous; the extension host is shared with every other extension.
Example
// src/extension.ts (package.json contributes command "wc.count", title "Count Words")
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
const cmd = vscode.commands.registerCommand('wc.count', () => {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showWarningMessage('No active editor');
return;
}
const sel = editor.selection;
const text = editor.document.getText(sel.isEmpty ? undefined : sel);
const words = text.split(/\s+/).filter(Boolean).length;
vscode.window.showInformationMessage(`Words: ${words}`);
});
context.subscriptions.push(cmd);
}
export function deactivate() {}Remember
- package.json contributes declare commands, settings, menus
- activate() registers handlers; push disposables to context.subscriptions
- F5 opens an Extension Development Host; vsce packages a .vsix
Watch out for
- Activating on every startup ("*") when a command or language activation event would do.