Liking cljdoc? Tell your friends :D

spel logo

spel - A command-line tool that lets you control a browser from the terminal.
Open pages · click buttons · fill forms · take screenshots · scrape content · run E2E tests · generate reports — all from simple shell commands.
Page SnapshotsInline ScriptingVisual AnnotationsVideo Recording
spel snapshot demospel eval demospel annotate demospel report demo

What is spel?

spel is a command-line tool that controls a real browser. You type commands in your terminal, and spel opens pages, clicks buttons, fills forms, takes screenshots, reads page content, and more. Think of it as a remote control for Chrome/Firefox/WebKit that works from the shell.

Concrete example — scrape a page and get its content as Markdown:

spel open https://news.ycombinator.com
spel markdownify                          # page content as clean Markdown
spel screenshot front-page.png            # take a screenshot
spel close

Why not just use Puppeteer / Playwright directly?

  • No Node.js, no node_modules, no 100 MB binary downloads. spel is a single self-contained binary (~71 MB). It uses Playwright Java under the hood, but you don't need to set up a Node project, manage npm dependencies, or deal with binary downloads on every npm install.
  • Persistent browser session. spel runs a background daemon — your browser stays open between commands. This makes it fast for interactive use.
  • Works as a CLI, not just a library. You don't need to write a script to automate a browser. Just type spel open, spel click, spel fill in your terminal.

Why not just use Claude Code's --chrome / browser MCP tools?

You can! If Claude Code's built-in browser works for you, keep using it. spel offers more when you need:

  • Persistent sessions across multiple commands (the browser stays open)
  • Accessibility snapshots — a structured, numbered view of the page that's better than raw HTML
  • E2E test generation — record a browser session and turn it into a test
  • Allure reports — detailed test reports with traces, screenshots, and network inspection
  • CI integration — run the same tests headlessly in CI with proper reporting
  • Three browser engines — Chromium, Firefox, and WebKit

Who is this for?

You want to...spel gives you...
Automate a browser from the terminalspel open, spel click, spel fill, spel screenshot
Scrape page contentspel markdownify, spel snapshot, spel get text
Write E2E testsClojure test framework with Allure reports, or record-and-generate
Control a browser from scripts or the terminalCLI commands + accessibility snapshots for reliable interaction
Run browser tests in CIHeadless mode + Allure reporting + video recording

Rationale

spel wraps Playwright Java with idiomatic Clojure: maps for options, anomaly maps for errors, with-* macros for lifecycle, and a native CLI binary for instant browser automation.

  • Single binary, no ecosystem baggage: One download, no node_modules, no npm, no transitive dependency surprises. Install the binary, install browsers, done.
  • Persistent daemon: First command auto-starts a background browser. Subsequent commands reuse it. No cold-start on every invocation — fast enough for interactive loops.
  • Accessibility snapshots: Pages are represented as structured, numbered documents (not raw HTML). You can reference elements by number — no brittle CSS selectors.
  • Record, then generate: Capture any browser session to JSONL and auto-generate idiomatic Clojure tests or reusable scripts.
  • Allure reports with network inspection: Full Allure reporting with Playwright traces, network visualization (method, status, headers, body), and visual diffs.
  • API testing built in: Intercept, assert, and inspect HTTP traffic in the same tool as your browser tests.
  • Three browser engines: Chromium, Firefox, and WebKit — full Playwright API coverage.
  • Inline Clojure scripting: Run arbitrary Clojure expressions mid-session via eval-sci — not just shell commands, but real code.

Quick Start

Install

Clojure library:

;; deps.edn
{:deps {com.blockether/spel {:mvn/version "0.9.5"}}}

Native CLI (download from GitHub releases):

# macOS (Apple Silicon)
curl -LO https://github.com/Blockether/spel/releases/latest/download/spel-macos-arm64
chmod +x spel-macos-arm64 && mv spel-macos-arm64 ~/.local/bin/spel

# Linux (amd64)
curl -LO https://github.com/Blockether/spel/releases/latest/download/spel-linux-amd64
chmod +x spel-linux-amd64 && mv spel-linux-amd64 ~/.local/bin/spel

# Linux (arm64)
curl -LO https://github.com/Blockether/spel/releases/latest/download/spel-linux-arm64
chmod +x spel-linux-arm64 && mv spel-linux-arm64 ~/.local/bin/spel

# Windows (PowerShell)
Invoke-WebRequest -Uri https://github.com/Blockether/spel/releases/latest/download/spel-windows-amd64.exe -OutFile spel.exe
Move-Item spel.exe "$env:LOCALAPPDATA\Microsoft\WindowsApps\spel.exe"

