typefox/vscode-messenger/vscode-messenger
Claude Code and agent skill by typefox/vscode-messenger
- community
Checking that the SKILL.md file is still in the repository.
Implement and debug RPC messaging between a VS Code extension and its webviews using the `vscode-messenger` library. Use when wiring up extension–webview (or webview–webview) communication, defining `NotificationType` / `RequestType` message contracts, calling `sendRequest` / `sendNotification` / `onRequest` / `onNotification`, registering webviews with `Messenger`, sending to `HOST_EXTENSION` or `BROADCAST` participants, debugging why messages don't arrive, or setting up the `vscode-messenger-devtools` extension via `Messenger.diagnosticApi()`.
Install
npx vskill@latest install typefox/vscode-messenger/vscode-messengerSKILL.md
VS Code Messenger
vscode-messenger is a typed RPC library for communication between a VS Code extension host and its webviews (WebviewView and WebviewPanel). It supports request/response, notifications, broadcasts, cancellation, and sender-scoped handlers.
This skill assumes the agent is implementing or debugging messaging code on top of this library — not contributing to the library itself.
Packages
Three npm packages, one per execution context. Install only what each side needs:
| Package | Used in | Purpose | |
|---|---|---|---|
vscode-messenger | Extension host | Messenger class, view registration, diagnostics | |
vscode-messenger-webview | Webview script | Messenger class for webview side, createCancellationToken | |
vscode-messenger-common | Both (or shared module) | NotificationType, RequestType, MessageParticipant, HOST_EXTENSION, BROADCAST |
Recommendation: keep all NotificationType / RequestType declarations in a shared TypeScript module that both the extension and the webview import from. The same method string and parameter/result types must line up on both ends, and a shared module is the simplest way to enforce that.
Defining message types
NotificationType<P> and RequestType<P, R> are pure type tags — at runtime they are just { method: string }. The generics ensure that sendRequest / onRequest and their notification counterparts type-check on both sides.
Extension side
Key APIs:
new Messenger(options?)—MessengerOptions:ignoreHiddenViews(defaulttrue),uniqueHandlers(throws if a handler for the same method is registered twice — incompatible with sender-scoped handlers; see that section below),debugLog.registerWebviewView(view, options?)/registerWebviewPanel(panel, options?)— returns aWebviewIdMessageParticipantwith the assignedwebviewId. Use this returned participant to address that specific instance (vs. thewebviewTypestring which addresses all instances of that type). The library auto-unregisters ononDidDispose.onRequest(type, handler, { sender? })/onNotification(type, handler, { sender? })— return aDisposable. Both sides: for notifications, multiple handlers for the same method stack and all fire. For requests, only one handler per method is allowed — a second registration for an overlapping scope throws synchronously at registration time (webview: any second request handler for the method; extension: a second handler whosesenderscope overlaps). On the extension side, use non-overlappingsender-scoped handlers if you need per-webview request logic for the same method (see below). Disposing a handler removes only that specific registration. The optionalsender(extension side only) filters the handler so it only fires for messages from that participant.sendRequest(type, receiver, params?, cancelable?)— returnsPromise<R>. Receiver is aMessageParticipant(webview by id, webview by type, or — once supported — another extension). Cannot beBROADCAST— throws immediately on both sides.sendNotification(type, receiver, params?)— fire-and-forget. Receiver may beBROADCAST.
ViewOptions.broadcastMethods: string[] — set per registered view to opt that view in to specific broadcast notification methods. A broadcast skips any view that doesn't list the method.
Webview side
The webview-side Messenger constructor calls acquireVsCodeApi() for you. Pass an existing instance only if your code already called acquireVsCodeApi() (it can be called only once per webview):
React webviews (Vite + StrictMode)
When the webview UI is a React app, create the Messenger once outside the component tree, and register handlers inside a useEffect that disposes them on cleanup. This is required because React StrictMode (dev) mounts every component twice (setup → cleanup → setup), and Vite HMR re-runs effects on every edit. Registering a request handler without disposing the previous one throws on the second run (A request handler is already registered for method ...); a notification handler without cleanup fires twice.
Key rules for React:
- One `Messenger` per webview, at module scope — never
new Messenger()inside a component body (acquireVsCodeApi()may be called only once, and a new instance per render leaks listeners). - Register in `useEffect`, dispose in its cleanup — the returned cleanup disposes each
Disposable, so the StrictMode double-invoke and HMR re-runs stay balanced. - `start()` is idempotent — calling it again after a remount is a no-op (
if (this.started) return). - Avoid registering in the component body or in a `useMemo` — those run on every render and will throw on the second request-handler registration.
Core patterns
Request / response
Either side can sendRequest; the other side handles it with onRequest. Errors thrown by the handler are surfaced as a rejected promise on the sender side with a ResponseError { message, data? }.
Notification
Fire-and-forget. Use onNotification to handle, sendNotification to send. No response, no awaiting.
Broadcast (notifications only)
Sending a request to BROADCAST throws immediately on both sides. Broadcast is for notifications only.
Cancellation
Extension side accepts a vscode.CancellationToken (or any CancellationToken-shaped object) directly:
Webview side bridges AbortSignal:
In the handler, the third argument is the CancellationToken:
Sender-scoped handlers (extension side only)
onRequest / onNotification accept { sender: MessageParticipant }. The handler only fires when the message's sender matches. Use this to handle the same method differently per-webview, e.g. when two webviews share a method but should be served by different logic.
Important: Sender-scoped handlers require registering multiple handlers for the same method. This is only possible when uniqueHandlers is unset or false (the default). Do not set uniqueHandlers: true if you intend to use sender-scoped handlers — it throws on any duplicate method registration, even with different senders.
Targeting specific webview instances
registerWebviewView / registerWebviewPanel return a WebviewIdMessageParticipant. Save it to address that one instance:
If you address by webviewType instead and multiple instances of that type are registered, sendRequest behaves as follows:
- The request is sent to all registered instances of that type.
Promise.raceis used — the first response wins, others are discarded.- With
ignoreHiddenViews: true(the default): hidden instances immediately reject, and that rejection participates in the race; if at least one visible instance responds successfully, its result is returned; if all instances are hidden, the request rejects. - To avoid this behavior entirely, address by
webviewIdinstead ofwebviewType.
sendNotification is sent to all instances of that type (hidden ones are silently skipped when ignoreHiddenViews is true).
Common gotchas
Setup prerequisites (must be correct before any message works)
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryChecking.github/skills/vscode-messenger/SKILL.md
Popularity
- Repository stars
- 61
- Repository forks
- 9
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/typefox/vscode-messenger/vscode-messenger)