Building Cypress Binary
Developmentbuilding-cypress-binaryBuilding Cypress Binary is an Agent Skill for development published in the cypress-io/cypress repository on GitHub: a SKILL.md instruction file an AI agent can load to do this task.
Builds and packages the Cypress Electron binary locally (yarn binary-build, binary-package, binary-zip, Docker/Linux parity), including non-interactive --version/--platform flags and unsetting ELECTRON_RUN_AS_NODE for agent hosts. Covers macOS signing, optional env speedups, dist smoke-test pitfalls, and why the tree is dirty after a build. Use when the user asks to build the Cypress binary, binary-package, electron MODULE_NOT_FOUND during binary-build, or local binary zip. For artifact debugging, use debugging-cypress-artifacts.
How to use this skill
Bring this guide into your coding agent with a prompt tailored to the tool you use.
- Open your project in Codex.
- Copy and paste the prompt below.
- Review files and risks before approving any action.
Inspect the Agent Skill at https://github.com/cypress-io/cypress/blob/HEAD/.cursor/skills/building-cypress-binary/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/building-cypress-binary, but wait for my approval before writing files or running scripts.
Copying this prompt does not install or run the skill. Review third-party files before use.
Building the Cypress binary
Canonical reference: guides/building-release-artifacts.md (npm .tgz vs binary .zip, CI context).
Artifact debugging (packaged CLI, CYPRESS_RUN_BINARY, git debug loop): debugging-cypress-artifacts.
Agent execution
Run from repo root with Yarn 1 and Node per .node-version. Request network for yarn / yarn lerna …; request all for yarn binary-build and yarn binary-package (long runs, temp dir under OS tmp, high memory). Sandbox vs full permissions does not fix a failed dist smoke test if ELECTRON_RUN_AS_NODE=1 is set — unset that var instead (below). Do not ask the user to approve each command separately during one build session.
Prerequisites: If node_modules/.bin/lerna or rollup is missing, run yarn first (postinstall runs the monorepo build; may take several minutes).
Agent hosts: Prefix binary commands with env -u ELECTRON_RUN_AS_NODE (or export env -u ELECTRON_RUN_AS_NODE for the shell session). Cursor/Electron environments often set this to 1, which is unrelated to sandboxing.
Commands (from repo root)
Use Yarn 1 and the Node version in .node-version.
yarn binary-build— build the Electron app and staging tree (runs broadlernabuild/build-prodas part of the pipeline).yarn binary-package— package the built binary (electron-builder).yarn binary-zip— zip the packaged output.
Linux parity with CI: run yarn binary-build and yarn binary-package inside yarn docker if you want the same environment as CI.
Non-interactive (CI, agents, no TTY)
scripts/binary/index.js prompts for missing options via Inquirer. If version and platform are already present in argv (parsed with minimist), those prompts are skipped.
| Step | Required argv |
|---|---|
binary-build | --version <semver> and --platform <os> |
binary-package | same as build |
binary-zip | --platform <os> only |
--platform: darwin | linux | win32 (defaults to os.platform() when interactive).
--version: must match what the built app reports from node index.js --version in the staged dist/ (via @packages/root). On develop this is often not root package.json’s 0.0.0-development — e.g. a release-style 15.x.x baked into packages. Before a long build, discover it with:
env -u ELECTRON_RUN_AS_NODE node packages/server/index.js --version
Or read stdout from a prior partial build’s dist/. A mismatch fails with different version reported.
macOS local example (skip notarization; Apple Silicon ad-hoc run after pack):
export SKIP_NOTARIZATION=1
export RESET_ADHOC_SIGNATURE=1 # arm64 only; harmless to omit on Intel
export V8_SNAPSHOT_DISABLE_MINIFY=1 # optional: faster packaging
BINARY_VERSION="$(env -u ELECTRON_RUN_AS_NODE node packages/server/index.js --version)"
env -u ELECTRON_RUN_AS_NODE yarn binary-build --version "$BINARY_VERSION" --platform darwin
env -u ELECTRON_RUN_AS_NODE yarn binary-package --version "$BINARY_VERSION" --platform darwin
yarn binary-zip --platform darwin
Yarn 1 forwards extra args to the script; an explicit -- before flags also works if you prefer it.
macOS
- Code signing: follow Apple’s code signing setup (see guide link above); code-signing.md for CI-oriented detail.
- Local builds often skip notarization: set
SKIP_NOTARIZATION=1(notarization needs an Apple Developer Program account).
Optional environment
| Variable | Effect |
|---|---|
V8_SNAPSHOT_DISABLE_MINIFY=1 | Faster packaging (less minification work). |
RESET_ADHOC_SIGNATURE=1 | Apple Silicon (M1+) — often required to run the packaged binary locally after an ad-hoc sign. |
SKIP_NOTARIZATION=1 | Skip macOS notarization for local builds. |
Unset for binary-build (do not export): ELECTRON_RUN_AS_NODE — see next section.
Why the repo looks “dirty” afterward
A full binary build drives yarn lerna run build and build-prod across packages, writes many dist/ artifacts, uses a root build/ symlink into a temp dir (scripts/binary/build.ts → TMP_BUILD_DIR), and can leave output interleaved with source (.jsbeside.ts**, some **.ts mutations**). Expect **git status` to be unusable until reset.
Full reset: git clean -xfd && yarn — destroys untracked/ignored files; do not rely on stash here.
Keeping WIP through a build: use the commit → build → clean → git reset HEAD~1 loop or a git worktree — see debugging-cypress-artifacts.
binary-build dist smoke test and ELECTRON_RUN_AS_NODE
After Lerna build / build-prod, scripts/binary/build.ts runs node index.js --version in the staged dist/ tree (TMP_BUILD_DIR, e.g. /tmp/cypress-build/darwin/dist). testDistVersion compares stdout to the --version argv.
Cannot find module 'electron' (false failure)
Cause: Parent shell has ELECTRON_RUN_AS_NODE=1 (common in Cursor/Electron agent hosts). packages/server/lib/util/electron-app.js isRunning() then returns true, start-cypress.js calls require('electron'), and Node fails — the production dist/ tree does not include the electron npm package (only the packaged Electron app later).
Not: missing copyAllToDist / sandbox hiding node_modules. Repro: with ELECTRON_RUN_AS_NODE=1 the staged dist fails; with env -u ELECTRON_RUN_AS_NODE the same node …/dist/index.js --version succeeds.
Mitigations:
- Agents:
env -u ELECTRON_RUN_AS_NODE yarn binary-build …(and package steps). - Repo:
testDistVersioninscripts/binary/build.tsomitsELECTRON_RUN_AS_NODEfrom the childexecaenv so builds are stable even when the parent sets it.
different version reported
Cause: --version argv does not match node index.js --version from the built dist (version baked via @packages/root during the build, which may differ from root package.json on develop).
Fix: Use the discovery command in Non-interactive above, or stdout from a partial dist/ after a failed build.