Scripting overview
ferridriver embeds a QuickJS engine (ferridriver-script) and exposes
it to four first-class surfaces. All four share one bundler
(rolldown), one bytecode cache, one set of globals, and one sandbox.
All four reach the same Rust core (Page, BrowserContext, Locator,
HttpClient). The JS layer is a thin binding — the hot path
(actionability checks, polling, network) stays in Rust.
Pipeline (compile once, run many)
- Imports work.
import './helpers.ts',import pkg from 'some-dep'— all bundled and tree-shaken. - No Node, no Bun in the run path. Rolldown runs
Platform::Neutral; QuickJS has no Node builtins. - Bytecode is cached in-memory and on disk. An in-process cache
serves repeat compiles within one process; a cross-process disk cache
(under the user cache dir, or
FERRIDRIVER_CACHE_DIR) lets an unchanged source tree skip both rolldown and the QuickJS compile on a fresh start. Disk entries live under an ABI-tag directory (QuickJS version, arch, endianness, pointer width) soModule::loadonly ever reads bytecode from a matching toolchain; a mismatch misses and recompiles. SetFERRIDRIVER_NO_BYTECODE_CACHEto disable the disk cache. - One bad file does not abort the batch. Bundle / compile failures are reported per file and skipped; the server still starts.
- Errors are source-mapped. A thrown error in a bundled step is
reported at the original
.ts:line:col, stack included.
Picking a surface
- MCP
run_script— agent-driven flows. One tool call runs many browser operations in one LLM turn. See/mcp/toolsand the run_script reference. - BDD JS / TS steps — human-readable
.featurefiles with step bodies your TS team already knows how to write. See/scripting/bdd-js-apiand/bdd/overview. - Extensions — when one
.tsfile should contribute both a reusable MCP tool and matching BDD step. The same file can ship both. See/scripting/extensions. - Standalone scripts — one-off automation runs from the CLI
(
ferridriver run).
Pages in this section
- Extensions —
defineTool,exposeAsTool,ferridriver.host, handler context, lifecycle. - BDD JS / TS API — full Cucumber-shaped
reference:
Given/When/Then/defineStep, hooks, World,DataTable, parameter types. run_scriptreference — the MCP action path: parameters, return shape, globals.- Sandbox —
process,fetch,fs,AbortController,ReadableStream,Blob,FormData, what is absent. - Capabilities —
allow.commands(declared shell / argv commands) andallow.net(HTTP host allow-list). - State and sessions —
globalThisvsvars, session lifetime, isolation, BDD per-scenario World.
Design rationale (why the system is shaped this way — VS Code / Deno /
WASM / Rollup comparison) is in the maintainer note
docs/plugin-architecture.md.