The skill file
Browser automation for AI agents. Use when the user needs to navigate websites, read page content, fill forms, click elements, take screenshots, or manage browser pages.
This is the exact skill bl add-skill installs to ~/.claude/skills/browserlane/SKILL.md — the file a coding agent reads on demand. Generated verbatim from bl v0.1.2 (the YAML frontmatter and top heading are omitted here; the page title and description carry them).
The bl CLI automates Chrome via the command line. The browser auto-launches on first use (daemon mode keeps it running between commands).
bl go <url> && bl map && bl click @e1 && bl mapCore Workflow
Every browser automation follows this pattern:
- Navigate:
bl go <url> - Map:
bl map(get element refs like@e1,@e2) - Interact: Use refs to click, fill, select — e.g.
bl click @e1 - Re-map: After navigation or DOM changes, get fresh refs with
bl map
Binary Resolution
Before running any commands, resolve the bl binary path once:
- Try
bldirectly — works if it's on yourPATH(the normal install). - Fall back to
./target/release/bl— a local release build in the project root.
Run bl --help (or the resolved path) to confirm it works, then use that path for every subsequent command.
Windows note: the binary is bl.exe. Use forward slashes in paths and quote any path that contains spaces.
Command Chaining
Chain commands with && to run them sequentially. The chain stops on first error:
bl go https://example.com && bl map && bl click @e3 && bl diff mapWhen to chain: Use && for sequences that should happen back-to-back (navigate → interact → verify). Run commands separately when you need to inspect output between steps.
When NOT to chain: Don't chain commands that depend on parsing the previous output (e.g. reading map output to decide what to click). Run those separately so you can analyze the result first.
Commands
Discovery
bl map— map interactive elements with @refs (recommended before interacting)bl map --selector "nav"— scope map to elements within a CSS subtreebl diff map— compare current vs last map (see what changed)
Navigation
bl go <url>— go to a pagebl back— go back in historybl forward— go forward in historybl reload— reload the current pagebl url— print current URLbl title— print page title
Reading Content
bl text— get all page textbl text "<selector>"— get text of a specific elementbl html— get page HTML (use--outerfor outerHTML)bl find "<selector>"— find element, return@e1ref (clickable withbl click @e1)bl find "<selector>" --all— find all matching elements →@e1,@e2, ... (--limit N)bl find text "Sign In"— find element by text content →@e1bl find label "Email"— find input by label →@e1bl find placeholder "Search"— find by placeholder →@e1bl find testid "submit-btn"— find by data-testid →@e1bl find xpath "//div[@class]"— find by XPath →@e1bl find alt "Logo"— find by alt attribute →@e1bl find title "Settings"— find by title attribute →@e1bl find role <role>— find element by ARIA role →@e1(--namefor accessible name filter)bl eval "<js>"— run JavaScript and print result (--stdinto read from stdin)bl count "<selector>"— count matching elementsbl screenshot -o file.png— capture screenshot (--full-page,--annotate)bl a11y-tree— accessibility tree (--everythingfor all nodes)
Interaction
bl click "<selector>"— click an element (also accepts@reffrom map)bl dblclick "<selector>"— double-click an elementbl type "<selector>" "<text>"— type into an input (appends to existing value)bl fill "<selector>" "<text>"— clear field and type new text (replaces value)bl press <key> [selector]— press a key on element or focused elementbl focus "<selector>"— focus an elementbl hover "<selector>"— hover over an elementbl scroll [direction]— scroll page (--amount N,--selector)bl scroll into-view "<selector>"— scroll element into view (centered)bl keys "<combo>"— press keys (Enter, Control+a, Shift+Tab)bl select "<selector>" "<value>"— pick a dropdown optionbl check "<selector>"— check a checkbox/radio (idempotent)bl uncheck "<selector>"— uncheck a checkbox (idempotent)
Mouse Primitives
bl mouse click [x] [y]— click at coordinates or current position (--button 0|1|2)bl mouse move <x> <y>— move mouse to coordinatesbl mouse down— press mouse button (--button 0|1|2)bl mouse up— release mouse button (--button 0|1|2)bl drag "<source>" "<target>"— drag from one element to another
Element State
bl value "<selector>"— get input/textarea/select valuebl attr "<selector>" "<attribute>"— get HTML attribute valuebl is visible "<selector>"— check if element is visible (true/false)bl is enabled "<selector>"— check if element is enabled (true/false)bl is checked "<selector>"— check if checkbox/radio is checked (true/false)bl is actionable "<selector>"— check if element is actionable (true/false)
Waiting
bl wait "<selector>"— wait for element (--state visible|hidden|attached,--timeout ms)bl wait url "<pattern>"— wait until URL contains substring (--timeout ms)bl wait load— wait until page is fully loaded (--timeout ms)bl wait text "<text>"— wait until text appears on page (--timeout ms)bl wait fn "<expression>"— wait until JS expression returns truthy (--timeout ms)bl sleep <ms>— pause execution (max 30000ms)
Capture
bl screenshot -o file.png— capture screenshot (--full-page,--annotate)bl pdf -o file.pdf— save page as PDF
Dialogs
bl dialog accept [text]— accept dialog (optionally with prompt text)bl dialog dismiss— dismiss dialog
Emulation
bl viewport— get current viewport dimensionsbl viewport <width> <height>— set viewport size (--dprfor device pixel ratio)bl window— get OS browser window dimensions and statebl window <width> <height> [x] [y]— set window size and position (--state)bl media— override CSS media features (--color-scheme,--reduced-motion,--forced-colors,--contrast,--media)bl geolocation <lat> <lng>— override geolocation (--accuracy)bl content "<html>"— replace page HTML (--stdinto read from stdin)
Frames
bl frames— list all iframes on the pagebl frame "<nameOrUrl>"— find a frame by name or URL substring
File Upload
bl upload "<selector>" <files...>— set files on input[type=file]
Recording
bl record start— start recording (--screenshots,--snapshots,--name)bl record stop— stop recording and save ZIP (-o path)
Cookies
bl cookies— list all cookiesbl cookies <name> <value>— set a cookiebl cookies clear— clear all cookies
Storage State
bl storage— export cookies + localStorage + sessionStorage (-o state.json)bl storage restore <path>— restore state from JSON file
Downloads
bl download dir <path>— set download directory
Pages
bl pages— list open pagesbl page new [url]— open new pagebl page switch <index|url>— switch pagebl page close [index]— close page
Debug
bl highlight "<selector>"— highlight element visually (3 seconds)
Session
bl start— start a local browser sessionbl start <url>— start connected to a remote browserbl stop— stop the browser sessionbl daemon start— start background browserbl daemon status— check if runningbl daemon stop— stop daemon
Common Patterns
Ref-based workflow (recommended for AI)
bl go https://example.com
bl map
bl click @e1
bl map # re-map after interactionVerify action worked
bl map
bl click @e3
bl diff map # see what changedRead a page
bl go https://example.com && bl textFill a form (end-to-end)
bl go https://example.com/login
bl map
# Look at map output to identify form fields
bl fill @e1 "user@example.com"
bl fill @e2 "secret"
bl click @e3
bl wait url "/dashboard"
bl screenshot -o after-login.pngScoped map (large pages)
bl map --selector "nav" # Only map elements in <nav>
bl map --selector "#sidebar" # Only map elements in #sidebar
bl map --selector "form" # Only map form controlsSemantic find (no CSS selectors needed)
bl find text "Sign In" # → @e1 [button] "Sign In"
bl find label "Email" # → @e1 [input] placeholder="Email"
bl click @e1 # Click the found element
bl find placeholder "Search..." # → @e1 [input] placeholder="Search..."
bl find testid "submit-btn" # → @e1 [button] "Submit"
bl find alt "Company logo" # → @e1 [img] alt="Company logo"
bl find title "Close" # → @e1 [button] title="Close"
bl find xpath "//a[@href='/about']" # → @e1 [a] "About"Authentication with state persistence
# Log in once and save state
bl go https://app.example.com/login
bl fill "input[name=email]" "user@example.com"
bl fill "input[name=password]" "secret"
bl click "button[type=submit]"
bl wait url "/dashboard"
bl storage -o auth.json
# Restore in a later session (skips login)
bl storage restore auth.json
bl go https://app.example.com/dashboardExtract structured data
bl go https://example.com
bl eval "JSON.stringify([...document.querySelectorAll('a')].map(a => ({text: a.textContent.trim(), href: a.href})))"Check page structure without rendering
bl go https://example.com && bl a11y-treeRemote browser
bl start ws://remote-host:9515/session
bl go https://example.com
bl map
bl stopMulti-page workflow
bl page new https://docs.example.com
bl text "h1"
bl page switch 0Annotated screenshot
bl screenshot -o annotated.png --annotateInspect an element
bl attr "a" "href"
bl value "input[name=email]"
bl is visible ".modal"Save as PDF
bl go https://example.com && bl pdf -o page.pdfEval / JavaScript
bl eval is the escape hatch for any DOM query or mutation the CLI doesn't cover directly.
Simple expressions — use single quotes:
bl eval 'document.title'
bl eval 'document.querySelectorAll("li").length'Complex scripts — use --stdin with a heredoc:
bl eval --stdin <<'EOF'
const rows = [...document.querySelectorAll('table tbody tr')];
JSON.stringify(rows.map(r => {
const cells = r.querySelectorAll('td');
return { name: cells[0].textContent.trim(), price: cells[1].textContent.trim() };
}));
EOFJSON output — use --json to get machine-readable output:
bl eval --json 'JSON.stringify({url: location.href, title: document.title})'Important: eval returns the expression result. If your script doesn't return a value, you'll get null. Always make sure the last expression evaluates to the data you want.
Timeouts and Waiting
All interaction commands (click, fill, type, etc.) auto-wait for the target element to be actionable. You usually don't need explicit waits.
Use explicit waits when:
- Waiting for navigation:
bl wait url "/dashboard"— after clicking a link that navigates - Waiting for content:
bl wait text "Success"— after form submission, wait for confirmation - Waiting for element:
bl wait ".modal"— wait for a modal to appear - Waiting for page load:
bl wait load— after navigation to a slow page - Waiting for JS condition:
bl wait fn "window.appReady === true"— wait for app initialization - Fixed delay (last resort):
bl sleep 2000— only when no better signal exists (max 30s)
All wait commands accept --timeout <ms> (default varies by command).
Ref Lifecycle
Refs (@e1, @e2) are invalidated when the page changes. Always re-map after:
- Clicking links or buttons that navigate
- Form submissions
- Dynamic content loading (dropdowns, modals)
Global Flags
| Flag | Description |
|---|---|
--headless | Hide browser window |
--json | Output as JSON |
-v, --verbose | Debug logging |
Tips
- All click/type/hover/fill actions auto-wait for the element to be actionable
- All selector arguments also accept
@reffrombl map - Use
bl mapbefore interacting to discover interactive elements - Use
bl map --selectorto reduce noise on large pages - Use
bl fillto replace a field's value,bl typeto append to it - Use
bl find text/find label/find testidfor semantic element lookup (more reliable than CSS selectors) - Use
bl find rolefor ARIA-role-based lookup - Use
bl a11y-treeto understand page structure without visual rendering - Use
bl text "<selector>"to read specific sections - Use
bl diff mapafter interactions to see what changed bl evalis the escape hatch for complex DOM queriesbl check/bl uncheckare idempotent — safe to call without checking state first- Screenshots save to the current directory by default (
-oto change) - Use
bl storage/bl storage restoreto persist auth across sessions