Skip to main content

This page takes you from a fresh machine to a checkout that builds and passes the checks. To install sbrs without a checkout, or for every system package a feature needs, see Building and installing.

Info

What you will learn

  • What to install first on macOS, Linux and Windows.
  • How the workspace is laid out.
  • How to build the library, the command line and their features.
  • How to keep builds small on a machine with little memory.
  • How to run the checks, including the tests that need a real Chrome.
  • How to write the generated files again, and how to build the Docker image.

At a glance

  • Rust 1.99, from rust-toolchain.toml
  • Library at the root, no default features
  • sbrs and sbrs-mcp in crates/cli
  • Checks: fmt, clippy, test, deny, mdbook
  • Real-Chrome tests: *_chrome.rs, one at a time

What you need#

  • Rust 1.99. The workspace sets rust-version = "1.99" in Cargo.toml, and rust-toolchain.toml pins the 1.99 channel with clippy and rustfmt, so rustup uses that toolchain inside the checkout.
  • A C compiler and linker. Some dependencies, such as ring, compile C code.
  • Git, to clone the repository.
  • Google Chrome or Chromium, only to run sbrs and the tests that drive a real browser. Building needs no browser.

Nothing here needs Python. Only the parity scripts in tools/ do (Python 3.10 or newer).

Terminal

Extra packages for some features#

Most features need nothing more. These do:

FeatureDebian and UbuntumacOS and Windows
s3libssl-dev pkg-confignothing
guilibgtk-3-dev libx11-dev libxdo-dev libxkbcommon-dev libxtst-dev libssl-dev pkg-confignothing to build; on macOS allow the program under Accessibility at run time
The Tauri examplelibwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libgtk-3-dev libssl-dev libx11-dev libxdo-dev, and Node LTSNode LTS (Windows also uses WebView2, which comes with Windows 10 and 11)

Tools for the checks#

ToolUsed forInstall
mdbookmdbook buildcargo install mdbook
cargo-deny, cargo-auditthe dependency checkscargo install cargo-deny cargo-audit
cargo-nextestfaster test runs and the one-thread chrome test groupcargo install cargo-nextest
justthe recipes in the justfilecargo install just
Tip

With mise, mise install sets up Rust 1.99, Python, Node, mdBook, just and cargo-deny from mise.toml, and mise run gate runs the checks a change must pass.

Get the code#

MustCodeAl/seleniumbase-rs

Port of seleniumbase from python to rust

10

Clone

Terminal

Check the toolchain

Terminal

Inside the checkout it should print version 1.99, which rust-toolchain.toml selects. If rustup says that toolchain is not installed, run rustup toolchain install 1.99.

Build and check the setup

doctor prints the SB_* settings, the browser it found, and the chromedriver it found with its major version next to Chrome’s.

Workspace layout#

The repository is a Cargo workspace of two packages. default-members names both, so a plain cargo build or cargo test at the root covers both.

seleniumbase-rsthe workspace root
Cargo.tomlthe workspace and the library package: version, rust-version 1.99, features
Cargo.lockthe locked dependency versions
rust-toolchain.tomlpins Rust 1.99 with clippy and rustfmt
srcthe library seleniumbase-rs: both engines, the MCP tools and the library half of the command line; no binary
lib.rsthe crate root and its public re-exports
apiBaseCase and the capability traits
browserBrowserConfig, the launcher and the WebDriver session
sb_cdpthe pure CDP engine
stealthfingerprints, evasions and binary patching
mcpthe tools of the MCP server
clithe library half of sbrs, with no parser
crates
clithe package seleniumbase-rs-cli
Cargo.tomldefault features: pdf, mcp-server, plugins-builtin
src
sbrs.rsthe sbrs command line
mcp_server.rsthe sbrs-mcp server
fig.rsthe Fig completion spec
report.rssbrs report
strict.rsrefuses, with status 2, what the parser is too loose about
testsevery test that runs the real sbrs or sbrs-mcp binary
testsintegration tests of the library
goldencompiled into the library
supportshared with crates/cli/tests
sb_cdp_mock.rsthe pure CDP API against a mocked browser
sb_cdp_chrome.rsthe same against a real Chrome, ignored by default
browser_smoke.rsthe WebDriver path against a real Chrome, ignored by default
benchessee Benchmarking
cdp_latency.rsthe pure CDP engine against a real Chrome
cpu.rsthe library's own work, no browser
examplesrunnable examples
tauri-profile-managerhas its own manifest and is not part of the workspace
docsthis site
parityapi.toml, the status of every Python SeleniumBase API
completionssbrs.usage.kdl, generated from crates/cli/src/sbrs.rs
toolsthe parity scripts and the Docs7 navigation script
dockerthe image that runs the test suite on Linux
.configthe nextest configuration and its chrome test group
Dockerfilethe sbrs image; its skeleton step lists every target
Makefilemake targets
justfilejust recipes
mise.tomltools and tasks for mise
deny.tomlthe cargo-deny policy
rust-analyzer.tomlsettings for rust-analyzer
CLAUDE.mdthe module map for coding assistants

