RPC messaging library for the VS Code extension platform. Makes the communication between your VS Code extension and its webviews much simpler.
npm CI License Codespaces Copilot Skill
- Send notifications or requests from an extension to a view, a view group, or broadcast to all registered views
- Send notifications or requests from a view to another view, a view group, or the host extension
- Typed API —
RequestType<P, R>andNotificationType<P>enforce matching parameter and result types on both sides - Sync and async request/notification handlers
- Request cancellation
- Automatically unregisters views on dispose
- Configurable logging
Install only what each side needs:
| Package | Install in | Purpose |
|---|---|---|
vscode-messenger |
Extension host | Messenger class, view registration, diagnostic API |
vscode-messenger-webview |
Webview script | Messenger class for webview, createCancellationToken |
vscode-messenger-common |
Shared module | NotificationType, RequestType, HOST_EXTENSION, BROADCAST |
Tip: Keep all NotificationType / RequestType declarations in a shared TypeScript module imported by both the extension and the webview. The same method string and parameter/result types must match on both ends.
import * as vscode from 'vscode'; import { Messenger } from 'vscode-messenger'; import { NotificationType, RequestType } from 'vscode-messenger-common'; const messenger = new Messenger(); // Register a webview view (or use registerWebviewPanel for WebviewPanel) messenger.registerWebviewView(webviewView); // Define message types — declare once, import on both sides const colorSelectType: NotificationType<string> = { method: 'colorSelected' }; const availableColorsType: RequestType<string, string[]> = { method: 'availableColor' }; const colorModifyType: NotificationType<string> = { method: 'colorModify' }; // Handle a notification from the webview messenger.onNotification(colorSelectType, (color: string) => { vscode.window.activeTextEditor?.insertSnippet(new vscode.SnippetString(`#${color}`)); }); // Handle a request from the webview and return a result messenger.onRequest(availableColorsType, (_params: string) => { return ['020202', 'f1eeee', 'a85b20', 'daab70', 'efcb99']; }); // Send a notification to all views of a given type messenger.sendNotification(colorModifyType, { type: 'webview', webviewType: 'calicoColors.colorsView' }, 'clear'); // Send a request to a view and await the result const selectedColor = await messenger.sendRequest( { method: 'getSelectedColor' }, { type: 'webview', webviewType: 'calicoColors.colorsView' }, '' );
import { Messenger } from 'vscode-messenger-webview'; import { HOST_EXTENSION } from 'vscode-messenger-common'; import { colorModifyType, availableColorsType, colorSelectType } from './shared/message-types'; const messenger = new Messenger(); // acquireVsCodeApi() is called automatically // Handle notifications from the extension messenger.onNotification(colorModifyType, (action: string) => { if (action === 'clear') clearColors(); if (action === 'add') addColor(); }); messenger.start(); // required — starts listening for incoming messages // Send a request to the host extension const colors = await messenger.sendRequest(availableColorsType, HOST_EXTENSION, ''); // Send a notification to the host extension messenger.sendNotification(colorSelectType, HOST_EXTENSION, 'a85b20');
Note:
messenger.start()must be called before any messages can be received. Forgetting it causes all incoming messages to be silently dropped.
| Participant | How to construct | Use for |
|---|---|---|
| Host extension | HOST_EXTENSION |
Targeting the extension from a webview |
| Webview by type | { type: 'webview', webviewType: '...' } |
All instances of a view type |
| Webview by id | returned by registerWebviewView / registerWebviewPanel |
One specific instance |
| Broadcast | BROADCAST |
All registered views (notifications only) |
// Extension side — pass any CancellationToken const cts = new vscode.CancellationTokenSource(); const result = await messenger.sendRequest(longOpType, target, params, cts.token); cts.cancel(); // Webview side — bridge an AbortSignal import { createCancellationToken } from 'vscode-messenger-webview'; const ctrl = new AbortController(); const result = await messenger.sendRequest(longOpType, HOST_EXTENSION, params, createCancellationToken(ctrl.signal)); ctrl.abort('timeout');
A webview receives a broadcast only when registered with broadcastMethods listing the method:
// Extension: opt the view in to specific broadcast methods messenger.registerWebviewView(view, { broadcastMethods: [refreshType.method] }); // Either side: broadcast to all opted-in views messenger.sendNotification(refreshType, BROADCAST);
Visual Studio Marketplace Version
The companion VS Code Messenger Developer Tool extension visualizes live message traffic — requests, responses, and notifications — between the extension host and its webviews. To enable it, expose messenger.diagnosticApi() from your extension's activate return value:
import { Messenger, type MessengerDiagnostic } from 'vscode-messenger'; const messenger = new Messenger(); export function activate(context: vscode.ExtensionContext): MessengerDiagnostic { // ... register views, handlers, etc. return messenger.diagnosticApi(); }
Open the devtool with Developer: Open vscode-messenger devtools from the Command Palette.
See the devtools README for full setup instructions, DiagnosticOptions, the event schema, and troubleshooting.
The calico-colors example demonstrates a complete extension with a WebviewView and a WebviewPanel sharing a single Messenger instance, typed message definitions in a shared module, broadcast usage, and diagnostic API integration.
This repository includes an Agent skill that teaches Agents how to implement and debug messaging with vscode-messenger. When the skill is active, the agnet understands the library's patterns — message type definitions, handler registration, start() requirements, broadcast opt-in, cancellation, and devtools setup — and can generate correct code without you having to explain the API.