manifest-v3-lint
v1.0.0
Published
Lint a Chrome extension manifest.json for Manifest V3 pitfalls, deprecated fields, and Chrome Web Store rejection risks.
Maintainers
Readme
manifest-v3-lint
Lint a Chrome extension's manifest.json for Manifest V3 pitfalls, leftover
Manifest V2 fields, and common Chrome Web Store rejection reasons — before
you find out about them from a rejection email.
Not a full schema validator. It's a fast, opinionated pre-flight check for
the specific mistakes that actually cause store rejections or silent
runtime failures: leftover background.page, string-format
content_security_policy, flat-array web_accessible_resources, URL
patterns left in permissions instead of host_permissions, and a few
Chrome Web Store listing limits (name length, description length, missing
icons).
Usage
npx manifest-v3-lint # lints ./manifest.json
npx manifest-v3-lint path/to/manifest.json
npx manifest-v3-lint --json # machine-readable output, for CIExits with code 1 if any errors were found (warnings alone exit 0) —
safe to drop into a CI pipeline or a pre-commit hook.
Example
manifest.json
✗ [manifest-version] manifest_version is 2, expected 3. Manifest V2 extensions are no longer accepted by the Chrome Web Store.
✗ [background-page] background.page / background.scripts is Manifest V2 syntax. Use background.service_worker instead.
✗ [browser-action] browser_action / page_action is Manifest V2 syntax. Use the unified "action" key instead.
✗ [permissions-host-mixup] URL match pattern(s) found in "permissions" — under Manifest V3 these belong in "host_permissions" instead.
! [missing-icons] No "icons" field. The Chrome Web Store requires at least a 128x128 icon for publishing.
4 error(s), 1 warning(s).What it checks
| Code | Level | What it catches |
|---|---|---|
| manifest-version | error | manifest_version isn't 3 |
| background-page | error | background.page / background.scripts (MV2) instead of background.service_worker |
| background-persistent | warn | Leftover background.persistent, ignored under MV3 |
| browser-action | error | browser_action / page_action instead of the unified action key |
| csp-string | error | content_security_policy as a plain string instead of an object |
| war-format | error | web_accessible_resources as a flat string array instead of { resources, matches } objects |
| permissions-host-mixup | error | URL match patterns left in permissions instead of host_permissions |
| broad-host-permission | warn | host_permissions requesting <all_urls> |
| missing-name / missing-version | error | Missing required manifest fields |
| name-too-long | error | name over the Chrome Web Store's 75-character limit |
| description-too-long | warn | description over the 132-character store-listing limit |
| missing-icons | warn | No icons field (128×128 is required to publish) |
Programmatic use
const { lint } = require('manifest-v3-lint');
const issues = lint(JSON.parse(fs.readFileSync('manifest.json', 'utf8')));
// [{ level: 'error', code: 'manifest-version', message: '...' }, ...]Why this exists
Built by the team behind Kromio — an AI Chrome extension builder — out of the same manifest mistakes we kept seeing generated extensions trip on. Free and open source, MIT licensed.
License
MIT
