CLI Reference

Beryl is MCP first. Your coding agent calls these commands as tools, and that is how we expect you to use Beryl. The same commands run in a terminal when you want one, which is what this page documents. MCP setup wires your agent in one command.

CLI version 0.91.1 · MCP setup

Install

Signs you in, wires the beryl MCP server into the agent you pick, and installs the beryl-test skill.

npx @beryl-so/cli@latest init

MCP setup lists the agents and their flags. Needs Node 20.19 or newer. To install permanently:

npm install -g @beryl-so/cli
beryl --version

Authenticate

beryl login opens beryl.so/cli/connect. Approve the code in your terminal and the token lands in ~/.config/beryl/config.json.

beryl login
beryl whoami

Without a browser:

  • --otp, or Enter at the prompt, emails a 6-digit code. A new email gets an account; a Google sign-in gets no code.
  • --email <addr> --code <digits> finishes that flow without a prompt, for agents.
  • --token <pat> uses an existing token from beryl.so → Account → Personal access tokens.
  • BERYL_API_KEY skips login entirely.

A token carries your full account access. beryl tokens revoke kills one, beryl logout --revoke does both.

Cloud runs

A job authors the tests from your document, and the suite runs in Beryl's cloud browsers.

beryl projects create https://app.example.com
beryl jobs create "Cover the checkout flows" --file ./checkout-flows.md
beryl jobs get <job-id>
beryl runs trigger --watch
beryl projects report

For a login-gated site, add --auth gated. Tests sign in as durable test accounts (beryl accounts) whose mail lands in the project mailbox (beryl mailbox). To fix a test, edit its plain-JSON plan and submit it with beryl tests recompile, which proves the change with a replay before it saves.

Exit codes

  • 0 success
  • 1 failure
  • 2 usage error
  • 3 authentication error

--watch streams progress and exits non-zero unless every test passed.

Configuration

Config stores your token and API URL. Scoped commands take --workspace and --project by id, name, or URL. Leave them out and the CLI reads BERYL_WORKSPACE / BERYL_PROJECT, then falls back to your only one.

The CLI pins nothing to a folder, so two 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

beryl init

Set up Beryl in this repo: sign in and wire up your coding agent (interactive)

Signs you in, wires the beryl MCP server into the coding agent you pick, and writes the beryl-test skill. Pick an agent with --claude, --cursor, --vscode and/or --opencode. With no flag it prompts (Enter picks Claude); with no flag and no TTY it wires nothing and prints the flags. --claude also wires the Claude DESKTOP app when installed, which needs a quit and reopen to pick the config up. --scope user (default) configures everything per-user, matching where your login token lives; --scope project writes config committed to the repo. Safe to re-run: it refreshes the skill to this CLI's version and skips whatever is already set up.

  • --scope <user|project>: Where to wire: user (default) is per-user, project is committed to the repo. Every teammate still runs beryl login to authenticate
  • --claude: Wire Claude Code (claude mcp add -s user, or a committed .mcp.json under --scope project), plus the Claude desktop app when it is installed
  • --cursor: Wire Cursor, plus a repo-local .cursor/rules/beryl.mdc authoring rule, since Cursor reads no skills dir
  • --vscode: Wire VS Code's user mcp.json (or .vscode/mcp.json under --scope project), plus a Beryl section in .github/copilot-instructions.md for Copilot
  • --opencode: Wire ~/.config/opencode/opencode.json (or the repo's opencode.json under --scope project), in opencode's own config shape
npx @beryl-so/cli@latest init
beryl init --claude
beryl init --cursor --opencode
beryl init --vscode --scope project

beryl guide

Print the Beryl test guide

beryl guide

Print the Beryl test guide

The guide to durable, healable tests: where new tests come from (jobs create), the ActionPlan shape, outcome assertions, natural-language intent, test accounts and the project mailbox ({{login_email}}, {{mailbox_address}}, {{inbox_address}} + await_email), and the run-fix loop. Same content as the beryl-test skill beryl init installs. Skip if a loaded beryl-test skill states v0.91.1; else call this first (works without logging in).

MCP tool: guide

beryl guide

beryl login

Authenticate the CLI with your Beryl account

beryl login

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 → Personal access 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 --json

beryl signup

Register a new Beryl account (emails a 6-digit verification code)

beryl signup

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] --json

beryl logout

Remove the stored token from the CLI config

beryl logout

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

beryl whoami

Show the signed-in account

MCP tool: whoami

beryl tokens

Manage the personal access tokens that authenticate the CLI and CI.

beryl tokens list

List your personal access tokens

MCP tool: tokens_list

beryl tokens create <name>

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)
beryl tokens revoke <token-id>

Revoke a personal access token

MCP tool: tokens_revoke

  • token-id: Token id from beryl tokens list
beryl tokens dismiss <token-id>

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.

beryl workspaces list

List workspaces you belong to

MCP tool: workspaces_list

beryl workspaces get

Show one workspace

MCP tool: workspaces_get

Also accepts --workspace (see Configuration).

beryl workspaces create <name>

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
beryl workspaces update

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).

beryl workspaces delete

Delete a workspace and everything in it

MCP tool: workspaces_delete

  • --force: Skip the confirmation prompt

Also accepts --workspace (see Configuration).

beryl workspaces history

Show the workspace's action history (who did what, when)

MCP tool: workspaces_history

Also accepts --workspace (see Configuration).

beryl workspaces leave

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.

beryl members list

List workspace members

Also accepts --workspace (see Configuration).

beryl members set-role <user-id> <role>

Change a member's role

  • user-id: Member's user id
  • role: OWNER, USER or VIEWER

Also accepts --workspace (see Configuration).

beryl members remove <user-id>

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.

beryl invites send <email>

Invite someone to the workspace by email

  • email: Invitee email
  • --role <OWNER|USER|VIEWER>: Role (default USER)

Also accepts --workspace (see Configuration).

beryl invites list

List the workspace's outstanding invitations

Also accepts --workspace (see Configuration).

beryl invites revoke <invitation-id>

Revoke a pending invitation

  • invitation-id: Invitation id

Also accepts --workspace (see Configuration).

beryl invites mine

List invitations sent to you

beryl invites accept <invitation>

Accept an invitation (by id, or by the token from the invite email)

  • invitation: Invitation id or emailed token
beryl invites decline <invitation-id>

