Developers spend hours searching documentation and writing boilerplate code. With 5 years of experience and over 20 AI tools developed, we deliver robust VS Code extensions that embed directly into the editor and speed up routine tasks by 2–3 times. Integration with Anthropic and OpenAI APIs allows flexible model choice for each task, and streaming via client.messages.stream() delivers the first tokens in 200–300 ms. The average cost for one code explanation via Claude Haiku is about $0.25, and test generation via GPT-4o mini is $0.15 per 1K tokens. Typical extension development costs range from $3,000 to $15,000, and can save a development team 30-50% in code review time. For a team of 10 developers, our custom extension can save up to $5,000 annually.
One common issue is generation latency. We use streaming, with the first tokens appearing in 200–300 ms. P99 latency for short requests is under 1.5 s. To reduce hallucinations, we add context from the active file and few-shot examples — this decreases incorrect suggestions by 40%. We employ lexical analysis and AST traversal to extract context, and use tokenization strategies to fit within the model's context window. Inference optimization via model quantization further reduces latency. Our debounce mechanism and retry logic ensure robust performance.
What problems do we solve?
- Generation latency — low-latency models (Claude Haiku, GPT-4o mini), streaming, and 300 ms debounce.
- Hallucinations — project context, few-shot, custom prompts for your stack (Django, React, FastAPI).
-
Extension API integration — common mistakes: missing cleanup in
deactivate(), WebView memory leaks. We address these during code review. - Marketplace publishing — preparing icons, description, testing on different VS Code versions (1–2 days).
How we do it
Stack: TypeScript, VS Code Extension API, Anthropic SDK / OpenAI SDK. For inline completion we use InlineCompletionItemProvider, for chat — WebView with acquireVsCodeApi(). All LLM calls are asynchronous, with retries on timeouts. Below is a comparison of models for different tasks.
| Task | Recommended Model | P99 Latency | Cost per 1K tokens |
|---|---|---|---|
| Explain code | Claude Haiku 4 | ~0.8 s | ~$0.25 |
| Refactor | Claude Sonnet 4 | ~1.2 s | ~$3.0 |
| Generate tests | GPT-4o mini | ~1.0 s | ~$0.15 |
| Chat history | GPT-4o | ~2.0 s | ~$5.0 |
| Approach | Flexibility | Performance | Development Complexity |
|---|---|---|---|
| Built-in VS Code models | Low | High | Low |
| LLM API (our implementation) | High | Medium (depends on model) | Medium |
| Local LLM via ONNX | Medium | Low (depends on GPU) | High |
VS Code Extension API provides rich capabilities for integrating AI services. Documentation
Example OpenAI configuration
{
"aiAssistant.model": "gpt-4o-mini",
"aiAssistant.apiKey": "sk-..."
}
Why a custom extension is better than a ready-made one?
Ready-made solutions from the Marketplace often don't know the specifics of your stack. We customize prompts for your libraries and add code actions for specific errors. For example, the extension can automatically suggest try/except for blocks at risk of exceptions. This reduces code review time by 2–3 times.
What's included in the work?
- Source code of the extension with documentation.
- Integration with your LLM (we do not provide free API keys).
- CI/CD setup for publishing.
- Support for 1 month after delivery.
How the inline completion provider works
The provider implements the InlineCompletionItemProvider interface. On every character input, a request is sent to the LLM with the context of the current file. We use a 300 ms debounce and cache results for identical contexts. This keeps p99 latency below 1.5 s.
Extension structure
The code below is a configuration for four commands and code actions.
{
"name": "ai-dev-assistant",
"displayName": "AI Dev Assistant",
"engines": { "vscode": "^1.85.0" },
"activationEvents": ["onStartupFinished"],
"contributes": {
"commands": [
{ "command": "aiAssistant.explainCode", "title": "AI: Explain Code" },
{ "command": "aiAssistant.refactor", "title": "AI: Refactor Selection" },
{ "command": "aiAssistant.generateTests", "title": "AI: Generate Tests" },
{ "command": "aiAssistant.openChat", "title": "AI: Open Chat" }
],
"keybindings": [
{ "command": "aiAssistant.explainCode", "key": "ctrl+shift+e", "when": "editorTextFocus" }
],
"configuration": {
"title": "AI Assistant",
"properties": {
"aiAssistant.apiKey": {
"type": "string",
"description": "Anthropic API Key"
},
"aiAssistant.model": {
"type": "string",
"default": "claude-haiku-4-5",
"enum": ["claude-haiku-4-5", "claude-sonnet-4-5"]
}
}
}
},
"main": "./out/extension.js"
}
Main extension file
import * as vscode from 'vscode';
import Anthropic from '@anthropic-ai/sdk';
let client: Anthropic;
export function activate(context: vscode.ExtensionContext) {
const config = vscode.workspace.getConfiguration('aiAssistant');
client = new Anthropic({ apiKey: config.get('apiKey') || '' });
context.subscriptions.push(
vscode.commands.registerCommand('aiAssistant.explainCode', explainSelectedCode)
);
// ... other commands
}
async function explainSelectedCode() {
const editor = vscode.window.activeTextEditor;
if (!editor) return;
const selection = editor.selection;
const selectedText = editor.document.getText(selection);
if (!selectedText) {
vscode.window.showWarningMessage('Select code to explain');
return;
}
await vscode.window.withProgress(
{ location: vscode.ProgressLocation.Notification, title: 'AI analyzing code...' },
async () => {
const response = await client.messages.create({
model: 'claude-haiku-4-5',
max_tokens: 1024,
messages: [{
role: 'user',
content: `Explain this code briefly and clearly:\n\`\`\`\n${selectedText}\n\`\`\``
}]
});
const explanation = response.content[0].type === 'text' ? response.content[0].text : '';
const outputChannel = vscode.window.createOutputChannel('AI Assistant');
outputChannel.appendLine('=== AI Explanation ===');
outputChannel.appendLine(explanation);
outputChannel.show();
}
);
}
Chat Panel
class ChatPanel {
private static currentPanel?: ChatPanel;
private readonly panel: vscode.WebviewPanel;
static createOrShow(extensionUri: vscode.Uri) {
if (ChatPanel.currentPanel) {
ChatPanel.currentPanel.panel.reveal();
return;
}
const panel = vscode.window.createWebviewPanel(
'aiChat', 'AI Chat', vscode.ViewColumn.Beside,
{ enableScripts: true }
);
ChatPanel.currentPanel = new ChatPanel(panel, extensionUri);
}
constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
this.panel = panel;
this.panel.webview.html = this.getWebviewContent();
this.panel.webview.onDidReceiveMessage(async message => {
if (message.type === 'chat') {
const stream = await client.messages.stream({
model: 'claude-sonnet-4-5',
max_tokens: 2048,
messages: message.history,
});
for await (const chunk of stream.textStream) {
this.panel.webview.postMessage({ type: 'token', text: chunk });
}
this.panel.webview.postMessage({ type: 'done' });
}
});
}
private getWebviewContent(): string {
return `<!DOCTYPE html>
<html>
<head><style>/* styles */</style></head>
<body>
<div id="messages"></div>
<input type="text" id="input" placeholder="Ask a question..." />
<button onclick="sendMessage()">Send</button>
<script>
const vscode = acquireVsCodeApi();
const history = [];
function sendMessage() {
const input = document.getElementById('input');
history.push({ role: 'user', content: input.value });
vscode.postMessage({ type: 'chat', history });
input.value = '';
}
window.addEventListener('message', event => {
const msg = event.data;
if (msg.type === 'token') {
// Append token
}
});
</script>
</body>
</html>`;
}
}
Code Actions Provider
class AICodeActionProvider implements vscode.CodeActionProvider {
provideCodeActions(
document: vscode.TextDocument,
range: vscode.Range,
): vscode.CodeAction[] {
const actions: vscode.CodeAction[] = [];
const selectedText = document.getText(range);
if (!selectedText) return actions;
const explainAction = new vscode.CodeAction('AI: Explain', vscode.CodeActionKind.RefactorRewrite);
explainAction.command = { command: 'aiAssistant.explainCode', title: 'Explain' };
actions.push(explainAction);
return actions;
}
}
Work process
- Analysis — we study your scenarios, select the LLM model.
- Design — we design commands, WebView, providers.
- Development — we write TypeScript code, configure API clients.
- Testing — we test on real projects, measure latency.
- Publishing — we publish to the VS Code Marketplace, set up CI/CD.
Approximate timelines
- Basic commands (explain, refactor): 3–5 days.
- Chat panel with WebView: 1 week.
- Inline completion provider: 1–2 weeks.
- Marketplace publishing: 1–2 days.
Typical mistakes in self-development
- Using
activate()without callingcontext.subscriptions.push()— commands are not registered. - Ignoring
dispose()for WebView — memory leak. - No fallback when API is unavailable — user sees a blank screen.
Contact us to evaluate your project. Order the development of an AI extension that will work specifically for your tasks. Our team's experience: 5 years, we guarantee quality and support for 30 days after publication. Tell us about your project — we'll suggest the optimal extension architecture. For an Anthropic VS Code extension, we configure the SDK accordingly; similarly for a Claude VS Code extension. The Inline Completion VS Code feature is implemented via InlineCompletionItemProvider. Our AI code autocomplete uses low-latency models. This AI-powered code extension is fully customizable.







