# How to collect feedback for a VS Code extension

> A VS Code extension collects feedback with a command palette entry. The command asks for a short note in an input box, posts it to the Escuta Produto REST API from the extension host with fetch, and falls back to opening the hosted form in the browser. Add the extension and editor versions as metadata.

Source: https://escutaproduto.com/resources/collect-feedback-vscode-extension
Last updated: 2026-10-11

## Why the extension sends feedback from the extension host

A VS Code extension runs its logic in the extension host, a Node process separate from the editor's window. That process can call the REST API directly, so the extension sends reports with `fetch` and never needs a web view for the form. The widget script is built for web pages, so it does not belong in the editor, and a web view for a single text box is more code than the job needs.

The best entry point is the command palette. Users already open it to run extension commands, so a command named something like "Send feedback to the team" is easy to find without adding a button to the interface. The [REST API reference](/docs/api) lists the body fields, and a successful send returns `201` with the new item `id`.

## Add a feedback command to the command palette

Declare the command in the extension manifest. The title is what users see when they search the palette:

```json
{
  "contributes": {
    "commands": [
      {
        "command": "yourExtension.sendFeedback",
        "title": "Send feedback to the team",
        "category": "Your Extension"
      }
    ]
  }
}
```

Then register the command when the extension activates. Push the disposable onto `context.subscriptions` so VS Code cleans it up when the extension is deactivated.

## Ask for a short note, then send it

Use `vscode.window.showInputBox` to collect a message. It is native to the editor, so it matches the theme and keyboard behavior that users expect. If the user cancels the box, the function returns `undefined` and the command stops without sending anything.

```js
const vscode = require("vscode");

const FORM_URL = "https://escutaproduto.com/f/your-product-slug?lang=en";

function activate(context) {
  const command = vscode.commands.registerCommand("yourExtension.sendFeedback", async () => {
    const message = await vscode.window.showInputBox({
      prompt: "What should the team know? Leave it short, or open the full form.",
      ignoreFocusOut: true,
    });

    if (message === undefined) return;

    if (message.trim().length < 2) {
      await vscode.env.openExternal(vscode.Uri.parse(FORM_URL));
      return;
    }

    const sent = await sendFeedback(context, message.trim());
    if (sent) {
      vscode.window.showInformationMessage("Thanks, your feedback reached the team.");
    } else {
      vscode.window.showWarningMessage("Could not send feedback. The form is open in your browser.");
      await vscode.env.openExternal(vscode.Uri.parse(FORM_URL));
    }
  });

  context.subscriptions.push(command);
}

module.exports = { activate };
```

The fallback matters. If the user is offline or the request fails, the hosted form opens in the browser, where they can write a longer message and try again later. An empty input box also opens the form, so a user who wants more room is never stuck.

## Send the report from the extension host

The `sendFeedback` helper posts the JSON body and reports whether the API returned `201`. It reads the extension version from the manifest and the editor details from the `vscode` namespace:

```js
async function sendFeedback(context, message) {
  const response = await fetch("https://escutaproduto.com/api/v1/feedback", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      key: "pk_your_product_key",
      kind: "other",
      message: message,
      metadata: {
        extensionVersion: context.extension.packageJSON.version,
        vscodeVersion: vscode.version,
        editor: vscode.env.appName,
        platform: process.platform,
      },
    }),
  });

  return response.status === 201;
}
```

Recent VS Code releases run a Node version with `fetch` built in. If your extension supports older editor versions, check which Node runtime it runs under before you rely on the global function, or use a small HTTP library instead.

## Which versions and editor details belong in metadata?

Metadata answers the questions a maintainer asks first. Keep it to a handful of values:

| Key | Source | Why it helps |
| --- | --- | --- |
| extensionVersion | context.extension.packageJSON.version | Shows whether a bug arrived with the last release |
| vscodeVersion | vscode.version | Separates editor regressions from extension bugs |
| editor | vscode.env.appName | Tells VS Code apart from other editors built on it |
| platform | process.platform | Explains problems that appear on one operating system |

The `editor` value matters more than it looks. Several editors are built on the VS Code codebase, and each one can ship a slightly different build. A report that names the editor saves a round of questions. The whole metadata object must stay under 4 KB, which these values never approach.

## How do you keep workspace paths and code out of reports?

An extension sits close to the user's code, so it is easy to send too much. Do not add file paths, file contents, workspace names or environment variables by default. If a bug depends on the active file, ask the user in the message box to describe the file type or the language, rather than sending the path.

The API also accepts a `pageUrl` field. For an editor extension it is usually empty, so leave it out unless you have a clear reason and your privacy notice covers it. Tell users what is sent. A one-line note in the README, such as "reports include your extension and editor versions", is enough for most people.

## Where do reports show up after they are sent?

Escuta Produto sends a Slack or Discord alert for each new item, through the incoming webhook you configure for the product. The alert shows the type, the product, the sender if one was given, an excerpt of up to 500 characters and a link to the dashboard. The [notifications guide](/docs/notifications) explains the webhook setup.

The team then works the inbox with statuses and internal notes. For a small extension team, the simple routine in the [triage guide](/resources/how-to-triage-customer-feedback) fits well. Developer-facing products have their own patterns for errors and docs, which the [developer tools article](/resources/collect-feedback-developer-tools) covers.

## Adding the extension to your Escuta Produto inbox

Create a product for the extension and copy its public key into the code. Install the extension in a development editor, run the palette command and send one report. Confirm that it appears in the inbox with the extension version and the editor name in the metadata. Then check the fallback by disconnecting from the network and running the command again, so you know the browser opens with the form.

For the wider question of when to ask for feedback in a product, the guide on [how to collect customer feedback](/resources/how-to-collect-customer-feedback) gives a good starting point, and the [open-source project article](/resources/collect-feedback-open-source) shows how to point users toward private feedback when a public issue is not the right place.

## Frequently asked questions

### Can a VS Code extension show the feedback widget?

The widget is a script for web pages, so it does not belong in the editor. Use a command palette entry that asks for a short note and posts it to the REST API from the extension host, with the hosted form as a fallback.

### Which VS Code version should the extension report?

Report the editor version from the vscode namespace and the app name from the environment. Several editors are built on VS Code, so the app name tells you which build the user runs, and the version tells you whether an editor update caused a problem.

### Should the extension send the active file name with feedback?

Not by default. File names can reveal private projects. Send them only when the user chooses to include them, and state in your README what the extension sends with every report.