Decline an invitation

  • invitation-id: Invitation id

beryl projects

Create and manage projects: a site you author tests for and run.

beryl projects list

List projects in the workspace

MCP tool: projects_list

Also accepts --workspace (see Configuration).

beryl projects get

Show one project, including its current exploration state

MCP tool: projects_get

Also accepts --workspace and --project (see Configuration).

beryl projects create [url]

Create a project for a URL, or an empty one with just --name

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>
  • --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

Also accepts --workspace (see Configuration).

beryl projects create https://app.example.com
beryl projects create https://app.example.com --auth gated
beryl projects create --name "Acme production"
beryl projects rename <name>

Rename a project

MCP tool: projects_rename

  • name: New name

Also accepts --workspace and --project (see Configuration).

beryl projects quarantine [state]

Turn auto quarantine on or off and tune when it mutes and releases a test

With auto quarantine on, the end of every run checks the tests that ran: a test that failed --failures times in the last --days days with a pass in between is quarantined (straight failures are a regression and never are), and a quarantined test, manual or auto, is released after --passes first-attempt passes in a row. Pass on|off and/or any of the numbers; projects get shows the current values.

MCP tool: projects_quarantine

  • state: on | off; omit to only tune the numbers
  • --failures <number>: Failures in the window that quarantine a test (1-50, default 3)
  • --days <number>: Window in days (1-90, default 7)
  • --passes <number>: Passes in a row that release a test (1-50, default 5)

Also accepts --workspace and --project (see Configuration).

beryl projects quarantine on
beryl projects quarantine on --failures 3 --days 7 --passes 5
beryl projects quarantine --passes 3
beryl projects quarantine off
beryl projects heal [state]

Turn self-heal on or off for a project and limit its time and runs

Self-heal is off by default: a failed test fails right away. With it on, a run holds a failed test that has passed before while a heal agent tries to repair its plan against the app, and the test passes if the repair is proven by a replay. --minutes caps the heal agent's time on one failed test (from 1 up to the platform limit, 5 unless the server is configured otherwise; the proving replay comes on top; 0 goes back to that limit) and --max-per-run caps how many failed tests one run may heal (0 removes the cap); past it the rest fail without a heal. A test turned off with tests heal <id> off never heals. projects get shows the current values.

MCP tool: projects_heal

  • state: on | off; omit to only change the limits
  • --minutes <number>: Minutes the heal agent may spend on one failed test (0 = the platform limit, 5 by default)
  • --max-per-run <number>: Failed tests one run may heal (0 = no cap)

Also accepts --workspace and --project (see Configuration).

beryl projects heal on
beryl projects heal on --minutes 2 --max-per-run 5
beryl projects heal --max-per-run 0
beryl projects heal off
beryl projects surfaces [surfaces...]

Turn project surfaces on or off

Surfaces are web-desktop, web-tablet, web-mobile, android, ios; a new project has web-desktop only. --add turns surfaces on and --remove turns them off, keeping the rest. Listing surfaces sets the exact set instead, and is refused when it would turn off a surface that is on unless you pass --replace. At least one surface stays on. Prints the set before and after. Turning a surface off removes no tests: delete a surface's tests to stop running them. android and ios test the app named by each environment's app id for that surface (envs update --app-id android=<package> --app-id ios=<bundle id>) from its newest uploaded build (config files upload app.apk, config files upload App.zip --kind ios_build), on Beryl's Android and iOS workers.

MCP tool: projects_surfaces

  • surfaces...: The exact set to enable: web-desktop | web-tablet | web-mobile | android | ios
  • --add <strings>: Turn this surface on (repeatable)
  • --remove <strings>: Turn this surface off (repeatable)
  • --replace: Let a listed exact set turn off surfaces that are on now

Also accepts --workspace and --project (see Configuration).

beryl projects surfaces --add android --add ios
beryl projects surfaces --remove web-tablet
beryl projects surfaces web-desktop web-mobile --replace
beryl projects findings-gate <mode>

Turn the findings gate on each run on or off

With the gate on (new-since-green), every run also reports a findings gate: failed when the environment's Site Health has a finding first seen after the last green run or came back after it (every current finding if there is no green run yet), unknown when Site Health has not run there or is not recording findings (its issue tracker must be connected). The gate sits next to the test verdicts and never changes one, nor the exit code of runs watch; read it from findings_gate on runs get. Off by default.

MCP tool: projects_findings_gate

  • mode: off | new-since-green

Also accepts --workspace and --project (see Configuration).

beryl projects findings-gate new-since-green
beryl projects findings-gate off
beryl projects delete

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).

beryl projects re-explore

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).

beryl projects report

Aggregate quality report across recent runs (pass rates, per-test history, 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).

beryl projects reusable-auth <url>

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.

beryl envs list

List a project's environments

MCP tool: envs_list

Also accepts --workspace and --project (see Configuration).

beryl envs get <env-id>

Show one environment

site_health_runs_reset_fields and site_health_tracker_reset_fields name stored Site Health settings that were invalid and fell back to defaults (* = all of them). Scheduled and CI runs, or ticket filing, auto-close and the digest, stop until they are saved again: envs update with any --health-* flag rewrites the run settings, any --tracker-* flag the tracker settings.

MCP tool: envs_get

  • env-id: Environment id

Also accepts --workspace and --project (see Configuration).

beryl envs create <name> <url>

Add an environment (e.g. staging) to a project

MCP tool: envs_create

  • name: Environment name
  • url: Root URL for this environment
  • --auth <public|gated>: Whether this environment needs a login

Also accepts --workspace and --project (see Configuration).

beryl envs update <env-id>

Update an environment's name, URL, app ids, auth settings, Site Health screen sizes, schedule, CI and pages, or issue tracker settings

