← BACK

eslint-package-json

Powerful ESLint rules for package.json

JavaScript ⭐ 19

eslint-package-json

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-casing Enforce kebab-case for keys in scripts and bin objects.
consistent-path-prefix Enforce consistent ./ prefix on local path fields. 🔧
dependency-version-range Enforce a consistent version range style for dependencies. 💡
description-format Enforce formatting of the description field. 🔧
no-absolute-paths Disallow absolute paths in path fields.
no-backslash-paths Enforce forward slashes in path fields. 🔧
no-core-module-dependencies Disallow dependencies that shadow Node.js built-in modules. 💡
no-deprecated-fields Disallow fields and scripts that npm has deprecated.
no-dist-tag-dependencies Disallow dist-tags as dependency specifiers.
no-duplicate-dependencies Disallow a dependency listed in multiple dependency groups. 🔧
no-empty-fields Disallow empty fields. 💡
no-exact-peer-dependencies Disallow exact versions for peer dependencies. 💡
no-exports-trailing-slash Disallow deprecated trailing-slash folder mappings in exports/imports. 🔧
no-fallback-export-arrays Discourage string-target fallback arrays in exports/imports.
no-git-dependencies Disallow git URLs as dependency specifiers.
no-http-dependencies Disallow HTTP URLs as dependency specifiers.
no-install-scripts Disallow install lifecycle scripts. 💡
no-invalid-direct-overrides Disallow npm overrides that conflict with direct dependencies. 🔧
no-local-dependencies Disallow local filesystem paths as dependency specifiers.
no-manual-maintainers Disallow a manually-set maintainers field. 💡
no-missing-files Disallow missing files referenced by package metadata.
no-nested-exports Disallow exports and imports in nested package.json files. 💡
no-orphan-script-hooks Disallow pre/post script hooks without a corresponding script.
no-orphan-types Disallow @types/* packages without a corresponding dependency. 💡
no-overrides-in-published-package Disallow overrides in packages that can be published. 💡
no-package-manager-engines Disallow package manager versions in the engines field. 💡
no-pre-release-dependencies Disallow pre-release versions as dependency specifiers.
no-redundant-files Disallow redundant entries in the files field. 🔧
no-redundant-repository-fields Disallow bugs/homepage values that duplicate what npm infers from repository. 🔧
no-restricted-dependencies Disallow specific dependencies.
no-restricted-fields Disallow specific fields. 💡
no-self-dependency Disallow a package depending on itself. 💡
no-typo-fields Disallow misspelled package.json field names. 🔧
no-wildcard-dependencies Disallow wildcard version ranges for dependencies.
no-workspace-protocol-in-published-package Disallow workspace: dependency specifiers in packages that can be published.
peer-dependencies-as-dev-dependencies Enforce peer dependencies to also be listed in devDependencies at a compatible version. 💡
prefer-engines-range Prefer open-ended >= ranges in the engines field. 💡
prefer-exports Prefer an exports-first package interface.
prefer-files-field Require a files allowlist that covers published entry points.
prefer-https-urls Prefer https:// URLs in metadata fields. 🔧
prefer-provenance Enforce npm provenance via publishConfig.provenance. 💡
prefer-shorthand Prefer the shorthand string form of fields where possible. 🔧
prefer-side-effects-field Recommend declaring the sideEffects field for packages. 💡
prefer-type-module Prefer the type field to be module. 💡
require-bin-shebang Require bin files to start with the exact #!/usr/bin/env node shebang.
require-default-condition Require a last default entry in exports/imports conditions objects.
require-engines Require the engines.node field.
require-entry-point Require an entry point field.
require-exports-root Require a usable . root entry in the exports field.
require-fields Require specific fields to be present, always or only for published packages.
require-private-when-workspaces Require private when workspaces is set. 💡
require-types-in-exports Require correctly ordered and module-compatible types in exports.
restrict-fields-when-private Disallow fields that have no effect when the package is private. 💡
sort-dependencies Enforce alphabetical ordering of dependencies. 🔧
sort-files Enforce a canonical order for entries in the files field. 🔧
sort-properties Enforce a canonical order for top-level package.json fields. 🔧
sort-scripts Enforce alphabetical ordering of scripts. 🔧
types-in-dev-dependencies Enforce @types/* packages to be in devDependencies. 💡
valid-fields Enforce 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.

Related