vscode-extension
- Repo stars 0
- Author updated Live
- Author repo skills-registry
- Domain
- Other
- Compatible agents
-
- Claude Code
- Cursor
- Cline
- Codex
- Windsurf
- Gemini CLI
- +20
- Trust score
- 84 / 100 · community maintained
- Author / version / license
- @tomevault-io · no license declared
- Token usage
- Lean
- Setup complexity
- Guided setup
- External API key
- Not required
- Operating systems
- macOS · Linux · Windows
- Runtime requirements
- Node.js
- Permissions
-
- Read-only
- Write / modify
- Shell exec
- Network behavior
- Local-only
- Install commands
- 26 variants
Profile is derived at build time from SKILL.md and install vectors. Subject to drift from author intent.
Heads up: 未限定 allowed-tools,默认拥有全部工具权限。; 正文出现疑似高熵凭证字符串,请人工确认。
---
name: vscode-extension
description: >- Use when this capability is needed. Use yo code or manual setup. Follow this structure: │ ├──…
category: other
runtime: Node.js
---
# vscode-extension output preview
## PART A: Task fit
- Use case: >- Use when this capability is needed. Use yo code or manual setup. Follow this structure: │ ├── launch.json # Extension Host debug config │ └── tasks.json # Build tasks runs entirely locally; runs on Node.js. Works with Claude Code, Cursor, Cline and 23 more..
- Inputs: target material, constraints, expected output, and acceptance criteria.
- Evidence boundary: follow “When to Use / Official Documentation / Procedure” and do not present inference as author intent.
## PART B: Execution result
- **01** The card summarizes the use case; runtime output centers on “>- Use when this capability is needed. Use yo code or manual setup. Follow this structure: │ ├── launch.json # Extension Host debug config │ └── tasks.json # Build tasks runs entirely locally; runs on Node.js. Works with Claude Code, Cursor, Cline and 23 more.”.
- **02** When the source has headings, the agent prioritizes “When to Use / Official Documentation / Procedure” so the result follows the author’s structure.
- **03** Typical output includes task judgment, concrete steps, required commands or file edits, validation, and follow-up options.
- **04** Risk context follows the fingerprint: read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
## Running Rules
- read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
- Validate with a small sample before expanding scope.
- Return the result, validation criteria, and next iteration options. The source does not require a stable slash command. After installation, invoke the skill by name and describe the task.
Name target files or source material, expected output, forbidden changes, and whether network or shell access is allowed. Permission fingerprint: read files, write/modify files, run shell commands.
Start with a small task and check whether the result follows “When to Use / Official Documentation / Procedure”. Inspect diffs, logs, previews, or tests before expanding scope.
Confirm the final output includes a concrete result, evidence, and next action. If it stays generic, tighten inputs, boundaries, and acceptance criteria.
---
name: vscode-extension
description: >- Use when this capability is needed. Use yo code or manual setup. Follow this structure: │ ├──…
category: other
source: tomevault-io/skills-registry
---
# vscode-extension
## When to use
- >- Use when this capability is needed. Use yo code or manual setup. Follow this structure: │ ├── launch.json # Extensi…
- Use it when the task has clear inputs, repeatable steps, and validation criteria.
## What to provide
- Target material, scope, expected result, and forbidden changes.
- Whether network, commands, file writes, or external services are allowed.
## Execution rules
- Organize steps around “When to Use / Official Documentation / Procedure” and keep inference separate from source facts.
- read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
- Validate with a small sample before expanding the task.
## Output requirements
- Return the deliverable, key evidence, validation method, and next action.
- Mark missing information as unknown; do not invent commands, platforms, or dependencies. The author source anchors workflow facts; repository files anchor sources and commands; Fluxly only adds fit, limitations, and quality judgment.
skill "vscode-extension" {
input -> user goal + target files + boundaries + acceptance criteria
context -> When to Use / Official Documentation / Procedure
rules -> SKILL.md triggers / order / output contract
runtime -> Node.js | read files, write/modify files, run shell commands | mostly runs locally
guardrails -> usually needs no extra API key + small-sample validation + diff/log review
output -> copyable result + checklist + next iteration
} VS Code Extension Development
When to Use
- Creating a new VS Code extension from scratch
- Adding commands, keybindings, or menu contributions
- Building tree views, sidebar panels, or webview UIs
- Implementing language features (completion, diagnostics, hover, CodeLens)
- Writing extension tests with
@vscode/test-electron - Packaging and publishing to the VS Code Marketplace
Official Documentation
- VS Code Extension API
- Extension Guides
- VS Code API Reference
- Extension Manifest (package.json)
- Activation Events
- Publishing Extensions
Procedure
Step 1 — Scaffold & Project Structure
Use yo code or manual setup. Follow this structure:
my-extension/
├── .vscode/
│ ├── launch.json # Extension Host debug config
│ └── tasks.json # Build tasks
├── src/
│ ├── extension.ts # Entry point: activate() and deactivate()
│ ├── commands/ # Command handler implementations
│ ├── providers/ # TreeDataProvider, CompletionProvider, etc.
│ ├── views/ # Webview panel creation and messaging
│ ├── services/ # Business logic, API clients
│ └── utils/ # Helpers, constants
├── webview-ui/ # React/Svelte webview source (if applicable)
│ ├── src/
│ └── vite.config.ts
├── test/
│ ├── suite/ # Integration tests (Extension Host)
│ └── unit/ # Pure unit tests (no VS Code API)
├── package.json # Extension manifest + contributions
├── tsconfig.json
├── esbuild.config.mjs # Bundler config
├── .vscodeignore # Files to exclude from VSIX
├── CHANGELOG.md
└── README.md
Key Rules:
src/extension.tsexportsactivate(context)anddeactivate().- Register all disposables via
context.subscriptions.push(...). - Keep
activate()lean — lazy-initialize heavy resources.
Step 2 — Extension Manifest (package.json)
{
"name": "my-extension",
"displayName": "My Extension",
"description": "A VS Code extension that does X",
"version": "0.1.0",
"publisher": "your-publisher-id",
"engines": { "vscode": "^1.96.0" },
"categories": ["Other"],
"activationEvents": [],
"main": "./dist/extension.js",
"contributes": {
"commands": [
{
"command": "myExtension.helloWorld",
"title": "Hello World",
"category": "My Extension"
}
],
"keybindings": [
{
"command": "myExtension.helloWorld",
"key": "ctrl+shift+h",
"mac": "cmd+shift+h"
}
],
"menus": {
"editor/context": [
{ "command": "myExtension.helloWorld", "group": "navigation" }
]
},
"configuration": {
"title": "My Extension",
"properties": {
"myExtension.enableFeature": {
"type": "boolean",
"default": true,
"description": "Enable the main feature"
}
}
}
}
}
Key Rules:
- Use
activationEvents: []for lazy activation (VS Code 1.74+). - Prefix all commands with
extensionName.commandName. - Declare every command in both
commandsandmenusas needed. - Use
whenclauses for conditional command availability.
Step 3 — Commands & Activation
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext): void {
// Register commands
context.subscriptions.push(
vscode.commands.registerCommand('myExtension.helloWorld', async () => {
const name = await vscode.window.showInputBox({
prompt: 'Enter your name',
placeHolder: 'World'
});
vscode.window.showInformationMessage(`Hello, ${name ?? 'World'}!`);
})
);
// Register providers
const treeProvider = new MyTreeDataProvider();
context.subscriptions.push(
vscode.window.registerTreeDataProvider('myExtension.treeView', treeProvider)
);
}
export function deactivate(): void {
// Cleanup resources if needed
}
Key Rules:
- Always push disposables to
context.subscriptions. - Use
asynccommands with proper error handling. - Show progress for long-running operations via
vscode.window.withProgress(). - Read configuration via
vscode.workspace.getConfiguration('myExtension').
Step 4 — Tree Views
import * as vscode from 'vscode';
export class MyTreeDataProvider implements vscode.TreeDataProvider<TreeItem> {
private _onDidChangeTreeData = new vscode.EventEmitter<TreeItem | undefined>();
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
refresh(): void {
this._onDidChangeTreeData.fire(undefined);
}
getTreeItem(element: TreeItem): vscode.TreeItem {
return element;
}
async getChildren(element?: TreeItem): Promise<TreeItem[]> {
if (!element) {
// Root items
return this.getRootItems();
}
// Child items
return this.getChildItems(element);
}
private async getRootItems(): Promise<TreeItem[]> {
return [
new TreeItem('Item 1', vscode.TreeItemCollapsibleState.Collapsed),
new TreeItem('Item 2', vscode.TreeItemCollapsibleState.None)
];
}
private async getChildItems(parent: TreeItem): Promise<TreeItem[]> {
return [];
}
}
class TreeItem extends vscode.TreeItem {
constructor(
public readonly label: string,
public readonly collapsibleState: vscode.TreeItemCollapsibleState
) {
super(label, collapsibleState);
}
}
Declare in package.json:
"contributes": {
"views": {
"explorer": [
{ "id": "myExtension.treeView", "name": "My Items" }
]
},
"viewsContainers": {
"activitybar": [
{
"id": "myExtension-sidebar",
"title": "My Extension",
"icon": "resources/icon.svg"
}
]
}
}
Step 5 — Webview Panels
export class MyWebviewPanel {
private panel: vscode.WebviewPanel | undefined;
constructor(private readonly extensionUri: vscode.Uri) {}
show(): void {
if (this.panel) {
this.panel.reveal();
return;
}
this.panel = vscode.window.createWebviewPanel(
'myExtension.panel',
'My Panel',
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots: [
vscode.Uri.joinPath(this.extensionUri, 'dist', 'webview')
]
}
);
this.panel.webview.html = this.getHtml(this.panel.webview);
// Handle messages from webview
this.panel.webview.onDidReceiveMessage(
(message: { command: string; data?: unknown }) => {
switch (message.command) {
case 'save':
this.handleSave(message.data);
break;
}
},
undefined,
[]
);
this.panel.onDidDispose(() => {
this.panel = undefined;
});
}
private getHtml(webview: vscode.Webview): string {
const scriptUri = webview.asWebviewUri(
vscode.Uri.joinPath(this.extensionUri, 'dist', 'webview', 'main.js')
);
const nonce = getNonce();
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'none'; script-src 'nonce-${nonce}';">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="root"></div>
<script nonce="${nonce}" src="${scriptUri}"></script>
</body>
</html>`;
}
private handleSave(data: unknown): void {
// Process save action
}
}
function getNonce(): string {
let text = '';
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 32; i++) {
text += chars.charAt(Math.floor(Math.random() * chars.length));
}
return text;
}
Key Rules:
- Always set
Content-Security-Policywith nonce — never allow inline scripts. - Use
localResourceRootsto restrict file access. - Communicate via
postMessage/onDidReceiveMessage— no direct DOM access. - Use
retainContextWhenHiddensparingly — it increases memory usage.
Step 6 — Language Features
// Completion Provider
class MyCompletionProvider implements vscode.CompletionItemProvider {
provideCompletionItems(
document: vscode.TextDocument,
position: vscode.Position
): vscode.CompletionItem[] {
const item = new vscode.CompletionItem('mySnippet', vscode.CompletionItemKind.Snippet);
item.insertText = new vscode.SnippetString('console.log($1);');
item.documentation = new vscode.MarkdownString('Inserts a console.log statement');
return [item];
}
}
// Diagnostics
const diagnosticCollection = vscode.languages.createDiagnosticCollection('myExtension');
function updateDiagnostics(document: vscode.TextDocument): void {
const diagnostics: vscode.Diagnostic[] = [];
// Analyze document and add diagnostics
const range = new vscode.Range(0, 0, 0, 10);
diagnostics.push(new vscode.Diagnostic(range, 'Issue found', vscode.DiagnosticSeverity.Warning));
diagnosticCollection.set(document.uri, diagnostics);
}
// Register
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider('typescript', new MyCompletionProvider()),
diagnosticCollection
);
Step 7 — Testing
Integration Tests (run in Extension Host):
import * as assert from 'assert';
import * as vscode from 'vscode';
suite('Extension Test Suite', () => {
vscode.window.showInformationMessage('Start all tests.');
test('Command is registered', async () => {
const commands = await vscode.commands.getCommands(true);
assert.ok(commands.includes('myExtension.helloWorld'));
});
test('Command executes successfully', async () => {
await vscode.commands.executeCommand('myExtension.helloWorld');
// Verify side effects
});
});
Unit Tests (no VS Code dependency):
import { describe, it, expect } from 'vitest';
import { parseInput } from '../src/utils/parser';
describe('Parser', () => {
it('should parse valid input', () => {
const result = parseInput('test input');
expect(result).toBeDefined();
});
});
Key Rules:
- Use
@vscode/test-electronfor integration tests that need the Extension Host. - Use Vitest for pure logic unit tests (no VS Code API dependency).
- Mock
vscodenamespace in unit tests when needed. - Test both command registration and execution.
Step 8 — Bundling & Publishing
Use esbuild for fast bundling:
// esbuild.config.mjs
import * as esbuild from 'esbuild';
const production = process.argv.includes('--production');
await esbuild.build({
entryPoints: ['src/extension.ts'],
bundle: true,
outfile: 'dist/extension.js',
external: ['vscode'],
format: 'cjs',
platform: 'node',
target: 'node20',
sourcemap: !production,
minify: production,
});
Publishing Checklist:
- Update
versioninpackage.json - Update
CHANGELOG.md - Run tests:
npm test - Package:
vsce package - Test VSIX locally:
code --install-extension my-extension-0.1.0.vsix - Publish:
vsce publish
.vscodeignore:
.vscode/**
src/**
test/**
webview-ui/src/**
node_modules/**
.gitignore
tsconfig.json
esbuild.config.mjs
**/*.map
Quick Reference
| Concept | API |
|---|---|
| Show message | vscode.window.showInformationMessage() |
| Input box | vscode.window.showInputBox() |
| Quick pick | vscode.window.showQuickPick() |
| Progress | vscode.window.withProgress() |
| File picker | vscode.window.showOpenDialog() |
| Status bar | vscode.window.createStatusBarItem() |
| Output channel | vscode.window.createOutputChannel() |
| Read config | vscode.workspace.getConfiguration() |
| File system | vscode.workspace.fs.readFile() |
| Watch files | vscode.workspace.createFileSystemWatcher() |
| Decorations | vscode.window.createTextEditorDecorationType() |
| CodeLens | vscode.languages.registerCodeLensProvider() |
| Hover | vscode.languages.registerHoverProvider() |
| Definition | vscode.languages.registerDefinitionProvider() |
Anti-Patterns
- Never block the extension host with synchronous operations — always use
async. - Never use
eval()orFunction()in webviews — use nonce-based CSP. - Never store secrets in configuration — use
context.secrets(SecretStorage API). - Never bundle
node_modulesin the VSIX — use esbuild to bundle into a single file. - Never use global state for communication between components — use event emitters.
Source: congiuluc/my-awesome-copilot — distributed by TomeVault.
Decide Fit First
Design Intent
How To Use It
Boundaries And Review