Add ~/.local/bin to your PATH:

export PATH="$HOME/.local/bin:$PATH"  # add to ~/.bashrc or ~/.zshrc

macOS Gatekeeper (binaries are not Apple-signed):

xattr -d com.apple.quarantine ~/.local/bin/spel

Post-install:

spel install   # install browsers
spel version   # verify installation

Guided Installation

  1. Download the correct binary for your platform from GitHub Releases.
  2. Make it executable and place it in your PATH.
  3. Run spel install to install browsers.
  4. Run spel version to verify.
  5. Test with spel open https://example.com and then spel close.
Corporate Proxy / Custom CA Certificates

If you're behind a corporate SSL-inspecting proxy (Zscaler, Netskope, etc.), spel install may fail with "PKIX path building failed". Set these env vars before running spel install:

Env VarFormatOn missing fileDescription
SPEL_CA_BUNDLEPEM fileErrorExtra CA certs (merged with defaults)
NODE_EXTRA_CA_CERTSPEM fileWarning, skipsShared with Node.js subprocess
SPEL_TRUSTSTOREJKS/PKCS12ErrorTruststore (merged with defaults)
SPEL_TRUSTSTORE_TYPEStringDefault: JKS
SPEL_TRUSTSTORE_PASSWORDStringDefault: empty
export SPEL_CA_BUNDLE=/path/to/corporate-ca.pem
export NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem
spel install --with-deps

All options merge with built-in defaults — public CDN certs continue to work.

Environment Variables

All env vars are optional. CLI flags always take priority over env vars.

Browser

Env VarCLI equivalentDescription
SPEL_BROWSER--browserBrowser engine: chromium (default), firefox, webkit
SPEL_CHANNEL--channelChromium channel: chrome, msedge, chrome-beta, etc.
SPEL_PROFILE--profileChrome/Edge user data directory (full profile: extensions, passwords, bookmarks)
SPEL_LOAD_STATE--load-statePlaywright storage state JSON path (alias: SPEL_STORAGE_STATE)
SPEL_EXECUTABLE_PATH--executable-pathCustom browser binary path
SPEL_USER_AGENT--user-agentCustom user agent string
SPEL_STEALTH--no-stealthSet to false to disable stealth mode (ON by default)

Session

Env VarCLI equivalentDescription
SPEL_SESSION--sessionSession name (default: default)
SPEL_JSON--jsonSet to true for JSON output
SPEL_TIMEOUT--timeoutCommand timeout in milliseconds

Network

Env VarCLI equivalentDescription
SPEL_PROXY--proxyProxy server URL
SPEL_PROXY_BYPASS--proxy-bypassProxy bypass patterns
SPEL_HEADERS--headersDefault HTTP headers (JSON string)
SPEL_IGNORE_HTTPS_ERRORS--ignore-https-errorsSet to true to ignore HTTPS errors

SSL/TLS

Env VarCLI equivalentDescription
SPEL_CA_BUNDLEPEM file with extra CA certs (merged with defaults)
NODE_EXTRA_CA_CERTSPEM file, also respected by Node.js subprocess
SPEL_TRUSTSTOREJKS/PKCS12 truststore path
SPEL_TRUSTSTORE_TYPETruststore type (default: JKS)
SPEL_TRUSTSTORE_PASSWORDTruststore password

Testing

Env VarCLI equivalentDescription
SPEL_INTERACTIVESet to true for headed mode in test fixtures
SPEL_SLOW_MOSlow motion delay in ms for test fixtures
SPEL_ALLURE_CWDWorking directory for Allure CLI process (set to /tmp on read-only filesystems like AWS Lambda)

Daemon Lifecycle

Env VarCLI equivalentDescription
SPEL_SESSION_IDLE_TIMEOUTAuto-shutdown daemon after this many ms of inactivity (default: 1800000 = 30 min, 0 disables)
SPEL_CDP_IDLE_TIMEOUTAuto-shutdown after CDP disconnect if no reconnect (ms, default: 1800000, 0 disables)
SPEL_CDP_LOCK_WAITMax seconds to wait for CDP route lock release (default: 120, 0 = fail immediately)
SPEL_CDP_LOCK_POLL_INTERVALPoll interval in seconds when waiting for CDP route lock (default: 2)

Advanced

Env VarCLI equivalentDescription
SPEL_AUTO_CONNECT--auto-connectSet to any value to auto-discover Chrome CDP
SPEL_AUTO_LAUNCH--auto-launchSet to any value to auto-launch browser with debug port (per-session isolation)
SPEL_CDP--cdpConnect via Chrome DevTools Protocol URL
SPEL_ARGS--argsExtra Chromium launch args (comma-separated)
SPEL_DRIVER_DIROverride Playwright browser driver directory
SPEL_DEBUG--debugSet to true for debug logging

