Library / SDK
cypress-io/eslint-plugin-cypress avatar
cypress-io/eslint-plugin-cypress

eslint-plugin-cypress encodes the Cypress best practices as lint rules

An ESLint plugin for projects that use Cypress

728 stars94 forksJavaScriptMIT

At a glance

What is it?
The Cypress ESLint plugin turns the framework's recommended practices into thirteen rules that flag fragile test code, and the plugin's own rules about the tests are the interesting part, since the no-unnecessary-waiting and unsafe-to-chain-command rules exist to catch the two mistakes that make a Cypress suite slow and flaky.
Who is it for?
eslint-plugin-cypress suits a Cypress shop that wants its test conventions enforced in review rather than in a wiki, and it suits a team tired of flaky suites because the rules target the specific failure modes Cypress documentation warns about.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Thirteen rules, and most of them are about fragile tests

The plugin enforces some of the best practices recommended for using Cypress, and the rule list is short enough to read in full. Three of them are hygiene rules. no-debug disallows using cy.debug() calls, no-pause disallows using cy.pause() calls, and no-force disallows using force: true with action commands, which is the usual way to get a test to pass by skipping the check it was meant to perform. Two are about how assertions are written. no-assigning-return-values disallows assigning the return values of cy calls, and no-and enforces .should() over .and() for starting assertion chains. The rest cover structural mistakes. no-chained-get disallows a chain of cy.get() calls, unsafe-to-chain-command disallows actions within chains, no-async-before disallows using async and await in Cypress before methods, and no-async-tests does the same for test cases. Two more are about waiting and querying, with no-unnecessary-waiting disallowing waiting for arbitrary time periods, and no-xpath disallowing using cy.xpath() calls, which is the one rule in the list marked as deprecated. The last is require-data-selectors, which asks for data attribute selectors.

Two configurations, and one of them enables no rules at all

There are two specific configurations, and the distinction between them is not obvious from the names. configs.globals defines the globals cy, Cypress, expect, assert and chai used in Cypress test specs, as well as globals.browser and globals.mocha from the globals package, and the readme is explicit that there are no default rules enabled in this configuration. configs.recommended enables the recommended rules and also includes the globals configuration. So the name globals is a misnomer if you read it as everything, since it is only about identifiers, and a team that installs it expecting the recommended rules gets none. Which rules are actually enabled is marked in the table, and four of the thirteen carry the recommended marker. no-assigning-return-values, no-async-tests, no-unnecessary-waiting and unsafe-to-chain-command are the ones in the recommended set, and no-and is the one marked as automatically fixable by the --fix command line option.

The flat config requirement is the migration story

The plugin and ESLint as of v10 no longer support the deprecated eslintrc-type config file format, so you must use a flat config file. The setup is a file called eslint.config.mjs at the root of the Cypress project, and the plugin is imported into it.

shell
import pluginCypress from 'eslint-plugin-cypress'

There is a specific migration detail that will bite anyone upgrading across the 5.0.0 boundary, because the configuration eslint-plugin-cypress/flat, which was deprecated in plugin version 5.0.0, is no longer available, and the migration is to drop the /flat suffix and use the equivalent eslint-plugin-cypress configuration. The prerequisites are also stated plainly, with ESLint v10 required and lower versions no longer supported, and there is a note for anyone who installed ESLint globally, who must then also install eslint-plugin-cypress globally. The readme points at the ESLint v10 configuration file resolution documentation for hierarchical use of configuration files.

The three configuration examples show the three ways to adopt it

The usage examples section gives three patterns, and they map to three levels of adoption. The first activates one rule, which is the pattern for a team that wants a single check and nothing else.

js
import { defineConfig } from 'eslint/config'
import pluginCypress from 'eslint-plugin-cypress'
export default defineConfig([
  {
    plugins: {
      cypress: pluginCypress,
    },
    rules: {
      'cypress/unsafe-to-chain-command': 'error',
    },
  },
])

The second uses the recommended configuration scoped to the Cypress spec files, and then turns one rule off, which is the pattern most teams will end up with.

js
import { defineConfig } from 'eslint/config'
import pluginCypress from 'eslint-plugin-cypress'
export default defineConfig([
  {
    files: ['cypress/**/*.js'],
    extends: [pluginCypress.configs.recommended],
    rules: {
      'cypress/no-unnecessary-waiting': 'off',
    },
  },
])

The third activates the globals configuration on its own, for teams that only want the identifiers defined. The readme notes that the rules are available by importing from eslint-plugin-cypress and can be individually activated, and that the examples should be adapted to your needs.

Where this plugin is the wrong choice

Three limits are worth naming. The first is scope, since the globals it defines are meaningful only inside Cypress specs, and installing it in a mixed repository is a decision about where the config applies rather than a project wide default. The second is the flat config requirement, which is not a problem for a new project but is for anyone still on eslintrc, and the plugin's answer there is that it is not supported. The third is that the rules encode one view of how Cypress should be written, and the recommended set reflects that view rather than a consensus. The no-unnecessary-waiting rule in particular conflicts with teams that wait for a specific visual state, which is why the readme's own recommended example turns it off. The repository shows a project that takes its own tooling seriously, with a .husky directory, an eslint.config.mjs at the root, a separate FLAT-CONFIG.md and ESLINTRC-CONFIG.md document for the two eras, a test-project/ directory that presumably exercises the plugin against a real Cypress project, and a docs/ directory with a page per rule, generated with eslint-doc-generator.

Editorial conclusion

eslint-plugin-cypress suits a Cypress shop that wants its test conventions enforced in review rather than in a wiki, and it suits a team tired of flaky suites because the rules target the specific failure modes Cypress documentation warns about. It is the wrong tool for a project that does not use Cypress, since the globals it defines mean nothing elsewhere, and it is the wrong choice if you are still on the old eslintrc format, because the plugin has dropped that path entirely. Before adopting it, read the rule list rather than the recommended configuration, because two of the rules are opinionated enough that teams routinely turn them off. The last push was on 2026-10-17 and the current release is v7.0.2 from 2026-09-08.

Frequently asked questions

How do I install eslint-plugin-cypress?

Run npm install eslint eslint-plugin-cypress with the save-dev flag, or yarn add eslint eslint-plugin-cypress with the dev flag. The plugin requires ESLint v10, since lower versions are no longer supported, and if you installed ESLint globally you must also install eslint-plugin-cypress globally.

Which rules does the Cypress recommended configuration enable?

The recommended configuration enables no-assigning-return-values, no-async-tests, no-unnecessary-waiting and unsafe-to-chain-command, and it also includes the globals configuration, which defines cy, Cypress, expect, assert and chai along with globals.browser and globals.mocha. The globals configuration on its own enables no rules.

Can I still use the eslint-plugin-cypress/flat configuration?

No. The eslint-plugin-cypress/flat configuration was deprecated in plugin version 5.0.0 and is no longer available. The migration is to drop the /flat suffix and use the equivalent eslint-plugin-cypress configuration, in a flat config file named eslint.config.mjs at the root of the Cypress project.

Official sources

  1. cypress-io/eslint-plugin-cypress on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cypress-io-eslint-plugin-cypress.svg)](https://hysenlabs.com/projects/cypress-io-eslint-plugin-cypress)

Was this useful?