Skip to main content

The sbrs binary provides quick commands for common tasks: opening pages, running smoke tests, executing CDP commands, patching binaries, generating files, and more. This page covers the most common workflows.

Info

What you will learn

  • How to build and invoke the CLI.
  • How to run smoke tests and assertions from the command line.
  • How to execute CDP commands and JSON scenarios.
  • How to patch binaries and diagnose the environment.
  • How to show the installed Chrome and its driver in your shell prompt.
  • How to turn on the built-in browser plugins.

Build the CLI#

The binary is built by the workspace package seleniumbase-rs-cli (crates/cli); the library seleniumbase-rs at the repository root carries no command-line code. To install it: cargo install --path crates/cli.

A justfile and Makefile provide common shortcuts such as just lint, just test-all, just docs, and just completions.

Help and version#

Every top-level option and subcommand argument includes a description, so --help shows what each flag does. --version prints the crate name and version.

Open a page#

Run a smoke test with UC mode#

Execute a raw CDP command#

Share a browser with DevTools MCP servers#

Launches Chrome with its DevTools endpoint open, prints the endpoint and configs for Google’s chrome-devtools-mcp and Microsoft’s Playwright MCP, and runs until Ctrl+C, which closes the browser. See DevTools MCP servers.

Run built-in plugins#

--plugin NAME and --plugin-opt NAME.KEY=VALUE (a TOML value, so quote a string) go before the command, repeat, and add to the [plugins] table of the settings file and SB_PLUGINS; the command line wins over the variable, which wins over the file. They apply to every command that starts a browser and to sbrs devtools. A mistake stops the command with exit status 2 before a browser starts. See Choosing plugins.

Save artifacts#

Assertions and waits#

Patch chromedriver#

Patch Chrome binary#

Diagnostic check#

doctor prints the active SB_* environment variables, the detected Chrome binary, and the patched-binary cache path. For chromedriver it looks, in order, at the file named by CHROMEDRIVER_PATH, at downloaded_drivers/ (where sbrs install puts it), and on PATH; a CHROMEDRIVER_PATH that names no file is reported rather than skipped. It also prints the driver’s major version next to Chrome’s, because a chromedriver only drives the Chrome of its own major version:

doctor output

Install a driver#

sbrs get is another name for sbrs install, as in Python SeleniumBase. The driver is chromedriver (the default), geckodriver (or firefoxdriver) or edgedriver (or msedgedriver); the version is latest, a major version or a full build, and for geckodriver a release such as 0.36.0. The driver goes to ./downloaded_drivers/ and its path is printed.

Without a version, chromedriver is the one that matches the installed Chrome, from Chrome for Testing (the latest stable one when Chrome is not found or no driver is listed for its version), msedgedriver the one for the installed Edge’s major version from msedgedriver.microsoft.com, and geckodriver the newest GitHub release. It needs network access and fetches only the driver: the Pure CDP engine needs none. Starting a WebDriver session finds or fetches the driver by itself, so run install ahead of time only to prepare an offline machine or a container. Python’s --path (copy the driver to a folder on the PATH) is not supported.

Show the browser in your shell prompt#

sbrs prompt prints one short line for a shell prompt: the major version of the installed Chrome (or Chromium) and whether a chromedriver of that version is already at hand. The chromedriver is looked for as doctor does: the file CHROMEDRIVER_PATH names, downloaded_drivers/ in the current folder, then the PATH. ✓driver means it matches, ✗driver that it is missing or of another major version (sbrs install fetches the right one), and ?driver that its version could not be read. --ascii writes +, - and ? instead, for terminals and fonts without check marks.

When no browser is found it prints nothing and exits with 0, so the prompt simply leaves the segment out; --verbose says on standard error what it looked at. The browser is the one --browser-path names, else SB_CHROME_BIN, else the installed Chrome or Chromium (CHROME_BIN, CHROMIUM_BIN, the usual install folders, the PATH). A path that is given but holds no file counts as no browser; it is never replaced by another one.

