All skills
aktsmm avatar

/vscode-extension-guide

@7ae9078
by yamapanaktsmm/agent-skills26 stars
4

Guide for creating VS Code extensions and plugins from scratch through Marketplace publication. Use when developing a VS Code extension/plugin, adding commands or keybindings, building TreeView or Webview UI, publishing to Marketplace, or troubleshooting activation and packaging issues.

Use this Skill: https://skilld.dev/gh/aktsmm/agent-skills/vscode-extension-guide

This session only. Nothing lands on disk.

referencespublishing.md

≈8.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Publishing to Marketplace

Complete guide for publishing your VS Code extension.

Prerequisites

  1. Publisher account at marketplace.visualstudio.com/manage
  2. Personal Access Token (PAT) from Azure DevOps
  3. vsce CLI installed: npm install -g @vscode/vsce

Creating a Publisher

  1. Go to marketplace.visualstudio.com/manage
  2. Sign in with Microsoft account
  3. Click "Create publisher"
  4. Fill in:
    • ID: Unique identifier (used in extension ID)
    • Name: Display name
    • Description: Optional

Getting Personal Access Token (PAT)

  1. Go to dev.azure.com
  2. Sign in → User Settings (top right) → Personal access tokens
  3. Click New Token
  4. Configure:
  • Name: "VS Code Marketplace" (or any descriptive name)
  • Organization: All accessible organizations ← Critical!
  • Expiration: Pick a real future date such as 1 year. The Custom defined field defaults to today's date in some Azure DevOps UIs, so a token issued without changing it is valid only for the current day — vsce verify-pat passes the same day, but vsce publish fails with Access Denied: The Personal Access Token used has expired. the moment the day rolls over.
  • Scopes: Click Show all scopes if Marketplace is hidden, then under Marketplace check Manage (preferred — Publish alone may be rejected by some publish API paths even when verify-pat succeeds)
  1. Click Create and copy token immediately (shown only once)

Before publishing, verify the token against the manifest's publisher from the same terminal session that will run vsce:

npx --yes vsce verify-pat <publisher-id> -p "$env:VSCE_PAT"

If verify-pat fails but VSCE_PAT exists in the User environment, reload it into the current process before retrying:

$env:VSCE_PAT = [System.Environment]::GetEnvironmentVariable("VSCE_PAT", "User")
npx --yes vsce verify-pat -p "$env:VSCE_PAT"

If you control the repository workflow, prefer a wrapper script over repeating manual environment-variable recovery steps. A small PowerShell wrapper can validate the current Process VSCE_PAT first, automatically fall back to the User-scoped VSCE_PAT when VS Code is still holding an expired process value, and then forward vsce verify-pat, vsce show, or vsce publish with the resolved token. This avoids the common failure mode where the User environment is correct but VS Code child processes still inherit a stale token from the older process environment.

Publisher authorization failure is not proof that the token expired. Verify permissions for the intended publisher; switching to another authorized publisher changes the extension ID and requires approval. Then synchronize manifest, activation-test IDs and listing links.

In CI, a nonempty secret is not proof of a valid PAT. Verify publisher authorization using the job's secret without printing it. Local Process/User environment values and repository/environment secrets are separate stores: a local refresh does not repair CI. A publish=false build validates no credentials unless it explicitly runs that read-only check. On authentication failure, retain the artifact and commit/tag identity; report publication and downstream GitHub Release as blocked and request owner-side secret repair, never the token in chat.

Login and Publish

# Login (first time or when token expires)
npx @vscode/vsce login <publisher-id>
# Paste PAT when prompted

# Verify login
npx @vscode/vsce ls-publishers

# Verify the PAT used by this terminal before publish
npx --yes vsce verify-pat -p "$env:VSCE_PAT"

# Publish new version
npx @vscode/vsce publish

# Publish an already-built VSIX (prevents packaging the wrong artifact)
npx @vscode/vsce publish -i ./my-extension-1.0.0.vsix

