Writing a Plugin

The Plugins API allows you to hook into and extend Cypress behavior.

Note: This document assumes you have read the Plugins Guide.

Plugins API

To get started, open up this file:


The plugins file must export a function with the following signature:

// cypress/plugins/index.js

// export a function
module.exports = (on, config) => {
  // configure plugins here

The exported function is called whenever a project is opened either with cypress open or cypress run.

Your function will receive 2 arguments: on and config.

You can return a synchronous function, or you can also return a Promise, and it will be awaited until it resolves. This enables you to perform asynchronous actions in your exported function such as reading files in from the filesystem.

If you return or resolve with an object, Cypress will then merge this object into the config which enables you to overwrite configuration or environment variables.


on is a function that you will use to register listeners on various events that Cypress exposes.

Registering to listen on an event looks like this:

module.exports = (on, config) => {
  on('<event>', (arg1, arg2) => {
    // plugin stuff here

Each event documents its own argument signature. To understand how to use them, please refer to the docs for each one.


config is the resolved Cypress configuration of the opened project.

This configuration contains all of the values that get passed into the browser for your project.

For a comprehensive list of all configuration values look here.

Some plugins may utilize or require these values, so they can take certain actions based on the configuration.

You can programmatically modify these values and Cypress will then respect these changes. This enables you to swap out configuration based on things like the environment you’re running in.

The config object also includes the following extra values that are not part of the standard configuration. These values are read only and cannot be modified from the plugins file.

  • configFile: The absolute path to the config file. By default, this is <projectRoot>/cypress.json, but may be a custom path or false if using the --config-file flag.
  • projectRoot: The absolute path to the root of the project (e.g. /Users/me/dev/my-project)
  • version: The version number of Cypress. This can be used to handle breaking changes.
Please check out our API docs for modifying configuration here.

List of events

The following events are available:

Event Description
file:preprocessor Occurs when a spec or spec-related file needs to be transpiled for the browser.
before:browser:launch Occurs immediately before launching a browser.
task Occurs in conjunction with the cy.task command.
after:screenshot Occurs after a screenshot is taken.

Execution context

Your pluginsFile is invoked when Cypress opens a project.

Cypress does this by spawning an independent child_process which then requires in your pluginsFile. This is similar to the way Visual Studio Code or Atom works.

You will need to keep in mind it is Cypress who is requiring your file - not your local project, not your local Node version, and not anything else under your control.

Because of this, this global context and the version of Node is controlled under Cypress.

Node version

Keep in mind - code executed in plugins may be executed by the Node version that comes bundled in Cypress itself.

This version of Node has nothing to do with your locally installed versions. Therefore you may want to write Node code which is compatible with this version or document that the user of your plugin will need to set a specific nodeVersion in their configuration.

You can find the current Node version we use when the nodeVersion is set to the default bundled here.

npm modules

When Cypress executes your pluginsFile it will execute with process.cwd() set to your project’s path. Additionally - you will be able to require any node module you have installed.

You can also require local files relative to your project.

For example, if your package.json looked like this:

  "name": "My Project",
  "dependencies": {
    "debug": "x.x.x"
  "devDependencies": {
    "lodash": "x.x.x"

Then you could do any of the following in your pluginsFile:

// cypress/plugins/index.js

const _ = require('lodash') // yup, dev dependencies
const path = require('path') // yup, built in node modules
const debug = require('debug') // yup, dependencies
const User = require('../../lib/models/user') // yup, relative local modules

console.log(__dirname) // /Users/janelane/Dev/my-project/cypress/plugins/index.js

console.log(process.cwd()) // /Users/janelane/Dev/my-project

Error handling

Cypress spawns your pluginsFile in its own child process so it is isolated away from the context that Cypress itself runs in. That means you cannot accidentally modify or change Cypress’s own execution in any way.

If your pluginsFile has an uncaught exception, an unhandled rejection from a promise, or a syntax error - we will automatically catch those and display them to you inside of the console and even in the Test Runner itself.

Errors from your plugins will not crash Cypress.

File changes

Normally when writing code in Node, you typically have to restart the process after changing any files.

With Cypress, we automatically watch your pluginsFile and any changes made will take effect immediately. We will read the file in and execute the exported function again.

This enables you to iterate on plugin code even with Cypress already running.

© 2020 Cypress.io
Licensed under the MIT License.