# Vscode Extension

> Build, package, and PUBLISH a VS Code extension (a TypeScript extension under integrations/<name>/, VS Code Extension API) to BOTH the Visual Studio Marketplace (vsce) and Open VSX (ovsx, which feeds Cursor / Windsurf / VSCodium / Gitpod). Use when creating a VS Code extension, packaging a .vsix, or shipping one to either marketplace. Covers the whole path plus the traps that each cost a round-trip: vsce/ovsx and their esbuild-based packaging SEGFAULT on Node 22+/25 (use Node 20); vsce REJECTS SVG images in README.md (use PNG or remove them); the VS Code Marketplace publisher is created via a browser form that is hostile to automation (create it by hand) and needs an Azure DevOps PAT; Open VSX is the easier, GitHub-login path (`ovsx create-namespace` + `ovsx publish -p <token>`) and reaches the arguably-better Cursor/Windsurf audience. Sibling of the other integration skills (raycast-extension, browser-extension). Triggers: 'build a VS Code extension', 'publish to the VS Code Marketplace', 'vsce package/publi

- Skill: `pooriaarab/vscode-extension` (Agent Skill)
- Install (CLI): `npx skillmds@latest add pooriaarab/vscode-extension`
- Raw SKILL.md: https://api.skillmd.com/api/skills/pooriaarab/vscode-extension/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: pooriaarab (https://skillmd.com/u/pooriaarab)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/pooriaarab/vscode-extension

---


# Building + publishing a VS Code extension

A VS Code extension is a TypeScript module on the **Extension API** (`package.json` manifest with `contributes`, `activationEvents`, `main`). Source in `integrations/<name>/`. Publish to two marketplaces from one `.vsix`: the **Visual Studio Marketplace** (`vsce`) and **Open VSX** (`ovsx` — what Cursor / Windsurf / VSCodium / Gitpod install from). Command playbook: `pooriaarab/scripts` `scripts/vscode-extension/README.md`.

## The trap that segfaults packaging: Node version

`vsce package` / `vsce publish` / `ovsx publish` run an esbuild-based bundler that **segfaults on Node 22 and 25** (exit 139, no useful error). **Use Node 20 LTS** (`/opt/homebrew/opt/node@20/bin` on PATH, or `nvm use 20`). Same class of failure as several other CLIs — if packaging dies silently, check Node first.

## The other traps

1. **vsce rejects SVG in README.md.** `vsce package` errors "SVGs are restricted in README.md" if the README embeds any `.svg` image. Use PNG, or remove the image. It also warns on a missing `repository`/`license` — add both to `package.json` to keep the listing clean.
2. **`package.json` needs `publisher`.** The `publisher` field = the Marketplace publisher id / the Open VSX namespace. Set it before packaging.
3. **The VS Code Marketplace publisher form fights automation.** Creating a publisher at `marketplace.visualstudio.com/manage/createpublisher` is a React form whose Create button doesn't reliably submit via browser automation (coordinate scaling + trusted-event issues), and it needs a Microsoft-account login + an **Azure DevOps PAT** (scope: Marketplace → Manage) for `vsce publish -p <PAT>`. **Create the publisher + PAT by hand** — it's a 5-minute human step, not worth automating.
4. **Open VSX is the easy path.** GitHub login at `open-vsx.org`, sign the one-time **Eclipse Publisher Agreement**, mint an access token — then it's fully headless.

## Build + package

```
export PATH="/opt/homebrew/opt/node@20/bin:$PATH"   # Node 20
npm install && npm run compile
npx @vscode/vsce package                             # -> <name>-<version>.vsix
```

## Publish

**Open VSX (headless, do this one first):**
```
npx ovsx create-namespace <publisher> -p <OVSX_TOKEN>   # once
npx ovsx publish <name>-<version>.vsix -p <OVSX_TOKEN>   # -> live for Cursor/Windsurf/VSCodium/Gitpod
```

**VS Code Marketplace (after the human publisher + PAT exist):**
```
npx @vscode/vsce publish -p <AZURE_DEVOPS_PAT>
```

Store the tokens in the product `.env.local` (`OVSX_TOKEN`, `VSCE_PAT`), never commit.

## Related skills
- `raycast-extension` — the other dev-tool command surface (needs store screenshots, unlike this).
- `marketplace-app-hosting` — extensions don't need hosting; they're published bundles.