A prompt runs it before every command line, so it starts no browser and uses no network:

  • The browser’s version is read from files: the app’s Info.plist on macOS, the version folder beside chrome.exe on Windows.
  • A version that only running the program tells (chromedriver --version, and Chrome on Linux) is cached for ten minutes in seleniumbase-rs/prompt-versions.json in the user cache folder (~/Library/Caches on macOS, $XDG_CACHE_HOME or ~/.cache on Linux, %LOCALAPPDATA% on Windows), together with the program’s size and modification time, so a new download or a browser update shows at once. --no-cache asks the programs every time. A program that has not answered within two seconds is given up on: a chromedriver shows as ?driver, a browser leaves the line out.

Measured with hyperfine on an Apple M1 (a debug build), a warm sbrs prompt takes about 9 ms, as long as sbrs version takes to start; with --no-cache, which runs chromedriver --version, about 23 ms. Asking Chrome itself with --version would take about 45 ms.

PlaceholderBecomes
{browser}chrome or chromium
{major}The browser’s major version, such as 155
{driver}The mark and the word driver: ✓driver, ✗driver or ?driver
{mark}The mark alone
{driver_major}The chromedriver’s major version; empty when it is missing or unknown

The default is --format '{browser} {major} {driver}'. {{ and }} print a brace. An unknown placeholder is refused with exit status 2, so a typo shows when you set the prompt up, not as a segment that never appears.

~/.bashrc

The single quotes keep $(...) for later: Bash runs it each time it draws the prompt (the promptvars option, on by default).

Run your tests#

sbrs test runs cargo test (or one example) and carries the global options into the tests as SB_* environment variables, the way Python SeleniumBase’s pytest options reach its tests:

Only options you actually pass are exported (SB_HEADLESS, SB_BROWSER, SB_MODE, SB_PROXY, …), so the config file and your own SB_* variables still apply to everything else. A test sees them when it loads its settings with Settings::load(). -n becomes --test-threads, and the exit status is Cargo’s.

Proxies from a list#

--proxy-list FILE reads a list of proxies, one per line, optionally named (the Rust counterpart of Python’s PROXY_LIST):

Each line is checked when the file is read, and an error names the line number (never the password). The same type, ProxyList, hands proxies out in turn or at random to Rust code; see seleniumbase_rs::config::proxy_list.

Encrypt and decrypt secrets#

Keep a password out of a test file by storing it encrypted.

Tip

The passphrase comes from the environment, never from an argument, so it stays out of shell history and process listings.

Info

Tokens use AES-256-GCM with a key derived from the passphrase (PBKDF2-HMAC-SHA256, 600,000 iterations, a fresh random salt each time). A wrong passphrase or a modified token fails to decrypt. They are not interchangeable with Python SeleniumBase’s sbrs encrypt, which is a reversible obfuscation with a fixed key.

Read a results database#

With the turso feature (cargo build --features turso), sbrs report reads the database a ResultStore writes. See Results Database and Encrypted Profiles.

The path can also come from SB_REPORT_DB. A path that does not exist is an error; report never creates a database.

Run a JSON scenario#

Example scenario.json:

Generate files#

The generated Rust uses run_browser_test (see Writing Browser Tests), and a test in tests/ runs with cargo test --test login. A folder sitting directly inside tests/ is one test target; tests/ui/README.md says how to register a folder anywhere else.

The generators are careful with what they write:

  • A name is relative to the current directory and may contain letters, digits, _, - and ., with / between folders. .., absolute paths, backslashes and other characters are rejected before anything is created, and a link that leads out of the directory is not followed.
  • An existing file is never overwritten. mkdir checks every file first and creates none of them if one exists. Pass --force to replace regular files.
  • They need no browser and ignore sbase_config.toml, so they work in an empty folder.

Terminal apps#

Feature: tui

Three commands are full-screen terminal apps. They are part of the opt-in tui feature:

Note

An sbrs built without the tui feature prints a hint and exits with status 2.

caseplans (alias case-plans) and behave-gui (alias gui-behave) are the Python Case Plans Generator and Behave Commander, which open Tkinter windows there. Each takes an optional folder or file; see Case Plans Generator and Behave Commander. sbrs caseplans --starter and sbrs behave-gui --new are the earlier commands that only write a file (a checklist, a new feature); they need no feature.

Import Python tests#