MCP tool: envs_update

  • env-id: Environment id
  • --name <string>: New name
  • --url <string>: New root URL
  • --app-id <strings>: App id for an app surface, as surface=id (android=com.acme.app, ios=com.acme.App), repeatable: that surface's tests install the newest uploaded build of it; "ios=" clears it. Warns, naming the uploaded ids, when no uploaded build has it
  • --auth <public|gated>: New auth choice
  • --viewport <all|phone|tablet_portrait|tablet_landscape|desktop|desktop_wide>: Screen size the Site Health visual checks run at, repeatable; replaces the set. Pass --viewport all to reset to all five.
  • --health-schedule <off|daily|weekly>: Run Site Health on a schedule (default off)
  • --health-time <string>: Time of day scheduled runs start, 24h, in --health-timezone (default 09:00)
  • --health-day <mon|tue|wed|thu|fri|sat|sun>: Day weekly runs start (default mon)
  • --health-timezone <string>: IANA timezone for the schedule, e.g. Europe/Berlin (default UTC)
  • --health-ci <off|every_build|main_only|deploy_only>: Which CI builds health run --ci checks; other builds skip and pass (default off)
  • --health-ci-fail-on <high|medium|never>: Lowest finding severity that fails the CI build; never reports only (default high)
  • --health-ci-tickets <on|off>: CI runs file tracker tickets; off leaves the findings to the PR (default off)
  • --health-pages <homepage|paths|sitemap|crawl>: Pages a run checks: the homepage, --health-path list, sitemap.xml, or a crawl from the homepage (default homepage)
  • --health-path <strings>: Page path for the paths mode, repeatable; replaces the list. none clears it
  • --health-crawl-depth <number>: Link hops from the homepage in crawl mode, 1-5 (default 2)
  • --health-max-pages <number>: Most pages one run checks, homepage included, 1-100 (default 25)
  • --health-include <strings>: Path pattern a page must match, e.g. '/blog/*', repeatable; replaces the list. none clears it
  • --health-exclude <strings>: Path pattern to skip, repeatable; replaces the list. none clears it
  • --health-logged-in <strings>: Path pattern checked signed in with the environment's saved test sign-in, repeatable; the rest run logged out. none clears it
  • --health-retries <number>: Extra attempts when a page check fails or times out, 0-3 (default 1)
  • --tracker <linear|off>: Tracker Site Health files tickets in; off stops filing for this environment (connect it first with health tracker connect)
  • --tracker-team <string>: Tracker team id (see health tracker teams)
  • --tracker-project <string>: Tracker project id inside the team (see health tracker projects); none clears it
  • --tracker-label <strings>: Label put on every ticket, repeatable; replaces the set (default beryl)
  • --tracker-priority <strings>: Severity to tracker priority, repeatable, e.g. high=urgent. Priorities: urgent, high, medium, low, none (default high=high, medium=medium, low=low)
  • --tracker-threshold <high|medium|low>: Lowest severity filed automatically; the rest go to the digest (default high)
  • --tracker-digest <off|daily|weekly>: Digest of findings that were not filed (default weekly)
  • --tracker-digest-to <ticket|slack>: Where the digest goes: one digest ticket, or the Slack alert channel (default ticket)
  • --tracker-auto-close <on|off>: Close a ticket once a run no longer sees its finding (default on)
  • --tracker-reopen <on|off>: Reopen the same ticket when a fixed finding comes back; off files a new one (default on)
  • --tracker-reopen-closed <on|off>: Reopen a ticket closed in the tracker while the check still fails (default on)
  • --tracker-max-tickets <number>: New tickets one run may file, 0-100; the rest go to the digest (default 10)
  • --tracker-assignee <string>: Tracker user id (a person or an agent user) new tickets go to; none clears it
  • --tracker-min-runs <number>: Runs in a row a finding must show in before a manual run files it (default 1)
  • --tracker-min-runs-scheduled <number>: Same, for scheduled and CI runs (default 2)
  • --tracker-pause <on|off>: Pause all ticket creation and updates without disconnecting

Also accepts --workspace and --project (see Configuration).

beryl envs update <env-id> --tracker linear --tracker-team <team-id>
beryl envs update <env-id> --app-id android=com.acme.app --app-id ios=com.acme.App
beryl envs update <env-id> --tracker-threshold medium --tracker-max-tickets 5
beryl envs update <env-id> --tracker-priority high=urgent --tracker-pause on
beryl envs update <env-id> --health-schedule daily --health-time 06:00 --health-timezone Europe/Berlin
beryl envs update <env-id> --health-pages crawl --health-max-pages 25 --health-exclude '/blog/*'
beryl envs update <env-id> --health-ci main_only --health-ci-fail-on medium
beryl envs delete <env-id>

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 environment, cadence (daily or weekly), local run time, timezone, and target groups (none = every active test).

beryl schedule list

List the project's schedules

MCP tool: schedule_list

Also accepts --workspace and --project (see Configuration).

beryl schedule add

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
  • --env <string>: Environment id to run against (default: the project's default environment)

Also accepts --workspace and --project (see Configuration).

beryl schedule add --frequency daily --hour 6 --tz UTC
beryl schedule add --env <env-id> --frequency daily --hour 6 --tz UTC
beryl schedule add --groups "Smoke,Checkout" --frequency weekly --day 0 --hour 9 --minute 15 --tz UTC
beryl schedule update <schedule-id>

Change a schedule's cadence, time, timezone, groups, or environment

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
  • --env <string>: Move the schedule to this environment id
  • --all-tests: Target every active test (clears the schedule's groups)

Also accepts --workspace and --project (see Configuration).

beryl schedule remove <schedule-id>

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.

beryl tests list

List 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
  • --access <string>: Only read or only write tests
  • --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, failing (failed or errored), failed, errored, cancelled, or quarantined
  • --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).

beryl tests get <test-id>

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).

beryl tests plan <test-id>

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).

beryl tests set-plan <test-id>

Replace a test's step plan (creates a new version)

Accepts an ActionPlan (the shape tests plan returns), 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
  • --plan <json>: The plan inline, instead of --file
  • --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.json
beryl tests set-plan 4f… --plan '{"steps":[{"action":"goto","url":"/pricing"}]}'
beryl tests rename <test-id> <title>

Rename a test

MCP tool: tests_rename

  • test-id: Test id
  • title: New title

Also accepts --workspace and --project (see Configuration).

beryl tests rename 4f… "Checkout happy path"
beryl tests set-intent <test-id> <intent>

Edit what a test proves, the target heal judges against

The intent is the plain-language statement of what the test proves; heal judges every repair against it. It belongs to the test, so every surface of the test gets a new version carrying the new text (same plan, recorded as your edit; see tests versions). The plan is NOT regenerated: change the steps with tests set-plan. Re-explore keeps matching the same test after an edit.

MCP tool: tests_set_intent

  • test-id: Test id
  • intent: New intent text

