Utiliser, créer et publier une extension VS Code en TypeScript : commandes, configuration, vues, webviews, diagnostics, tests, bundling et publication sur le Marketplace et Open VSX.
Deux registres comptent. Le Visual Studio Marketplace de Microsoft alimente VS Code. Open VSX, géré par la fondation Eclipse, alimente tous les autres éditeurs bâtis sur le code de VS Code : VSCodium, Cursor, Windsurf, Gitpod, Theia. Ces éditeurs n'ont pas le droit d'utiliser le Marketplace de Microsoft. Publier sur les deux, c'est toucher tout le monde.
Le Marketplace construit la page de l'extension à partir du package.json et du README.md. Les champs à compléter :
{
"name": "todo-radar",
"displayName": "TODO Radar",
"description": "Repère, liste et contrôle les TODO, FIXME et HACK de votre projet.",
"version": "0.1.0",
"publisher": "iducation",
"license": "MIT",
"icon": "media/icon.png",
"repository": {
"type": "git",
"url": "https://github.com/iducation/todo-radar"
},
"bugs": {
"url": "https://github.com/iducation/todo-radar/issues"
},
"categories": ["Linters", "Other"],
"keywords": ["todo", "fixme", "hack", "comments", "tasks"],
"galleryBanner": {
"color": "#1e1e1e",
"theme": "dark"
},
"engines": {
"vscode": "^1.100.0"
}
}Les contraintes que vsce vérifie, et qui bloquent la publication si elles ne sont pas respectées :
| Élément | Contrainte |
|---|---|
icon | PNG d'au moins 128×128 px, jamais de SVG |
| Images du README et du CHANGELOG | URL en https, pas de SVG sauf badges de fournisseurs reconnus |
keywords | 30 au maximum |
name et displayName | Uniques sur tout le Marketplace |
repository | Sans lui, vsce avertit et les liens relatifs du README cassent |
Les liens relatifs du README (./media/demo.gif) sont réécrits vers le dépôt indiqué dans repository. C'est pour ça que ce champ compte.
Le README devient la page du Marketplace. Les extensions qui marchent ont toutes la même structure : une phrase qui dit ce que fait l'extension, une capture animée, la liste des fonctions, les réglages, les commandes. Le GIF de démonstration fait plus pour les installations que tout le texte.
Tenez aussi le CHANGELOG.md : il s'affiche dans un onglet de la page et VS Code le montre après une mise à jour.
Sur le Marketplace, toute extension appartient à un publisher. On le crée une fois :
marketplace.visualstudio.com/manage avec un compte Microsoft ;iducation) : il est définitif et apparaît dans l'identifiant de chaque extension ;L'ID doit correspondre exactement au champ publisher du package.json.
Pour obtenir la coche bleue « éditeur vérifié », on prouve la possession d'un nom de domaine depuis la même page, par un enregistrement DNS TXT. Le domaine doit avoir au moins six mois et l'éditeur avoir publié depuis au moins six mois.
vsce publie avec un jeton d'Azure DevOps. Historiquement, on créait un Personal Access Token avec la portée Marketplace → Manage, valable pour All accessible organizations. Ce type de jeton, dit « global », est retiré le 1er décembre 2026. Après cette date, Microsoft demande de publier avec une identité Microsoft Entra ID.
Concrètement, selon votre situation :
| Situation | Méthode |
|---|---|
| Publication manuelle, avant le 1er décembre 2026 | PAT global, comme ci-dessous |
| Publication automatisée, durable | Identité Entra ID et vsce publish --azure-credential |
| Pas d'accès Azure du tout | Téléversement manuel du .vsix sur la page de gestion du publisher |
La méthode historique, pour comprendre et pour dépanner :
dev.azure.com, créer une organisation si vous n'en avez pas ;npm install -g @vscode/vsce
vsce login iducationvsce demande le jeton et le mémorise.
La méthode Entra ID repose sur DefaultAzureCredential : vsce publish --azure-credential utilise l'identité Azure déjà connectée dans l'environnement (Azure CLI, identité managée, identité fédérée de CI). On ajoute cette identité comme membre du publisher, rôle Contributor, sur la page de gestion. La documentation officielle Publishing Extensions détaille la mise en place avec une identité managée ; c'est un investissement d'une heure, à faire une fois.
.vsixAvant de publier, on fabrique le paquet et on l'installe soi-même :
vsce packageExecuting prepublish script 'npm run vscode:prepublish'...
DONE Packaged: /home/william/todo-radar/todo-radar-0.1.0.vsix (9 files, 41.2 KB)Le script vscode:prepublish lance automatiquement le build de production. Un .vsix est une archive ZIP : vous pouvez l'ouvrir pour vérifier son contenu.
code --install-extension todo-radar-0.1.0.vsixTestez dans votre VS Code habituel, pas dans la fenêtre de développement : c'est là que se révèlent les fichiers oubliés par .vscodeignore et les dépendances non bundlées. Le .vsix sert aussi à distribuer une extension interne en entreprise sans passer par un registre public.
vsce publishOu en incrémentant la version au passage, selon le versionnement sémantique :
vsce publish patch # 0.1.0 → 0.1.1, correctif
vsce publish minor # 0.1.0 → 0.2.0, nouvelle fonction
vsce publish major # 0.1.0 → 1.0.0, changement incompatibleDans un dépôt Git, ces commandes modifient package.json, créent un commit et un tag. La page apparaît sur le Marketplace en quelques minutes, après une analyse automatique de sécurité.
Pour faire tester une fonction à des volontaires sans toucher tout le monde :
vsce publish --pre-releaseLes utilisateurs choisissent Switch to Pre-Release Version sur la page de l'extension. Deux contraintes : les versions doivent rester au format major.minor.patch (pas de -beta.1), et une version publiée en préversion ne peut pas être republiée en version stable. La convention répandue : numéros mineurs impairs pour les préversions (0.3.x), pairs pour les versions stables (0.4.x).
Une extension qui embarque un binaire natif publie une variante par système :
vsce package --target win32-x64
vsce package --target darwin-arm64
vsce publish --packagePath todo-radar-win32-x64-0.1.0.vsix todo-radar-darwin-arm64-0.1.0.vsixVS Code installe automatiquement la variante adaptée. TODO Radar, en pur JavaScript, n'en a pas besoin.
Depuis la page de gestion, Unpublish masque l'extension en conservant ses statistiques ; c'est réversible. Remove la supprime définitivement, et son nom reste réservé pour toujours. Réfléchissez avant le second.
La procédure, une seule fois :
publisher du manifeste.npx ovsx create-namespace iducation -p <jeton>Ensuite, à chaque version, on publie le même .vsix que pour le Marketplace :
npx ovsx publish todo-radar-0.1.0.vsix -p <jeton>Open VSX analyse aussi chaque paquet : secrets oubliés dans le code, fichiers connus comme malveillants, noms trop proches d'une extension existante. Un faux positif sur un secret se neutralise avec un commentaire // secret-detector:ignore sur la ligne concernée.
Créer un namespace ne le rend pas « vérifié ». Pour obtenir le badge, on en revendique la propriété par une issue sur le dépôt EclipseFdn/open-vsx.org.
Publier à la main finit toujours par un oubli : un test non lancé, un registre oublié. Le flux qu'on vise : un tag v0.2.0 poussé sur GitHub déclenche tests, empaquetage et publication sur les deux registres. Les bases des workflows sont expliquées dans l'article sur GitHub Actions et la CI/CD.
name: Release
on:
push:
tags: ['v*']
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run test:unit
- run: xvfb-run -a npm test
- name: Empaqueter
run: npx @vscode/vsce package -o todo-radar.vsix
- name: Publier sur le Marketplace
run: npx @vscode/vsce publish --packagePath todo-radar.vsix
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
- name: Publier sur Open VSX
run: npx ovsx publish todo-radar.vsix
env:
OVSX_PAT: ${{ secrets.OVSX_PAT }}
- uses: softprops/action-gh-release@v2
with:
files: todo-radar.vsixPoints à noter :
vsce et ovsx lisent automatiquement les variables VSCE_PAT et OVSX_PAT, pas besoin de -p ;.vsix est attaché à la release GitHub pour ceux qui installent hors registre ;xvfb-run fournit l'écran virtuel dont les tests d'intégration ont besoin sous Linux.Le workflow ne bump pas la version : on met à jour package.json et le CHANGELOG.md, on commite, puis on pousse le tag.
npm version minor -m "release: %s"
git push --follow-tagsAvec le retrait des PAT globaux, l'étape Marketplace devra passer à Entra ID : on remplace le secret par une connexion azure/login avec identité fédérée, puis vsce publish --azure-credential. Le reste du workflow ne change pas.
Le travail ne s'arrête pas au premier envoi. Le tableau de bord du publisher affiche installations, désinstallations et notes. Les issues GitHub sont le canal de retour principal : une extension sans réponse aux issues perd vite ses utilisateurs.
Gardez un œil sur engines.vscode. Remonter la version minimale donne accès à de nouvelles API, mais chaque relèvement exclut des utilisateurs. Et testez régulièrement contre la version Insiders (version: 'insiders' dans .vscode-test.mjs) pour découvrir les régressions avant vos utilisateurs.
TODO Radar est passée d'une commande « Hello World » à une extension publiée, testée et livrée automatiquement. Les mêmes briques servent à construire n'importe quel outil : un client pour votre API interne, un validateur de fichiers de configuration, un assistant connecté à votre ticketing. Le plus dur n'est pas l'API, c'est de choisir ce qui mérite d'être automatisé dans l'éditeur. Commencez par ce qui vous agace tous les jours.