Convert a SeleniumBase or Selenium WebDriver Python file:

Use --source selenium-base or --source selenium to override automatic detection. Use --test-name user_can_log_in to choose the generated function name. Unsupported statements are retained as TODO comments and diagnostics.

Warning

Review generated code before compiling or running it.

Import Playwright and Puppeteer tests#

Convert Playwright tests or scripts (JavaScript, TypeScript or Python) and Puppeteer scripts or tests (JavaScript or TypeScript, or a Chrome DevTools Recorder .json export) into Rust tests for the pure CDP engine:

import-pw and import-pptr are short names for the two commands. The language comes from the file extension (.js, .mjs, .cjs, .ts, .mts, .py, .json), else from the content; --language js|ts|python (Puppeteer: js|ts|json) overrides it. Each test()/it() becomes one #[tokio::test] named after its describe and test titles; a script without titles (codegen output, a plain script) becomes one test named after the file, or after --test-name. Without --output the Rust goes to standard output; one line per statement that became a TODO(playwright) or TODO(puppeteer) comment goes to standard error. As with import-python, the exit status tells what happened:

CaseExit status
A gap, a statement that became a TODO comment: a warning0
A statement the importer could not read: an error1
A file it cannot read6
A source it refuses (over 2 MB, or a Recorder export given to import-playwright)2

Run the generated tests headless with SB_HEADLESS=true cargo test. See Migrate Playwright Tests and Migrate Puppeteer Tests for every mapping.

Install shell completions#

The supported values are bash, elvish, fish, powershell, zsh, fig (a Fig spec) and usage (a usage spec), see below.

The shell scripts are short: each time you press the completion key they ask sbrs itself for the candidates, so sbrs has to be on PATH, and the candidates are exactly the commands, aliases, flags and values the command line accepts. Every command and flag is listed in the CLI reference.

Note

Ensure the destination directory exists. For Zsh, add $HOME/.zfunc to fpath before running compinit.

usage and mise#

sbrs completions usage prints a usage spec (KDL), the same file as completions/sbrs.usage.kdl in the repository. The usage CLI turns it into completions for more shells, Markdown and man pages:

Warp, inshellisense and Amazon Q#

Warp uses your shell’s own completions for commands it has no built-in spec for (the “native shell completions” setting, on by default), so once the Bash, Zsh or Fish completion above is installed, sbrs completes in Warp too.

Warp’s built-in specs, inshellisense and Amazon Q read Fig completion specs (withfig/autocomplete). sbrs completions fig writes one:

The spec is not in withfig/autocomplete yet, so these tools do not know sbrs until it is. How the repository’s copy is made and how to submit it is in Submit the Fig spec.

Warp Workflows: the repository has ready-made sbrs commands in .warp/workflows/ (smoke test, install a driver, doctor, explain the prompt segment, record, import Playwright or Puppeteer tests, create a test folder). Warp shows them in the command palette when you are inside the repository; copy them to ~/.warp/workflows/ to have them everywhere.

Common global flags#

--uc#

Enable UC (undetected) mode.

--cdp#

Enable CDP mode.

--headless#

Run browser headlessly.

--browserNAME#

Select browser (chrome, chromium, edge, firefox). Without it the config file’s browser, else Chrome.

--proxyPROXY#

Route traffic through a proxy (host:port, or a name from --proxy-list).

--proxy-listFILE#

Choose the proxy from a list of proxies.

-nN#

Number of parallel tests for sbrs test.

Troubleshooting#

sbrs: command not found

Likely cause. Binary not on PATH.

Fix. Use ./target/debug/sbrs or install with cargo install --path crates/cli.

Global flag rejected

Likely cause. Flag placed after the subcommand.

Fix. Put global flags before the subcommand: sbrs --headless open URL.

CDP command fails

Likely cause. Not in CDP mode.

Fix. Add --cdp or use a CDP-enabled config.

doctor shows missing Chrome

Likely cause. Chrome not installed or not on PATH.

Fix. Set SB_CHROME_BIN to the full path.

The sbrs prompt segment does not appear

Likely cause. No browser found, or SB_CHROME_BIN names no file.

Fix. Run sbrs prompt --verbose.