CLI Examples

The CLI is the primary way to use spel. The first command auto-starts a background browser daemon; subsequent commands reuse the same browser session.

Navigate and interact:

spel open https://example.org             # open a page
spel click "text=More information"        # click a link by text
spel fill "#search" "browser automation"  # fill an input field
spel press Enter                          # press a key
spel screenshot result.png                # take a screenshot
spel close                                # close the session

Read page content:

spel get title                            # page title
spel get text                             # all visible text
spel get html                             # full HTML
spel markdownify                          # page as clean Markdown
spel snapshot -i                          # accessibility snapshot with numbered refs

Multiple sessions in parallel:

spel --session shop open https://shop.example.com
spel --session docs open https://docs.example.com
spel --session shop screenshot shop.png
spel --session docs screenshot docs.png

Use your real Chrome profile (with extensions, saved passwords, etc.):

export SPEL_CHANNEL=chrome
export SPEL_PROFILE="$HOME/.config/google-chrome/Default"
spel open https://github.com    # opens with your logged-in session

Run spel --help for the full command list (~150 commands covering navigation, interaction, content extraction, network interception, cookies, tabs, frames, debugging, and more).

Clojure Library

spel is also a Clojure library for writing browser automation and tests programmatically:

(require '[com.blockether.spel.core :as core]
         '[com.blockether.spel.page :as page])

(core/with-testing-page [pg]
  (page/navigate pg "https://example.org")
  (page/title pg))
;; => "Example Domain"

Device emulation:

(core/with-testing-page {:device :iphone-14 :locale "fr-FR"} [pg]
  (page/navigate pg "https://example.org"))

Combined browser + API testing (shared Playwright trace):

(core/with-testing-page [pg]
  (page/navigate pg "https://example.org/login")
  (core/api-get (core/page-api pg) "/api/me"))

API Testing & Playwright-Style Tests

Write browser and API tests side-by-side: spel lets you write browser tests (open pages, click buttons, verify DOM) and API tests (call endpoints, check responses) using the same framework. You get full Playwright traces for both.

API testing on its own:

(core/with-testing-api {:base-url "https://api.example.org"} [ctx]
  (core/api-get ctx "/users"))

Combine browser + API for a single trace: You can link UI and API actions within the same test, ensuring one trace covers front-end and back-end steps:

(core/with-testing-page [pg]
  (page/navigate pg "https://example.org/login")
  (core/api-get (core/page-api pg) "/api/me"))

(core/with-testing-page [pg]
  (page/navigate pg "https://example.org/login")
  (core/with-page-api pg {:base-url "https://api.example.org"} [ctx]
    (core/api-get ctx "/me")))

Retry/polling logic built in: To handle flaky endpoints or wait for backend jobs:

(core/with-retry {}
  (core/api-get ctx "/flaky-endpoint"))

(core/with-retry {:max-attempts 10 :delay-ms 1000 :backoff :fixed
                  :retry-when (core/retry-guard #(= "ready" (:status %)))}
  (core/api-get ctx "/job/123"))

Important: Do not nest with-testing-page inside with-testing-api (or vice versa). Each creates its own Playwright instance, browser, and context, so you end up with separate traces. Use page-api or with-page-api when you want UI and API steps in one trace.

Allure reporting: Browser and API tests can feed the same Allure report with traces, screenshots, steps, and network inspection, so one run tells the whole story.

See the full API reference, browser options, Allure reporting, and API testing.

Video Recording

Record browser sessions as WebM files for debugging and CI artifacts.

(def ctx (core/new-context browser {:record-video-dir "videos"}))

See PDF, stitch, and video options.

Test Generation (Codegen)

Record browser sessions and transform them to idiomatic Clojure code.

spel codegen record -o recording.jsonl https://example.org
spel codegen recording.jsonl > my_test.clj

See codegen CLI reference for full actions and output formats.

Building from Source

# Install browsers (via Playwright Java CLI)
clojure -M -e "(com.microsoft.playwright.CLI/main (into-array String [\"install\" \"--with-deps\"]))"

# Build JAR
clojure -T:build jar

# Build native image (requires GraalVM)
clojure -T:build native-image

# Run tests
make test
make test-allure

# Start REPL
make repl

Changelog

See CHANGELOG.md.

License

Apache License 2.0 — see LICENSE.

Can you improve this documentation? These fine people already did:
blockether-deployer, Karol Wojcik & Michał Kruk
Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close