The module map of src/ is in CLAUDE.md and in the Developer guide.

Build#

Features#

PackageOn by defaultNotes
seleniumbase-rs (the library)nothingEvery feature is opt-in: gui, tui, turso, playwright, plugins, ocr, visual, pdf, mcp-server, s3, azure, gcp, test-util, full-tracing, tokio-console and more.
seleniumbase-rs-cli (sbrs, sbrs-mcp)pdf, mcp-server, plugins-builtinForwards tui, gui and turso to the library, and also plugins, the plugin-* features, test-util, full-tracing and tokio-console.
Note

A build of both packages unifies their features, so the command line’s pdf and mcp-server reach the library too. Use -p seleniumbase-rs to build and test the library with its own defaults, as a project that depends on it would. The library job in .github/workflows/ci.yml does exactly that.

Terminal

sbrs-mcp needs the mcp-server feature, so a build without default features has sbrs only. Every feature and what it costs is in Building and installing.

Install the binaries#

Terminal

Keep builds small#

A cold build compiles a large dependency tree. Three environment variables keep it within a small machine’s memory:

Terminal
CARGO_BUILD_JOBSnumber#

How many compiler processes run at once. 2 keeps memory low.

Default: "every core"

CARGO_INCREMENTAL0 or 1#

0 turns off the incremental cache in target/. sccache needs it off to cache anything.

CARGO_PROFILE_DEV_DEBUGnumber#

0 leaves debug information out of development builds: smaller files and faster links.

Use the same values for every cargo command, so builds share their compiled artifacts instead of compiling them again.

Warning

Run one heavy cargo command at a time: cargo serialises builds in one target directory anyway. Do not share one CARGO_TARGET_DIR between several checkouts or worktrees of this repository: they overwrite each other’s compiled library, and doctests then fail with “extern location does not exist”. A development target/ with the test, bench and check artifacts grows past 10 GB.

Run the checks#

Every change must pass these, the same ones CI runs.

Format

Terminal

Lint

Terminal

src/mcp and src/sb_cdp are held to the stricter pedantic lint set. An #[allow(...)] needs a reason = "...".

Test

Terminal

Count failures from the exit code and the test result: lines, never from a filtered search of the output.

Check the dependencies

Terminal

Run them when Cargo.lock changed. cargo deny check reads deny.toml, where every ignored advisory has a written reason.

Build the book

Terminal

Run it when the docs changed. It writes the book to book/.

Tip

With cargo-nextest, cargo nextest run --features "mcp-server test-util" replaces the test step, but it does not run doctests: add cargo test --doc --features "mcp-server test-util". Code that only builds with the results database is checked by cargo check --features turso --all-targets.

Tests that need a real Chrome#

Needs Chrome

