eslint-package-json

September 1, 2026 Β· View on GitHub

Powerful ESLint rules for package.json

Lint and autofix your package.json files with ESLint, powered by @eslint/json.

This plugin catches real package.json mistakes (invalid names, bad version ranges, broken exports, misplaced @types/*, redundant files entries, and more) and fixes many of them automatically.

Install

npm install --save-dev eslint eslint-package-json

Requires ESLint >=10.4, flat config, and ESM.

Usage

Add the recommended config to your eslint.config.js:

import {defineConfig} from 'eslint/config';
import packageJson from 'eslint-package-json';

export default defineConfig({
	files: ['**/package.json'],
	plugins: {
		'package-json': packageJson
	},
	extends: [
		'package-json/recommended'
	]
});

This lints every package.json in your project. To tweak individual rules, add them to the same config object:

import {defineConfig} from 'eslint/config';
import packageJson from 'eslint-package-json';

export default defineConfig({
	files: ['**/package.json'],
	plugins: {
		'package-json': packageJson
	},
	extends: [
		'package-json/recommended'
	],
	rules: {
		'package-json/dependency-version-range': [
			'error',
			{
				range: 'caret'
			}
		]
	}
});

If you prefer to wire it up manually instead of using a preset:

import json from '@eslint/json';
import {defineConfig} from 'eslint/config';
import packageJson from 'eslint-package-json';

export default defineConfig({
	files: ['**/package.json'],
	language: 'json/json',
	plugins: {
		json,
		'package-json': packageJson
	},
	rules: {
		'package-json/valid-fields': 'error'
	}
});

Configs

  • recommended β€” Enables the rules that catch real, uncontroversial mistakes.
  • all β€” Enables every rule. Useful for discovering rules; not recommended for everyday use.

Rules

πŸ’Ό Configurations enabled in.
βœ… Set in the recommended configuration.
πŸ”§ Automatically fixable by the --fix CLI option.
πŸ’‘ Manually fixable by editor suggestions.

NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β DescriptionπŸ’ΌπŸ”§πŸ’‘
consistent-name-casingEnforce kebab-case for keys in scripts and bin objects.
consistent-path-prefixEnforce consistent ./ prefix on local path fields.βœ…πŸ”§
dependency-version-rangeEnforce a consistent version range style for dependencies.βœ…πŸ’‘
description-formatEnforce formatting of the description field.πŸ”§
no-absolute-pathsDisallow absolute paths in path fields.βœ…πŸ’‘
no-absolute-paths-in-scriptsDisallow absolute paths in scripts.βœ…
no-backslash-pathsEnforce forward slashes in path fields.βœ…πŸ”§
no-core-module-dependenciesDisallow dependencies that shadow Node.js built-in modules.βœ…πŸ’‘
no-deprecated-fieldsDisallow fields and scripts that npm has deprecated.βœ…
no-dist-tag-dependenciesDisallow dist-tags as dependency specifiers.βœ…
no-duplicate-dependenciesDisallow a dependency listed in multiple dependency groups.βœ…πŸ”§πŸ’‘
no-empty-fieldsDisallow empty fields.βœ…πŸ’‘
no-exact-peer-dependenciesDisallow exact versions for peer dependencies.πŸ’‘
no-exports-trailing-slashDisallow trailing-slash folder mappings in exports/imports.βœ…πŸ”§
no-fallback-export-arraysDiscourage string-target fallback arrays in exports/imports.βœ…
no-git-dependenciesDisallow git URLs as dependency specifiers.
no-http-dependenciesDisallow HTTP URLs as dependency specifiers.βœ…
no-incompatible-peer-dependency-rangesDisallow incompatible ranges for peer dependencies also listed as runtime dependencies.βœ…πŸ’‘
no-install-scriptsDisallow install lifecycle scripts.βœ…πŸ’‘
no-invalid-direct-overridesDisallow npm overrides that conflict with direct dependencies.βœ…πŸ”§
no-local-dependenciesDisallow local filesystem paths as dependency specifiers.
no-manual-maintainersDisallow a manually-set maintainers field.βœ…πŸ’‘
no-missing-filesDisallow missing files referenced by package metadata.
no-nested-exportsDisallow exports and imports in nested package.json files.βœ…πŸ’‘
no-orphan-script-hooksDisallow pre/post script hooks without a corresponding script.βœ…
no-orphan-typesDisallow @types/* packages without a corresponding dependency.βœ…πŸ’‘
no-overrides-in-published-packageDisallow overrides in packages that can be published.βœ…πŸ’‘
no-package-manager-enginesDisallow package manager versions in the engines field.βœ…πŸ’‘
no-pre-release-dependenciesDisallow pre-release versions as dependency specifiers.
no-redundant-filesDisallow redundant entries in the files field.βœ…πŸ”§
no-redundant-repository-fieldsDisallow bugs/homepage values that duplicate what npm infers from repository.πŸ”§
no-restricted-dependenciesDisallow specific dependencies.
no-restricted-fieldsDisallow specific fields.πŸ’‘
no-self-dependencyDisallow a package depending on itself.βœ…πŸ’‘
no-typo-fieldsDisallow misspelled package.json field names.βœ…πŸ”§
no-wildcard-dependenciesDisallow wildcard version ranges for dependencies.βœ…
no-workspace-protocol-in-published-packageDisallow workspace: dependency specifiers in packages that can be published.βœ…
peer-dependencies-as-dev-dependenciesEnforce peer dependencies to also be listed in devDependencies at a compatible version.βœ…πŸ’‘
prefer-engines-rangePrefer open-ended >= ranges in the engines field.βœ…πŸ’‘
prefer-exportsPrefer an exports-first package interface.βœ…
prefer-files-fieldRequire a files allowlist that covers published entry points.βœ…
prefer-https-urlsPrefer https:// URLs in metadata fields.βœ…πŸ”§
prefer-provenanceEnforce npm provenance via publishConfig.provenance.πŸ’‘
prefer-shorthandPrefer the shorthand string form of fields where possible.βœ…πŸ”§
prefer-side-effects-fieldRecommend declaring the sideEffects field for packages.βœ…πŸ’‘
prefer-type-modulePrefer the type field to be module.βœ…πŸ’‘
require-bin-executableRequire bin files to be executable by their owner.βœ…
require-bin-shebangRequire bin files to start with the exact #!/usr/bin/env node shebang.βœ…
require-default-conditionRequire a last default entry in exports/imports conditions objects.βœ…
require-enginesRequire the engines.node field.βœ…
require-entry-pointRequire an entry point field.βœ…
require-exports-rootRequire a usable . root entry in the exports field.
require-fieldsRequire specific fields to be present, always or only for published packages.βœ…
require-privateRequire the private field to be true.πŸ’‘
require-private-when-workspacesRequire private when workspaces is set.βœ…πŸ’‘
require-types-in-exportsRequire correctly ordered and module-compatible types in exports.βœ…
restrict-fields-when-privateDisallow fields that have no effect when the package is private.πŸ’‘
sort-dependenciesEnforce alphabetical ordering of dependencies.βœ…πŸ”§
sort-filesEnforce a canonical order for entries in the files field.βœ…πŸ”§
sort-propertiesEnforce a canonical order for top-level package.json fields.βœ…πŸ”§
sort-scriptsEnforce alphabetical ordering of scripts.πŸ”§
types-in-dev-dependenciesEnforce @types/* packages to be in devDependencies.πŸ’‘
valid-fieldsEnforce valid values for package.json fields.βœ…πŸ”§πŸ’‘

FAQ

How is this different from eslint-plugin-package-json?

Both lint package.json through ESLint, and eslint-plugin-package-json is a great project. I built this because I wanted a different design:

  • Fewer, more powerful rules. Instead of dozens of near-identical rules (one per field, one per dependency group), I use a handful of rules with options. For example, one dependency-version-range rule with a dependencyTypes option replaces a whole family of no-caret-* / prefer-tilde-* rules. Less to learn, less to configure.
  • Native @eslint/json. I target ESLint's official JSON language directly, with no parser compatibility layer.
  • Autofix-first. Every rule that can safely fix or suggest a fix does.

Why not npm-package-json-lint?

It's a separate CLI with its own config format and no autofix. This plugin lives inside ESLint, so it shares your editor integration, --fix, and flat config.

How do I disable a rule for package.json?

package.json must be valid JSON, so it cannot contain comments.

Disable the rule in eslint.config.js instead:

import {defineConfig} from 'eslint/config';
import packageJson from 'eslint-package-json';

export default defineConfig({
	files: ['**/package.json'],
	plugins: {
		'package-json': packageJson
	},
	extends: [
		'package-json/recommended'
	],
	rules: {
		'package-json/no-orphan-types': 'off',
	},
});

Use a more specific files pattern when the rule should be disabled for only one package.