# Resume an explicitly requested publish idempotently, not as a read-only check
npx @vscode/vsce publish -i ./my-extension-1.0.0.vsix --skip-duplicate

# Publish with version bump
npx @vscode/vsce publish minor  # 0.1.0 → 0.2.0
npx @vscode/vsce publish patch  # 0.1.0 → 0.1.1

vsce option names vary by version. For an existing VSIX, prefer the documented -i input option. If syntax must be checked, run help only in a process without VSCE_PAT; the help output itself can disclose the effective token, including to private tool logs.

Pre-publish Checklist

Item Check
publisher in package.json Matches your publisher ID
version Incremented from previous
README.md Exists (lowercase!) and has content
LICENSE Included
icon 128x128 PNG, path in package.json
.vscodeignore Excludes unnecessary files

package.json Requirements

{
  "name": "my-extension",
  "displayName": "My Extension",
  "description": "Brief description for Marketplace",
  "version": "1.0.0",
  "publisher": "your-publisher-id",
  "icon": "images/icon.png",
  "repository": {
    "type": "git",
    "url": "https://github.com/user/repo"
  },
  "categories": ["Other"],
  "keywords": ["keyword1", "keyword2"]
}

Valid Categories

Programming Languages, Snippets, Linters, Themes, Debuggers,
Formatters, Keymaps, SCM Providers, Other, Extension Packs,
Language Packs, Data Science, Machine Learning, Visualization,
Notebooks, Education, Testing, AI, Chat

Version Constraints

  • ✅ Valid: 1.0.0, 1.2.3, 0.0.1
  • ❌ Invalid: 1.0.0-beta.1, 1.0.0-rc1 (prerelease tags rejected)
  • Use GitHub Releases for beta distribution instead

Inspect Package Before Publishing

# List files that will be included
npx @vscode/vsce ls

# Create VSIX without publishing (for inspection)
mkdir -p artifacts/vsix
npx @vscode/vsce package --out artifacts/vsix/my-extension-1.0.0.vsix

Use the repository's release hygiene test for payload safety. Besides checking paths, compare packaged runtime, Webview JS/CSS, locales and icons with the same release build. Compare runtime manifest fields structurally, including publisher, version, engines, entry point, localization, contributions and opt-ins. Negative tests must reject same-name stale assets and wrong engine requirements; file lists alone prove neither content identity nor installability.

On a byte mismatch, report paths without dumping payloads. Normalize line endings only to diagnose formatter/checkout differences, never to waive the release gate. Build a clean checkout of the CI commit with the same locked toolchain and rerun strict comparison. If it passes, keep the original verified CI artifact; otherwise resolve the content drift before publication. Remove only the temporary checkout you created, preserving the user's working tree.

If a release test asserts the extension version inside docs or spec files (README, CHANGELOG, a FULL_SPECIFICATION-style file), bump every one of them together with package.json. A single doc lagging the package version fails the release gate even when the build itself is correct, so update the version in all asserted files before tagging.

Local Preview Packages

An unpublished local VSIX often has no repository URL or license file yet. If its README uses relative links (for example, a language switch or local image), vsce can reject packaging because it cannot rewrite those links. For a local-only preview:

New-Item -ItemType Directory -Force artifacts/vsix | Out-Null
npx --yes @vscode/vsce package `
  --allow-missing-repository `
  --skip-license `
  --no-rewrite-relative-links `
  --out artifacts/vsix/my-extension-0.0.1.vsix

Use the exact options reported by the pinned vsce package --help; do not guess similar names. --no-rewrite-relative-links is safe only when every relative target is included in the VSIX. Inspect the archive and verify the README language target and each relative image exist at those exact paths; an image excluded by .vscodeignore cannot fall back to GitHub in a local preview.

Do not add Marketplace/version/install badges that imply publication before the extension exists there. Local previews can use factual static badges such as Local Preview, the declared minimum VS Code version, local-only privacy, and available languages. Once published, replace these with real Marketplace and repository links.