Also accepts --workspace and --project (see Configuration).

beryl tests set-intent 4f… "Proves a shopper can check out and sees an order number."
beryl tests set-groups <test-id>

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. Every surface of the test carries the same set.

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…
beryl tests set-access <test-id> <access>

Mark a test read or write

read: the test only reads the app. write: it creates, edits, renames, deletes or toggles something that persists. The label is yours to set; Beryl does not infer it from the plan. A write test must clean up in after, ending with a proof expect. The label covers every surface of the test, so each surface's plan must clean up.

MCP tool: tests_set_access

  • test-id: Test id
  • access: read | write

Also accepts --workspace and --project (see Configuration).

beryl tests set-access 4f… write
beryl tests set-access 4f… read
beryl tests add-groups <test-ids...>

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 Smoke
beryl tests quarantine <state> <test-ids...>

Mute flaky tests: they keep running, but their 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 the project's release threshold of consecutive clean passes (default 5) the test reports rehab_ready: a suggestion while auto quarantine is off, the actual release once projects quarantine on has turned it on. off un-quarantines. Several ids are one call; tests already in the requested state are left alone rather than rejected. Who quarantined what is recorded, readable with beryl tests events.

MCP tool: tests_quarantine

  • state: on | off
  • test-ids...: One or more test ids

Also accepts --workspace and --project (see Configuration).

beryl tests quarantine on 4f…
beryl tests quarantine on 4f… 9a… 1c…
beryl tests quarantine off 4f…
beryl tests events <test-id>

Who quarantined, grouped or renamed a test, and why

Lifecycle history for one test, newest first: quarantine and release (by a person or by auto-quarantine, with the run and failure streak behind it), group changes, and renames. Plan edits are NOT here: those are versions, and beryl tests versions can restore them.

MCP tool: tests_events

  • test-id: Test id
  • --limit <number>: How many events (default 100, max 500)

Also accepts --workspace and --project (see Configuration).

beryl tests events 4f…
beryl tests events 4f… --limit 20
beryl tests delete <test-ids...>

Delete 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…
beryl tests recompile <test-id>

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
  • --plan <json>: The plan inline, instead of --file

Also accepts --workspace and --project (see Configuration).

beryl tests versions <test-id>

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).

beryl tests version <test-id> <version-no>

Show one specific version of a test (including its plan)

MCP tool: tests_version

  • test-id: Test id
  • version-no: Version number

Also accepts --workspace and --project (see Configuration).

beryl tests diff <test-id> <from> <to>

Diff two versions of a test's plan

MCP tool: tests_diff

  • test-id: Test id
  • from: From version number
  • to: To version number

Also accepts --workspace and --project (see Configuration).

beryl tests restore <test-id> <version-no>

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 id
  • version-no: Version number to restore

Also accepts --workspace and --project (see Configuration).

beryl tests reset <test-id>

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).

beryl tests heal <test-id> <state>

Turn self-healing on or off for a test

Only matters while the project's self-heal is on (projects heal on); it is off by default, and then no test heals.

MCP tool: tests_heal

  • test-id: Test id
  • state: on or off

Also accepts --workspace and --project (see Configuration).

beryl tests history <test-id>

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).

beryl tests script <test-id>

Print the rendered Playwright spec for a test

Fetches the banked test's rendered .spec.ts: 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

Also accepts --workspace and --project (see Configuration).

beryl tests script 4f…
beryl tests export <test-ids...>

Export tests as Playwright .spec.ts files in a ZIP

Writes the ZIP to disk. With --inline, nothing is written: the result carries the same files as {files: [{filename, content}]}.

MCP tool: tests_export

  • test-ids...: One or more test ids
  • --out <string>: Output file (default beryl-tests.zip)
  • --inline: Return the files in the result instead of writing a 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.

beryl groups list

List the project's test groups and how many tests each holds

MCP tool: groups_list

Also accepts --workspace and --project (see Configuration).

beryl groups create <name>

Create a group

MCP tool: groups_create

  • name: Group name (unique per project)

Also accepts --workspace and --project (see Configuration).

beryl groups create Smoke
beryl groups rename <group> <name>

Rename a group (tests keep their membership)

MCP tool: groups_rename

  • group: Current group name or id
  • name: New name

Also accepts --workspace and --project (see Configuration).

beryl groups delete <group>

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.

beryl runs trigger

Trigger a test run (whole suite, a subset, or one environment)

Runs execute in Beryl's cloud. With --watch the CLI follows 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. A project runs one run at a time: a run triggered while another is in flight comes back queued with its queue_position and starts on its own, in trigger order, when the runs ahead of it finish (--watch waits through the queue).

MCP tool: runs_trigger

  • --test <strings>: Run only these test ids (repeatable)
  • --group <strings>: Run only the active tests in these groups (by name, repeatable, union of members), 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: Follow progress and exit non-zero on failure
  • --timeout <number>: With --watch: max minutes to wait. A test that waits for an asynchronous process (a wait_until step) can run for minutes, so set this generously for a suite that has one.
  • --fail-fast: With --watch: cancel the run and exit 1 on the first failing test, instead of waiting for the rest of the suite. Built for CI gates; off by default
  • --retries <number>: Retry a failing test up to N times (0 disables); omit for the default
  • --commit <string>: Commit sha of your app this run tests, shown on the run. Detected automatically in GitHub Actions and GitLab CI (or from BERYL_COMMIT_SHA); this overrides it
  • --branch <string>: Branch of your app this run tests, shown on the run. Detected automatically in GitHub Actions and GitLab CI (or from BERYL_BRANCH); this overrides it

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 --group Checkout --watch
beryl runs trigger --retries 0 --watch
beryl runs trigger --commit $(git rev-parse HEAD) --branch main --watch
beryl runs queue

Show the run in flight and the runs waiting behind it

A project runs one run at a time. Returns active (the pending or running run, or null) and queued, the waiting runs in the order they will start, each with its queue_position. Cancel a waiting run with runs cancel.

MCP tool: runs_queue

Also accepts --workspace and --project (see Configuration).

beryl runs list

List 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).

