Liking cljdoc? Tell your friends :D

spel logo

spel - The Swiss Army Knife browser tool for AI agents and Clojure developers.
Browser automation · E2E and API testing · Allure reporting · Accessibility snapshots · Inline Clojure scripting · Record and Generate - one native binary, three browser engines.
Accessibility SnapshotsInline Clojure via --evalVisual AnnotationsAgent Scaffolding
spel snapshot demospel eval demospel annotate demospel agents demo

Rationale

Playwright's Java API is imperative and verbose — option builders, checked exceptions, manual resource cleanup. Clojure deserves better. And AI agents deserve more than a shell wrapper.

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. It does everything a modern agentic workflow needs — in one tool.

  • Swiss Army Knife for agents: Browser automation, API testing, test reporting, agentic search and verification, accessibility snapshots, inline code execution, and test generation — all in a single native binary. No stitching tools together.
  • Agentic by design: Accessibility snapshots with numbered refs let AI agents see the page as a structured document, not raw HTML. Persistent daemon, --eval scripting, and zero brittle CSS selectors — agents reason and act in a loop without restarting.
  • Inline Clojure execution: Run arbitrary Clojure expressions in the browser context via --eval — mix business logic with automation, call any GraalVM-bound function, compose scripts on the fly. No other browser tool lets an agent write and execute real code mid-session.
  • Record, then generate: Capture any browser session to JSONL and auto-generate idiomatic Clojure tests or reusable scripts. Record once, replay forever.
  • Allure reports with network inspection: Full Allure reporting with embedded Playwright traces, network request/response visualization (method, status, headers, JSON body), and visual diffs. Debug failures from the report, not from logs.
  • API testing built in: Intercept, assert, and inspect HTTP traffic in the same tool as your browser tests — no separate client needed.
  • Native CLI binary: GraalVM native image, zero JVM startup, persistent daemon — fast enough for interactive agentic loops and CI alike.
  • Not a port: Wraps Playwright Java directly — full API coverage, all three engines (Chromium, Firefox, WebKit).

Quick Start

Install

Clojure library:

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

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 (for LLM agents)

If you're an LLM agent installing spel for a user, follow these steps. Ask questions where indicated — adapt to the user's answers.

Step 1: Detect platform and install binary

Detect the user's OS and architecture, then download the correct binary:

PlatformBinary name
macOS Apple Siliconspel-macos-arm64
Linux x86_64spel-linux-amd64
Linux ARM64spel-linux-arm64
Windows x86_64spel-windows-amd64.exe

Agent:

  1. Run uname -s + uname -m (Unix) or check $env:PROCESSOR_ARCHITECTURE (Windows)
  2. Download from https://github.com/Blockether/spel/releases/latest/download/<binary>
  3. Place in ~/.local/bin/ (Unix) or %LOCALAPPDATA%\spel\ (Windows)
  4. Make executable: chmod +x (Unix only)
  5. On macOS: remove quarantine with xattr -d com.apple.quarantine
  6. Ensure the install directory is in PATH — detect shell and add to the correct config file

Step 2: Ask — Which browser?

"Which browser do you primarily use? Chrome, Edge, or Brave?"

Based on the answer, set the default channel:

AnswerChannel
Chrome (default)chrome (no flag needed)
Edgemsedge
Bravebrave

Set SPEL_CHANNEL environment variable to the chosen channel (e.g. msedge, brave). Skip for Chrome — it's the default.

Step 3: Ask — Use your real browser profile?

"Do you want spel to use your real browser profile? This gives you all your extensions, saved passwords, bookmarks, and preferences inside spel."

If yes, detect the profile path:

OSChromeEdge
macOS~/Library/Application Support/Google/Chrome/Default~/Library/Application Support/Microsoft Edge/Default
Linux~/.config/google-chrome/Default~/.config/microsoft-edge/Default
Windows%LOCALAPPDATA%\Google\Chrome\User Data\Default%LOCALAPPDATA%\Microsoft\Edge\User Data\Default

Verify the profile exists, then set:

Set SPEL_PROFILE environment variable to the detected path.

If no, skip — spel will use a fresh browser context each time.

Step 4: Ask — Corporate proxy?

"Are you behind a corporate proxy (Zscaler, Netskope, etc.)? If unsure, try spel install first — if it fails with 'PKIX path building failed', you need this."

If yes:

