用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/fabioc-aloha/BrainBenchmark --skill vscode-extension-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | vscode-extension-patterns |
| description | Reusable patterns for VS Code extension development. |
| user-invokable | false |
Reusable patterns for VS Code extension development.
VS Code APIs evolve with each monthly release. Patterns may become outdated or better alternatives may emerge.
Refresh triggers:
Last validated: February 2026 (VS Code 1.109+)
Check current state: VS Code API, Release Notes
// Gather data in parallel, build HTML with async
const [health, knowledge, sync] = await Promise.all([
checkHealth(true), getKnowledgeSummary(), getSyncStatus()
]);
panel.webview.html = await getWebviewContent(health, knowledge, sync);
Key: Make getWebviewContent async if it needs directory scanning or other async ops.
class WelcomeViewProvider implements vscode.WebviewViewProvider {
resolveWebviewView(webviewView: vscode.WebviewView) {
webviewView.webview.options = { enableScripts: true };
webviewView.webview.html = this.getHtmlContent();
webviewView.webview.onDidReceiveMessage(async (message) => {
switch (message.command) {
case 'refresh': await this.refresh(); break;
}
});
}
}
// Register in extension.ts
vscode.window.registerWebviewViewProvider('alex.welcomeView', new WelcomeViewProvider());
Problem: Inline event handlers (onclick="...") violate Content Security Policy and can be blocked.
Solution: Use data-cmd attributes with delegated event listeners:
<!-- ❌ WRONG: Inline handlers (CSP violation) -->
<button onclick="handleClick()">Click</button>
<!-- ✅ CORRECT: data-cmd pattern -->
<button data-cmd="play">Play</button>
<button data-cmd="stop">Stop</button>
// Single delegated listener for all commands
document.addEventListener('click', (e) => {
const target = e.target.closest('[data-cmd]');
if (!target) return;
const cmd = target.getAttribute('data-cmd');
switch (cmd) {
case 'play': audio.play(); break;
case 'stop': audio.pause(); audio.currentTime = 0; break;
}
});
Benefits:
Tiered settings: Essential (🔴) → Recommended (🟡) → Auto-Approval (🟠) → Extended Thinking (🧠) → Enterprise (🔵)
Safety rules:
config.inspect(key)?.globalValue before applyingasync function applySettings(settings: Record<string, unknown>) {
const config = vscode.workspace.getConfiguration();
for (const [key, value] of Object.entries(settings)) {
if (config.inspect(key)?.globalValue === undefined) {
await config.update(key, value, vscode.ConfigurationTarget.Global);
}
}
}
Pattern: Documentation-first approach for complex settings ecosystems (VS Code 1.109+ chat settings).
Steps:
Research Phase — Comprehensive discovery
Documentation Phase — Create reference materials before implementation
Implementation Phase — Safe automated application
settings.json.backup-{timestamp})Extension Integration — Make it permanent
setupEnvironment.ts ESSENTIAL_SETTINGS, RECOMMENDED_SETTINGS, etc.offerEnvironmentSetup())Validation Phase
Key insights from Feb 2026 implementation:
chat.hooks.enabled) marked experimental but not stable yet.ps1 file for complex scriptsWhen to use this pattern:
Template structure:
docs/guides/
├── FEATURE-SETTINGS-GUIDE.md # Comprehensive reference
├── FEATURE-SETTINGS-SUMMARY.md # Current state snapshot
└── FEATURE-SETTINGS-APPLIED.md # Change log (gitignore if sensitive)
.vscode/
└── recommended-feature-settings.jsonc # Template (gitignore)
src/commands/
└── setupEnvironment.ts # Settings constants + apply logic
Benefits:
const PATTERNS = [
{ pattern: /learned|discovered|realized/i, confidence: 0.8 },
{ pattern: /key insight|the trick is/i, confidence: 0.85 },
];
Use confidence thresholds for auto-actions. Higher threshold = fewer false positives.
function isDuplicate(newText: string, existing: string[]): boolean {
const normalize = (s: string) => s.toLowerCase().replace(/[^\w\s]/g, '');
return existing.some(e => calculateSimilarity(normalize(newText), normalize(e)) > 0.8);
}
Extensions must work on any machine:
// ✅ CORRECT: Dynamic paths
const rootPath = vscode.workspace.workspaceFolders?.[0].uri.fsPath;
const globalPath = path.join(os.homedir(), '.alex');
// ❌ WRONG: Hardcoded paths
const rootPath = 'c:\\Development\\MyProject'; // Never!
Key utilities:
vscode.workspace.workspaceFolders — Current workspaceos.homedir() — Platform-independent homepath.join() — Cross-platform path building# Load PAT from .env
$env:VSCE_PAT = (Get-Content .env | Select-String "VSCE_PAT" | ForEach-Object { $_.Line.Split("=",2)[1] })
vsce publish
Version collision: Increment patch → update package.json, README badge, CHANGELOG → retry.
interface LearningGoal {
id: string;
title: string;
category: 'coding' | 'reading' | 'practice' | 'review';
targetCount: number;
currentCount: number;
type: 'daily' | 'weekly';
expiresAt: string;
}
// Auto-increment on activity
async function autoIncrementGoals(activityType: 'session' | 'insight') {
const data = await loadGoalsData();
for (const goal of data.goals) {
if (shouldIncrement(goal, activityType) && !isExpired(goal)) {
goal.currentCount = Math.min(goal.currentCount + 1, goal.targetCount);
}
}
await saveGoalsData(data);
}
Never store secrets in settings — use VS Code's SecretStorage API:
// Module-level cache
let secretStorage: vscode.SecretStorage | null = null;
let cachedToken: string | null = null;
// Initialize during activation
export async function initSecrets(context: vscode.ExtensionContext): Promise<void> {
secretStorage = context.secrets;
cachedToken = await secretStorage.get('myExtension.apiToken') || null;
// Migration: Move token from settings to secrets
const config = vscode.workspace.getConfiguration('myExtension');
const settingsToken = config.get<string>('apiToken')?.trim();
if (settingsToken && !cachedToken) {
await secretStorage.store('myExtension.apiToken', settingsToken);
cachedToken = settingsToken;
await config.update('apiToken', undefined, vscode.ConfigurationTarget.Global);
vscode.window.showInformationMessage();
}
}
(): | {
cachedToken;
}
Key points:
context.secrets.get() / store() / delete() are asyncAlways add Content-Security-Policy when enableScripts: true:
import { getNonce } from './sanitize';
function getWebviewHtml(webview: vscode.Webview): string {
const nonce = getNonce();
return `<!DOCTYPE html>
<html>
<head>
<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: data:;
font-src ${webview.cspSource};
">
</head>
<body>
<script nonce="${nonce}">
const vscode = acquireVsCodeApi();
// ... your code
</script>
</body>
</html>`;
}
// Nonce generator
function getNonce(): string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
return Array.from({ length: 32 }, () =>
chars.charAt(Math.floor(Math.random() * chars.length))
).join('');
}
Problem: After adding CSP with script-src 'nonce-${nonce}', all inline event handlers (onclick, onchange) stop working because CSP blocks inline JavaScript.
Solution: Replace inline handlers with data attributes and event delegation:
<!-- ❌ BLOCKED BY CSP -->
<button onclick="cmd('upgrade')">Upgrade</button>
<button onclick="cmd('launchSkill', {skill: 'code-review'})">Review</button>
<!-- ✅ CSP-COMPLIANT -->
<button data-cmd="upgrade">Upgrade</button>
<button data-cmd="launchSkill" data-skill="code-review">Review</button>
<script nonce="${nonce}">
document.addEventListener('click', function(e) {
const el = e.target.closest('[data-cmd]');
if (el) {
e.preventDefault();
const command = el.getAttribute('data-cmd');
const skill = el.getAttribute('data-skill');
vscode.postMessage(skill ? { command, skill } : { command });
}
});
</script>
Benefits:
Problem: window.open(), location.reload(), and direct external links silently fail in sandboxed webviews.
Solution: WebView sends message to extension host; extension performs privileged action:
// In webview HTML
vscode.postMessage({ type: 'openExternal', url: 'https://example.com' });
// In extension host
panel.webview.onDidReceiveMessage(async (message) => {
if (message.type === 'openExternal') {
await vscode.env.openExternal(vscode.Uri.parse(message.url));
}
});
Key insight: WebView ↔ Extension Host communication mirrors browser Content Script ↔ Background Script patterns.
Always respect VS Code's telemetry settings:
function isTelemetryEnabled(): boolean {
// Check VS Code global setting first
if (!vscode.env.isTelemetryEnabled) {
return false;
}
// Then check extension-specific setting
const config = vscode.workspace.getConfiguration('myExtension');
return config.get<boolean>('telemetry.enabled', true);
}
function log(event: string, data?: Record<string, unknown>): void {
if (!isTelemetryEnabled()) {
return;
}
// Send telemetry...
}
React to settings changes at runtime:
export function activate(context: vscode.ExtensionContext) {
// Listen for configuration changes
context.subscriptions.push(
vscode.workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('myExtension.featureA')) {
// Refresh feature A
refreshFeatureA();
}
if (e.affectsConfiguration('myExtension.telemetry')) {
// Update telemetry state
}
})
);
}
Key points:
affectsConfiguration() to filter relevant changescontext.subscriptions for cleanupVS Code 1.109 introduces a native agent platform that extensions can leverage:
AGENTS.md)Extensions can ship agent definitions that VS Code auto-discovers:
<!-- .github/agents/my-agent.agent.md -->
---
name: "MyAgent"
description: "Specialized agent for domain X"
---
# MyAgent Instructions
Agent-specific instructions and knowledge go here.
Setting: chat.useAgentsMdFile: true enables automatic loading.
Extensions can define skills in .github/skills/ that are auto-loaded into chat:
Setting: chat.agentSkillsLocations: [".github/skills"]
Each skill folder contains a SKILL.md (knowledge) and optional synapses.json (connections).
Register custom chat participants that users can @mention:
const participant = vscode.chat.createChatParticipant('myext.agent', async (request, context, stream, token) => {
// Access to request.prompt, request.command
// Stream responses with stream.markdown(), stream.button(), stream.reference()
stream.markdown('Hello from my agent!');
});
participant.iconPath = vscode.Uri.joinPath(context.extensionUri, 'icon.png');
context.subscriptions.push(participant);
Register tools that any chat participant can invoke:
const tool = vscode.lm.registerTool('myext-searchDocs', {
async invoke(options, token) {
const query = options.input.query;
// Perform tool action
return new vscode.LanguageModelToolResult([
new vscode.LanguageModelTextPart(JSON.stringify(results))
]);
}
});
context.subscriptions.push(tool);
Declare in package.json:
{
"contributes": {
"languageModelTools": [{
"name": "myext-searchDocs",
"displayName": "Search Documentation",
"modelDescription": "Searches project documentation for relevant content",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "Search query" }
},
"required": ["query"]
}
}]
}
}
Models supporting extended thinking can be configured per-model:
{
"claude-opus-4-*.extendedThinkingEnabled": true,
"claude-opus-4-*.thinkingBudget": 16384
}
VS Code 1.109+ supports Model Context Protocol servers:
Setting: chat.mcp.gallery.enabled: true
MCP servers extend AI capabilities with external tools (Azure, GitHub, databases).
| Setting | Value | Purpose |
|---|---|---|
chat.agent.enabled | true | Enable custom agents |
chat.agentSkillsLocations | [".github/skills"] | Auto-load skills |
chat.useAgentsMdFile | true | Use AGENTS.md |
chat.mcp.gallery.enabled | true | MCP tool access |
10-category audit scoring system (5 points each, 50 total):
| # | Category | What to Check |
|---|---|---|
| 1 | Activation Events | package.json activationEvents match actual needs |
| 2 | Extension Context | context.subscriptions, secrets, globalState usage |
| 3 | Disposable Management | All disposables pushed to subscriptions |
| 4 | Command Registration | Commands in package.json match registerCommand |
| 5 | Configuration Access | getConfiguration usage, onDidChangeConfiguration |
| 6 | Webview Security | CSP policies, nonce usage, enableScripts |
| 7 | Language Model/Chat | vscode.lm patterns, tool registration |
| 8 | Telemetry | vscode.env.isTelemetryEnabled respected |
| 9 | Error Handling | try/catch patterns, error type handling |
| 10 | File System | vscode.workspace.fs vs Node.js fs |
Quick wins (high impact, low effort):
vscode.env.isTelemetryEnabledonDidChangeConfiguration for runtime updatescontext.secrets instead of settings for tokensScoring:
When to apply: Before marketplace publishing, after major features, quarterly reviews.
See synapses.json for connections.