Packaging Runner Gotchas

  • If packaging rejects versions that already have a release tag, keep its tests independent of the repository's current release state. Test the untagged-success path in a temporary Git work tree, and test tagged-version rejection separately. A test that expects the manifest's current version to be untagged passes before release and fails immediately after the tag is created.
  • Create the parent directory passed to --out before invoking vsce; the CLI can enumerate a valid package and still fail at the final write with ENOENT.
  • On Windows, spawning npx.cmd directly from Node can fail with EINVAL. In an npm-managed project, invoke process.env.npm_execpath through process.execPath and use npm exec --package=@vscode/vsce@<version-from-one-project-constant> -- vsce ...; validate npm_execpath exists and is npm's CLI before spawning. For pnpm/yarn projects, use that manager's native exec command instead of forcing npm.
  • Treat the VSIX file as the completion source of truth. A quiet or truncated terminal is not success; confirm the artifact exists, has a fresh timestamp, and has a plausible size before moving to publish.
  • If vsce package appears to hang inside a shared VS Code terminal during vscode:prepublish, check for active node processes and the expected artifact before retrying. Do not stack repeated npx vsce package attempts against the same output path.
  • When terminal capture is unreliable, redirect package output to a log file or run the package command as a dedicated VS Code task, then remove any temporary task entries before committing.
  • If prepublish already passed separately, still let vsce package run its configured prepublish unless the local vsce package --help explicitly documents a supported skip flag. Unsupported flags such as guessed --no-prepublish are a sign to check local help rather than continue by trial and error.
  • Prefer npx vsce package --out <file> over ambiguous npm exec -- vsce package --out <file> forms. If vsce reports Invalid version <path>, the package path was parsed as a version argument; switch runner syntax rather than changing the version.
  • Run git status --short after packaging and vsce ls, not only before committing. Repository prepublish scripts can regenerate tracked metadata or JSON formatting; if that happens after the release commit/tag, either commit the mutation before packaging or restore and rebuild the VSIX so the artifact matches the tagged commit.
  • Use gh run watch only to wait, with temporary log capture when needed. Before publication, require the Actions API to report completed/success, the expected commit SHA and successful mandatory audit/test/package steps; quiet output or a watcher exit alone is not proof. If local audits are unavailable, push the candidate commit and run authorized validation-only CI before creating a publication-triggering tag. Tag only the validated SHA and separately verify publication and public package identity.
  • After dependency changes, require a nonempty lockfile with public resolved URLs and integrity, then prove clean npm ci and full audit pass. On managed devices that block direct public registries, use the approved quarantine proxy; never force a blocked --registry or weaken TLS. If a trusted mirror writes its own host into resolved, change only that URL while preserving version and integrity, then test the published lockfile through the proxy. If this cannot be verified locally, use an authorized hosted CI workflow to generate and verify the lockfile; obtain approval if repository policy excludes workflows. Tag and publish only the validated commit and VSIX, without bypassing the quarantine.
  • Failed npm ci can leave local dependencies incomplete. If offline restore lacks a locked tarball, export that exact public-registry tarball from the verified CI run separately from the VSIX, match its bytes to the lockfile integrity, then use npm cache add <tarball> --offline and npm ci --offline with the approved registry configuration. Verify local compilation and remove recovery copies. For artifacts under dot-directories, set include-hidden-files: true only with a narrowly allowlisted upload path and if-no-files-found: error; never enable broad hidden-directory uploads that could expose credentials.
  • Prefer an exact archive allowlist for small extensions, not only forbidden-pattern checks, and run it automatically after every package. Verify extension/package.json, compiled entry points, locale bundles, icon, license, and every linked README are present while src/, tests, sourcemaps, debug logs, private storage snapshots, and generator scripts are absent. Account for vsce normalizing README.md to readme.md and extension LICENSE to LICENSE.txt; pin the observed archive names.
const expected = new Set([
  "extension/package.json",
  "extension/out/extension.js",
]);
const actual = new Set(zipEntries);
const missing = [...expected].filter((name) => !actual.has(name));
const unexpected = [...actual].filter((name) => !expected.has(name));
if (missing.length || unexpected.length) {
  throw new Error(
    `VSIX payload mismatch: missing=${missing}; unexpected=${unexpected}`,
  );
}