beryl runs get <run-id>

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 every per-test result unless --page is given; pass --page to read a large run a slice at a time, optionally narrowed by --status, --group or --q, which keeps the output readable rather than saving a round trip. With --page the match total and page counts come back under results_page. Paged results are the run's settled tests only: anything still running, healing or queued is left out. A result carries heal when Beryl healed it: its steps were rewritten with the intent unchanged, proved in a browser and it re-ran green; version_no is the revision it wrote (see tests diff) and rationale the agent's reason. A red that Beryl tried and failed to heal carries heal_attempt: status is how the heal ended, reason why, and heal_job_id the job. A red that Beryl did not try to heal carries heal_skip_reason saying why. 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)
  • --page <number>: Return only this 1-indexed page of results instead of every result
  • --page-size <number>: Results per page when --page is given (default 20, max 100)
  • --status <string>: With --page, show only this bucket: passed, failed, errored, cancelled, or quarantined
  • --group <string>: With --page, show only results whose test is in this group (by name; see beryl groups list)
  • --ungrouped: With --page, show only results whose test carries no group
  • --q <string>: With --page, show only results whose test title contains this text (case-insensitive)

Also accepts --workspace and --project (see Configuration).

beryl runs watch <run-id>

Follow a run 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
  • --fail-fast: Cancel the run and exit 1 on the first failing test, instead of waiting for the rest of the suite. Built for CI gates; off by default

Also accepts --workspace and --project (see Configuration).

beryl runs cancel <run-id>

Cancel an in-flight run, or take a queued one out of the queue

MCP tool: runs_cancel

  • run-id: Run id

Also accepts --workspace and --project (see Configuration).

beryl runs report <run-id>

Show the generated report for a run

Returns the run's stored generated report (404 until it has been generated). causes groups the failures: every test that failed inside the same signup steps (a fresh {{inbox_address}} user) is one signup cause, so a broken signup reads as one problem; each other failure is its own test cause. 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).

beryl runs download <run-id>

Get a run's results with signed artifact URLs, or download them to disk

With neither --dir nor --out, writes nothing: returns the JSON manifest, whose screenshot, DOM snapshot, trace and frame URLs are short-lived signed links any HTTP client can fetch. 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. With --out, writes only the manifest. The URLs expire, so fetch rather than stash them.

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.json
beryl runs explain <result-id>

Explain, 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, links, security, and a visual check of layout at phone, tablet and desktop sizes, graded from a real check of your live pages.

beryl health get

Show the latest Site Health report, or one report by id

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, plus the stage a running check is on; call again to pick up the finished result. Visual findings sit in the layout category, which also grades them per screen size (screens: phone, tablet, desktop) and as mobile (phone and tablet only). Each carries a key, the selector, measured values, the viewports it shows at and a fix hint in recommendation. The performance category grades Google PageSpeed on mobile and on desktop separately (speeds, each with its own Core Web Vitals) and takes the worse of the two; one that couldn't be measured is left out. A category's unchecked lists checks this run couldn't determine (e.g. robots.txt timed out): they neither pass nor fail. Pass --report for a single-page check started with health run --path. site_health_runs_reset_fields and site_health_tracker_reset_fields name stored settings that were invalid and fell back to defaults (* = all of them): scheduled and CI runs, or ticket filing, stop until they are saved again with envs update.

MCP tool: health_get

  • --env <string>: Environment id (defaults to the project's default environment)
  • --report <string>: Report id (from health run)
  • --run <string>: Run id: every page of one run, finding counts and the CI gate verdict
  • --screenshots: Include the annotated screenshots (as images over MCP, data URIs in --json)

Also accepts --workspace and --project (see Configuration).

beryl health run

Run a fresh Site Health check, or a visual check of one page

Queues a check and returns immediately (or, with --wait, once it finishes; a check takes one to three minutes). Without --path it is the full Site Health run of the environment URL. With --path it runs only the visual checks (clipping, overlap, tap targets, scroll traps, content stability, scroll-through) on that page, logged out unless it matches the environment's --health-logged-in patterns, at the chosen --viewport sizes (default: the environment's configured set). Returns the in-flight report instead of stacking a second one of the same scope. A full run also checks the environment's configured pages (see envs update --health-pages); each page gets its own report, grouped under the homepage report's run_id. With --ci it starts a CI run, waits for every page, prints a Markdown summary you can post as the PR comment, and exits 1 when findings at or above the environment's fail-on severity exist, a page couldn't be checked, or the run failed. Builds that the environment's CI mode doesn't cover skip and exit 0; if the stored run settings are invalid it exits 1 rather than skipping. CI runs file tracker tickets only when --health-ci-tickets is on.

