Lints a VS Code extension package.json for the manifest mistakes that make vsce package/publish fail or ship a broken listing. 14 rules, offline. Runs entirely in your browser — nothing is uploaded.
Same engine as the VS Code extension, byte for byte.
This page is the working piece. The full pack has everything below.
Find the package.json lines that stop vsce before you run the release build
One hour of specialised freelance developer time runs $75-$150 on Upwork's own 2026 rate guide; a rejected publish usually costs more than one.
Buy the full version — $29· ReadyStack
Real numbers from this tool, line by line.
Six blockers, six build cycles: for the indie author shipping a VS Code extension to the Marketplace and Open VSX, the sample manifest bundled with VSIX Publish Lint returns 12 findings - 6 that stop vsce outright and 6 that ship a worse listing - while vsce itself reports exactly one of them, and only after the compile step has already run.
That order is the problem. vsce package runs your vscode:prepublish script first, validates the manifest second, and stops at the first thing it dislikes. Fix that line, run again, wait for TypeScript again, meet the next one.
The bundled _fixtures/dirty.json, scored by the 16 rules:
error name_invalid L2 "Release Notes Helper"
error publisher_missing L2 no publisher key at all
error version_invalid L5 "0.9.1-beta.2"
error invalid_category L7 "Linter"
error badge_host_unapproved L9 my-jenkins.internal.example
error types_vscode_ahead L22 @types/vscode ^1.96.0 vs engines ^1.74.0
...plus 6 warnings: repository, license and icon missing, "*" activation,
a redundant onCommand:, and a description 45 characters over the 200 shown.
Four of those six errors are one-character-class mistakes. categories is a closed vocabulary and the plural matters: Linters, not Linter. name is half of the publisher.name id, so it must be lowercase with no spaces; displayName holds the pretty title. version must be three numeric parts - pre-releases go through --pre-release, not a -beta.2 suffix. Badge images come only from an approved host list, so one served from an internal Jenkins is refused, not quietly dropped.
The fifth catches people who did everything else right. If devDependencies["@types/vscode"] is newer than engines.vscode, you are compiling against API your declared minimum build does not have. Bumping the types package is a routine dependency update; bumping engines.vscode is a decision about who may install you. The two drift apart silently until a release day.
The six warnings never fail an upload, which is why they survive. A missing icon is the grey default tile next to competitors who shipped one; a description over 200 characters is cut off in search results; "*" in activationEvents starts your extension at every window launch.
The same manifest corrected, _fixtures/clean.json, is 0 findings. A third example - a theme extension with no engines block and a two-part "1.0" version - returns 2, both fatal, neither visible until upload.
Why not simply ask a chat model? The two checks that cost the most are the ones it cannot do: it cannot see the version @types/vscode is pinned to against the engines.vscode in your manifest, and it will cheerfully produce category names that are not on the list - plausible-sounding names are what a language model invents best. Nor can it give you a line number.
VSIX Publish Lint runs the 16 rules over the manifest you have open, offline, printing rule id, severity, line, what breaks and the field to change. That tier is free and finishes the job: one manifest, all 16 rules, as often as you like, nothing watermarked and nothing held back.
The licence key covers a different job, on the ownership axis: lint every manifest in the workspace in one pass and write the result out as a JSON or SARIF file you keep and can gate CI on, so the check runs on the pull request, not on release day. $29 once, one key per person or team seat, 7-day full refund. For scale: specialised freelance developer work is listed at $75 to $150 an hour in Upwork's own 2026 rate guide.
It reads a VS Code extension package.json and reports the manifest problems that stop vsce package or vsce publish, plus the ones that ship a degraded Marketplace listing. Sixteen rules cover engines.vscode, the @types/vscode pairing, publisher, name, version, categories, badge hosts, entry point, repository, license, icon, activation events and description length. Every finding names the field and the replacement.
Extension authors who publish to the VS Code Marketplace or Open VSX, and the people who maintain a monorepo of several extensions. It is aimed at the moment just before a release: you have a manifest, you are about to tag, and you would rather not learn from a failed upload that categories must say Linters and not Linter.
vsce tells you about one blocker at a time and only after your compile step has run, so a manifest with six problems costs six build cycles. It also stays silent on the non-fatal ones, such as a missing icon or repository, which do not fail the upload but do shape what shoppers see. This checks all sixteen at once, before the build.
Free covers one manifest completely: open a package.json, run the lint, get all sixteen rules with line numbers and fixes, unlimited times, offline, with no watermark and no countdown. The licence key adds a different job: linting every extension manifest in the workspace in one pass, and writing the result to a JSON or SARIF file you own and can gate CI on.
Specialised freelance developer work is listed at $75 to $150 an hour on Upwork's 2026 rate guide. A publish that is rejected after the build costs at least that in rework and a delayed release, and the review of a manifest before a release is exactly the errand people bill an hour for. The extension is $29 once.
One question, answered by the person who built it. Your email only if you want the answer sent.