Build the full expected set from the extension's actual runtime contract (manifest-derived entrypoint plus intentionally packaged assets); do not weaken the comparison to a size check or forbidden glob alone.

Isolated Install Gate

Do not treat a development-host launch as proof that the VSIX installs. After exact payload verification, install the same artifact into an isolated test profile and list extensions with versions:

await runVSCodeCommand(["--install-extension", vsix, "--force"], {
  version: minimumVscodeVersion,
  cachePath: testCache,
  reuseMachineInstall: false,
});
const { stdout } = await runVSCodeCommand(
  ["--list-extensions", "--show-versions"],
  {
    version: minimumVscodeVersion,
    cachePath: testCache,
    reuseMachineInstall: false,
  },
);

Require the exact lowercase <publisher>.<name>@<version> line. A strong local release gate is: dependency audit → unit/Extension Host tests → package → exact ZIP verification → isolated install → behavior-scoped live smoke for changed external integrations. The live smoke must use that same VSIX in disposable user-data/extensions roots and observe the real result; a resolved command or dispatch status is insufficient when the contract requires a downstream response. Derive the VSIX filename from manifest name/version so version bumps cannot leave scripts or docs pointing to a stale artifact.

runVSCodeCommand adds isolated --user-data-dir and --extensions-dir arguments when reuseMachineInstall is false (the default). Resolve cachePath from a repository-owned disposable test root, not user input. If you bypass that helper and invoke the CLI yourself, provide both directories explicitly under that root before using --install-extension.

Post-publish Verification

  • Apply the Release Completion Contract below; use read-only checks, never another publish command to prove existence.
  • If an artifact audit is required, use https://marketplace.visualstudio.com/_apis/public/gallery/publishers/<publisher>/vsextensions/<extension>/<version>/vspackage. A 405 from HEAD is inconclusive; download via GET directly to a temporary file and inspect the actual ZIP.
  • Compare size and SHA256 with the local VSIX or GitHub Release asset when exact-byte provenance was required before publication. Otherwise treat additional downloads as follow-up audit, not a new completion gate.
  • If a pushed release tag fails CI before publication, keep the failed tag as provenance. Fix the issue, bump to a new patch version, synchronize package/lock/changelog/spec files, and publish a new tag; do not move or reuse the pushed tag.

Local VSIX Artifact Hygiene

Store generated .vsix files under artifacts/vsix/ rather than the repository root. This keeps the root readable, makes cleanup scriptable, and reduces the chance of attaching or inspecting the wrong local file.

New-Item -ItemType Directory -Force artifacts/vsix | Out-Null
npx @vscode/vsce package --out artifacts/vsix/my-extension-1.0.0.vsix
npx @vscode/vsce publish -i ./artifacts/vsix/my-extension-1.0.0.vsix

When you keep historical local builds, set a retention rule and prune old archives automatically. Keeping only the latest 10 local VSIX files is usually enough for rollback and spot-checking.

$vsixDir = "artifacts/vsix"
Get-ChildItem $vsixDir -Filter "my-extension-*.vsix" |
  Sort-Object { [version]($_.BaseName -replace '^my-extension-', '') } -Descending |
  Select-Object -Skip 10 |
  Remove-Item -Force

If the project ships multiple package variants such as a release VSIX and a dev/coexistence VSIX, keep all of them under artifacts/vsix/ except the one release artifact you intentionally attach. Apply the same hygiene checks to every variant so the smaller test build does not silently diverge from the release payload.

.vscodeignore

Minimize package size:

