E2EConfig is the type of the object e2e.config.ts default-exports. Write
the object literal and end it with satisfies E2EConfig: the editor
completes every key, unknown keys are flagged, and the export keeps its
literal type. Every rule below is enforced when the runner resolves the
config, not by the type.
e2e.config.ts
INVALID_CONFIG at every level. There is no
top-level app key: the engine declares the app it drives (see
the app under test).
Loading
--config <path> selects an explicit file. Otherwise the runner searches the
working directory and each parent for e2e.config.ts or e2e.config.mts,
stopping at the repository root. Both names in one directory is
CONFIG_AMBIGUOUS. The selected file’s directory is the project root.
Config and test modules run as ESM. e2e loads the .ts, .mts, and .tsx
files a project reaches by path as ES modules whatever the nearest
package.json type says, so a CommonJS package keeps its module type.
Packages imported by name keep the format their own manifest declares. A
config or test written with require or module.exports fails to load.
Top level
Every numeric value must be a safe integer.
targets
{ engine: playwright({ url }) } is a complete target. Two targets on one
platform name themselves. A target without an engine runs opaquely through
agent tools; the runner cannot observe or drive it through an engine.
Ordinary tests whose requires list names a capability the target lacks are
skipped for that target. A test.setup needed by a selected session consumer
must be runnable there; if its required capabilities are missing, selection
fails with COLLECTION_ERROR. Calling an unsupported engine operation or
acquiring a fixture it does not contribute fails with
UNSUPPORTED_CAPABILITY.
The app under test
The app is declared by the engine that drives it. The browser engine takes the declaration as options ofplaywright(...); the device engine derives it
from the app it pins. The runner resolves it at config load and owns what is
built on it: navigation and origin policy, cache and session identity, the
report’s target record, and the app process.
command
The child inherits only
PATH, HOME, TMPDIR, TMP, TEMP,
SystemRoot, and COMSPEC. Model credentials, E2E_USER_* values, and CI
tokens are not inherited automatically. Every value explicitly supplied in
command.env is forwarded, including a credential or token. The runner
never terminates a process it did not start.
services
Exactly one of
readyUrl or waitForExit is required per service.
reuseExisting works on a readyUrl service and skips its teardown; on a
waitForExit service it is INVALID_CONFIG. Services start in declaration
order before any app command, each ready before the next starts. Services
declared identically by several targets start once; two targets that order
shared services differently are INVALID_CONFIG.
On every exit path the runner stops every app command, then the services in
reverse order, then runs their teardown commands in reverse order. A
failing teardown is recorded as a cleanup run error and never skips the
teardowns after it. Starting your app shows a full
example.
artifacts
kinds accepts screenshot, trace, and video. The default set is
screenshot and trace, captured best-effort. A configured kind the target’s
engine cannot produce fails before collection with UNSUPPORTED_ARTIFACT.
video is never in the default set; --video adds it for one run.
store receives every artifact the moment it is complete on disk and returns
its own reference, which the report records as the artifact’s ref beside
the local path. A failed put never fails the run. A store never crosses a
process boundary: each worker constructs its own from the config module.
video
Withvideo among the kinds, or --video, every selected engine must support
recording; otherwise configuration fails with UNSUPPORTED_ARTIFACT.
Playwright opens a page when recording starts and writes WebM segments, one
per page it records. The agent-device engine writes an MP4 of the device
screen. Other engines define their recording format and when segments exist.
A failed launch or a recording that cannot be finalized may leave no video.
The first file lands under the attempt’s artifact directory as
video/video.webm for Playwright or video/video.mp4 for agent-device.
Playwright names later segments video/video-part<n>.webm. Each segment has
startedAt set to when recording began, so
step.startedAt - artifact.startedAt is a step’s offset into that segment.
Recording costs an encoder per page and about a megabit per second of disk.
A recording masks nothing, so a video artifact is recorded with
redaction: 'incomplete'. Turning video on or off never invalidates cached
replays.
screen
agents
default is the one tests run with, and it exists even when
the config names none. Other names are other brains for the same suite:
e2e run --agent <name> re-points the default, a test or describe block pins
one with { agent: 'name' } or several with { agent: ['buyer', 'admin'] },
and any agent.* call can name one. An unknown name fails by where it was
written: --agent is INVALID_CONFIG, a pin is COLLECTION_ERROR, a call’s
agent is INVALID_ARGUMENT. Names are ASCII letters, numbers, _, -,
or .. See Agents and personas.
e2e.config.ts
executor, or the executor itself. The bare form is shorthand for
{ executor }. Every diagnostic names the agent: agents.ux.model.
Judgments (
assert, waitFor, extract) allow 8192 output tokens per call
and set no temperature.
model
Reports record the instance’s
provider and modelId as the step’s
provider and model. Each worker re-resolves the config module and
constructs its own instance. A config whose digest differs between the runner
and a worker fails with CONFIG_NOT_DETERMINISTIC. See
Choosing a model.
credentials
credentials.user(name) resolves a configured entry into a Credential.
The username is a plain string; the password is an opaque Secret that test
code cannot read, accepted only by locator.fill and agent.act params. An
unconfigured name throws AUTH_CREDENTIAL_UNAVAILABLE.
cache
Inread-write mode, the trace cache records an agent.act() only after a
later recorded verification passes, such as a locator assertion or an
agent.assert() step. A trailing act with no verification is not recorded.
read-only mode can replay existing entries but writes none; off disables
both. Caching agent steps explains verification and when a replay
hands off.
Commit your traces
e2e init adds .e2e/cache/ to .gitignore, so committing entries is
opt-in. Remove that line to share replays with CI and teammates; CI stays
read-only unless cache: 'read-write' is set. See
Caching agent steps.
limits
Resolved limits are immutable for a run. Per-call options may only lower them. A key exists here exactly when the runner has an enforcement site for it.Environment variables
The runner reads a closed set, listed on the Environment variables page. The ones that change what a config resolves to:<NAME> is the credential name uppercased with every character outside
A-Z0-9 replaced by _, so power-user becomes E2E_USER_POWER_USER_USERNAME.
A pair for a name absent from credentials is ignored.
Resolution order
A missing model is checked once per run, when the
agent fixture is first
acquired, and stops the run with exit 2. A custom executor with no model
skips the check.
CI
CI mode is on unlessCI is unset, empty, whitespace only, 0, or false
(trimmed and lowercased first). Every other value turns it on.
