VS Code Marketplace
Proxy and cache VS Code extension VSIX downloads from Microsoft's Visual Studio Marketplace via its Gallery API. Use it for extensions only on the Microsoft marketplace and not mirrored on open-vsx.org; it can also host private extensions.
At a glance
| Config type | vscode-marketplace |
| Default upstream | marketplace.visualstudio.com |
| Modes | proxy · local · hybrid |
| Addressing | per-package |
| Private publish | ✅ VSIX upload (PUT …/vsix) |
| Air gap | no composed listing offline: a gallery answers by query |
| Signatures | the registry signs what it hosts ([registries.vsx_signing]), relays the upstream's for what it proxies, and keeps one attached to a republished version |
Proxy setup
Use BatleHub as your extension gallery
Same protocol, same routes as the OpenVSX page — the gallery is the client side, so it does not depend on which upstream sits behind the registry:
{
"extensionsGallery": {
"serviceUrl": "https://batlehub.example.com/proxy/<registry>/vscode/gallery",
"itemUrl": "https://batlehub.example.com/proxy/<registry>/vscode/item",
"resourceUrlTemplate": "https://batlehub.example.com/proxy/<registry>/vscode/unpkg/{publisher}/{name}/{version}/{path}"
}
}The editor sends no credentials to its gallery, so this registry needs anonymous = ["releases:read", "source:read"] under [registries.rbac], or an authenticating ingress. See the warning on the OpenVSX page.
An editor that cannot send a credential
product.json has nowhere to put a token, so a registry that refuses anonymous reads is reached through the local gallery proxy (batlehub-cli proxy serve, RFC 0011 §4.4) rather than by opening the registry up:
# Sign in once, then run the proxy; the editor is pointed at what it prints.
batlehub-cli --server https://batlehub.example.com auth login
batlehub-cli --server https://batlehub.example.com auth write-token-file
batlehub-cli proxy serve --registry https://batlehub.example.com/proxy/<registry>The proxy attaches the credential, rewrites every gallery URL onto itself so the .vsix download is authenticated too, and — while no credential resolves — answers a search with a single Sign in to BatleHub entry instead of the empty view an anonymous gallery produces. Point the editor at the loopback URL it prints, in place of the serviceUrl above.
Download a VSIX directly
Download a VSIX directly by coordinate and install it. Replace <registry> with your configured registry name; use latest as the version to fetch the newest release:
# Pinned version
curl -H "Authorization: Bearer $BATLEHUB_TOKEN" \
"https://batlehub.example.com/proxy/<registry>/ms-python.python/2024.2.1/vsix" \
-o ms-python.python-2024.2.1.vsix
# Or the latest version
curl -H "Authorization: Bearer $BATLEHUB_TOKEN" \
"https://batlehub.example.com/proxy/<registry>/ms-python.python/latest/vsix" \
-o ms-python.python.vsix
code --install-extension ms-python.python-2024.2.1.vsixPublishing (local / hybrid)
The registry must be in local or hybrid mode. A vscode-marketplace registry shares the VSIX upload/download endpoint with OpenVSX; point the PUT …/{publisher}.{name}/{version}/vsix upload at your vscode-marketplace registry name:
curl -X PUT \
-H "Authorization: Bearer $BATLEHUB_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @my-org.my-extension-1.0.0.vsix \
"https://batlehub.example.com/proxy/<registry>/my-org.my-extension/1.0.0/vsix"Signatures
A current editor's Extensions view installs only entries that carry a signature asset. This registry gets one three ways, and the OpenVSX page is where each is explained: the marketplace's own signature is relayed for what is proxied (a stock VS Code verifies it, nothing to set); a key under [registries.vsx_signing] signs what is published here; and a marketplace extension republished here keeps its signature when the archive is attached after the upload:
curl -X PUT -H "Authorization: Bearer $BATLEHUB_TOKEN" -H "Content-Type: application/zip" \
--data-binary @ms-vscode.hexeditor-1.11.1.sigzip \
"https://batlehub.example.com/proxy/<registry>/ms-vscode.hexeditor/1.11.1/vsix/signature"Authentication
Pass a BatleHub token as a Bearer header on the VSIX request. Anonymous access works only when the registry's RBAC grants the anonymous role read access.
Notes
- The direct VSIX route is
…/proxy/<registry>/{publisher}.{name}/{version}/vsix, identical to OpenVSX — the two types share the same handler. - Prefer OpenVSX for extensions that are mirrored on open-vsx.org; use this type only for Microsoft-marketplace-exclusive extensions.
See also
- Using BatleHub — tokens, publishing prerequisites, the CLI
- Registries overview · Caching · Access Control