**
!package.json
!README.md
!LICENSE
!CHANGELOG.md
!out/**
!images/icon.png

src/**
test/**
node_modules/**
*.ts
tsconfig*.json
.github/**
.vscode/**
*.vsix
artifacts/**

Updating Published Extensions

# Increment version and publish
npx @vscode/vsce publish patch

# Or manually update version first
npm version patch
npx @vscode/vsce publish

Unpublishing

# Unpublish specific version
npx @vscode/vsce unpublish <publisher>.<extension> --version <version>

# Unpublish entire extension (use with caution!)
npx @vscode/vsce unpublish <publisher>.<extension>

Common Errors

Error Cause Fix
Missing publisher No publisher in package.json Add "publisher": "your-id"
Personal Access Token... PAT invalid or expired Regenerate PAT with correct scopes
Access Denied... PAT used has expired The current VSCE_PAT value is expired, the open terminal still has an old value, the PAT was issued with Custom defined expiration defaulting to today, or the PAT lacks Marketplace > Manage scope (so verify-pat passes but publish is rejected) Regenerate the PAT with a real future expiration and Marketplace > Manage scope, update VSCE_PAT, reload the current process, and run vsce verify-pat before publish
version already exists Same version published Increment version number
README not found File missing or wrong case Create README.md (lowercase)
invalid prerelease Version like 1.0.0-beta Use standard version format
unknown option Local vsce version differs Check vsce <command> --help and use supported flags

Release Completion Contract

When the user explicitly asks to release a VS Code extension, do not stop at a version bump, commit, or push. Treat the release as incomplete until all of these are done or explicitly blocked:

  1. Package the VSIX under artifacts/vsix/.
  2. Inspect the VSIX contents or run the repo-specific package integrity test.
  3. Run the Isolated Install Gate above against the generated VSIX; do not modify the normal user profile.
  4. Follow the repository's single publication route. For tag-triggered CI, first validate the candidate commit with an explicit non-publishing branch run, then push its matching tag and let CI publish and attach the same VSIX. Do not publish locally first and make CI collide with an existing version.
  5. For manual publication, publish the verified VSIX, push the matching tag and attach that VSIX to the GitHub Release; ensure the tag does not independently trigger a second publish.
  6. Keep manual workflow dispatch non-publishing by default and serialize runs capable of publishing the same package, including branch and tag routes. Check both the dispatch input and ref: a tag condition can override publish=false. Never move a published tag; follow the repository's version/retry policy after failure.
  7. Confirm the public item page is accessible and the public gallery API or vsce show --json returns the intended publisher, extension and version. Confirm the GitHub Release asset is uploaded, the tag resolves to the release commit, and the intended branch is synchronized with its remote.

Successful submission can precede Marketplace validation and public visibility. While the page or API is stale, use authenticated read-only status when available to distinguish pending validation from rejection. Use one bounded watcher with an explicit deadline and resumable status; never republish merely to check.

Once these checks and the pre-agreed quality gates pass, report publication complete and stop. Extra screenshots, repeated page loads and optional package hash comparisons are follow-up audits, not reasons to withhold completion. If a repository explicitly required exact artifact equality before publication, retain that gate; do not invent or relax gates mid-run. Update local state and task status without reopening completed verification.

If a blocker appears after the version bump, report the state separately: Version, VSIX, Marketplace publish, Git tag, and GitHub Release.

GitHub Release After Marketplace Publish

When attaching the VSIX to a GitHub Release, pin the release to a full commit SHA if you use --target. Short SHAs can be rejected by the GitHub API.

$full = git rev-parse HEAD
gh release create v1.0.0 .\artifacts\vsix\my-extension-1.0.0.vsix --target $full --title "v1.0.0 - Release title" --notes-file .\release-notes-v1.0.0.md

If you already calculate the VSIX checksum locally, record the size and SHA256 digest in the release notes too. GitHub Release asset metadata then becomes an independent proof of exactly which artifact was published, which is useful when Marketplace metadata is still stale right after publish.

$vsix = ".\artifacts\vsix\my-extension-1.0.0.vsix"
Get-Item $vsix | Select-Object Name, Length
Get-FileHash $vsix -Algorithm SHA256 | Select-Object Hash

Verify the GitHub Release and remote tag independently while Marketplace validation or metadata propagation is pending:

gh release view vX.Y.Z --json "tagName,name,url,isDraft,isPrerelease,publishedAt"
git ls-remote --tags origin vX.Y.Z

Record submission and public availability separately until the Release Completion Contract passes; do not use duplicate-safe publish as a verification command.

Marketplace URLs

  • Your extensions: https://marketplace.visualstudio.com/manage/publishers/<publisher-id>
  • Published extension: https://marketplace.visualstudio.com/items?itemName=<publisher>.<extension>
  • Statistics: Available in manage portal after publish

PAT Security & Persistence

Persist VSCE_PAT safely (Windows)

# 1. Set for the current terminal session (type directly – never paste into chat!)
$env:VSCE_PAT = "<your-pat>"

# 2. Persist to User environment variables (survives reboots)
[Environment]::SetEnvironmentVariable("VSCE_PAT", $env:VSCE_PAT, "User")

# 3. Verify without revealing the value
if ($env:VSCE_PAT) { "present (length: $($env:VSCE_PAT.Length))" } else { "missing" }

⚠️ SetEnvironmentVariable does not update already-open terminals. Open a new terminal (or restart VS Code) after persisting.

If a publish command still uses an expired token after you update the User environment, the current terminal probably kept the old process value. Reassign $env:VSCE_PAT from the User value in that terminal, then run verify-pat again.

If the PAT was accidentally exposed

  1. Revoke immediately at dev.azure.com → User Settings → Personal access tokens → Revoke
  2. Generate a new token (same scopes)
  3. Update VSCE_PAT with the new value

Rules

  • ❌ Never paste a PAT into chat, issue comments, or commit messages
  • ❌ Never echo $env:VSCE_PAT – check existence/length only
  • ❌ Never run vsce publish --help with VSCE_PAT set; some versions print the effective PAT default even into private tool logs
  • ✅ Use VSCE_PAT env var; vsce publish picks it up automatically
  • ✅ Set expiry ≤ 1 year and rotate on a schedule

.vscodeignore – Recommended Exclusion Patterns

Keep the published VSIX small and free of dev-only artefacts:

# Source & config (already compiled to out/)
src/**
**/tsconfig.json
**/.eslintrc.json
**/*.map
**/*.ts
!out/**

# Dev tooling
.vscode/**
.vscode-test/**
.playwright-mcp/**
.github/**
node_modules/**

# Dev-only content (never ship to users)
docs/**
output/**
output_sessions/**
research/**
session/**
FULL_SPECIFICATION.md
AGENTS.md

# Local artifacts (exclude secondary docs only if no shipped link needs them)
artifacts/**

# Large or unnecessary assets
images/demo-animated.gif
*.vsix

Tip: Run npx @vscode/vsce ls to preview exactly what will be packaged before running vsce package or vsce publish.

Gotcha: vsce ls --packagePath foo.vsix does not enumerate entries; for packaged VSIX verification (e.g. confirming node_modules/** is excluded), open the VSIX as a ZIP and list every entry instead:

Add-Type -AssemblyName System.IO.Compression.FileSystem
$zip = [System.IO.Compression.ZipFile]::OpenRead((Resolve-Path foo.vsix))
$zip.Entries | Select-Object FullName, Length

Judging node_modules/** exclusion

Before excluding node_modules/**, confirm out/*.js only requires vscode and Node built-ins, with no live external imports:

Select-String -Path out\*.js -Pattern 'require\("([^.][^"]+)"\)' -AllMatches
Select-String -Path out\*.js -Pattern 'import\("[^.]'  # dynamic imports

A dependencies entry that is only reached through a guarded dynamic import(...) disabled in the extension host (e.g. a CLI-side SDK that exits early when vscode is present) ships its entire transitive tree as dead weight. One real case: @github/copilot-sdk → @github/copilot ≈ 285 MB → packaged VSIX 181 MB. After moving the unused dep out and excluding node_modules/**, the same VSIX dropped to ~45 KB (≈4000× smaller). Compare VSIX size against the previous release; an unchanged-huge size usually means .vscodeignore is not actually excluding node_modules/**.

Marketplace auto-resolves relative-path images

When the README references images by relative path (e.g. ![demo](images/demo.gif)), the Marketplace web view and the in-VS Code extension details pane both resolve those paths against repository.url in package.json and fetch the file from raw.githubusercontent.com/<owner>/<repo>/<branch>/<path>. So as long as the repository is public and the image is pushed to the default branch, you can keep it out of the VSIX to drop multi-megabyte demo media without breaking the listing.

This auto-resolution applies to images, not to arbitrary Markdown links. If you exclude secondary documents such as README_ja.md from the VSIX, link to them with an absolute GitHub URL from the primary README.md instead of a relative Markdown link to a publicly readable document.

Marketplace publication does not authorize making a private source repository public. Private raw GitHub image URLs will not serve anonymous readers: use public distribution assets, keep required icons in the VSIX, and provide alternate language content on the listing or a publicly reachable page. Verify support access as an intended user, not only as the maintainer. A private issue tracker is not a public support channel: use an approved accessible alternative or clearly disclose restricted access in the feedback UI and listing. Keep bugs.url, UI actions and README destinations aligned; neither a VSIX link nor a support need authorizes a repository visibility change.

An unchanged documentation icon may pin an earlier published asset version. Validate its publisher, extension, asset type and expected image rather than requiring the URL version to equal a not-yet-published package version. The new VSIX must still contain its own declared runtime and Activity Bar icons.

Verify VSIX integrity before publish

vsce ls validates .vscodeignore filtering, but it cannot detect a truncated or zip-corrupt VSIX (which can happen when the package step is interrupted by build watchers or transient I/O). Run the exact ZIP verifier and the Isolated Install Gate above before vsce publish; never install release-test artifacts into the normal user profile. A ZIP parser error such as End of central directory record signature not found means the artifact is truncated and must be rebuilt.

Also treat vsce package completion based on the output file (size + mtime), not on console messages — terminal capture sometimes drops the DONE Packaged: ... line, but the artifact on disk is the source of truth. If the VSIX exists but ZIP inspection fails, check whether node / vsce is still writing the file. Once no package process remains, delete the corrupt artifact, rebuild with a deterministic output path, and inspect that rebuilt file instead of reusing the partial archive.

Get-ChildItem artifacts/vsix/my-extension-1.0.0.vsix |
  Select-Object Length, LastWriteTime

If the extension manifest references icons such as icon.png for the Marketplace tile and icon.svg for activity bar or command UI, add a release check that asserts the referenced files physically exist before packaging.

Marketplace Propagation Notes

  • vsce show --json and the human listing can lag; do not republish solely from stale metadata.
  • Gallery "latest" resolution lags too, so code --install-extension <publisher>.<name> --force right after publish can silently install the previous version. While propagation is pending, do not install or verify by extension ID: install the identical verified local VSIX (or one downloaded from the version-specific endpoint) with code --install-extension <path> --force, confirm with code --list-extensions --show-versions, and do not republish.
  • Follow the Release Completion Contract; after the public page and exact API identity/version are confirmed, stop waiting unless a pre-agreed artifact gate is still unmet.
  • If publish is paused by review, auth, duplicate, or permissions, report version, artifact checksum, commit, tag, push, and publish state separately so the same VSIX can be resumed without guessing.

Source: SKILL.md on GitHub

1 warning8d5 checks · Risk SAFE
  • Gen Agent Trust Hub8d

    The skill provides a comprehensive and secure guide for developing and publishing VS Code extensions. It follows security best practices, particularly concerning secret management and webview implementation.

  • Socket8d

    No alerts

  • Snyk8d

    Risk: LOW · No issues

  • Runlayer7mo

    9/9 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 7ae9078. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 18 hours ago.

Activeupdated last week
argument-hint
作りたい拡張機能、追加したい機能、困っている点
user-invocable
true
metadata
{
  "author": "yamapan (https://github.com/aktsmm)"
}

README badge

README badge for aktsmm/agent-skills/vscode-extension-guide