This guide is for engineers, architects, and operators who need to understand how Cypress works internally: how the binary boots, how the proxy intercepts and rewrites traffic, how the browser-side driver talks to the Node server, how the GUI is built, and how to operate, secure, and contribute to the project. It is derived directly from the Cypress monorepo source at commit 1f8ff3b.
For day-to-day test authoring (commands, configuration, CLI flags), see the companion Cypress User Guide. This document focuses on the system, not the API.
1. Executive Summary
Cypress is a browser-based test runner distributed as two things:
- A small npm package (
cypress) that installs, verifies, and launches a binary. - A self-contained binary — an Electron application that bundles a Node server, an HTTP/HTTPS proxy, a browser-side driver, and a Vue-based GUI.
The architectural keystone is that test code runs inside the browser, in the same event loop as the application under test (AUT), while a Node process behind a proxy gives Cypress full control over the network, the filesystem, and the browser automation protocol.
| Attribute | Value (from source) |
|---|---|
| Language | TypeScript / JavaScript (primary), with some Vue, SCSS |
| Repository shape | Monorepo (Yarn workspaces): packages/*, npm/*, cli/, tooling/, system-tests/ |
| Total source | ~8.98M characters across 7,015 files |
| Node engine | >= 22.19.0 |
| Bundled browser | Electron (also drives Chrome, Edge, Firefox; WebKit experimental) |
| Process model | Electron main (Node) + renderer (GUI) + browser (AUT) + spawned children |
| GUI stack | Vue 3 + GraphQL (Nexus) + Vite dev server |
| Test runtime | Mocha (structure) + Chai (assertions) + jQuery/Sizzle (DOM) + Sinon (stubs) |
Note
"Cypress the product" and "the Cypress monorepo" are different scopes. The npm-published
cypresspackage is a thin downloader/launcher; the testing engine lives inpackages/*and is compiled into the binary. This guide covers both.
2. System Architecture
2.1 High-level component map
┌─────────────────────────────────────────────────────────────────────────┐
│ cypress (npm package) — cli/ │
│ commander CLI → downloads/verifies binary → spawns it (execa, xvfb) │
└───────────────────────────────┬───────────────────────────────────────────┘
│ spawn binary with args
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ ELECTRON MAIN (Node) — packages/server, packages/electron │
│ │
│ cypress.ts (mode dispatch: run | interactive | info | version | ...) │
│ │ │
│ ├── OpenProject / ProjectBase (project lifecycle, config) │
│ ├── ServerBase (HTTP server + static AUT serving) │
│ │ └── NetworkProxy (packages/proxy) → Http request pipeline │
│ │ ├── https-proxy (CA + MITM TLS) │
│ │ └── network (CombinedAgent, client certs, CA) │
│ ├── SocketBase → SocketE2E / SocketCt (socket.io to the browser) │
│ ├── DataContext + GraphQL (Nexus) (state for the GUI) │
│ └── automation / browsers (CDP / WebDriver / Electron) │
└──────────┬───────────────────────────────────────┬────────────────────────┘
│ socket.io (automation, run events) │ serves GUI + AUT
▼ ▼
┌────────────────────────┐ ┌──────────────────────────────────────┐
│ GUI (renderer) │ │ BROWSER (Chrome/Electron/FF/Edge) │
│ packages/app + │ │ ┌─────────────────────────────────┐ │
│ packages/launchpad │ │ │ runner: hosts AUT <iframe> │ │
│ (Vue 3, GraphQL) │ │ │ driver: cy.* commands, spec │ │
│ packages/reporter │ │ │ reporter: command log │ │
│ (command log) │ │ └─────────────────────────────────┘ │
└────────────────────────┘ └──────────────────────────────────────┘
2.2 The two "sides" of Cypress
Cypress's defining trait is the split between the browser side and the server side, bridged by a socket connection.
- Browser side (
packages/driver,packages/runner,packages/reporter): Runs inside the test browser. The driver is the engine that executescy.*commands, manages the command queue, retries queries/assertions, and synchronizes with the AUT, which it hosts in an iframe. The runner wires the AUT iframe to the driver and reporter; the reporter renders the live command log. - Server side (
packages/serverand friends): Runs in Node inside Electron's main process. It serves the GUI and the AUT, proxies and (optionally) rewrites all HTTP/HTTPS traffic, performs browser automation (cookies, screenshots, downloads) over CDP/WebDriver, and exposes thecy.task/cy.exec/file APIs that need Node.
The two sides communicate over socket.io (SocketBase → SocketE2E/SocketCt): the browser asks the server to perform automation actions and backend events; the server pushes run lifecycle events back.
2.3 Boot sequence
- The user runs
npx cypress run|open. The CLI (cli/lib/cli.ts, commander-based) parses flags, thencli/lib/exec/locates the cached binary and spawns it viaexeca(wrapping withxvfbon headless Linux). - The binary boots Electron.
packages/server/lib/cypress.tsresolves a mode (run,interactive,info,version,record,smokeTest, …) and calls./modes. - To keep Electron boot fast, requires are deliberately lazy — the entry comment notes that eagerly requiring everything up front wastes ~1.5s before the correct mode is even known. (Startup is further accelerated by V8 snapshots — see §7.)
- The mode resolves project config (
packages/config), constructs anOpenProject/ProjectBase, starts aServerBasewith itsNetworkProxy, opens the chosen browser, and either drives a headless run or hands control to the GUI.
Important
runElectron()checks whether it is already running inside Electron. In production the binary is Electron, so it runs the mode in-process; in dev it spawns a child Electron process. This dual path is why some operations are described as "spawn a new child process" in the code.
3. Package Inventory
The monorepo is organized into four workspace roots. The most architecturally significant packages:
3.1 packages/ — the engine
| Package | Role |
|---|---|
server |
Node core: mode dispatch, project lifecycle, HTTP server, automation, sockets, sessions, screenshots, video, reporter bridge |
driver |
Browser-side command engine: the cy.* API, command queue, retry-ability, assertions, AUT management |
runner |
Hosts the AUT iframe; injects the driver; coordinates runner/reporter |
reporter |
Vue command-log UI (the left-hand panel) |
app |
The main Cypress App GUI (Vue 3) — spec list, runner page, settings, debug |
launchpad |
The pre-project GUI (Vue 3) — choose testing type, browser, onboarding |
frontend-shared |
Shared Vue components, GraphQL client, theming used by app + launchpad |
data-context |
Central server-side state + GraphQL (Nexus) schema backing the GUI |
proxy |
The NetworkProxy / Http request pipeline |
https-proxy |
MITM HTTPS proxy with on-the-fly certificate generation (CA, Server) |
network |
HTTP agents (CombinedAgent, HttpAgent, HttpsAgent), CA handling, client certificates |
network-interception / network-tools |
Lower-level interception helpers, document-domain injection, remote-state tracking |
net-stubbing |
The server/proxy half of cy.intercept |
rewriter |
Rewrites HTML/JS responses (e.g. obstructive code, source rewriting) with deferred source maps |
config |
The configuration schema (options.ts), validation, AST utilities for editing config files |
scaffold-config |
Detects frameworks/bundlers and scaffolds component-testing config |
errors |
The templated, typed error system (errTemplate) |
types |
Public TypeScript types shared across packages |
socket |
socket.io wrapper (custom parser for large attachments) |
launcher |
Browser detection and launching |
electron |
Electron app wrapper and window management |
telemetry |
OpenTelemetry spans/exporters (opt-in) |
extension |
Browser extension (cookie/automation helpers for some browsers) |
packherd-require |
Custom module loader with transpile caching |
v8-snapshot-require |
Runtime support for V8-snapshot startup |
stderr-filtering |
Stream transforms that filter noisy child-process stderr |
3.2 npm/ — published companion packages
These are published to npm separately and are what users add for component testing and plugins:
@cypress/react, @cypress/vue, @cypress/angular (+ @cypress/angular-zoneless), @cypress/svelte, @cypress/mount-utils, @cypress/vite-dev-server, @cypress/webpack-dev-server, @cypress/webpack-preprocessor, @cypress/webpack-batteries-included-preprocessor, @cypress/vite-plugin-cypress-esm, @cypress/grep, @cypress/puppeteer, @cypress/xpath, @cypress/schematic, @cypress/eslint-plugin-dev.
3.3 cli/ — the npm-published launcher
The cypress npm package itself. Responsibilities: parse the CLI (commander), download/verify/manage the binary, and spawn it. Notable dependencies: commander (CLI), execa (spawn), @cypress/xvfb (virtual display on Linux), listr2 (install progress), cachedir (binary cache location), proxy-from-env (honor proxy vars), yauzl (unzip the binary), tmp, fs-extra.
3.4 tooling/ — build & startup tooling
| Tool | Purpose |
|---|---|
v8-snapshot |
Builds a V8 heap snapshot of the module graph for fast Electron startup |
packherd |
Bundles/loads modules with a transpile cache, the basis for snapshot-aware requiring |
electron-mksnapshot |
Generates the Electron-compatible V8 snapshot blob |
3.5 system-tests/ — end-to-end test harness
A very large directory (the single largest contributor to source size, dominated by __snapshots__/). It contains fixture projects (projects/*), framework integration fixtures (project-fixtures/*), and the harness (system-tests/lib/) that boots real Cypress against those projects and diffs output against snapshots. It is test infrastructure, not product code.
Note
When auditing or porting the engine, you can largely ignore
system-tests/and anypackages/**/cypress/e2e/**directory — those are Cypress testing itself, not the runtime users execute.
4. The Network Proxy (Core Subsystem)
Cypress routes all AUT traffic through its own proxy. This is what enables cy.intercept, cookie/automation control, cross-origin testing, and HTML/JS rewriting.
4.1 Request pipeline
ServerBase (packages/server/lib/server-base.ts) owns a NetworkProxy (packages/proxy/lib/network-proxy.ts). Every browser request enters NetworkProxy.handleHttpRequest(req, res), which delegates to an internal Http pipeline (packages/proxy/lib/http). The pipeline runs request middleware then response middleware, with hooks for:
- Matching
cy.interceptroute matchers and applying stubs/overrides (vianet-stubbing). - Tracking pre-requests from the browser via CDP so the proxy can correlate browser requests with proxied ones (
addPendingBrowserPreRequest). - Service worker awareness (registration/version/client tracking) so intercepts and credentials behave correctly when a SW is in play.
- Resource-type and credential-level classification (
resourceTypeAndCredentialManager) to decide cookie/credential handling per request.
4.2 HTTPS interception
packages/https-proxy performs a man-in-the-middle on TLS so Cypress can inspect and rewrite HTTPS traffic. The CA class (https-proxy/lib/ca.ts) generates and caches a root certificate plus per-host leaf certificates on demand; the Server class terminates TLS using those certs and forwards to the upstream.
4.3 Agents, CA bundles, client certs
packages/network provides the HTTP layer:
CombinedAgentdispatches toHttpAgent/HttpsAgentbased on protocol.- CA resolution honors npm/Node CA settings:
npm_config_cafile,npm_config_ca, andNODE_EXTRA_CA_CERTS. ClientCertificates/ClientCertificateStoreimplement theclientCertificatesconfig option, matching per-URL certs (PEM or PFX) using aUrlMatcher.
4.4 Response rewriting
packages/rewriter modifies responses in flight. With modifyObstructiveCode (default true), it strips frame-busting / top-comparison code that would break running the app inside Cypress's iframe. experimentalSourceRewriting and experimentalModifyObstructiveThirdPartyCode extend this. A DeferredSourceMapCache keeps source maps accurate after rewriting.
Warning
Because Cypress MITMs HTTPS and rewrites responses, it is unsuitable as a general-purpose proxy and must only run against environments you control or are authorized to test. The generated root CA is trusted only within the Cypress-launched browser profile.
5. Browser Automation & Multi-Origin
5.1 Automation layer
The server's automation layer (packages/server/lib/automation/) performs actions the browser-side driver cannot do alone: reading/writing cookies, taking screenshots, handling downloads, and clearing browser state. The browser requests these over socket.io; the server fulfills them via the browser's debugging protocol (CDP for Chromium/Electron, WebDriver BiDi/classic for Firefox, the packages/extension for some cases).
5.2 Sockets
SocketBase (socket-base.ts) is the shared socket.io server; SocketE2E and SocketCt specialize it for the two testing types. The custom socket parser (packages/socket) uses an UnlimitedAttachmentsDecoder to handle large binary payloads (e.g. screenshots) without the default attachment cap.
5.3 cy.origin and remote state
Cross-origin testing is coordinated by RemoteStates (network-tools/lib/remote-states.ts) plus document-domain injection (DocumentDomainBehavior / OriginBehavior). When a test enters cy.origin(), Cypress spins up a secondary driver in the target origin and proxies commands to it, keeping the primary spec frame in control. injectDocumentDomain and experimentalSkipDomainInjection tune how document.domain is handled (the former is being phased out as Chrome deprecates document.domain mutation).
5.4 Sessions
cy.session is backed server-side by session.ts and client-side by driver/src/cy/commands/sessions/. Sessions cache cookies, localStorage, and sessionStorage keyed by an id, restoring them between tests to avoid repeated logins. testIsolation (default true) controls whether browser state is reset before each test, which interacts directly with session restoration.
6. The GUI & Data Layer
6.1 GraphQL-backed state
packages/data-context (DataContext, DataActions, GlobalPubSub) is the single source of truth for GUI state on the server side. It exposes a GraphQL API built with Nexus (data-context/graphql, schema in data-context/schemas). The GUI (a Vue 3 app) queries and mutates through this schema; GlobalPubSub pushes live updates (e.g. spec file changes, run progress).
6.2 Two front-ends
- Launchpad (
packages/launchpad): the onboarding/selection GUI shown before a project is open — pick E2E vs Component, choose a browser, scaffold config. - App (
packages/app): the main GUI after a project opens — spec explorer, the runner page (which embedsrunner+reporter), settings, and the debug/Cloud panels.
Both share packages/frontend-shared (components, GraphQL client, theming). In development they are served by Vite; the server proxies the dev server through internal routes (CYPRESS_INTERNAL_VITE_* env vars).
6.3 Internal routes
The server mounts internal routes under reserved prefixes (the namespace config defaults to __cypress): /__cypress/assets/*, /__launchpad/*, /__cypress-studio/*, /__cypress-cy-prompt/*, plus a GraphQL endpoint and a socket route (/__socket). These never collide with the AUT because of the namespace prefix.
7. Startup Performance: V8 Snapshots
Cold-start time matters for a tool launched constantly in CI. Cypress addresses it with V8 snapshots:
tooling/packherd+packages/packherd-requireprovide a module loader with a transpile cache (DefaultTranspileCache) and aPackherdModuleLoaderthat can resolve modules from a precomputed map (DependencyMap).tooling/v8-snapshotbuilds a snapshot of the initialized module graph;tooling/electron-mksnapshotturns it into an Electron-loadable blob;packages/v8-snapshot-requirewires requiring to read from the snapshot at runtime.SNAPSHOT_BUNDLER,DISABLE_SNAPSHOT_REQUIRE, andPROJECT_BASE_DIRare the relevant build/runtime toggles.
The lazy-require strategy in cypress.ts complements this: even with snapshots, the entry avoids pulling in mode-specific code until the mode is known.
Tip
If you are debugging a "works from source but not from binary" issue, suspect the snapshot/packherd layer.
DISABLE_SNAPSHOT_REQUIRE=1forces normal Node requiring and is the first thing to try when module resolution behaves differently in the packaged binary.
8. Configuration Reference (Complete)
Configuration is defined in packages/config/src/options.ts as an array of { name, defaultValue, validation, ... } records. getPublicConfigKeys() distinguishes user-facing options from internal/runtime ones; unknown keys passed via CLI trigger an INVALID_CONFIG_OPTION warning.
8.1 Public (user-facing) options
| Option | Default | Notes |
|---|---|---|
animationDistanceThreshold |
5 |
px of movement still considered "animating" |
baseUrl |
null |
URL prefix for cy.visit/cy.request |
blockHosts |
null |
Glob list of hosts to block |
chromeWebSecurity |
true |
Chromium same-origin security |
clientCertificates |
[] |
Per-URL client certs |
defaultBrowser |
null |
Preferred browser |
defaultCommandTimeout |
4000 |
ms; most commands/assertions |
downloadsFolder |
cypress/downloads |
|
env |
{} |
User env values (read via Cypress.env) |
execTimeout |
60000 |
ms; cy.exec |
fileServerFolder |
'' |
Static file server root |
fixturesFolder |
cypress/fixtures |
|
excludeSpecPattern |
type-dependent | Specs to ignore |
includeShadowDom |
false |
Query into shadow roots by default |
justInTimeCompile |
true |
Compile specs on demand |
keystrokeDelay |
0 |
ms between simulated keystrokes |
modifyObstructiveCode |
true |
Strip frame-busting code |
numTestsKeptInMemory |
50 |
Snapshots kept in memory |
pageLoadTimeout |
60000 |
ms; page transitions |
port |
null |
Fixed server port |
projectId |
null |
Cypress Cloud project id |
redirectionLimit |
20 |
Max redirects |
reporter |
'spec' |
Mocha reporter |
reporterOptions |
null |
Reporter config |
requestTimeout |
5000 |
ms; request stage |
responseTimeout |
30000 |
ms; response stage |
retries |
{ runMode: 0, openMode: 0 } |
Auto test retries |
screenshotOnRunFailure |
true |
Auto-screenshot on failure |
screenshotsFolder |
cypress/screenshots |
|
scrollBehavior |
'top' |
Pre-action scroll |
slowTestThreshold |
10000 (E2E) / 250 (CT) |
ms |
supportFile |
type-dependent | Loaded before every spec |
supportFolder |
false |
|
taskTimeout |
60000 |
ms; cy.task |
testIsolation |
true |
Reset state per test |
trashAssetsBeforeRuns |
true |
Clear assets before run |
userAgent |
null |
Override UA |
video |
false |
Record run video |
videoCompression |
false |
CRF value or false |
videosFolder |
cypress/videos |
|
viewportHeight |
660 (E2E) / 500 (CT) |
|
viewportWidth |
1000 (E2E) / 500 (CT) |
|
waitForAnimations |
true |
|
watchForFileChanges |
true |
Re-run on change (open mode) |
specPattern |
type-dependent | Spec discovery glob |
8.2 Experimental options
All default false (some are deprecated/removed shims kept for warnings):
experimentalCspAllowList, experimentalInteractiveRunEvents, experimentalRunAllSpecs, experimentalMemoryManagement, experimentalModifyObstructiveThirdPartyCode, injectDocumentDomain, experimentalOriginDependencies, experimentalSourceRewriting, experimentalSingleTabRunMode, experimentalWebKitSupport, experimentalFastVisibility, experimentalStudio, experimentalPromptCommand, experimentalJustInTimeCompile. Deprecated/no-op shims that emit warnings include experimentalSessionAndOrigin, experimentalSkipDomainInjection, and videoUploadOnPasses.
8.3 Internal / runtime options (not user-set)
Used by the engine, not meant for cypress.config: autoOpen, browsers, clientRoute (/__/), configFile (cypress.config.js), cypressBinaryRoot, devServerPublicPathRoute (/__cypress/src), hosts, isInteractive, isTextTerminal, morgan, namespace (__cypress), repoRoot, reporterRoute, socketId, socketIoCookie (__socket), socketIoRoute (/__socket), version, isDefaultProtocolEnabled, hideCommandLog, hideRunnerUi.
8.4 Environment variables (operational)
| Variable | Effect |
|---|---|
CYPRESS_<KEY> |
Sets config/env values (prefix stripped) |
CYPRESS_INSTALL_BINARY |
Control/skip binary download |
CYPRESS_DOWNLOAD_MIRROR |
Binary download mirror |
CYPRESS_CACHE_FOLDER |
Override binary cache |
CYPRESS_DOWNLOAD_USE_CA |
Use system CA for download |
HTTP_PROXY / HTTPS_PROXY / NO_PROXY |
Outbound proxy config |
NODE_EXTRA_CA_CERTS, npm_config_cafile, npm_config_ca |
Extra CA bundles for the request layer |
CI |
Auto-detected; influences defaults |
ELECTRON_EXTRA_LAUNCH_ARGS, ELECTRON_ENABLE_LOGGING |
Electron tuning/debugging |
NODE_TLS_REJECT_UNAUTHORIZED |
TLS verification (use with caution) |
UV_THREADPOOL_SIZE |
libuv threadpool sizing for the server |
CYPRESS_INTERNAL_ENV |
dev / production / test mode of the binary |
CYPRESS_INTERNAL_ENABLE_TELEMETRY[_VERBOSE] |
Enable OpenTelemetry |
DEBUG=cypress:* |
Enable debug logging by namespace |
Tip
DEBUG=cypress:server:*(or a more specific namespace likecypress:server:cypress,cypress:proxy,cypress:network) is the primary diagnostic lever. Namespaces map directly to theDebug('cypress:...')calls throughout the server.
9. Operations
9.1 Running headless in CI
cypress run is headless by default, detects CI via CI, and exits non-zero on failure. On Linux without a display, the CLI launches @cypress/xvfb automatically (cli/lib/exec/xvfb.ts, XVFB_DISPLAY_NUM).
Deployment checklist:
- [ ] Node
>= 22.19.0on the runner - [ ] Cache the global binary directory between builds (path from
cypress cache path) - [ ] Pin the
cypressversion inpackage.jsonand lockfile - [ ] Pre-start the app or point
baseUrlat a reachable URL beforecypress run - [ ] For corporate networks, set proxy vars and (if needed)
NODE_EXTRA_CA_CERTS - [ ] For recording: set
projectId+ pass--record --key
9.2 Parallelization & recording
cypress run --record --key <k> --parallel --ci-build-id <id> --group <name> records to Cypress Cloud and load-balances specs across machines. The exit code 112 is reserved for "cannot proceed in parallel/serial network" Cloud errors (see exitErr in cypress.ts), distinct from the generic failure code 1.
9.3 Logs & artifacts
- Server logs:
DEBUG=cypress:*to stderr.packages/stderr-filteringcleans child-process noise. - Screenshots/videos: written to
screenshotsFolder/videosFolder;trashAssetsBeforeRunsclears them per run. - Crash/exception handling:
unhandled_exceptions.tsanderrors.ts(logException) capture and report fatal errors;GracefulExitcontrols exit codes. - Telemetry: off unless
CYPRESS_INTERNAL_ENABLE_TELEMETRYis set; spans flow throughpackages/telemetry(OpenTelemetry).
9.4 Browser selection & detection
packages/launcher detects installed browsers per platform (darwin/linux/windows) and resolves the binary path; --browser <name|path> selects one. Electron is always available because it ships with the binary.
10. Security Analysis
| Area | Finding |
|---|---|
| TLS MITM | Cypress generates a root CA (https-proxy/lib/ca.ts) and mints per-host leaf certs to inspect HTTPS. The CA is trusted only within the launched browser profile, but it is a deliberate interception capability — run only against authorized targets. |
| Web security disabled | Tests commonly set chromeWebSecurity: false to allow cross-origin behavior in Chromium. This weakens the browser's same-origin protections for the test session; never point such a session at untrusted sites. |
| Code rewriting | modifyObstructiveCode (default on) and the experimental rewriters alter response bodies. This is required to run third-party apps in an iframe but means the AUT does not always receive byte-identical responses. |
| Arbitrary Node execution | cy.task and cy.exec run code/commands in Node (task.ts, exec.ts) with the privileges of the Cypress process. Spec files therefore have local-execution power — treat specs as trusted code and never run untrusted specs. |
| Filesystem access | cy.readFile/cy.writeFile/cy.fixture and the file server read/write within the project; fileServerFolder/downloadsFolder define scope. |
| Secrets | Record keys and credentials are injected via CYPRESS_* env vars and --key. Keep them in CI secret stores, not in cypress.config. The Cloud API layer (server/lib/cloud) encrypts requests (cloud_request_encryption). |
| TLS verification | NODE_TLS_REJECT_UNAUTHORIZED=0 and permissive CA settings can disable verification — avoid except for known self-signed test environments. |
| CSP | experimentalCspAllowList controls how Content-Security-Policy headers are handled so the runner can inject its harness; tightening it is safer but may break injection. |
Caution
The combination of HTTPS MITM, optional disabling of web security, response rewriting, and arbitrary Node execution means a Cypress process is effectively a privileged automation host. Run it only against systems you own or are explicitly authorized to test, and never execute spec files from untrusted sources.
11. Code Quality & Conventions
- Language & style: TypeScript throughout the engine, with
Bluebirdpromises in the driver (for cancellation/timeout semantics) andlodashutilities pervasively. ESLint config is centralized inpackages/eslint-configwith a custom plugin (npm/eslint-plugin-dev). - Error system:
packages/errorsuses a templatederrTemplateDSL (PartialErr,Format,Guard,StackTrace) so user-facing errors are typed, consistently formatted, and carry structured stacks. Prefer adding errors here over ad-hocthrow new Error. - Command registration: Driver commands are registered at runtime via
Commands.addAll/addQuery/addAllSync, not as static exports — which is why static AST analysis under-reports the API and the published type definitions (cli/types/cypress.d.ts) are the authoritative public surface. - Queries vs commands: The driver distinguishes retriable queries (registered with
addQuery) from actions/utilities (addAll). New retriable selectors should be queries so they inherit auto-retry. - State management: The driver keeps a
state(...)bag and a command queue; the GUI keeps state inDataContextbehind GraphQL. These are the two canonical state stores. - Testing: Unit tests live beside packages; the heavyweight coverage is
system-tests/which snapshots full-run output. The reported confidence gap for this analysis was test-coverage breadth (32 areas), consistent with a project whose correctness is proven largely through system tests rather than per-unit tests.
12. Potential Improvements & Tech Debt
These are observations grounded in the source and the active community issue tracker at this commit.
document.domaindeprecation:injectDocumentDomainand the domain-injection path exist to support cross-origin behavior that Chrome is removing. The deprecatedexperimentalSkipDomainInjectionshim should eventually be retired in favor ofcy.origineverywhere.- Electron browser deprecation: Community issue #33560 plans to deprecate the Electron browser target (distinct from the Electron the binary is built on). Headless-Electron-specific bugs (e.g. #31068 around video) reinforce moving default CI to Chrome/Chromium.
- Install-script blocking: npm RFC #868 (issue #33980) will block install scripts by default, which threatens the
postinstallbinary download. A non-postinstall install path (explicitcypress install) is the mitigation and should become the documented default. - Offline behavior:
cy.promptfails without internet (#33927); features that call out to Cloud/AI services need graceful offline degradation. - WebKit through the proxy: Sub-resource timeouts via the proxy under WebKit (#33926) indicate the proxy's WebKit path is less mature than Chromium's;
experimentalWebKitSupportremains experimental for good reason. - Monorepo build complexity: The V8-snapshot + packherd startup pipeline is powerful but adds a layer where "works from source, fails in binary" bugs hide. Investing in snapshot-layer diagnostics (beyond
DISABLE_SNAPSHOT_REQUIRE) would reduce debugging cost. - Platform support cadence: Issue #33541 (Ubuntu 26.04 as a build platform) reflects ongoing maintenance pressure to track new OS LTS releases for the build matrix.
13. Contributing
13.1 Repository setup
The repo is a Yarn-workspaces monorepo. High-level layout:
cypress/
├── cli/ # the published `cypress` npm package (CLI + binary mgmt)
├── packages/ # the engine (server, driver, app, proxy, ...)
├── npm/ # published companion packages (@cypress/react, etc.)
├── tooling/ # build & startup tooling (v8-snapshot, packherd)
├── system-tests/ # full end-to-end snapshot tests + fixture projects
├── scripts/ # binary build, release, gulp tasks, semantic-commit checks
└── package.json # workspace root (Node >= 22.19.0)
13.2 Where things live
| To change... | Edit... |
|---|---|
A cy.* command |
packages/driver/src/cy/commands/** (+ types in cli/types/cypress.d.ts) |
| The CLI surface | cli/lib/cli.ts (commander definitions) |
| A config option | packages/config/src/options.ts (+ validation) |
| The proxy / interception | packages/proxy, packages/net-stubbing, packages/network |
| A user-facing error | packages/errors/src/** (use errTemplate) |
| The GUI | packages/app, packages/launchpad, packages/frontend-shared |
| GUI state / data | packages/data-context (+ GraphQL schema) |
| Component-testing adapters | npm/react, npm/vue, npm/angular*, npm/svelte |
13.3 Conventions to honor
- Commits are validated by semantic-commit checks (
scripts/semantic-commits,scripts/github-actions/semantic-pull-request). - Add errors to the templated error system, not inline.
- Register retriable selectors as queries so they auto-retry.
- Keep the public type definitions (
cli/types/cypress.d.ts) in lockstep with new driver commands — they are the contract users (and tooling) depend on. - Prefer adding coverage as a
system-testsfixture project + snapshot for end-to-end behavior.
14. Quick Reference
Subsystem → package
CLI / binary mgmt ........... cli/
Mode dispatch / Node core ... packages/server/lib/cypress.ts, modes/
Project lifecycle ........... OpenProject, ProjectBase (server/lib)
HTTP server ................. ServerBase (server/lib/server-base.ts)
Proxy pipeline .............. packages/proxy (NetworkProxy → Http)
HTTPS MITM .................. packages/https-proxy (CA, Server)
HTTP agents / certs ......... packages/network
cy.intercept ................ packages/net-stubbing
Response rewriting .......... packages/rewriter
Browser <-> server bridge ... SocketBase/E2E/Ct (server/lib) + packages/socket
cy.* command engine ......... packages/driver
AUT hosting / runner ........ packages/runner
Command log ................. packages/reporter
GUI (Vue) ................... packages/app, packages/launchpad, frontend-shared
GUI state / GraphQL ......... packages/data-context
Config schema ............... packages/config/src/options.ts
Errors ...................... packages/errors
Startup snapshots ........... tooling/v8-snapshot, packages/packherd-require
Component testing ........... npm/react|vue|angular|svelte + dev servers
Operational commands
DEBUG=cypress:server:* npx cypress run # diagnose server
DISABLE_SNAPSHOT_REQUIRE=1 npx cypress run # bypass V8-snapshot module loading
npx cypress info # binary, cache, browsers
npx cypress cache path|list|prune|clear # manage binary cache
npx cypress run --record --key K --parallel --ci-build-id ID
Key defaults
| Setting | Default |
|---|---|
| Node engine | >= 22.19.0 |
namespace (internal route prefix) |
__cypress |
defaultCommandTimeout |
4000 ms |
pageLoadTimeout |
60000 ms |
testIsolation |
true |
| Parallel-network Cloud exit code | 112 |
| Generic failure exit code | 1 |