MCP tool: health_run

  • --env <string>: Environment id (defaults to the project's default environment)
  • --path <string>: Page path to check, e.g. /pricing
  • --viewport <phone|tablet_portrait|tablet_landscape|desktop|desktop_wide>: Screen size, repeatable: phone (390x844), tablet_portrait (768x1024), tablet_landscape (1024x768), desktop (1440x900), desktop_wide (1920x1080)
  • --wait: Wait for the check to finish
  • --screenshots: Include the annotated screenshots (as images over MCP, data URIs in --json)
  • --ci: CI run: wait, print a PR-ready summary, exit 1 at or above the fail-on severity
  • --branch <string>: Branch of the CI build (default: read from the CI environment)
  • --deploy: The CI build is a deploy (for --health-ci deploy_only)

Also accepts --workspace and --project (see Configuration).

beryl health run
beryl health run --path /pricing --viewport phone --wait
beryl health run --ci
beryl health run --ci --deploy --env <env-id>
beryl health intended <key>

Mark a visual finding as intended, so it stops counting against the grade

Takes the finding's key from health get. The finding stays in the report, flagged intended, and is left out of the grade on this report and every later run of the environment. --clear removes the mark.

MCP tool: health_intended

  • key: Finding key
  • --env <string>: Environment id (defaults to the project's default environment)
  • --clear: Remove the mark

Also accepts --workspace and --project (see Configuration).

beryl health tracker status

Show how Site Health files findings as issue tracker tickets for an environment

Returns the environment's tracker settings with every default filled in, the workspace's connection (status: disconnected means the token expired or was revoked; ticket changes queue until you reconnect), the number of queued changes, open tickets (filed in the tracker), unfiled_tickets the tracker hasn't accepted yet with its last_sync_error, digest findings, and last_sync: what the latest run filed, updated, closed or skipped. reset_fields names stored settings that were invalid and fell back to defaults (* = all of them); filing, auto-close and the digest stop (last_sync.skipped: settings_invalid) until they are saved again. Change settings with envs update --tracker-*.

MCP tool: health_tracker_status

  • --env <string>: Environment id (defaults to the project's default environment)

Also accepts --workspace and --project (see Configuration).

beryl health tracker tickets

List the findings Site Health tracks in the issue tracker, with their tickets

One row per finding: status watching (seen, waiting for enough runs in a row), digest (not filed), open, closed (with close_reason fixed, intended or tracker) or stale (its page is gone), plus the ticket key and URL once filed and queued when a change is waiting to reach the tracker.

MCP tool: health_tracker_tickets

  • --env <string>: Environment id (defaults to the project's default environment)
  • --status <watching|digest|open|closed|stale>: Only rows in this status

Also accepts --workspace and --project (see Configuration).

beryl health tracker connect

Get the link that connects an issue tracker to the workspace

Returns an authorize URL for a workspace admin to open in a browser. Once approved, Beryl files tickets as its own app user, and any changes queued while disconnected are applied. Then pick a team with envs update --tracker-team.

MCP tool: health_tracker_connect

  • --tracker <linear>: Issue tracker (default linear)

Also accepts --workspace (see Configuration).

beryl health tracker disconnect

Remove the workspace's issue tracker connection

Deletes the stored tokens. Tickets already filed stay in the tracker; to stop filing for one environment only, use envs update --tracker off or --tracker-pause on.

MCP tool: health_tracker_disconnect

  • --tracker <linear>: Issue tracker (default linear)
  • --force: Skip the confirmation prompt

Also accepts --workspace (see Configuration).

beryl health tracker teams

List the teams of the connected issue tracker

MCP tool: health_tracker_teams

  • --tracker <linear>: Issue tracker (default linear)

Also accepts --workspace (see Configuration).

beryl health tracker projects

List a tracker team's projects

MCP tool: health_tracker_projects

  • --tracker <linear>: Issue tracker (default linear)
  • --team <string>: Team id (see health tracker teams) (required)

Also accepts --workspace (see Configuration).

beryl jobs

Test-creation jobs: the cloud agent follows a prompt, reads any document it comes with, and authors tests.

beryl jobs create <prompt>

Create tests from a prompt, with an optional document, on Beryl's cloud

Queues a job from a prompt (what to test; a line is enough) and an optional document (Markdown, plain text, PDF or DOCX: --file, --text, or --content-base64 with --filename): the agent explores the environment, drafts one flow per scenario the prompt asks for, reading the document when there is one, and authors one test per enabled surface of the project. The agent signs in as the environment's default test account, or the one --account names, and the tests it saves sign in as that account too. New tests get no groups. A job runs once and ends done, partial (some tests saved, the rest listed with why) or failed; jobs retry authors what a partial or failed job left out, jobs clone runs the whole document again. With --ci (or a project CI token as BERYL_TOKEN, which always creates CI jobs) the job never pauses for input: a scenario behind a login it cannot pass is skipped with the reason. The prompt and document are sent to the LLM that drives the agent, so leave out anything you would not share with it.

MCP tool: jobs_create

  • prompt: What to test: the instruction the agent follows; a line is enough
  • --file <string>: Path to a document (PRD, release notes) the agent reads with the prompt
  • --text <string>: The document as text, instead of a file
  • --content-base64 <string>: A binary document (PDF, DOCX) base64-encoded, instead of a file; needs --filename
  • --filename <string>: With --content-base64: the document's name; its extension sets the type
  • --env <string>: Environment id to explore (defaults to the project's default)
  • --account <string>: Label of the test account to sign in as (see accounts list); defaults to the environment's default account
  • --ci: Non-interactive job for CI: never waits for a captured session, skips what it blocks

Also accepts --workspace and --project (see Configuration).

beryl jobs create "Cover the checkout flow: add an item, pay by card, see the confirmation" --env <env-id>
beryl jobs create "Draft a test for each scenario in the release notes" --file ./release-notes.md
beryl jobs create "Cover the admin console" --file ./admin-console.md --account admin
BERYL_TOKEN=beryl_ci_... beryl jobs create "Cover the brief" --file ./brief.md --ci --workspace <ws-id> --project <project-id>
beryl jobs list

List the project's test-creation jobs

MCP tool: jobs_list

Also accepts --workspace and --project (see Configuration).

beryl jobs get <job-id>

Show a job's status and the tests it created

MCP tool: jobs_get

  • job-id: Job id

Also accepts --workspace and --project (see Configuration).

beryl jobs clone <job-id>

Run a job again: queue a new job with the same prompt, document, environment and account

The prompt and document are sent to the LLM that drives the agent, so leave out anything you would not share with it.

MCP tool: jobs_clone

  • job-id: Job id to clone

Also accepts --workspace and --project (see Configuration).

beryl jobs retry <job-id>

Author only what a partial or failed job left out, optionally with an edited prompt or document

Queues a new job that authors each scenario the job drafted but has no test on some surface, and each scenario it skipped, on the surfaces that miss them. The new tests join the same flows. --prompt replaces the job's instruction and --file or --text its document; anything not passed is reused from the job. The prompt and document are sent to the LLM that drives the agent, so leave out anything you would not share with it.

MCP tool: jobs_retry

  • job-id: Job id to retry
  • --prompt <string>: An edited instruction for the agent
  • --file <string>: Path to an edited document (Markdown or plain text)
  • --text <string>: The edited document as text, instead of --file

Also accepts --workspace and --project (see Configuration).

beryl jobs retry <job-id>
beryl jobs retry <job-id> --prompt "Refund lives under Orders; test it there"
beryl jobs retry <job-id> --file ./brief-v2.md
beryl jobs delete <job-id>

Delete a job; the flows and tests it created stay

MCP tool: jobs_delete

  • job-id: Job id
  • --force: Skip the confirmation prompt

Also accepts --workspace and --project (see Configuration).

beryl explorations

Inspect the agent's exploration runs: how it crawled a site and authored its tests.

beryl explorations list

List the agent's exploration passes for a project

Also accepts --workspace and --project (see Configuration).

beryl explorations get <exploration-id>

Show one exploration: authored tests, abandoned flows, coverage, frontier

  • exploration-id: Exploration id

Also accepts --workspace and --project (see Configuration).

beryl explorations steps <exploration-id>

List every step the agent took in an exploration

  • exploration-id: Exploration id

Also accepts --workspace and --project (see Configuration).

beryl explorations cancel <exploration-id>

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).

beryl explorations watch <exploration-id>

Stream an exploration live: watch the agent explore and author tests

Replays every recorded step on connect, then follows live until the exploration ends. Exits 0 only if it completed; a failed or cancelled exploration, or a stream that keeps closing without a final status, exits 1.

  • 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.

beryl config vars list

List the project's config variables (visible to the agent during runs)

MCP tool: config_vars_list

Also accepts --workspace and --project (see Configuration).

beryl config vars set <key> <value>

Create or update a config variable

MCP tool: config_vars_set

  • key: Variable name
  • value: Variable value
  • --env <string>: Scope to one environment id

Also accepts --workspace and --project (see Configuration).

beryl config vars get <key>

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).

beryl config vars delete <key>

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).

beryl config secrets list

List the project's secrets (values are never returned); a test account's password is managed on the account, not here

MCP tool: config_secrets_list

Also accepts --workspace and --project (see Configuration).

beryl config secrets set <key> <value>

Create a secret (write-only; re-setting a key replaces it)

MCP tool: config_secrets_set

  • key: Secret name
  • value: Secret value (or - to read from stdin)
  • --env <string>: Scope to one environment id

Also accepts --workspace and --project (see Configuration).

beryl config secrets get <key>

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).

beryl config secrets delete <key>

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).

