This is the agent entry point for the WebdriverIO monorepo. Humans should start
with CONTRIBUTING.md. Agents should read this file first,
then the nearest scoped AGENTS.md in the tree they are changing.
Do not copy policy into tool-specific files. Cursor, Claude Code, Copilot, and Codex should follow this document. Tool adapters stay thin and point here.
pnpm + Lerna workspace. Source lives in packages/*/src. Runtime and tests
consume compiled packages/*/build (and CJS under packages/*/cjs).
packages/wdio-protocols protocol command specs (source of generated types)
packages/webdriver raw WebDriver / BiDi / Appium client
packages/webdriverio user-facing `$`, element/browser commands
packages/@wdio/cli testrunner CLI + launcher
packages/@wdio/runner worker that runs one capability
packages/@wdio/local-runner
packages/@wdio/*-framework | *-reporter | *-service
infra/compiler esbuild + protocol type generation
infra/repo-tools docs index, scoped tests, CI lane helpers
infra/utils protocol metadata and shared helpers
infra/bidiCodegen BiDi CDDL type generation
infra/docs documentation website generation
infra/release changelog, tags, and backports
infra/createPackage scaffold a new workspace package
infra/depcheck dependency checks
tests/ smoke suites (mock driver, no real browser)
e2e/ real-browser / component / display-server suites
website/ Docusaurus site (many pages are generated)
Architecture sketches: High-level overview, test execution, worker creation, CLI commands, type generation. Ownership: .github/OWNERSHIP.md.
Use the Node version in .nvmrc (currently 24) and the pnpm version
pinned in package.json#packageManager. Do not switch the package manager.
pnpm install
pnpm run setup # clean + generate + compile all packagesCloud / Codespaces agents: run .agents/setup once, then
.agents/resume to confirm the toolchain before editing.
Edits to src/ are invisible to tests until the compiler runs:
pnpm run dev # watch all packages
pnpm run dev webdriverio # watch one package (dir or npm name)| Path | Owner |
|---|---|
packages/*/build, packages/*/cjs |
@wdio/compiler |
packages/wdio-protocols/src/commands |
compiler type-generation plugin |
packages/webdriver/src/bidi/ generated files |
pnpm run generate:bidi |
website/docs/api/** (except a few hand-written pages) |
pnpm run docs:generate |
website/docs/_*.md, website/sidebars.json |
docs generation |
CHANGELOG.md |
release process |
Protocol specs are hand-authored in packages/wdio-protocols/src/protocols/.
The generated command types next to them are not.
Prefer the smallest proof that covers the touched contract. Do not start with
pnpm test or pnpm run ci — those run the full unit + smoke + component
(+ e2e) pipeline and waste time.
The table is the regression check. It is not proof that a feature works the way a user runs it. Before you report a feature or bug fix as done, follow verify-webdriverio. Use a named smoke suite for the testrunner, an example script for a real browser and driver, the runner benchmark for performance, and typings for public types. A unit test is not that proof.
| Change | Minimum local proof |
|---|---|
| Mixed / unsure | pnpm run test:changed --dry-run then pnpm run test:changed |
| One command / util in a package | pnpm run test:package <name> or npx vitest packages/<pkg>/tests/.../<file>.test.ts |
| Public command / interface shape | package unit tests and pnpm run test:typings (or the matching test:typings:*) |
| Testrunner, CLI, reporter, service, framework wiring | pnpm run test:smoke:list then pnpm run test:smoke <suite> (see tests/AGENTS.md) |
@wdio/browser-runner / e2e/browser-runner |
pnpm run test:component |
@wdio/session / e2e/session |
pnpm run test:e2e:session |
@wdio/display-server / @wdio/local-runner / e2e/wdio/display-server |
pnpm run test:e2e:display-server (Linux with no display only; elsewhere rely on CI) |
Chromedriver setup in @wdio/utils / e2e/wdio/chromedriver |
pnpm run test:e2e:chromedriver (with CHROMIUM_130_BINARY set; the Linux ARM64 routing needs a Linux ARM64 host, elsewhere rely on CI) |
Docs-only (website/docs, JSDoc, package README) |
pnpm run docs:list then pnpm run docs:generate |
| Root CI / toolchain files | treat as run-all; run pnpm run test:local |
Unit tests mirror source: src/commands/element/getCSSProperty.ts →
tests/commands/element/getCSSProperty.test.ts. Mock other packages; do not
spin up a browser in unit tests.
pnpm run changed:lanes --json classifies a diff with the same filters as
.github/workflows/test.yml. pnpm run test:changed
runs the local equivalent (package unit tests + typings; pass --smoke or
--e2e for those lanes). Pushes to main still run the full matrix.
Put a change in the existing owner. Do not add a parallel helper in another package to work around a missing export — extend the owner and update callers.
| Concern | Owner |
|---|---|
| Shared TS types (capabilities, options) | @wdio/types |
| Protocol command specs | @wdio/protocols |
| HTTP / BiDi transport | webdriver |
| User-facing browser/element API | webdriverio |
| Config parsing | @wdio/config |
| Shared utils | @wdio/utils |
| Reporter base class | @wdio/reporter |
| Worker / hooks | @wdio/runner |
| CLI / launcher | @wdio/cli |
| Build + type generation | infra/compiler |
| Docs index / scoped tests / CI lanes | infra/repo-tools |
New packages: pnpm run create. Do not invent a package layout by hand.
User docs come from several sources. Update the source, then regenerate:
- Guidelines:
website/docs/**/*.md - Service / reporter pages: that package's
README.md - Protocol API:
@wdio/protocolsspecs - WDIO command API: JSDoc on the command implementation
- Third-party plugins:
infra/docs/src/3rd-party/
pnpm run docs:list prints a path + title index. Config examples are copied
through the repo; search for every occurrence before renaming a key.
multi-remotein English text, nevermultiremote.Multi-remoteat the start of a sentence, heading or title.multiRemote/MultiRemotein camelCase / PascalCase code, e.g.isMultiRemote.- Never write
multiremoteorMultiremote, e.g.isMultiremote,multiremote(). - Exceptions, kept for compatibility: the
id: multiremotepermalink and/docs/multiremotelinks, file and folder names, the Allure historyId key'multiremote', the v9 column ofv10Migration.md, the v10 migration skill (it has to name the old identifiers), andCHANGELOG.md.
Must print nothing before committing. It flags every multiremote /
Multiremote and filters out the exceptions above:
git grep -nE "[Mm]ultiremote" -- ':!AGENTS.md' ':!CHANGELOG.md' \
':!website/_sidebars.json' ':!**/__fixtures__/**' ':!**/__snapshots__/**' \
':!.agents/skills/wdio-v10-migration/**' \
| grep -vE "multiremotebrowser|/multiremote|multiremote/|[.-]multiremote|multiremote[.-]|'multiremote', '|return 'multiremote'|^website/docs/Multiremote\.md:2:|^website/docs/v10Migration\.md:[0-9]+:(\| \`|APIs spelled|The old \`isMultiremote\`|Search for \`multiremote\`)"- Inspect
git status -sbbefore editing. Do not switch branches or rewrite history that another process is using. - Follow through on the requested change. A plan is a checkpoint, not done.
- Resolve routine choices; ask only when the request cannot decide a user-visible or breaking contract.
- Keep PRs to one topic. Conventional Commits (
fix(webdriverio): ...). - Stage only intended files. Do not commit
node_modules, build output, or generated docs. - Tests must fail on the original defect. Do not hide flakes with retries, longer timeouts, or weaker assertions — fix the cause.
- Verify user-facing work with verify-webdriverio before claiming it is done. Record the command, the output, and the observable result. A passing unit test does not replace that.
- UI / docs-site visual changes need a before/after screenshot in the PR.
- American English. Match existing code style; do not reformat unrelated files.
Read the matching guide in full before editing that tree.
- Contributor / GitHub process: CONTRIBUTING.md
- Product direction: ROADMAP.md
- webdriverio commands: packages/webdriverio/AGENTS.md
- webdriver client / BiDi: packages/webdriver/AGENTS.md
- Protocol specs: packages/wdio-protocols/AGENTS.md
- CLI / launcher: packages/wdio-cli/AGENTS.md
- Session CLI: packages/wdio-session/AGENTS.md
- Local runner: packages/wdio-local-runner/AGENTS.md
- Reporters: packages/wdio-reporter/AGENTS.md
- Compiler / types: infra/compiler/AGENTS.md
- Repo helpers: infra/repo-tools/AGENTS.md
- Infra packages: infra/AGENTS.md
- Docs generation: infra/docs/AGENTS.md
- Smoke tests: tests/AGENTS.md
- E2E / component: e2e/AGENTS.md
- Docs site: website/AGENTS.md
- Testing skill: .agents/skills/wdio-testing/SKILL.md
- Verify a change: .agents/skills/verify-webdriverio/SKILL.md
- Hot-path perf skill: .agents/skills/wdio-perf/SKILL.md
- Ownership map: .github/OWNERSHIP.md
- Docs skill: .agents/skills/wdio-docs/SKILL.md
- v10 user migration: website/docs/v10Migration.md and .agents/skills/wdio-v10-migration/SKILL.md. Update both together.
wdio-docs, wdio-testing, wdio-perf, and verify-webdriverio set metadata.internal: true so npx skills add does not offer them. Leave that flag on. The session skill stays in @wdio/session and is installed with npx wdio session skill --install.