Use for VS Code extensions with native chat, tools, and MCP.
Scanned 9/10/2026
Install to Claude Code
npx -y skills add LoopyLuci/Skills --skill vscode-extension-development --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Vscode Extension Development?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/loopyluci-vscode-extension-development)More formats (shields.io, HTML) on the badges page.
---
name: vscode-extension-development
description: Use for VS Code extensions with native chat, tools, and MCP.
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
hermes:
tags: [vscode, extension, development, chat, mcp, native-ui, build]
---
# VS Code Extension Development
## Overview
Build VS Code extensions that integrate natively into the editor's UI — activity bar, chat sidebar, and tool infrastructure. Covers the full lifecycle: project setup, tool registration, chat integration, build pipeline, and packaging.
## Critical Pitfalls
### 1. ChatParticipant ≠ Chat Provider (COMMON MISTAKE)
`vscode.chat.createChatParticipant` registers an `@mention` participant in the built-in chat. `vscode.lm.registerLanguageModelChatProvider` + `languageModelChatProviders` registers a MODEL in the chat model picker. Neither adds a "+ dropdown" entry — see the ground-truth note below.
**Correct approach (all three, for full integration):**
- `ChatParticipant` → `@Hermes` mentions in any chat session
- `LanguageModelChatProvider` → Hermes in the model picker
- `viewsContainers.activitybar` → your own sidebar chat (the surface real third-party AI extensions use)
**GROUND TRUTH (verified VS Code 1.131, July 2026): the Chat "+" dropdown ("New Chat / New Codex Agent / New Copilot CLI Session") is populated ONLY by VS Code's built-in agent-host harnesses (Agent Host Protocol). Third-party extensions do not appear there — not even Claude Code** (inspected `anthropic.claude-code-2.1.220/package.json`: zero chatParticipants, zero languageModelChatProviders — only viewsContainers/commands). A "missing + dropdown entry" is a non-bug; do not chase it. The agent-host protocol (`chat.agentHost.enabled`) is the only opt-in path, and it's experimental.
### 2. activitybar vs panel in viewsContainers
`viewsContainers.panel` puts your webview in the BOTTOM panel area. `viewsContainers.activitybar` puts an ICON in the LEFT sidebar (like Explorer, Search, Git). For Claude-like integration, use `activitybar`.
```json
"viewsContainers": {
"activitybar": [{
"id": "hermes-chat",
"title": "Hermes Agent",
"icon": "./assets/icon.svg"
}]
}
```
### 3. LanguageModelChatProvider API location
`registerLanguageModelChatProvider` is in `vscode.lm`, NOT `vscode.chat`. And it may not be in `@types/vscode` for older type versions — use `(vscode.lm as any).registerLanguageModelChatProvider(...)` with try/catch for forward compatibility.
### 4. MCP tools/list requires initialization first
The MCP protocol requires `initialize` before `tools/list`. Without it, tools returns empty array. Always send `initialize` first in tests.
### 5. Extension activation on reload
After `code --install-extension`, VS Code doesn't always reload. Use `code -r -g D:/path/file:1` to force a window reload that triggers the new extension host.
### 6. onStartupFinished is essential
Without `onStartupFinished` in activationEvents, the MCP server won't auto-start. Early builds failed because the stale .vsix didn't have this event.
## Build Pipeline
```bash
# 1. Type-check (zero errors required)
npx tsc --noEmit --pretty
# 2. Bundle with esbuild
node esbuild.js
# 3. Package .vsix
rm -f *.vsix && npx vsce package
# 4. Kill old MCP server
PID=$(netstat -ano | grep 19999 | grep LISTENING | awk '{print $5}')
[ -n "$PID" ] && taskkill /F /PID $PID
# 5. Install and reload
code --install-extension hermes-agent-vscode-1.0.0.vsix --force
code -r -g README.md:1
```
## Tool Call Loop Pattern
The LLM outputs tool calls in ` ```tool {"name":"...","arguments":{...}} ``` ` blocks. Parse, execute, feed results back, repeat.
```typescript
// Extract tool calls from LLM text
const calls = [];
const pattern = /```tool\n?([\s\S]*?)```/g;
let match;
while ((match = pattern.exec(text)) !== null) {
const parsed = JSON.parse(match[1].trim());
if (parsed?.name) calls.push({ name: parsed.name, arguments: parsed.arguments || {} });
}
// Remove tool blocks from final text
const clean = text.replace(/```tool\n?[\s\S]*?```/g, '').trim();
```
Max 8-10 iterations. Each tool call result goes back as a user message with `[Tool Result: name]` wrapper.
## Native Chat Integration Checklist
- [ ] `package.json` has `languageModelChatProviders` contribution with vendor name
- [ ] `package.json` has `viewsContainers.activitybar` for sidebar icon
- [ ] `package.json` has `activationEvents: ["onStartupFinished"]`
- [ ] Extension registers `ChatParticipant` via `vscode.chat.createChatParticipant`
- [ ] Extension registers `LanguageModelChatProvider` via `vscode.lm.registerLanguageModelChatProvider`
- [ ] Extension registers `WebviewViewProvider` for the activity bar panel
- [ ] SVG icon is 24x24, stroke-based, matches VS Code's icon style
- [ ] `.vscodeignore` does NOT exclude `assets/` directory
- [ ] System prompt includes tool descriptions in the LLM-compatible format
## package.json Contribution Structure
```json
{
"contributes": {
"languageModelChatProviders": [{
"vendor": "hermes",
"icon": "./assets/hermes-icon.svg",
"name": "Hermes Agent",
"description": "..."
}],
"viewsContainers": {
"activitybar": [{
"id": "hermes-chat",
"title": "Hermes Agent",
"icon": "./assets/hermes-icon.svg"
}]
},
"views": {
"hermes-chat": [{
"type": "webview",
"id": "hermes.chatPanel",
"name": "Chat"
}]
},
"commands": [...],
"configuration": { "properties": { ... } }
}
}
```
## When to Use
- Building any VS Code extension with chat UI
- Integrating AI agents into VS Code's native chat
- Setting up MCP servers as VS Code extensions
- Creating activity bar panels with webview UI
## Support Files
- `references/native-chat-integration.md` — deeper chat integration detail
- `references/shared-db-bridge.md` — safe pattern for a second process reading/writing another app's live SQLite DB (node:sqlite, read-only reads, source-tagged writes, live-DB verification recipe). Use when syncing an extension with an app-owned state DB (e.g. Hermes Desktop `state.db`).
- `references/skin-theme-sync.md` — mirror an app's skin/theme engine onto webview CSS custom properties (built-in presets + user YAML overrides, light/dark polarity from VS Code's active theme, live reload via config watcher + fs.watch, lazy `require('vscode')` accessor so the module stays unit-testable in pure Node).
- `references/eslint9-flat-config.md` — hardening `npm run lint` for a TS extension: ESLint 9 + typescript-eslint 8 flat config, rule tuning rationale (require-await off for tool-registry contract, no-misused-promises checksVoidReturn:false for event-emitter code, unnecessary-condition/optional-chain off for defensive config paths), and the dead-code cleanup workflow (89→0 problems, zero behavior change).
- `references/mcp-reliability-self-healing.md` — making an MCP-over-HTTP server hosted by a VS Code extension self-healing: EADDRINUSE port-fallback retry (error listener + recursive `listen`), health-check watchdog with auto-restart after N consecutive failures, and using `context.secrets` (SecretStorage) instead of settings.json for API keys.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!