Tests that start a real browser live in files named *_chrome.rs, plus browser_smoke.rs; edge_msedgedriver.rs and firefox_geckodriver.rs drive Edge and Firefox. They are #[ignore]d, so the default run skips them. Run them one test binary at a time: a Chrome that is starved of CPU and memory misses its 20 second DevTools deadline.

  • .config/nextest.toml puts these binaries in a chrome test group with one thread, and reports a test as slow after 60 seconds (it is ended after three such periods). --run-ignored only runs the Edge and Firefox tests too.
  • mise run chrome runs tests/*_chrome.rs, tests/browser_smoke.rs and crates/cli/tests/*_chrome.rs one binary at a time, and skips playwright_chrome.
  • The WebDriver tests need a chromedriver that matches Chrome: sbrs install downloads it into downloaded_drivers/. The pure CDP tests need none.
  • As root or in a container, Chrome needs --no-sandbox: the tests pass it when CI is set. To run them in Docker with Chromium and Xvfb, see Run the tests in a container.

Write the generated files again#

Some files are generated. Edit their source, then write them again:

FileMade fromCommand
completions/sbrs.usage.kdl and docs/help/cli_reference.mdthe declarations in crates/cli/src/sbrs.rsSB_UPDATE_COMPLETIONS=1 cargo test -p seleniumbase-rs-cli --bin sbrs usage_spec
docs/parity.mdparity/api.tomljust parity-docs
the navigation in docs/docs.jsondocs/SUMMARY.mdpython3 -I tools/docs7_nav.py
docs/completions/fig-sbrs.tssbrs completions fig, through prettiersee docs/completions/README.md

The usage_spec test fails when the first two are stale, and just parity-docs fails when docs/parity.md was out of date. No test checks the Fig spec.

Make, just and mise#

The repository has the same everyday tasks in three runners. Use whichever you have.

Taskjustmakemise
Format checkjust fmtmake fmtmise run fmt
Testsjust testmake testmise run test
The library alonejust test-librarymake test-library-
Lintjust lintmake lintmise run lint
Every check in a row-make allmise run gate
Real-Chrome tests--mise run chrome
The bookjust docsmake docsmise run docs
sbrs --help, --version and doctorjust smokemake smokemise run smoke
Shell completions into target/completionsjust completionsmake completions-
Warning

just lint, just test-all, just build and their make twins turn on s3,azure,gcp,playwright,mcp-server,full-tracing,gui,tui (the justfile adds pdf), so they need the gui and s3 system packages. They are not the CI checks above; mise run gate is closer to those.

The Docker image#

The Dockerfile builds sbrs with Rust 1.99, without the command line’s default features, and copies it into a debian:bookworm-slim image with Chromium and its driver. It runs as the non-root user sbrs. More is under Container and Deployment.

Warning

The Dockerfile caches dependencies with a skeleton step that creates an empty file for every target the manifests declare. A new [[bin]], [[bench]], [[example]] or [[test]], in either manifest, must be added to that step, or the image build fails. tests/dockerfile_skeleton.rs checks it.

Working with an AI assistant#

The repository is set up for coding assistants: CLAUDE.md is the module map, the commands and the things that have bitten before, AGENTS.md is a short rule sheet, llms.txt indexes the docs, and rust-analyzer.toml makes analysis cover the mcp-server and test-util features. Two optional tools make an assistant read far less:

Neither is needed to build, test or contribute. tokensave init writes its index to .tokensave/, which the repository’s .gitignore does not list: if git status shows it, add it to .git/info/exclude. Whoever opens the pull request owns the result; see Working with AI assistants.

Paste into an AI coding assistant that can run commands in this checkout

Check this seleniumbase-rs checkout. Read CLAUDE.md first. Export CARGO_BUILD_JOBS=2 CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 and run one cargo command at a time: cargo fmt —all — —check, then cargo clippy —all-targets —features “mcp-server test-util” — -D warnings, then cargo test —features “mcp-server test-util”. Do not edit any code. Report the exit code of each command, and the passed and failed counts from the “test result” lines, not from a filtered search of the output.

Build problems#

The linker or C compiler is missing

The build stops with linker 'cc' not found or a missing link.exe. Install the build tools for your system: xcode-select --install on macOS, build-essential (or gcc gcc-c++ make) on Linux, and the Visual Studio 2022 Build Tools with the C++ workload on Windows. Open a new terminal afterwards.

Rust is too old, or 1.99 is missing

Cargo refuses a package that needs a newer rustc, or rustup says the 1.99 toolchain is not installed. Run rustup toolchain install 1.99 and check rustc --version inside the checkout. Every package of the workspace needs 1.99.

The build runs out of memory

The linker is killed, or the machine stops responding. Set the three variables from Keep builds small, lower CARGO_BUILD_JOBS further, and stop other builds. In a 4 GB container the doctests also need -- --test-threads=2.

Blocking waiting for file lock

Another cargo command is building in the same target directory. Wait for it, or stop it. rust-analyzer checks into a target directory of its own (targetDir = true in rust-analyzer.toml), so it does not hold this lock.

extern location does not exist

Two checkouts share one CARGO_TARGET_DIR and overwrote each other’s compiled library. Give each checkout its own target directory, and do not cargo clean a target directory that another build is using.

The gui or s3 feature fails on Linux

A missing system library: gui links GTK and X11, and s3 needs OpenSSL. Install the packages from Extra packages for some features.

The first build fails without a network

A first build downloads crates from crates.io, and the plugin crates from GitHub. Run cargo fetch while you are online; later builds can then use --offline.

A test says a generated file is stale

Write the file again with the command from Write the generated files again and commit the result with your change.

A manifest test or the Docker build fails

tests/dockerfile_skeleton.rs fails, or the image build stops, after you added a [[bin]], [[bench]], [[example]] or [[test]]: list it in the skeleton step of the Dockerfile. tests/library_manifest.rs fails when a command-line crate is in the library’s [dependencies]: it belongs in crates/cli/Cargo.toml.

More system-specific notes are in Operating systems.

Next steps#