---
id: app/continuous-integration/overview
title: 'Continuous Integration with Cypress: Run Tests in CI'
description: >-
  Set up Cypress in CI: install and run commands, boot your server, record to
  Cypress Cloud, run in parallel, and use Cypress Docker images on any CI
  provider.
section: app
source_path: docs/app/continuous-integration/overview.mdx
version: 3163d68b20e695f2c76d40c85c3f3b956dd19a3b
updated_at: '2026-08-21T20:59:04.402Z'
---
# Continuous Integration with Cypress

Cypress runs in any continuous integration (CI) provider, including GitHub Actions, CircleCI, GitLab CI, Jenkins, and AWS CodeBuild. Running your Cypress tests on every push and pull request catches regressions before they reach your users, and recorded results show you exactly what happened when a test fails.

Setting it up takes two commands: install Cypress, then run it. This guide covers those commands and everything around them: booting your app's server, choosing a Docker image, caching, parallelization, and setup guides for each major CI provider.

What you'll learn

*   How to install and run Cypress in any CI provider
*   How to start your app's server before running tests
*   How to record results to Cypress Cloud and run tests in parallel
*   How to pick a Cypress Docker image for a consistent test environment
*   How to configure machine resources, caching, and environment variables
*   How to troubleshoot common CI failures

## What is Continuous Integration?

Continuous integration is the practice of merging code changes into a shared repository frequently, where each change is verified by an automated build and test run. When Cypress is part of that pipeline, every commit runs your end-to-end and component tests against your application, so a change that breaks a user flow fails the build instead of shipping.

## Setting up CI

### Install and run Cypress

Running Cypress in CI is almost the same as running it locally in your terminal. You generally only need to do two things:

1.  **Install Cypress**

*   npm
*   Yarn
*   pnpm
*   Bun

```
npm install cypress --save-dev
```

```
yarn add cypress --dev
```

```
pnpm add --save-dev cypress
```

```
bun add --dev cypress
```

1.  **Run Cypress**

*   npm
*   Yarn
*   pnpm
*   Bun

```
npx cypress run
```

```
yarn cypress run
```

```
pnpm cypress run
```

```
bunx cypress run
```

Where these commands go depends on your CI provider: each defines its own configuration file format for the steps in a build. Refer to your CI provider's documentation for where to add the commands to install and run Cypress, or start from one of our [CI examples](#CI-Examples).

### Boot your server

Typically you will need to boot a local server before running Cypress. A web server is a **long running process** that never exits, so you need to run it in the **background** or your CI provider will never move on to the next command. You also need to wait for the server to be ready before Cypress starts. A command like this has a race condition:

```
npm start & npx cypress run # don't do this
```

There is no guarantee that your server has booted by the time `cypress run` executes, so your tests may try to visit your local server before it is ready. Instead of adding an arbitrary wait (like `sleep 20`), use a tool that waits for the server to respond.

