Skip to content
Back to skills

Vscode Extension Development

ASecurity

Use for VS Code extensions with native chat, tools, and MCP.

  • 2 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 10, 2026
ai-agentstypescriptgobashsqlnodegitapi

Works with

  • claude code
  • vscode
  • cli
  • api
  • mcp

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned September 10, 2026

npx -y skills add LoopyLuci/Skills --skill vscode-extension-development --agent claude-code

Installs 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 with every re-scan.

Security grade badge for Vscode Extension Development
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/loopyluci-vscode-extension-development/badge)](https://www.skillsdirectory.com/skills/loopyluci-vscode-extension-development)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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.

Files in this skill

  • SKILL.md7.1 KB
  • references/eslint9-flat-config.md4.4 KB
  • references/mcp-reliability-self-healing.md3.5 KB
  • references/native-chat-integration.md3.8 KB
  • references/shared-db-bridge.md3.7 KB
  • references/skin-theme-sync.md4.6 KB
  • scripts/test-mcp-fallback.js1.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…