beryl config files list

List uploaded files: fixtures tests attach and Android and iOS app builds

MCP tool: config_files_list

Also accepts --workspace and --project (see Configuration).

beryl config files get <file>

Show one uploaded file's metadata

MCP tool: config_files_get

  • file: File name or id

Also accepts --workspace and --project (see Configuration).

beryl config files upload <file>

Upload a file: a fixture an upload step attaches, or an Android or iOS app build

The bytes go straight to storage over a short-lived URL, never through the API, up to 1 GB. An .apk uploads as an Android build (or pass --kind android_build): Beryl reads its package name, version and native ABIs, refuses one the emulators cannot run (an .aab, a split APK, a too-new minSdk, ARM-only native code on x86 emulators). An iOS simulator build (the .app folder zipped, or EAS's .tar.gz) uploads with --kind ios_build: Beryl reads its bundle id and version and refuses an .ipa, a device build or one with no arm64 slice. App tests of an environment whose app id for that surface matches install the newest build; the upload warns when no environment has the build's app id. Beryl keeps the newest 5 builds per app per environment. Upload after each build, e.g. in CI.

MCP tool: config_files_upload

  • file: Path to the local file
  • --env <string>: Scope to one environment id
  • --kind <fixture|android_build|ios_build>: fixture: a file tests attach. android_build: an Android APK (the default for .apk). ios_build: a zipped or tarred iOS simulator .app

Also accepts --workspace and --project (see Configuration).

beryl config files upload ./fixtures/avatar.png
beryl config files upload ./android/app/build/outputs/apk/release/app-release.apk
beryl config files upload ./MyApp.zip --kind ios_build
beryl config files download <file-id>

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).

beryl config files delete <file-id>

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.

beryl mailbox get

The project's mailbox address

Returns the address {{mailbox_address}} resolves to, creating it on first ask. Every test that reads mail receives here, at its own +tag alias of this mailbox: a plan cites {{inbox_address}}, minted per execution and read by that test alone, so parallel tests never consume each other's codes. A test never types the bare address (the save refuses it); only an account's own signup and sign-in plans (accounts signup, accounts set-login) may fill it. Every alias minted is listed by mailbox identities, and a plan that signs up with one must delete the account in its after section.

MCP tool: mailbox_get

Also accepts --workspace and --project (see Configuration).

beryl mailbox list

List the project's mailboxes

MCP tool: mailbox_list

Also accepts --workspace and --project (see Configuration).

beryl mailbox identities

The +tag addresses Beryl minted for this project's tests, and how each cleanup ended

Every {{inbox_address}} a run rendered is recorded: which test and run minted it, and what the runner saw of its teardown (clean, skipped, failed, unverified, or none when the plan has no after section). This is the list of identities that may still exist on the site under test. Rows are kept for 30 days.

MCP tool: mailbox_identities

  • --run <string>: Only addresses minted by this run id
  • --test <string>: Only addresses minted by this test id
  • --limit <number>: Newest N rows (default 100, max 500)

Also accepts --workspace and --project (see Configuration).

beryl mailbox identities
beryl mailbox identities --run run_123 --json
beryl mailbox create

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 invitee
beryl mailbox delete <mailbox-id>

Delete 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).

beryl mailbox read <mailbox-id>

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 --json
beryl mailbox emails <mailbox-id>

List 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 third-party-integrations

Test a site's own integrations (Connect Slack) against Beryl's accounts on those providers.

beryl third-party-integrations list

The third party providers this project's tests can connect to

Lists the providers set up on this Beryl deployment. A test may use third_party_authorize / await_third_party / send_third_party only for a provider listed here; anything else is refused at save time.

MCP tool: third_party_integrations_list

Also accepts --workspace and --project (see Configuration).

beryl third-party-integrations target

The channel this project's tests pick when the app asks where to post

Returns the project's own destination on Beryl's provider account (for Slack, a channel), creating it on first ask. When a test connects the app, it picks this channel in the app's settings; await_third_party then waits for the app's message there. recorded_app_ids maps each environment id to the app whose first message was seen there; an environment accepts only its own app once recorded. Pass env and app to record that app yourself (a Slack app id, A...), which send_third_party needs to know whose bot to mention. A 409 means the provider is not set up on this deployment (see third-party-integrations list).

MCP tool: third_party_integrations_target

  • --provider <string>: Provider key from third-party-integrations list, e.g. slack (required)
  • --env <string>: Environment id to record app for (with app)
  • --app <string>: The connected app's id on the provider, e.g. a Slack app id (with env)

Also accepts --workspace and --project (see Configuration).

beryl third-party-integrations target --provider slack
beryl third-party-integrations target --provider slack --env <env-id> --app A0123ABCD

beryl accounts

Durable identities on the site under test: what an authenticated test signs in as.