If you run your tests with the official [Cypress GitHub Action](https://github.com/cypress-io/github-action), its `start` and `wait-on` options boot and wait for your server without any extra packages. See our [GitHub Actions guide](/llm/markdown/app/continuous-integration/github-actions.md).

#### `start-server-and-test` module

The [start-server-and-test](https://github.com/bahmutov/start-server-and-test) module starts your server, waits until a URL responds, runs your test command, and shuts the server down when the tests finish.

*   npm
*   Yarn
*   pnpm
*   Bun

```
npm install start-server-and-test --save-dev
```

```
yarn add start-server-and-test --dev
```

```
pnpm add --save-dev start-server-and-test
```

```
bun add --dev start-server-and-test
```

In your `package.json` scripts, pass the command that boots your server, the URL your server is hosted on, and your Cypress test command.

package.json

```
{
  "scripts": {
    "start": "my-server -p 3030",
    "cy:run": "cypress run",
    "test": "start-server-and-test start http://localhost:3030 cy:run"
  }
}
```

In the example above, the `cy:run` command will only be executed when the URL `http://localhost:3030` responds with an HTTP status code of 200. The server also shuts down when the tests complete.

**Gotchas**

When [working with `webpack-dev-server`](https://github.com/bahmutov/start-server-and-test#note-for-webpack-dev-server-users) or another server that does not respond to `HEAD` requests, use an explicit `GET` method to ping the server like this:

package.json

```
{
  "scripts": {
    "test": "start-server-and-test start http-get://localhost:3030 cy:run"
  }
}
```

When working with local `https` in webpack, set a system environment variable to allow the local certificate:

package.json

```
{
  "scripts": {
    "start": "my-server -p 3030 --https",
    "cy:run": "cypress run",
    "cy:ci": "START_SERVER_AND_TEST_INSECURE=1 start-server-and-test start https-get://localhost:3030 cy:run"
  }
}
```

#### `wait-on` module

If you'd rather manage the server process yourself, the [wait-on](https://github.com/jeffbski/wait-on) module blocks until a URL responds. Background the server, wait for it, then run Cypress:

```
npm start & npx wait-on http://localhost:8080
```

```
npx cypress run
```

Most CI providers automatically kill background processes, so you don't have to worry about cleaning up your server process once Cypress finishes.

However, if you're running this script locally you'll have to do a bit more work to collect the backgrounded PID and then kill it after `cypress run`.

#### `concurrently` module

A general-purpose process runner like [concurrently](https://github.com/open-cli-tools/concurrently) can compose the same flow: start the server and a `wait-on`\-gated test command together, kill the server when the tests finish (`-k`), and pass or fail based on the test command alone (`-s first`).

```
npx concurrently -k -s first "npm start" "npx wait-on http://localhost:8080 && npx cypress run"
```

### Record tests

Cypress can record your test runs and make the results available in [Cypress Cloud](/llm/markdown/cloud/get-started/introduction.md), giving you insight into what happened when your tests ran in CI.

Recording tests allows you to:

*   See the number of failed, pending, and passing tests.
*   Debug failures with [Test Replay](/llm/markdown/cloud/features/test-replay.md), which captures the state of your application so you can inspect the DOM, network requests, and console logs at every step of the failed test.
*   Get the entire stack trace of failed tests, or hand that same failure context to your AI coding agent through [Cypress Cloud MCP](/llm/markdown/cloud/integrations/cloud-mcp.md) so it can debug the failing run for you.
*   View screenshots taken when tests fail and when using [`cy.screenshot()`](/llm/markdown/api/commands/screenshot.md).
*   Detect and manage [flaky tests](/llm/markdown/cloud/features/flaky-test-management.md) that pass and fail across recorded runs.
*   Analyze trends in your test suite with [Analytics](/llm/markdown/cloud/features/analytics/overview.md), like run duration, most common errors, and slowest tests.
*   Generate [UI Coverage](/llm/markdown/ui-coverage/get-started/introduction.md) and [Cypress Accessibility](/llm/markdown/accessibility/get-started/introduction.md) reports from your recorded runs with no additional test code or configuration (premium solutions).
*   See which machines ran each test when [parallelized](/llm/markdown/cloud/features/smart-orchestration/parallelization.md).

To record tests:

1.  [Set up your project to record](/llm/markdown/cloud/get-started/setup.md#Setup) and copy your record key.
2.  [Pass the `--record` flag to `cypress run`](/llm/markdown/app/references/command-line.md#cypress-run) within CI, along with the record key, either inline with the `--key` flag or via the [`CYPRESS_RECORD_KEY` environment variable](#Environment-variables).

*   npm
*   Yarn
*   pnpm
*   Bun

```
npx cypress run --record --key=abc123
```

```
yarn cypress run --record --key=abc123
```

```
pnpm cypress run --record --key=abc123
```

```
bunx cypress run --record --key=abc123
```

[Read the full guide on Cypress Cloud.](/llm/markdown/cloud/get-started/introduction.md)

### Run tests in parallel

Cypress can run tests in parallel across multiple machines, cutting your total run time roughly in proportion to the number of machines.

You'll want to refer to your CI provider's documentation on how to set up multiple machines to run in your CI environment.

Once multiple machines are available within your CI environment, you can pass the [\--parallel](/llm/markdown/app/references/command-line.md#cypress-run-parallel) flag to have your tests run in parallel. Parallelization requires recording to [Cypress Cloud](/llm/markdown/cloud/get-started/introduction.md), which load-balances specs across your machines.

*   npm
*   Yarn
*   pnpm
*   Bun

```
npx cypress run --record --key=abc123 --parallel
```

```
yarn cypress run --record --key=abc123 --parallel
```

```
pnpm cypress run --record --key=abc123 --parallel
```

```
bunx cypress run --record --key=abc123 --parallel
```

[Read the full guide on parallelization.](/llm/markdown/cloud/features/smart-orchestration/parallelization.md)

## Cypress Docker Images

CI providers, such as [GitHub Actions](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container) and [CircleCI](https://circleci.com/docs/executor-intro/#docker), allow workflows to run using [Docker container images](https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/).

Cypress supports the use of [Docker](https://docs.docker.com/get-started/docker-overview/) through the provisioning of official [Cypress Docker images](https://github.com/cypress-io/cypress-docker-images). Images are Linux-based and support the following platforms:

*   Linux/amd64
*   Linux/arm64

Cypress Docker images provide a consistent environment tailored for use with Cypress. By choosing an appropriate Cypress Docker image, you determine the exact environment that your Cypress tests run in. This shields your workflows from version updates made by your CI provider, for instance if they update Node.js or browser versions.

Cypress Docker images are available from:

*   [Docker Hub](https://hub.docker.com/u/cypress)
*   [Amazon ECR (Elastic Container Registry) Public Gallery](https://gallery.ecr.aws/cypress-io)

### Cypress Docker variants

*   [cypress/base](https://github.com/cypress-io/cypress-docker-images/tree/master/base) is the entry-level Cypress Docker image, allowing you to test in the Electron browser, built in to Cypress. It contains a complete Linux (Debian) operating system, together with the [prerequisite operating system packages](/llm/markdown/app/get-started/install-cypress.md#UbuntuDebian) for Cypress, Node.js, npm and Yarn v1 Classic. An image `<tag>` gives you the choice of Node.js version.
    
*   [cypress/browsers](https://github.com/cypress-io/cypress-docker-images/tree/master/browsers) builds on the [cypress/base](https://github.com/cypress-io/cypress-docker-images/tree/master/base) image. For `Linux/amd64` images it adds **Chrome**, **Firefox** and **Edge** browsers. For `Linux/arm64` images it adds **Firefox** browsers from version `136` and above, and **Chrome** browsers from version `151` and above. Edge browsers are currently not available for `Linux/arm64`. A corresponding image `<tag>` allows selection of the combined Node.js and browser versions. The version tag for the unavailable Edge browser on the `Linux/arm64` platform is an empty place-holder only, required for multi-platform support compatibility.
    
*   [cypress/included](https://github.com/cypress-io/cypress-docker-images/tree/master/included) builds on the [cypress/browsers](https://github.com/cypress-io/cypress-docker-images/tree/master/browsers) image. It adds a fixed version of **Cypress**, globally installed by npm. A short-form image `<tag>` selects the version of Cypress. A corresponding long-form `<tag>` selects the version of Cypress and documents the combined Node.js and browser versions.
    
*   [cypress/factory](https://github.com/cypress-io/cypress-docker-images/tree/master/factory) provides the base operating system image and allows individual selection of other components by version. It is used to generate customized Docker images.
    

### CI Docker examples

You can find examples that use Cypress Docker images below:

*   [cypress-docker-images examples](https://github.com/cypress-io/cypress-docker-images/blob/master/README.md#examples)
*   [cypress-example-kitchensink](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/README.md)
*   [Real World App - CircleCI](https://github.com/cypress-io/cypress-realworld-app/blob/develop/.circleci/config.yml)
*   [Real World App - GitHub Actions](https://github.com/cypress-io/cypress-realworld-app/blob/develop/.github/workflows/main.yml)
*   [cypress-docker-images - GitHub Actions](https://github.com/cypress-io/cypress-docker-images/blob/master/.github/workflows/example-cypress-github-action.yml)

## CI Examples

We maintain in-depth setup guides for the most popular CI providers, and working example configurations for many others.

### AWS Amplify Console

*   [Basic Example (amplify.yml)](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/amplify.yml)

### AWS CodeBuild

Read our extensive guide on how to set up Cypress in [AWS CodeBuild](/llm/markdown/app/continuous-integration/aws-codebuild.md).

### Azure Pipelines

*   [Basic Example (azure-ci.yml)](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/basic/azure-ci.yml)
*   [Parallelized Example (azure-ci.yml)](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/azure-ci.yml)

### Bitbucket Pipelines

Read our extensive guide on how to set up Cypress in [Bitbucket Pipelines](/llm/markdown/app/continuous-integration/bitbucket-pipelines.md).

### Buildkite

*   [Parallel Example](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/.buildkite/pipeline.yml)

### CircleCI

Read our extensive guide on how to set up Cypress in [CircleCI](/llm/markdown/app/continuous-integration/circleci.md).

### GitHub Actions

Read our extensive guide on how to set up Cypress in [GitHub Actions](/llm/markdown/app/continuous-integration/github-actions.md).

### GitLab

Read our extensive guide on how to set up Cypress in [GitLab](/llm/markdown/app/continuous-integration/gitlab-ci.md).

### Jenkins

*   [Basic Jenkinsfile](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/basic/Jenkinsfile)
*   [Parallel Jenkinsfile](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/Jenkinsfile)

### Netlify

Use our official [netlify-plugin-cypress](https://github.com/cypress-io/netlify-plugin-cypress) to execute end-to-end tests before and after deployment to the Netlify platform.

### Semaphore

*   [Basic .semaphore.yml](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/basic/.semaphore.yml)
*   [Parallel .semaphore.yml](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/.semaphore/semaphore.yml)

### TravisCI

*   [Basic .travis.yml](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/basic/.travis.yml)
*   [Parallel .travis.yml](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/.travis.yml)

## Advanced setup

### Machine requirements

Hardware requirements to run Cypress depend on how much memory the browser, the application under test, and the server (if running it locally) need to run the tests without crashing. Visit our [System Requirements](/llm/markdown/app/get-started/install-cypress.md#System-requirements) guide for minimum hardware recommendations.

**Some signs that your machine may not have enough CPU or memory to run Cypress:**

*   The recorded video artifacts have random pauses or dropped frames.
*   [Debug logs of the CPU and memory](/llm/markdown/app/references/troubleshooting.md#Log-memory-and-CPU-usage) frequently show CPU percent above 100%.
*   The browser crashes.

You can see the total available machine memory and the current free memory by running the [`cypress info`](/llm/markdown/app/references/command-line.md#cypress-info) command.

```
npx cypress info
...
Cypress Version: 15.18.1 (stable)
System Platform: linux (Debian - 12)
System Memory: 73.6 GB free 48.6 GB
```

You can see the CPU parameters on the CI machines by executing the command below.

```
node -p 'os.cpus()'
[
  {
    model: 'Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz',
    speed: 3399,
    times: { user: 760580, nice: 1010, sys: 158130, idle: 1638340, irq: 0 }
  }
  ...
]
```

**Example projects and the machine configurations used to run them on CI:**

*   The [Real World App](https://github.com/cypress-io/cypress-realworld-app) project runs tests on a CircleCI machine using the [Docker executor](https://circleci.com/docs/executor-intro/#docker) with [`resource_class: large`](https://circleci.com/docs/configuration-reference/#docker-execution-environment) providing 4 vCPUs and 8 GB of RAM. `cypress info` reports `System Memory: 73.6 GB free 48.6 GB`.
*   The [Real World App](https://github.com/cypress-io/cypress-realworld-app) project also executes its tests on [GitHub Actions](https://docs.github.com/en/actions) using the [Cypress GitHub Action](https://github.com/cypress-io/github-action) with the [standard Ubuntu GitHub-hosted runner for Public repositories](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners) providing 4 vCPUs and 16 GB of RAM. `cypress info` reports `System Memory: 16.8 GB free 15.5 GB` with CPUs reported as `AMD EPYC 7763 64-Core Processor`.

**Tip:** if there are problems with longer specs, try splitting them into shorter ones.

### Dependencies

Cypress runs on many CI providers' virtual machine environments out-of-the-box without needing additional dependencies installed.

#### Linux

If you see a message about a missing dependency when you run Cypress in a Linux CI environment, then refer to the [Linux Prerequisites](/llm/markdown/app/get-started/install-cypress.md#Linux-Prerequisites) lists for guidance.

### Caching

Cypress downloads its binary to the global system cache - on Linux that is `~/.cache/Cypress`. By ensuring this cache persists across builds you can save minutes off install time by preventing a large binary download.

We recommend that you:

*   Cache the `~/.cache` folder after running `npm install`, `yarn`, [`npm ci`](https://docs.npmjs.com/cli/ci) or equivalents as demonstrated in the configs below.
    
*   **Do not** cache `node_modules` across builds. Instead, cache the package manager's own cache directory (`~/.npm` for npm or `~/.cache/yarn` for yarn). These tools maintain package-level caches that track installed versions, validate integrity, and only re-download packages that have changed. Caching `node_modules` directly bypasses these built-in mechanisms and can cause issues such as Cypress not downloading the Cypress binary on `npm install`.
    
*   If you are using `npm install` in your build process, consider [switching to `npm ci`](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable) and caching the `~/.npm` directory for a faster and more reliable build.
    
*   If you are using `yarn`, caching `~/.cache` will include both the `yarn` and Cypress caches. Consider using `yarn install --frozen-lockfile` as an [`npm ci`](https://docs.npmjs.com/cli/ci) equivalent.
    
*   If you need to override the binary location for some reason, use the [CYPRESS\_CACHE\_FOLDER](/llm/markdown/app/references/advanced-installation.md#Binary-cache) environment variable.
    
*   Make sure you are not restoring the previous cache using lax keys; then the Cypress binaries can "snowball", accumulating every version you have ever installed.
    

**Tip:** you can find lots of CI examples with configured caching in our [cypress-example-kitchensink](https://github.com/cypress-io/cypress-example-kitchensink#ci-status) repository.

### Environment variables

You can set various environment variables to modify how Cypress runs.

#### Configuration Values

You can set any [configuration value](/llm/markdown/app/references/configuration.md) as an environment variable by prefixing it with `CYPRESS_`. This overrides values in the Cypress configuration.

**_Typical use cases would be modifying things like:_**

*   `CYPRESS_BASE_URL` - point tests at a preview or staging deployment
*   `CYPRESS_REPORTER` - switch to a CI-friendly reporter like `junit`
*   `CYPRESS_DEFAULT_COMMAND_TIMEOUT` - allow more time on slower CI machines
*   `CYPRESS_VIEWPORT_WIDTH` and `CYPRESS_VIEWPORT_HEIGHT` - vary the screen size per CI job

The install-time variable [`CYPRESS_INSTALL_BINARY`](/llm/markdown/app/references/advanced-installation.md#Download-URLs) is also commonly set in CI, to skip or redirect the binary download.

Refer to the [Environment Variables recipe](/llm/markdown/app/references/configuration.md#Environment-Variables) for more examples.

**_Record Key_**

If you are [recording your runs](#Record-tests) on a public project, you'll want to protect your Record Key. [Learn why.](/llm/markdown/cloud/account-management/projects.md#Identification)

Instead of hard coding it into your run command like this:

*   npm
*   Yarn
*   pnpm
*   Bun

```
npx cypress run --record --key abc-key-123
```

```
yarn cypress run --record --key abc-key-123
```

```
pnpm cypress run --record --key abc-key-123
```

```
bunx cypress run --record --key abc-key-123
```

You can set the record key as the environment variable `CYPRESS_RECORD_KEY` and we'll automatically use that value. You can now omit the `--key` flag when recording.

*   npm
*   Yarn
*   pnpm
*   Bun

```
npx cypress run --record
```

```
yarn cypress run --record
```

```
pnpm cypress run --record
```

```
bunx cypress run --record
```

Set `CYPRESS_RECORD_KEY` in your CI provider's settings as a secret or masked environment variable so it doesn't appear in your configuration files or build logs.

`CYPRESS_RECORD_KEY` must be set as an actual operating system environment variable (for example via `export CYPRESS_RECORD_KEY=...` or your CI provider's secrets). Cypress reads it directly from your shell or CI environment — it is **not** read from `cypress.env.json` or the `env` block of your Cypress configuration, since those only populate test environment variables. If you don't want to set an environment variable, pass the key inline with the `--key` flag instead.

#### Git information

Cypress assumes there is a `.git` folder and uses Git commands to get each property, like `git show -s --pretty=%B` to get the commit message.

Under some environment setups (e.g. `docker`/`docker-compose`) if the `.git` directory is not available or mounted, you can pass all git related information under custom system environment variables.

*   Branch: `COMMIT_INFO_BRANCH`
*   Message: `COMMIT_INFO_MESSAGE`
*   Author email: `COMMIT_INFO_EMAIL`
*   Author: `COMMIT_INFO_AUTHOR`
*   SHA: `COMMIT_INFO_SHA`
*   Remote: `COMMIT_INFO_REMOTE`

If the commit information is missing in the Cypress Cloud run then [GitHub Integration](/llm/markdown/cloud/integrations/github.md) or other tasks might not work correctly. To see the relevant Cypress debug logs, set the system environment variable `DEBUG` on your CI machine and inspect the terminal output to see why the commit information is unavailable.

```
DEBUG=cypress:server:record
```

**_Source control credentials_**

The remote origin Cypress records comes from `git config --get remote.origin.url`, and some CI providers authenticate the checkout by embedding a token in that URL. Any credential sitting there is readable by every later step in the job and becomes part of the recorded run.

Use your CI provider's standard checkout authentication rather than supplying your own long-lived token. Providers issue credentials that expire when the job ends, such as the GitHub Actions `GITHUB_TOKEN`, the GitLab CI/CD job token, a CircleCI checkout key, or the Azure Pipelines `System.AccessToken`. Substituting a personal access token puts a credential that lasts months in the same exposed position.

If your checkout leaves a credential in the remote URL, set `COMMIT_INFO_REMOTE` to a clean URL so the recorded remote does not include it. On GitLab CI, for example, `CI_PROJECT_URL` has no token in it:

```
export COMMIT_INFO_REMOTE="$CI_PROJECT_URL.git"
```

#### CI Build Information

In some newer CI providers, Cypress can't map the system environment variables required to link back to builds or pull requests. In this case we provide users some environment variables to help pass that information along.

*   Pull Request Id: `CYPRESS_PULL_REQUEST_ID`
*   Pull Request URL: `CYPRESS_PULL_REQUEST_URL`
*   Build URL: `CYPRESS_CI_BUILD_URL`

Setting these will allow links within the Cloud run to take you to the appropriate place.

#### Custom Environment Variables

You can also set custom values for use in your tests. Which API you use depends on whether the value is sensitive.

**_Private values: `cy.env()`_**

For secrets like API tokens, set an OS environment variable prefixed with `CYPRESS_` using your CI provider's secret or masked variable settings:

```
export CYPRESS_SERVICE_API_TOKEN=secret-token-123
```

Cypress strips the prefix, and your tests read the value with [`cy.env()`](/llm/markdown/api/commands/env.md), which retrieves only the values you request without serializing them into browser state:

```
cy.env(['SERVICE_API_TOKEN']).then(({ SERVICE_API_TOKEN }) => {
  cy.request({
    url: 'https://api.example.com/users',
    headers: { Authorization: `Bearer ${SERVICE_API_TOKEN}` },
  })
})
```

**_Public values: `Cypress.expose()`_**

For non-sensitive configuration that is safe to appear in browser state, like feature flags or API versions, pass values with the `--expose` CLI flag:

*   npm
*   Yarn
*   pnpm
*   Bun

```
npx cypress run --expose apiVersion=v2,featureFlag=true
```

```
yarn cypress run --expose apiVersion=v2,featureFlag=true
```

```
pnpm cypress run --expose apiVersion=v2,featureFlag=true
```

```
bunx cypress run --expose apiVersion=v2,featureFlag=true
```

and read them synchronously with [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md):

```
const apiVersion = Cypress.expose('apiVersion') // => 'v2'
```

Refer to the dedicated [Environment Variables & Secrets guide](/llm/markdown/app/guides/environment-variables.md) for more examples.

### Module API

Oftentimes it can be less complex to programmatically control and boot your servers with a Node script.

If you're using our [Module API](/llm/markdown/app/references/module-api.md) then you can write a script that boots and then shuts down the server later. As a bonus, you can work with the results and do other things.

scripts/run-cypress-tests.js

```
const cypress = require('cypress')
const server = require('./lib/my-server')

;(async () => {
  await server.start()

  // kick off a cypress run
  const results = await cypress.run()

  // stop your server when it's complete
  await server.stop()
})()
```

```
node scripts/run-cypress-tests.js
```

## Common problems and solutions

### Missing binary

When npm or yarn install the `cypress` package, a `postinstall` hook is executed that downloads the platform-specific Cypress binary. If the hook is skipped for any reason the Cypress binary will be missing (unless it was already cached).

To better diagnose the error, add [commands to get information about the Cypress cache](/llm/markdown/app/references/command-line.md#cypress-cache-command) to your CI setup. This will print where the binary is located and what versions are already present.

*   npm
*   Yarn
*   pnpm
*   Bun

```
npx cypress cache path
npx cypress cache list
```

```
yarn cypress cache path
yarn cypress cache list
```

```
pnpm cypress cache path
pnpm cypress cache list
```

```
bunx cypress cache path
bunx cypress cache list
```

If the required binary version is not found in the cache, you can try the following:

1.  Clean your CI's cache using your CI's settings to force a clean `npm install` on the next build.
2.  Run the binary install yourself by adding the command `npx cypress install` to your CI script. If there is a binary already present, it should finish quickly.

### Xvfb

When running on Linux, Cypress needs an X11 server; otherwise it spawns its own X11 server during the test run. When running several Cypress instances in parallel, the spawning of multiple X11 servers at once can cause problems for some of them. In this case, you can separately start a single X11 server and pass the server's address to each Cypress instance using the `DISPLAY` variable.

First, spawn the X11 server in the background at some port, for example `:99`. If you have installed `xvfb` on Linux or if you are using one of our Docker images from [cypress-docker-images](https://github.com/cypress-io/cypress-docker-images), the tools below should be available.

```
Xvfb :99 &
```

Second, set the X11 address in a system environment variable

```
export DISPLAY=:99
```

Start Cypress as usual

*   npm
*   Yarn
*   pnpm
*   Bun

```
npx cypress run
```

```
yarn cypress run
```

```
pnpm cypress run
```

```
bunx cypress run
```

After all tests across all Cypress instances finish, kill the Xvfb background process using `pkill`

```
pkill Xvfb
```

In certain Linux environments, you may experience connection errors with your X11 server. In this case, you may need to start Xvfb with the following command:

```
Xvfb -screen 0 1024x768x24 :99 &
```

Cypress internally passes these Xvfb arguments, but if you are spawning your own Xvfb, you would need to pass these arguments. This is necessary to avoid using 8-bit color depth with Xvfb, which will prevent Chrome or Electron from crashing.

### Colors

If you want colors to be disabled, you can pass the `NO_COLOR` environment variable to disable colors. You may want to do this if ASCII characters or colors are not properly formatted in your CI.

```
NO_COLOR=1 cypress run
```

## See also

*   [Cypress Real World App](https://github.com/cypress-io/cypress-realworld-app) runs parallelized CI jobs across multiple operating systems, browsers, and viewport sizes.
*   [cypress-example-kitchensink](https://github.com/cypress-io/cypress-example-kitchensink#ci-status) is set up to run on multiple CI providers.
*   [Command Line](/llm/markdown/app/references/command-line.md) - all `cypress run` flags and options
*   [Test Replay](/llm/markdown/cloud/features/test-replay.md)
*   [Cross Browser Testing Guide](/llm/markdown/app/guides/cross-browser-testing.md)