Set both SPEL_CA_BUNDLE and NODE_EXTRA_CA_CERTS environment variables to the path of the corporate CA bundle (PEM format). Ask the user where the cert file is, or help them find it.

See the Corporate Proxy section below for details.

Step 5: Install browsers

Run spel install to download Chromium. If the user chose Edge, also run spel install msedge.

Step 6: Ask — Automation or testing?

"Will you use spel for automation only (scripting, scraping, agents) or also for writing tests (with assertions and Allure reports)?"

Scaffold agent skills (tests are included by default — use --no-tests for automation-only):

# Full scaffolding with test agents (default)
spel init-agents

# Automation only — SKILL reference only, no test scaffolding
spel init-agents --no-tests

Choose the right loop for your coding agent:

spel init-agents --loop=opencode   # OpenCode (default)
spel init-agents --loop=claude     # Claude Code
spel init-agents --loop=vscode     # VS Code / Copilot

Step 7: Verify

Run spel version to confirm installation. Then test with spel open https://example.com — it should open and return JSON. Run spel close after.

If the user chose to use a profile, test with their profile path to verify it works.

Step 8: Persist configuration

Save the user's choices so they don't need to pass flags every time. Detect their shell and OS, then write to the correct config file:

OSShellConfig file
macOS/Linuxzsh~/.zshrc
macOS/Linuxbash~/.bashrc
macOS/Linuxfish~/.config/fish/config.fish (use set -Ux VAR value)
WindowsPowerShell$PROFILE (use [Environment]::SetEnvironmentVariable("VAR", "value", "User"))
Windowscmdsetx VAR value

Agent: detect the shell (echo $SHELL on Unix, $PSVersionTable on Windows) and write the env vars to the correct file using the correct syntax. Do not assume bash.

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.

Env VarCLI equivalentDescription
Browser
SPEL_CHANNEL--channelBrowser channel: chrome, msedge, brave
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
SPEL_SESSION--sessionSession name (default: default)
SPEL_JSON--jsonSet to true for JSON output
SPEL_TIMEOUT--timeoutCommand timeout in milliseconds
Network
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
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
Advanced
SPEL_CDP--cdpConnect via Chrome DevTools Protocol URL
SPEL_ARGS--argsExtra Chromium launch args (comma-separated)
SPEL_DEBUG--debugSet to true for debug logging

Browser Automation

(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"

Pass an opts map for device emulation:

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

For explicit lifecycle control, with-playwright/with-browser/with-context/with-page nesting is available. See the full API reference.

API Testing & Writing Tests

Browser testing:

(core/with-testing-page [pg]
  (page/navigate pg "https://example.org")
  (page/title pg))

API testing:

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

Combined UI + API — use page-api or with-page-api to share a single Playwright trace:

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

;; with-page-api: same context, different base-url
(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")))

Important: Do NOT nest with-testing-page inside with-testing-api (or vice versa). Each creates its own Playwright instance, browser, and context — you get two separate traces instead of one. Use page-api/with-page-api to combine UI and API testing under a single trace.

See SKILL.md for fixtures, steps, and attachments.

See SKILL.md for fixtures, steps, and attachments.

Native CLI

spel compiles to a native binary via GraalVM - no JVM startup, instant execution. The CLI provides commands for browser automation (open, screenshot, snapshot, annotate), a persistent browser daemon, session recording (codegen), PDF generation, and an --eval mode for inline Clojure scripting via SCI. Run spel --help for the full command list.

Agent Scaffolding

Point your AI agent at spel and let it write your E2E tests.

spel init-agents                              # OpenCode (default)
spel init-agents --loop=claude                # Claude Code
spel init-agents --loop=vscode                # VS Code / Copilot
spel init-agents --flavour=clojure-test       # clojure.test instead of Lazytest
spel init-agents --no-tests                   # SKILL only (interactive dev)
FlagDefaultPurpose
--loop TARGETopencodeAgent format: opencode, claude, vscode
--ns NSdir nameBase namespace for generated tests
--flavour FLAVOURlazytestTest framework: lazytest or clojure-test
--no-testsScaffold only the SKILL (API reference) — no test agents
--dry-runPreview files without writing
--forceOverwrite existing files
--test-dir DIRtest-e2eE2E test output directory
--specs-dir DIRtest-e2e/specsTest plans directory

Video Recording

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

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

See recording options and test fixtures.

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 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:
Karol Wojcik, Michał Kruk & blockether-deployer
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