beryl accounts list

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. Below them, grouped as throwaway, the newest accounts test executions created for themselves through {{inbox_address}}: which run and test minted each, and how its teardown ended. They are kept for 30 days.

MCP tool: accounts_list

  • --env <string>: Only accounts on this environment id
  • --throwaway-limit <number>: How many of the newest throwaway accounts to show (default 50, max 500, 0 hides them)

Also accepts --workspace and --project (see Configuration).

beryl accounts get <account-id>

Show one test account: origin, lifetime, sign-in state

One test account by id. type is its origin: captured (a session from the Chrome plugin), provisioned (Beryl signed it up; lifetime permanent or throwaway), or provided (your own account).

MCP tool: accounts_get

  • account-id: Account id from beryl accounts list

Also accepts --workspace and --project (see Configuration).

beryl accounts get acc_123
beryl accounts create

Add a test account: the customer's own, or one Beryl signs up

Two kinds. --type provided records a dedicated account you already have on the site: pass --email and --password, and it is usable immediately. --type provisioned reserves one Beryl will sign up itself, addressed at the project mailbox; --lifetime says whether it is kept (permanent, the default) or a throwaway. It starts pending and becomes usable after beryl accounts signup. A captured account (a signed-in session from the Beryl Chrome extension) is not created here: capture it with the extension (https://chromewebstore.google.com/detail/beryl/nnjhiapfdhhmmjabnafdaomdmhlolfkp), then give it a probe with beryl accounts set-login --probe. Works for Google-only apps too: bank a dedicated Google test account as provided and author its sign-in plan through Google's form. The first account an environment gets is its default whatever you pass.

MCP tool: accounts_create

  • --type <provided|provisioned>: Whose account this is (default: provided when --password is given)
  • --lifetime <permanent|throwaway>: provisioned only: keep it, or a throwaway (default permanent)
  • --label <string>: Identity label a plan's auth_label names (default 'default')
  • --email <string>: provided only: the account's email
  • --password <string>: 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 provisioned --login-method otp
beryl accounts create --email [email protected] --password 'hunter2' --label admin
beryl accounts create --email [email protected] --password 'hunter2'  # Google-only app
beryl accounts capture

Store a signed-in session as a captured test account

Usually done by the Beryl Chrome extension (https://chromewebstore.google.com/detail/beryl/nnjhiapfdhhmmjabnafdaomdmhlolfkp) from a signed-in tab; this takes the same session JSON from a file or inline: {schema_version: 2, final_url, cookies (CDP shape), local_storage, session_storage, indexed_db}. Upserts by --label on the environment, so capturing an existing label replaces its session. Cookies for other domains are dropped and listed. A captured account cannot sign itself in: give it a probe with beryl accounts set-login --probe, then prove it with beryl accounts check. Its session is never served back to a client.

MCP tool: accounts_capture

  • --file <string>: The captured session, as JSON (path, or - for stdin)
  • --session <json>: The captured session inline, instead of --file
  • --label <string>: Identity label a plan's auth_label names (default 'default')
  • --email <string>: The signed-in user's email
  • --env <string>: Environment id (default: the project's)
  • --default: Make this the environment's default

Also accepts --workspace and --project (see Configuration).

beryl accounts capture --file session.json --label admin
beryl accounts signup <account-id>

Store 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)
  • --plan <json>: The signup ActionPlan inline, instead of --file

Also accepts --workspace and --project (see Configuration).

beryl accounts signup acc_123 --file signup-plan.json
beryl accounts set-login <account-id>

Store 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 (or --plan inline) 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. A captured account (from the Beryl Chrome extension) takes --probe alone: it rides the captured session and cannot sign itself in, so there is no --file or --plan. --surface android stores the sign-in Android tests use instead, beside the web one; Beryl proves it on an Android worker the first time a signed-in android test runs. A test-creation job saves one itself when it meets the app's login screen, so this is for fixing or replacing it. 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 except for a captured account
  • --plan <json>: The sign-in ActionPlan inline, instead of --file
  • --probe <json>: The liveness probe plan (JSON, a 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
  • --surface <android|ios>: An app surface: store (or read) the sign-in through the app's own screens. Both plans are plans for that device (device android or ios, starting with a launch); a signed-in app test restores the session this sign-in saved on the device

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…
beryl accounts set-login acc_456 --probe probe.json  # captured account
beryl accounts set-login acc_123 --surface android --file app-signin.json --probe app-probe.json
beryl accounts set-login acc_456 --probe '{"steps":[{"action":"goto","url":"/account"},{"action":"expect","selector":"text=Sign out","expect_kind":"visible"}]}'
beryl accounts get-login <account-id>

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
  • --surface <android|ios>: An app surface: store (or read) the sign-in through the app's own screens. Both plans are plans for that device (device android or ios, starting with a launch); a signed-in app test restores the session this sign-in saved on the device

Also accepts --workspace and --project (see Configuration).

beryl accounts check <account-id>

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_123
beryl accounts update <account-id>

Change 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).

beryl accounts delete <account-id>

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.

beryl account get

Show your account profile

beryl account update

Update your profile

  • --name <string>: New display name
  • --newsletter: Toggle the newsletter subscription
beryl account deletion-preview

Preview what deleting your account would remove or leave

beryl feedback

Send product feedback to the Beryl team.

beryl feedback send <message>

Send product feedback to the Beryl team

  • message: Your feedback

beryl billing

Review a workspace's plan usage, subscription, and invoices; upgrade or switch plans.

beryl billing plans

List the plans: price, cloud run minutes, storage, overage terms

beryl billing usage

Show plan usage: cloud run minutes, storage held, and this month's overage

Also accepts --workspace (see Configuration).

beryl billing checkout

Get a Stripe Checkout link that moves a Free workspace onto Team or Business

  • --plan <string>: team or business (required)

Also accepts --workspace (see Configuration).

beryl billing plan

Switch a paid workspace between Team and Business in place (prorated)

  • --plan <string>: team or business (required)

Also accepts --workspace (see Configuration).

beryl billing subscription

Show the workspace's subscription

Also accepts --workspace (see Configuration).

beryl billing invoices

List recent invoices

  • --limit <number>: How many invoices

Also accepts --workspace (see Configuration).

beryl billing portal

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

beryl 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 --json

beryl mcp

Run the Beryl MCP server (stdio): every CLI command as an agent tool

beryl mcp

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