Versions

Create Plugins

ESLint plugins extend ESLint with additional functionality. In most cases, you’ll extend ESLint by creating plugins that encapsulate the additional functionality you want to share across multiple projects.

Creating a plugin

A plugin is a JavaScript object that exposes certain properties to ESLint:

  • meta - information about the plugin.
  • configs - an object containing named configurations.
  • rules - an object containing the definitions of custom rules.
  • processors - an object containing named processors.

To get started, create a JavaScript file and export an object containing the properties you’d like ESLint to use. To make your plugin as easy to maintain as possible, we recommend that you format your plugin entrypoint file to look like this:

const plugin = {
    meta: {},
    configs: {},
    rules: {},
    processors: {}
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

If you plan to distribute your plugin as an npm package, make sure that the module that exports the plugin object is the default export of your package. This will enable ESLint to import the plugin when it is specified in the command line in the --plugin option.

Meta Data in Plugins

For easier debugging and more effective caching of plugins, it’s recommended to provide a name and version in a meta object at the root of your plugin, like this:

const plugin = {

    // preferred location of name and version
    meta: {
        name: "eslint-plugin-example",
        version: "1.2.3"
    },
    rules: {
        // add rules here
    }
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

The meta.name property should match the npm package name for your plugin and the meta.version property should match the npm package version for your plugin. The easiest way to accomplish this is by reading this information from your package.json, as in this example:

import fs from "fs";

const pkg = JSON.parse(fs.readFileSync(new URL("./package.json", import.meta.url), "utf8"));

const plugin = {

    // preferred location of name and version
    meta: {
        name: pkg.name,
        version: pkg.version
    },
    rules: {
        // add rules here
    }
};

export default plugin;

As an alternative, you can also expose name and version properties at the root of your plugin, such as:

const plugin = {

    // alternate location of name and version
    name: "eslint-plugin-example",
    version: "1.2.3",
    rules: {
        // add rules here
    }
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

Rules in Plugins

Plugins can expose custom rules for use in ESLint. To do so, the plugin must export a rules object containing a key-value mapping of rule ID to rule. The rule ID does not have to follow any naming convention except that it should not contain a / character (so it can just be dollar-sign but not foo/dollar-sign, for instance). To learn more about creating custom rules in plugins, refer to Custom Rules.

const plugin = {
    meta: {
        name: "eslint-plugin-example",
        version: "1.2.3"
    },
    rules: {
        "dollar-sign": {
            create(context) {
                // rule implementation ...
            }
        }
    }
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

In order to use a rule from a plugin in a configuration file, import the plugin and include it in the plugins key, specifying a namespace. Then, use that namespace to reference the rule in the rules configuration, like this:

// eslint.config.js
import example from "eslint-plugin-example";

export default [
    {
        plugins: {
            example
        },
        rules: {
            "example/dollar-sign": "error"
        }
    }
];

Processors in Plugins

Plugins can expose processors for use in configuration file by providing a processors object. Similar to rules, each key in the processors object is the name of a processor and each value is the processor object itself. Here’s an example:

const plugin = {
    meta: {
        name: "eslint-plugin-example",
        version: "1.2.3"
    },
    processors: {
        "processor-name": {
            preprocess(text, filename) {/* ... */},
            postprocess(messages, filename) { /* ... */ },
        }
    }
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

In order to use a processor from a plugin in a configuration file, import the plugin and include it in the plugins key, specifying a namespace. Then, use that namespace to reference the processor in the processor configuration, like this:

// eslint.config.js
import example from "eslint-plugin-example";

export default [
    {
        plugins: {
            example
        },
        processor: "example/processor-name"
    }
];

Configs in Plugins

You can bundle configurations inside a plugin by specifying them under the configs key. This can be useful when you want to bundle a set of custom rules with a configuration that enables the recommended options. Multiple configurations are supported per plugin.

You can include individual rules from a plugin in a config that’s also included in the plugin. In the config, you must specify your plugin name in the plugins object as well as any rules you want to enable that are part of the plugin. Any plugin rules must be prefixed with the plugin namespace. Here’s an example:

const plugin = {
    meta: {
        name: "eslint-plugin-example",
        version: "1.2.3"
    },
    configs: {},
    rules: {
        "dollar-sign": {
            create(context) {
                // rule implementation ...
            }
        }
    }
};

// assign configs here so we can reference `plugin`
Object.assign(plugin.configs, {
    recommended: [{
        plugins: {
            example: plugin
        },
        rules: {
            "example/dollar-sign": "error"
        },
        languageOptions: {
            globals: {
                myGlobal: "readonly"
            },
            parserOptions: {
                ecmaFeatures: {
                    jsx: true
                }
            }
        }
    }]
});

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

This plugin exports a recommended config that is an array with one config object. When there is just one config object, you can also export just the object without an enclosing array.

In order to use a config from a plugin in a configuration file, import the plugin and access the config directly through the plugin object. Assuming the config is an array, use the spread operator to add it into the array returned from the configuration file, like this:

// eslint.config.js
import example from "eslint-plugin-example";

export default [
    ...example.configs.recommended
];

Testing a Plugin

ESLint provides the RuleTester utility to make it easy to test the rules of your plugin.

Linting a Plugin

ESLint plugins should be linted too! It’s suggested to lint your plugin with the recommended configurations of:

Share Plugins

In order to make your plugin available publicly, you have to publish it on npm. When doing so, please be sure to:

  1. List ESLint as a peer dependency. Because plugins are intended for use with ESLint, it’s important to add the eslint package as a peer dependency. To do so, manually edit your package.json file to include a peerDependencies block, like this:

    {
        "peerDependencies": {
            "eslint": ">=9.0.0"
        }
    }
    
  2. Specify keywords. ESLint plugins should specify eslint, eslintplugin and eslint-plugin as keywords in your package.json file.

Change Language