CLI Reference
One binary, beryl: the CLI, the local test runner, and the MCP server your coding agent uses. New to Beryl? Start with the quickstart.
CLI version 0.36.0 · Product docs
Install
One command does the whole setup. It signs you in via the browser, wires the beryl and playwright MCP servers into Claude Code (add --cursor for Cursor), installs the beryl-test authoring skill, and installs @playwright/test + Chromium for local runs:
npx @beryl-so/cli@latest initThe CLI is a Node.js package (Node 20.19+). For a permanent install:
npm install -g @beryl-so/cli
beryl --versionAuthenticate
beryl login signs in via the browser: the CLI opens beryl.so/cli/connect, you approve the code shown in the terminal, and the minted personal access token is stored in ~/.config/beryl/config.json.
beryl login
beryl whoamiWithout a browser:
- Press Enter at the login prompt (or pass
--otp) for an emailed 6-digit code. A brand-new email gets an account created automatically; an email that signs in with Google has no emailed code, so use the browser flow. --email <addr> --code <digits>completes the emailed-code flow without a prompt. It is meant for agents, paired with a code already requested (e.g. read from aberyl mailbox).--token <pat>uses an existing token from beryl.so → Account → API tokens.- In CI, skip
loginentirely and set theBERYL_API_KEYenvironment variable.
A token has the same access as your account. Revoke any with beryl tokens revoke, or beryl logout --revoke to sign out and kill the token in one step.
Local runs
beryl runs local runs tests on your machine: each test's spec is fetched and executed with your local @playwright/test and Chromium (installed by init). OTP/signup email steps and test-account sign-ins work as they do in the cloud; passwords are fetched once and scrubbed from any error output. Results and replay artifacts import into Beryl as a normal run.
beryl runs local
beryl runs local --url-override http://localhost:3000
beryl runs local 4f… --no-sync --dir ./beryl-local--no-sync keeps a run entirely off the record while iterating; --dir writes specs, artifacts, and reports to disk. Exits 0 only if every executed test passed.
Cloud runs
The same suite runs in Beryl's cloud browsers. Point Beryl at a URL and watch the agent explore your app and author tests live in the terminal, then trigger runs whenever you like:
beryl projects create https://app.example.com --watch
beryl tests list
beryl runs trigger --watch
beryl projects reportLogin-gated sites: create the project with --auth gated. Tests sign in as durable test accounts (beryl accounts) whose mail arrives at the project's own mailbox (beryl mailbox), so OTP and magic-link flows are self-contained.
CI integration
--watch streams progress and exits non-zero unless every test passed, so one line gates a deploy. Use --url-override to aim the suite at a preview deployment, --header KEY=VALUE to reach auth-walled previews (e.g. x-vercel-protection-bypass), and --json for machine-readable output (NDJSON while streaming).
env:
BERYL_API_KEY: ${{ secrets.BERYL_API_KEY }}
run: |
npx @beryl-so/cli runs trigger --url-override "$PREVIEW_URL" --watch --timeout 30Exit codes: 0 success (all tests passed) · 1 failure · 2 usage error · 3 authentication error.
MCP for coding agents
beryl mcp serves every non-interactive command below as an MCP tool over stdio (spaces and dashes become underscores, so runs trigger is the tool runs_trigger). Your agent can create projects, author and edit test plans, trigger runs, and read failures through exactly the same commands documented here. init wires this for you; manual setup is one line:
# Claude Code
claude mcp add beryl -s user -- npx -y @beryl-so/cli@latest mcp
# Cursor / other MCP clients
{ "command": "npx", "args": ["-y", "@beryl-so/cli@latest", "mcp"] }The config holds no token. The server reads your CLI login from ~/.config/beryl. Where there is no browser to sign in, like CI, set BERYL_API_KEY instead.
Configuration
Config persists your token and API URL, nothing else. Most commands act on a workspace and a project. Every scoped command accepts --workspace and --project (by id, name, or URL); when omitted, the CLI resolves them from (in order): the BERYL_WORKSPACE / BERYL_PROJECT environment variables, or, when there is exactly one, your only workspace or project. Nothing is pinned to a folder, so parallel sessions in the same directory can target different projects.
Global flags on every command: -V, --version · --json · --api-url · --token · -h, --help.
beryl init
Set up Beryl in this repo: sign in and wire up your coding agent
Set up Beryl in this repo: sign in and wire up your coding agent (interactive)
One-command onboarding: signs you in (browser confirm, or an emailed one-time code) and wires up your coding agent. Nothing is detected and nothing is conditional: every run wires the beryl AND playwright MCP servers, writes the authoring skill (user scope: your home .agents/skills/ + .claude/skills/, so it follows you into every session; --scope project: the repo's own dirs, committed for teammates), and installs the Chromium browser if missing (the Playwright runner ships with the CLI, so any repo can run tests locally), since browser authoring and local runs depend on it. By default the servers are wired per-user (matching where your login token lives) via `claude mcp add -s user`; pass --scope project to write a committed .mcp.json for a shared repo instead. No workspace/project pin and no URL prompt: ask Claude to write tests for your site and it resolves the workspace, project, and URL. Safe to re-run: every run refreshes the authoring skill to this CLI's version (overwriting an older or edited copy; `beryl guide` prints the same content), and skips whatever else is already set up.
--scope <user|project>: Where to wire the MCP servers. `user` (default) configures them per-user (matching where your Beryl login token lives) via `claude mcp add -s user`. `project` writes a committed .mcp.json for a shared repo. Every teammate still runs `beryl login` to authenticate--cursor: Also write the same two MCP servers to Cursor's config
npx @beryl-so/cli@latest init
beryl init --scope project
beryl init --cursorberyl guide
Print the Beryl test-authoring guide
Print the Beryl test-authoring guide
The full guide to authoring durable, healable tests: the ActionPlan shape, outcome assertions, natural-language intent, test accounts and the project mailbox ({{login_email}}, {{mailbox_address}}, {{inbox_address}} + await_email), and the local run-fix loop. Same content as the beryl-test skill `beryl init` installs. Skip if a loaded beryl-test skill states v0.36.0; else call this first (works without logging in).
MCP tool: guide
beryl guideberyl login
Authenticate the CLI with your Beryl account
Authenticate the CLI with your Beryl account (interactive)
Signs in via your browser (a code you confirm at beryl.so) and stores a personal access token in the CLI config. Pass --otp (or --email) to skip the browser and sign in with an emailed one-time code instead. A new email gets an account created automatically. Pass --token to use an existing token from Account → API tokens. Pass --email plus --code (the 6 digits from the email, e.g. read from a `beryl inbox`) to complete the OTP flow without a prompt. In CI, prefer the BERYL_API_KEY environment variable.
--token <string>: Use an existing personal access token--otp: Skip the browser and sign in with an emailed code--email <string>: Email for the one-time code sign-in (default: your last sign-in, or your git user.email, offered as the prompt default)--code <string>: The emailed 6-digit code. Skips the prompt for non-interactive use (requires --email; also skips sending a fresh code, so pair it with a code already requested via `beryl login`, `beryl signup`, or the API)--token-name <string>: Name for the minted token (default: CLI on <hostname>)
beryl login
beryl login --otp
beryl login --token beryl_pat_…
beryl login --email [email protected]
beryl login --email [email protected] --code 123456 --jsonberyl signup
Register a new Beryl account (emails a 6-digit verification code)
Register a new Beryl account (emails a 6-digit verification code)
Creates a passwordless account for the email and sends it a 6-digit code. Finish with `beryl login --email <addr> --code <the 6 digits>`, which verifies the account, creates its workspace, and signs the CLI in. With an inbox from `beryl mailbox create` as the address, an agent can provision a fresh account end-to-end with no human at a prompt.
MCP tool: signup
--email <string>: Email address for the new account (required)
beryl signup --email [email protected] --jsonberyl logout
Remove the stored token from the CLI config
Remove the stored token from the CLI config
MCP tool: logout
--revoke: Also revoke the token server-side so it can never be used again
beryl whoami
Show the signed-in account
Show the signed-in account
MCP tool: whoami
beryl tokens
Manage the personal access tokens that authenticate the CLI and CI.
List your personal access tokens
MCP tool: tokens_list
Mint a new personal access token (shown once)
MCP tool: tokens_create
name: A label for the token
--expires-at <string>: Expiry as an ISO timestamp (default: never)
Revoke a personal access token
MCP tool: tokens_revoke
token-id: Token id from `beryl tokens list`
Remove an already-revoked token from your list
MCP tool: tokens_dismiss
token-id: Token id from `beryl tokens list`
beryl workspaces
Create and manage workspaces, and pick the one your commands act on by default.
List workspaces you belong to
MCP tool: workspaces_list
Show one workspace
MCP tool: workspaces_get
Also accepts --workspace (see Configuration).
Create a workspace
MCP tool: workspaces_create
name: Workspace name
--domain <string>: Company domain to associate--visible-to-org: Let anyone on your email domain discover and join it
Rename a workspace or change its visibility
MCP tool: workspaces_update
--name <string>: New name--visible-to-org: Toggle org discoverability--autofix: Toggle autofix
Also accepts --workspace (see Configuration).
Delete a workspace and everything in it
MCP tool: workspaces_delete
--force: Skip the confirmation prompt
Also accepts --workspace (see Configuration).
Show the workspace's action history (who did what, when)
MCP tool: workspaces_history
Also accepts --workspace (see Configuration).
Leave a workspace you are a member of
MCP tool: workspaces_leave
--force: Skip the confirmation prompt
Also accepts --workspace (see Configuration).
beryl members
Manage who belongs to a workspace and their roles.
List workspace members
Also accepts --workspace (see Configuration).
Change a member's role
user-id: Member's user idrole: OWNER or USER
Also accepts --workspace (see Configuration).
Remove a member from the workspace
user-id: Member's user id
--force: Skip the confirmation prompt
Also accepts --workspace (see Configuration).
beryl invites
Send, list, and revoke workspace invitations, and accept ones sent to you.
Invite someone to the workspace by email
email: Invitee email
--role <OWNER|USER>: Role (default USER)
Also accepts --workspace (see Configuration).
List the workspace's outstanding invitations
Also accepts --workspace (see Configuration).
Revoke a pending invitation
invitation-id: Invitation id
Also accepts --workspace (see Configuration).
List invitations sent to you
Accept an invitation (by id, or by the token from the invite email)
invitation: Invitation id or emailed token
Decline an invitation
invitation-id: Invitation id
beryl projects
Create and manage projects: a site Beryl explores, authors tests for, and runs.
List projects in the workspace
MCP tool: projects_list
Also accepts --workspace (see Configuration).
Show one project, including its current exploration state
MCP tool: projects_get
Also accepts --workspace and --project (see Configuration).
Create a project. With a URL the agent starts exploring; with just --name an empty one
MCP tool: projects_create
url: Root URL of the site to test. Omit to create an empty project (see --name)
--name <string>: Name for an empty project when no URL is given. Add a URL later with `beryl envs update <env-id>`, or author tests over the CLI/MCP--auth <public|gated>: Whether the site needs a login (gated) or not (public). Default: detected from the site, and only asked when detection is genuinely unsure--force-new-login: Ignore any reusable saved login--no-explore: Create the project without starting the cloud exploration. Author tests yourself via `beryl tests create` or your coding agent over MCP--watch: Stream the agent's exploration live--timeout <number>: With --watch: max minutes to wait
Also accepts --workspace (see Configuration).
beryl projects create https://app.example.com --watch
beryl projects create https://app.example.com --auth gated
beryl projects create https://app.example.com --auth public --no-explore
beryl projects create --name "Acme production"Rename a project
MCP tool: projects_rename
name: New name
Also accepts --workspace and --project (see Configuration).
Delete a project and all its tests and runs
MCP tool: projects_delete
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
Send the agent back in to run/heal existing tests and discover new flows
--watch: Stream the agent's exploration live--timeout <number>: With --watch: max minutes to wait
Also accepts --workspace and --project (see Configuration).
Aggregate quality report across recent runs (pass rates, flaky tests, trend)
MCP tool: projects_report
--runs <number>: How many recent runs to aggregate--env <string>: Limit to one environment id
Also accepts --workspace and --project (see Configuration).
Check whether a saved login can be reused for a URL before creating a project
MCP tool: projects_reusable_auth
url: The URL you plan to test
Also accepts --workspace (see Configuration).
beryl envs
Manage a project's environments: the URLs and auth Beryl runs tests against.
List a project's environments
MCP tool: envs_list
Also accepts --workspace and --project (see Configuration).
Show one environment
MCP tool: envs_get
env-id: Environment id
Also accepts --workspace and --project (see Configuration).
Add an environment (e.g. staging) to a project
MCP tool: envs_create
name: Environment nameurl: Root URL for this environment
--auth <public|gated>: Whether this environment needs a login
Also accepts --workspace and --project (see Configuration).
Update an environment's name, URL, or auth settings
MCP tool: envs_update
env-id: Environment id
--name <string>: New name--url <string>: New root URL--auth <public|gated>: New auth choice
Also accepts --workspace and --project (see Configuration).
Delete an environment
MCP tool: envs_delete
env-id: Environment id
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
beryl schedule
Manage the schedules on which Beryl runs a project's tests automatically. A project can hold many independent schedules; each has its own cadence (daily or weekly), local run time, timezone, and target groups (none = every active test).
List the project's schedules
MCP tool: schedule_list
Also accepts --workspace and --project (see Configuration).
Add a schedule (daily, or weekly on a given day)
MCP tool: schedule_add
--frequency <daily|weekly>: How often (default daily)--day <number>: Weekly only: day of week, 0=Monday … 6=Sunday--hour <number>: Hour of day 0-23--minute <number>: Minute 0-59--tz <string>: IANA timezone (e.g. America/Los_Angeles)--groups <string>: Comma-separated group names or ids the schedule targets (the run covers the union of their active tests at fire time); omit to run every active test
Also accepts --workspace and --project (see Configuration).
beryl schedule add --frequency daily --hour 6 --tz UTC
beryl schedule add --groups "Smoke,Checkout" --frequency weekly --day 0 --hour 9 --minute 15 --tz UTCChange a schedule's cadence, time, timezone, or groups
MCP tool: schedule_update
schedule-id: Schedule id (see schedule list)
--frequency <daily|weekly>: How often (default daily)--day <number>: Weekly only: day of week, 0=Monday … 6=Sunday--hour <number>: Hour of day 0-23--minute <number>: Minute 0-59--tz <string>: IANA timezone (e.g. America/Los_Angeles)--groups <string>: Comma-separated group names or ids the schedule targets (the run covers the union of their active tests at fire time); omit to run every active test--all-tests: Target every active test (clears the schedule's groups)
Also accepts --workspace and --project (see Configuration).
Remove a schedule (its tests and groups stay)
MCP tool: schedule_remove
schedule-id: Schedule id (see schedule list)
Also accepts --workspace and --project (see Configuration).
beryl tests
Author, inspect, version, and heal a project's tests: the checks Beryl runs on each run.
Validate a plan JSON file offline, before sending it to the server
Checks a plan against the published ActionPlan JSON Schema: every action's required fields, plus the two structural rules (the first EXECUTED step must be a goto, and at least one step across before + steps must be an expect). Runs entirely locally, so a malformed plan fails here instead of costing a server round-trip. Schema: https://api.beryl.so/api/v1/schemas/action-plan.schema.json
MCP tool: tests_lint
--file <string>: Plan JSON file, or - for stdin (required)
beryl tests lint --file plan.jsonList the project's tests with their latest result
Prints a concise table by default (title / status / id / last result / last run). Pass --wide for every field, or --json for the raw records. Returns every test unless --page is given; pass --page to walk a large project a slice at a time.
MCP tool: tests_list
--env <string>: Filter by environment id--group <string>: Show only tests in this group (by name; see `beryl groups list`)--wide: Show all columns, not the concise default--page <number>: Return only this 1-indexed page instead of every test--page-size <number>: Tests per page when --page is given (default 20, max 100)--status <string>: With --page, show only this bucket: passed, failed, or blocked--ungrouped: With --page, show only tests carrying no group--q <string>: With --page, show only tests whose title contains this text (case-insensitive)
Also accepts --workspace and --project (see Configuration).
Show one test
Returns the test's metadata row (status, flags, per-environment last result), not the plan. `tests plan` prints the stored JSON plan, `tests script` the rendered Playwright spec.
MCP tool: tests_get
test-id: Test id
Also accepts --workspace and --project (see Configuration).
Print a test's current step plan (JSON)
Returns the stored json_plan of the test's current version. `tests get` returns the metadata row, `tests script` the rendered Playwright spec.
MCP tool: tests_plan
test-id: Test id
Also accepts --workspace and --project (see Configuration).
Create a test case from a JSON action plan (for tests authored locally, e.g. by your coding agent)
The plan is a JSON object whose steps are {action, selector, url, value, ...}: the first EXECUTED step must be a goto, and at least one step must be an expect. Before anything is banked, the plan is proven by replaying it in a browser ON YOUR MACHINE with the Playwright runner bundled in the CLI (your repo's own @playwright/test wins when present): the server renders the spec (`tests/compile`), the CLI runs it (minting a run inbox for await_email steps and resolving the saved login exactly as a cloud run would), and only a green replay creates the test (bound to the replayed plan by its hash). This holds over MCP too: the replay runs on the machine hosting the MCP server, never on Beryl's; if the Chromium browser is missing there the tool returns the install command (`beryl init` installs it; on a terminal the CLI offers to). A red replay banks NOTHING: the failure evidence comes back (over MCP the screenshot is image content), you fix the plan file and re-run. The proving run is imported as the test's first run (--no-sync to skip). A plan that signs in with a session Beryl captured server-side cannot replay locally (that session never leaves Beryl's cloud). It falls back to server-side verification automatically, and says so. A session-mode plan replays locally fine: the server renders it with its account's stored sign-in steps in front, so the same identity is exercised on your machine. Optional `before` and `after` arrays hold setup and teardown steps: `after` runs even when a main step fails, which is how a create/update/delete test cleans up the record it made on the runs that go red. Recovery: a 409 `duplicate_title` carries existing_test_id + existing_plan_hash, so reconcile with that test (`tests get` / `tests set-plan`), don't rename-and-retry; a 409 `plan_hash_mismatch` means the submitted plan is not the bytes that were replayed (re-run `tests create`); a 429 with Retry-After 30 means the verify slots are saturated (wait and retry).
MCP tool: tests_create
--title <string>: Title for the new test (required)--file <string>: Plan JSON file, or - for stdin (required)--description <string>: One to three sentences stating what this test proves: the immutable outcome Beryl's healing checks against. State the purpose, not the steps; the one observable signal that's true only if the flow worked.--no-verify: Skip verification entirely: bank the authored plan as-is, unproven--url-override <string>: Replay against this base URL instead of the environment's (e.g. http://localhost:3000). The banked test is then unproven against its real environment, and the CLI says so.--group <strings>: Put the test in an existing project group (by name), repeatable. An unknown name is an error (create groups with `beryl groups create`). Omit for no group.--env <string>: Environment id to compile and prove against--sync: Import the green proving replay as the test's first run (--no-sync: bank only, no run recorded)--dir <string>: Keep the rendered spec, artifacts, and JSON report under this directory
Also accepts --workspace and --project (see Configuration).
beryl tests create --title "Checkout happy path" --file plan.json
beryl tests create --title "Checkout happy path" --file plan.json --description "Proves a shopper can buy a product: after paying, an order-confirmation page with an order number appears."
beryl tests create --title "Checkout happy path" --file plan.json --url-override http://localhost:3000Replace a test's step plan from a JSON file (creates a new version)
Accepts the same plan shape as `tests create`, including the optional `before` and `after` sections. `after` runs on pass and on fail, so cleanup happens even when the test goes red. Pass `--description` when the re-authored plan changes what the test proves; omit it to keep the test's existing intent. Saves the edit with NO replay: it rides into the next run unproven; `tests recompile` is the verify-first alternative.
MCP tool: tests_set_plan
test-id: Test id
--file <string>: Plan JSON file, or - for stdin (required)--description <string>: One to three sentences stating what this test proves: the immutable outcome Beryl's healing checks against. State the purpose, not the steps; the one observable signal that's true only if the flow worked. Omit to keep the test's existing intent.
Also accepts --workspace and --project (see Configuration).
beryl tests plan 4f… > plan.json # edit, then:
beryl tests set-plan 4f… --file plan.jsonRename a test
MCP tool: tests_rename
test-id: Test idtitle: New title
Also accepts --workspace and --project (see Configuration).
beryl tests rename 4f… "Checkout happy path"Replace the groups a test belongs to
Groups are project-defined labels used to filter, run, or schedule a slice of the suite (`beryl runs trigger --group <name>`). This REPLACES the whole set: pass every group you want, or none to clear it. Names must already exist in the project (`beryl groups list`); an unknown name is an error, never a new group.
MCP tool: tests_set_groups
test-id: Test id
--group <strings>: Group name, repeatable. Omit entirely to clear the set.
Also accepts --workspace and --project (see Configuration).
beryl tests set-groups 4f… --group Checkout --group Smoke
beryl tests set-groups 4f…Add groups to one or more tests, keeping the groups they already have
The additive counterpart of `tests set-groups`: every listed test gains the given groups and loses none, so you don't need to know what each test already carries. Names must already exist in the project (`beryl groups list`); an unknown name is an error, never a new group.
MCP tool: tests_add_groups
test-ids...: One or more test ids
--group <strings>: Group name to add, repeatable (at least one)
Also accepts --workspace and --project (see Configuration).
beryl tests add-groups 4f… 9a… --group Smoke
beryl tests add-groups 4f… --group Checkout --group SmokeMute a flaky test: it keeps running, but its failures stop failing the run
A quarantined test still executes and its result is still recorded and visible. Its red lands in the run's quarantined_count and gates neither the run's verdict nor exit codes, so it can't red-light a deploy. Use it on a persistently flaky test instead of deleting it (which destroys the history) or asking support to deactivate it (which stops it running at all). After 5 consecutive clean passes the test reports rehab_ready (advisory only, nothing un-quarantines itself). `off` un-quarantines.
MCP tool: tests_quarantine
test-id: Test idstate: on | off
Also accepts --workspace and --project (see Configuration).
beryl tests quarantine 4f… on
beryl tests quarantine 4f… offDelete tests, their version history, and their results
Several ids are deleted together in one transaction: an unknown id fails the whole call and nothing is deleted.
MCP tool: tests_delete
test-ids...: One or more test ids
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
beryl tests delete 4f… --force
beryl tests delete 4f… 9a… 1c…Validate + verify an edited plan against the live site before persisting
Unlike `tests set-plan` (which saves the edit and lets it ride into the next run), this replays the edited plan against the live site before anything persists. A deterministic replay failure (verdict `drop`) REJECTS the edit (persisted:false, the prior plan stays live) and returns the failure evidence (over MCP the screenshot is image content). Verdict `flag` (the runner errored, no verdict on the flow) persists the plan but reports it unverified. Returns 429 with Retry-After 30 when the 2 inline-verify slots are saturated (wait and retry).
MCP tool: tests_recompile
test-id: Test id
--file <string>: Plan JSON file, or - for stdin (required)
Also accepts --workspace and --project (see Configuration).
List a test's version history
MCP tool: tests_versions
test-id: Test id
--limit <number>: Page size--cursor <number>: Continue from a previous next_cursor
Also accepts --workspace and --project (see Configuration).
Show one specific version of a test (including its plan)
MCP tool: tests_version
test-id: Test idversion-no: Version number
Also accepts --workspace and --project (see Configuration).
Diff two versions of a test's plan
MCP tool: tests_diff
test-id: Test idfrom: From version numberto: To version number
Also accepts --workspace and --project (see Configuration).
Restore a test to an earlier version
Copies the named older version's plan forward as a NEW head version, unlike `tests reset`, which flips authored_by back to `system` and leaves the plan untouched.
MCP tool: tests_restore
test-id: Test idversion-no: Version number to restore
Also accepts --workspace and --project (see Configuration).
Discard user edits and return the test to its latest system-authored version
Flips authored_by back to `system` WITHOUT changing the plan (the next regeneration overwrites it), unlike `tests restore`, which copies an older version's plan forward as a new version.
MCP tool: tests_reset
test-id: Test id
Also accepts --workspace and --project (see Configuration).
Turn self-healing on or off for a test
MCP tool: tests_heal
test-id: Test idstate: on or off
Also accepts --workspace and --project (see Configuration).
Pass/fail history, streak, and stability for a test
MCP tool: tests_history
test-id: Test id
--limit <number>: How many runs of history--env <string>: Filter by environment id
Also accepts --workspace and --project (see Configuration).
Print the rendered Playwright spec for a test (or an unbanked plan file)
With a test id, fetches the banked test's rendered .spec.ts. With --file, compiles a plan JSON that has NOT been banked yet (the same render `tests create` proves locally) so you can inspect exactly what would run before creating anything. This returns the executable spec. `tests plan` returns the stored JSON plan it is rendered from, `tests get` the metadata row.
MCP tool: tests_script
test-id: Test id (omit when passing --file)
--file <string>: Compile this plan JSON file instead of a banked test--url-override <string>: With --file: resolve relative gotos against this base URL--env <string>: With --file: environment id to render against
Also accepts --workspace and --project (see Configuration).
beryl tests script 4f…
beryl tests script --file plan.jsonExport tests as Playwright .spec.ts files in a ZIP
MCP tool: tests_export
test-ids...: One or more test ids
--out <string>: Output file (default beryl-tests.zip)
Also accepts --workspace and --project (see Configuration).
beryl groups
Manage a project's test groups: labels a test can carry any number of, used to filter, run, or schedule a slice of the suite. Groups are created only here (or in Settings → Groups); assigning a test to an unknown name is an error.
List the project's test groups and how many tests each holds
MCP tool: groups_list
Also accepts --workspace and --project (see Configuration).
Create a group
MCP tool: groups_create
name: Group name (unique per project)
Also accepts --workspace and --project (see Configuration).
beryl groups create SmokeRename a group (tests keep their membership)
MCP tool: groups_rename
group: Current group name or idname: New name
Also accepts --workspace and --project (see Configuration).
Delete a group: its tests stay; a schedule targeting only this group goes with it
MCP tool: groups_delete
group: Group name or id
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
beryl runs
Trigger a run of a project's tests (e.g. in CI), then watch, inspect, and download results.
Trigger a test run (whole suite, a subset, or one environment)
Runs execute in Beryl's cloud. With --watch the CLI streams live progress and exits 0 only if every test passed, so wire it straight into CI. A run with a heal-eligible failure completes only after Beryl has tried to heal it: a repaired test is re-run inside the same run and counts as passed (reported as `healed`), so the final counts, the report and the completion email all reflect the repair.
MCP tool: runs_trigger
--test <strings>: Run only these test ids (repeatable)--group <string>: Run only the active tests in this group (by name), resolved to ids before the run, so the run records exactly what it ran. Cannot be combined with --test.--env <string>: Environment id to run against--url-override <string>: Replace the base URL (preview deploys)--header <strings>: Send a custom request header on every navigation, KEY=VALUE (repeatable). Reaches auth-walled preview deploys, e.g. --header x-vercel-protection-bypass=<token>--watch: Stream progress and exit non-zero on failure--timeout <number>: With --watch: max minutes to wait--retries <number>: Retry a failing test up to N times (0 disables); omit for the default
Also accepts --workspace and --project (see Configuration).
beryl runs trigger --watch
beryl runs trigger --url-override https://preview-123.example.com --watch --timeout 30
beryl runs trigger --url-override https://preview-123.example.com --header x-vercel-protection-bypass=<token> --watch
beryl runs trigger --test 4f… --test 9a…
beryl runs trigger --group Smoke --watch
beryl runs trigger --retries 0 --watchRun tests on your machine with Playwright; results sync to Beryl
Unlike `runs trigger`, the browser runs on YOUR machine: each test's rendered spec is fetched and run with the Playwright runner bundled in the CLI (your repo's own @playwright/test wins when present) and the Chromium binary it drives. Both are checked once before any spec is fetched, so a machine that can't run tests says so once instead of failing every test (on a terminal the CLI offers to install the missing browser; over MCP it prints the exact install command). Signup/OTP flows work: the CLI answers the spec's await_email steps over the API against the same mailbox the cloud runner uses. Authenticated tests work too: for a plan that signs itself in with {{login_email}}/{{login_password}}, the email is baked into the fetched spec and the password is fetched once over the logged secret-reveal route, handed to the spec the way the cloud runner does, and scrubbed from any error text or DOM snapshot before results upload; a test whose account has no stored password is skipped with the exact fix-it command. When the run finishes, the results and replay artifacts are imported into Beryl as a normal run (trigger source `local`), so history, replay, and reports all work; pass --no-sync to keep a run entirely off the record while iterating. Session-mode tests behave as in the cloud: their account signs in once per invocation and every session-mode test rides that session; a failed sign-in fails those tests with the same SESSION_* reason a cloud run reports. Only a test that depends on a session Beryl captured server-side is skipped, with a note. Run those with `runs trigger`. Point --url-override at a local dev server or preview, and --dir to keep specs, artifacts, and reports on disk. Exits 0 only if every executed test passed.
MCP tool: runs_local
test-ids...: Test ids to run (from `beryl tests list`); omit to run every active test
--all: Run every active test in the project (the default when no ids are given)--group <string>: Run only the active tests in this group (by name). Cannot be combined with test ids.--url-override <string>: Run against this base URL instead of the environment's (e.g. http://localhost:3000)--env <string>: Environment id to run against and attach the imported run to. Use for a standing environment; --url-override is for a throwaway host--sync: Import the results into Beryl as a run when finished (--no-sync: local only, nothing recorded)--dir <string>: Write each test's spec, artifacts, and JSON report under this directory
Also accepts --workspace and --project (see Configuration).
beryl runs local
beryl runs local 4f… 9a…
beryl runs local --url-override http://localhost:3000
beryl runs local 4f… --no-sync --dir ./beryl-localList recent runs
Returns the 50 most recent runs unless --page is given; pass --page to walk the full history a slice at a time.
MCP tool: runs_list
--env <string>: Filter by environment id--page <number>: Return only this 1-indexed page instead of the 50 most recent runs--page-size <number>: Runs per page when --page is given (default 8, max 100)
Also accepts --workspace and --project (see Configuration).
Show one run with its per-test results
Over MCP the failure screenshots come back as viewable image content, so an agent can look at the page that broke instead of guessing from the error string. Set screenshots to false to skip fetching them. Ignored outside MCP (the terminal cannot show an image). Returns the run row with its per-test results. `runs report` returns the generated report document, `runs explain` an AI explanation of one failed result.
MCP tool: runs_get
run-id: Run id
--screenshots: Attach failure screenshots as image content (MCP only; default true)
Also accepts --workspace and --project (see Configuration).
Attach to a run and stream progress until it finishes
Replays what already happened, then follows live. Exits 0 only if every test passed.
MCP tool: runs_watch
run-id: Run id
--timeout <number>: Max minutes to wait
Also accepts --workspace and --project (see Configuration).
Cancel an in-flight run
MCP tool: runs_cancel
run-id: Run id
Also accepts --workspace and --project (see Configuration).
Show the generated report for a run
Returns the run's stored generated report (404 until it has been generated). `runs get` returns the raw run row with per-test results.
MCP tool: runs_report
run-id: Run id
Also accepts --workspace and --project (see Configuration).
Download a run's results, with its artifacts, to disk
With --dir, fetches the artifact bytes (screenshots, DOM snapshots, the Playwright trace zip, and the filmstrip frames of the failing tests) into <dir>/<test-result-id>/ alongside a run.json manifest. Artifact URLs are short-lived, so download rather than stash them. With --out (or neither), writes only the JSON manifest.
MCP tool: runs_download
run-id: Run id
--dir <string>: Write run.json plus the artifact files into this directory--all-frames: With --dir: also fetch the filmstrip frames of passing tests--out <string>: Write the JSON to a file instead of stdout
Also accepts --workspace and --project (see Configuration).
beryl runs download 7c1… --dir ./beryl-run
beryl runs download 7c1… --out run.jsonExplain, with AI, why a test result failed
Takes a single test-RESULT id (not a run id) and returns an AI failure explanation for that result. `runs get` lists a run's results and their ids.
MCP tool: runs_explain
result-id: Test result id (from `beryl runs get`)
Also accepts --workspace and --project (see Configuration).
beryl health
Site Health, or how your site reads to search engines and visitors: content, speed, mobile, links and security, graded from a real check of your live pages.
Show the latest Site Health report for a project environment
A check runs automatically when a project or environment gets its URL. While one is in flight the report comes back with status queued/running and no grades yet; call again to pick up the finished result.
MCP tool: health_get
--env <string>: Environment id (defaults to the project's default environment)
Also accepts --workspace and --project (see Configuration).
Run a fresh Site Health check for a project environment
Queues a new check and returns immediately. Returns the in-flight report instead of stacking a second one when a check is already running.
MCP tool: health_run
--env <string>: Environment id (defaults to the project's default environment)
Also accepts --workspace and --project (see Configuration).
beryl health run
beryl health run --env 4f…beryl explorations
Inspect the agent's exploration runs: how it crawled a site and authored its tests.
List the agent's exploration passes for a project
Also accepts --workspace and --project (see Configuration).
Show one exploration: authored tests, abandoned flows, coverage, frontier
exploration-id: Exploration id
Also accepts --workspace and --project (see Configuration).
List every step the agent took in an exploration
exploration-id: Exploration id
Also accepts --workspace and --project (see Configuration).
Cancel an in-flight exploration
Stops a running exploration without touching the project or its tests: the lever for a runaway/non-convergent pass burning agent budget.
exploration-id: Exploration id
Also accepts --workspace and --project (see Configuration).
Stream an exploration live: watch the agent explore and author tests
Replays every recorded step on connect, then follows live until the exploration completes or fails.
exploration-id: Exploration id
--timeout <number>: Max minutes to wait
Also accepts --workspace and --project (see Configuration).
beryl config
Manage the variables, secrets, and files the agent can use while exploring and running.
List the project's config variables (visible to the agent during runs)
MCP tool: config_vars_list
Also accepts --workspace and --project (see Configuration).
Create or update a config variable
MCP tool: config_vars_set
key: Variable namevalue: Variable value
--env <string>: Scope to one environment id
Also accepts --workspace and --project (see Configuration).
Show one config variable
Returns the variable row with its value in plaintext (variables are not secret). A sensitive value lives in `config secrets`, readable only via `config secrets get --reveal`.
MCP tool: config_vars_get
key: Variable key or id
Also accepts --workspace and --project (see Configuration).
Delete a config variable
MCP tool: config_vars_delete
key: Variable key or id
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
List the project's secrets (values are never returned)
MCP tool: config_secrets_list
Also accepts --workspace and --project (see Configuration).
Create a secret (write-only; re-setting a key replaces it)
MCP tool: config_secrets_set
key: Secret namevalue: Secret value (or - to read from stdin)
--env <string>: Scope to one environment id
Also accepts --workspace and --project (see Configuration).
Show one secret's metadata, or reveal its value with --reveal
Returns metadata only by default; --reveal is a logged, member-gated decrypt (unlike `config vars get`, which returns its value in plaintext).
MCP tool: config_secrets_get
key: Secret key or id
--reveal: Return the decrypted value: the explicit read that lets the agent drive a real login while authoring. Member-gated; every reveal is logged--env <string>: With --reveal: prefer the row scoped to this environment id when the key exists at both scopes (matches what a run against that environment resolves)
Also accepts --workspace and --project (see Configuration).
Delete a secret
MCP tool: config_secrets_delete
key: Secret key or id
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
List files uploaded for the agent to use (e.g. CSVs, upload fixtures)
MCP tool: config_files_list
Also accepts --workspace and --project (see Configuration).
Show one uploaded file's metadata
MCP tool: config_files_get
file: File name or id
Also accepts --workspace and --project (see Configuration).
Upload a file
MCP tool: config_files_upload
file: Path to the local file
--env <string>: Scope to one environment id
Also accepts --workspace and --project (see Configuration).
Get a short-lived download URL for a file
MCP tool: config_files_download
file-id: File id
Also accepts --workspace and --project (see Configuration).
Delete an uploaded file
MCP tool: config_files_delete
file-id: File id
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
beryl mailbox
The project's standing email addresses, where its tests receive sign-in mail.
The project's mailbox address
Returns the address {{mailbox_address}} resolves to, creating it on first ask. Every test that reads mail receives here. A test needing an address the site has never seen cites {{inbox_address}} instead. That renders a `+tag` alias of this same mailbox, so a signup stays repeatable without a second address to manage.
MCP tool: mailbox_get
Also accepts --workspace and --project (see Configuration).
List the project's mailboxes
MCP tool: mailbox_list
Also accepts --workspace and --project (see Configuration).
Add a second mailbox to the project
Only needed when a flow requires two genuinely separate inboxes at the same time (both sides of an invite handshake). For an address the site has not seen before, cite {{inbox_address}} in the plan instead: it aliases the existing mailbox and costs nothing to manage.
MCP tool: mailbox_create
--label <string>: What this mailbox is for, e.g. 'invitee'--default: Make it the project's default
Also accepts --workspace and --project (see Configuration).
beryl mailbox create --label inviteeDelete a mailbox and every email it has received
Destructive: the address is configured into the site under test, so removing it breaks every test that signs in through it.
MCP tool: mailbox_delete
mailbox-id: Mailbox id from `beryl mailbox list`
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
Read the latest email in a mailbox (waits for one to arrive)
Waits up to --timeout-s for a matching email and returns it (one blocking request; the server caps the wait at 50s, so re-run to keep waiting). With --extract-code, also asks the server to pull the one-time code out of the email (AI-assisted when the email is ambiguous; `code` is null if none was found). Use --recipient-contains to read only one `+tag` alias's mail when several identities share the mailbox. Exits non-zero if nothing arrives before the timeout. Waits for and returns ONE latest matching email. `mailbox emails` lists what has already arrived, without waiting.
MCP tool: mailbox_read
mailbox-id: Mailbox id from `beryl mailbox list`
--timeout-s <number>: Seconds to wait for a matching email (0 = don't wait; max 50, default 30)--since <string>: Only emails received after this ISO timestamp--from-contains <string>: Only emails whose sender contains this--subject-contains <string>: Only emails whose subject contains this--recipient-contains <string>: Only mail delivered to an address containing this (a +tag alias)--extract-code: Also return the one-time code found in the email as `code`
Also accepts --workspace and --project (see Configuration).
beryl mailbox read mbx_123 --timeout-s 45 --json
beryl mailbox read mbx_123 --subject-contains code --extract-code --jsonList the emails a mailbox has received
Returns the already-received emails without waiting. `mailbox read` blocks for a matching one and returns just it.
MCP tool: mailbox_emails
mailbox-id: Mailbox id from `beryl mailbox list`
--since <string>: Only emails received after this ISO timestamp--limit <number>: Return only the most recent N emails (newest first)
Also accepts --workspace and --project (see Configuration).
beryl accounts
Durable identities on the site under test: what an authenticated test signs in as.
List the test accounts an environment's tests sign in as
Every test account on the project, with the identity label a plan's `auth_label` names. The row marked * is the default: what a plan gets when it sets requires_auth without an auth_label.
MCP tool: accounts_list
--env <string>: Only accounts on this environment id
Also accepts --workspace and --project (see Configuration).
Add a test account: the customer's own, or one Beryl signs up
Two kinds. `--type user_provided` records a dedicated account you already have on the site: pass --email and --password, and it is usable immediately. `--type beryl` reserves one Beryl will sign up itself, addressed at the project mailbox. It starts `pending` and becomes usable after `beryl accounts signup`. The first account an environment gets is its default whatever you pass.
MCP tool: accounts_create
--type <user_provided|beryl>: Whose account this is (default: user_provided when --password is given)--label <string>: Identity label a plan's auth_label names (default 'default')--email <string>: user_provided only: the account's email--password <string>: user_provided only: stored encrypted as a project secret, never returned--login-method <password|magic_link|otp>: How tests sign in as it (default password)--env <string>: Environment id (default: the project's)--default: Make this the environment's default
Also accepts --workspace and --project (see Configuration).
beryl accounts create --email [email protected] --password 'hunter2'
beryl accounts create --type beryl --login-method otp
beryl accounts create --email [email protected] --password 'hunter2' --label adminStore a test account's signup plan and sign it up on its environment
Runs the app's signup form once in a real browser and, if it ends logged in, marks the account ready. The plan is an ordinary ActionPlan of the SIGNUP flow. Type {{mailbox_address}} into the email field and {{login_password}} into the password field. Both resolve at replay time, and an `await_email` step reads the project mailbox, so a verification code works. The plan is kept on the account, so the same identity can be signed up again on a new environment. For an account that already exists on the site, store its sign-in with `accounts set-login` instead.
MCP tool: accounts_signup
account-id: Account id from `beryl accounts list`
--file <string>: The signup ActionPlan, ending logged in, as JSON (path, or - for stdin) (required)
Also accepts --workspace and --project (see Configuration).
beryl accounts signup acc_123 --file signup-plan.jsonStore the sign-in plan a run replays once, plus the probe that proves it
Session mode: instead of every authenticated test signing in for itself, the account signs in ONCE at the start of a run and every test rides that session. This stores the two plans that makes possible. --file is the SIGN-IN plan (not the signup): it must end logged in. Type {{login_email}} into the email field and {{login_password}} into the password field; an emailed code or magic link arrives at the account's own address, so an `await_email` step reads it with no human involved. --probe is the liveness check: a two-step plan (goto a gated page, then a POSITIVE assertion that only holds when signed in: the account menu, a 'Sign out' control). It is replayed in a fresh browser carrying only the captured session. It is REQUIRED, and not a formality: assertions like `hidden`, `count 0`, and a URL match on a redirect all pass against a logged-out page, so without a positive signal a dead session would run every test logged-out and still report the run green. Storing only stores. Run `beryl accounts check` to prove it against the live app.
MCP tool: accounts_set_login
account-id: Account id from `beryl accounts list`
--file <string>: The sign-in ActionPlan, as JSON (path, or - for stdin) (required)--probe <string>: The liveness probe plan, as JSON (path, or - for stdin): goto a gated page, then assert something only a signed-in user sees (required)--base-hash <string>: The login_plan_hash from `beryl accounts get-login`. The write is rejected if the stored plan changed since. Omit only when writing the first plan
Also accepts --workspace and --project (see Configuration).
beryl accounts set-login acc_123 --file signin.json --probe probe.json
beryl accounts set-login acc_123 --file signin.json --probe probe.json --base-hash 9f2c…Read the stored sign-in plan, its probe, and the hash a safe write must cite
The login plan is readable, not just writable: it heals, so overwriting without reading first can clobber a repair you never saw. Pass login_plan_hash back as --base-hash on the next `accounts set-login`.
MCP tool: accounts_get_login
account-id: Account id
Also accepts --workspace and --project (see Configuration).
Sign in now and prove the session survives into a fresh browser
Replays the stored sign-in plan, captures the session it produces, then injects that session into a clean browser and runs the probe. Green here is the same green a run gets, because it is the same code path. A failure tells you which half broke: SESSION_LOGIN_FAILED means the sign-in itself did not complete (fix the plan); SESSION_PROOF_FAILED means the sign-in worked but the session did not survive the move to a fresh browser, so this app keeps its credential somewhere that cannot be carried (a service worker, a WebAuthn binding). In that case the account is marked unsupported: its session-mode tests fail at setup with SESSION_UNSUPPORTED on every run until re-authored with auth_mode "inline" and their own sign-in steps; inline tests are unaffected. Blocks for two browser replays.
MCP tool: accounts_check
account-id: Account id
Also accepts --workspace and --project (see Configuration).
beryl accounts check acc_123Change a test account's password, login method, or default flag
MCP tool: accounts_update
account-id: Account id
--email <string>: New email--password <string>: New password (re-marks the account ready)--login-method <password|magic_link|otp>: How tests sign in as it--default: Make this the environment's default
Also accepts --workspace and --project (see Configuration).
Delete a test account
Removes the identity. Tests naming it in auth_label start failing with a clear reason rather than silently signing in as somebody else.
MCP tool: accounts_delete
account-id: Account id
--force: Skip the confirmation prompt
Also accepts --workspace and --project (see Configuration).
beryl account
View and update your personal account profile.
Show your account profile
Update your profile
--name <string>: New display name--newsletter: Toggle the newsletter subscription
Preview what deleting your account would remove or leave
beryl feedback
Send product feedback to the Beryl team.
Send product feedback to the Beryl team
message: Your feedback
beryl billing
Review a workspace's plan usage, subscription, and invoices.
Show plan usage: monthly cloud run minutes
Also accepts --workspace (see Configuration).
Show the workspace's subscription
Also accepts --workspace (see Configuration).
List recent invoices
--limit <number>: How many invoices
Also accepts --workspace (see Configuration).
Get a Stripe billing-portal link for the workspace
Also accepts --workspace (see Configuration).
beryl version
Show the running CLI version, API URL, and Node version
Show the running CLI version, API URL, and Node version
Answers "which build am I actually talking to?" (the one question a long-lived `beryl mcp` process can't otherwise answer, since it loads source at spawn and never hot-reloads). Needs no login, so it still works when a token is missing or broken. Also reports whether the running build is behind npm's `latest` (best-effort: `update_available` is null when the registry can't be reached, and the check is skipped entirely under BERYL_NO_UPDATE_CHECK).
MCP tool: version
beryl version
beryl version --jsonberyl mcp
Run the Beryl MCP server (stdio): every CLI command as an agent tool
Run the Beryl MCP server (stdio): every CLI command as an agent tool
Exposes the CLI's commands as MCP tools over stdio, so coding agents (Claude Code, Cursor, …) can create projects, trigger runs, watch the agent, and edit tests. Authenticate via BERYL_API_KEY or a prior `beryl login`.
claude mcp add beryl -- beryl mcp