Claude
Skills
Sign in
Back

qe-browser

Included with Lifetime
$97 forever

Browser automation for QE agents using Vibium (WebDriver BiDi) with assertions, batch execution, visual diff, prompt-injection scanning, and semantic intents. Use when any QE skill needs to drive a real browser — visual testing, accessibility audits, E2E flow verification, pentest validation, or exploratory testing.

AI Agentsscripts

What this skill does


# QE Browser

Thin AQE-owned wrapper around [Vibium](https://github.com/VibiumDev/vibium) that adds QE-specific primitives: typed assertions, batch execution, visual-diff against baselines, prompt-injection scanning, and semantic intent scoring.

**Engine:** Vibium — single ~10MB Go binary, built on WebDriver BiDi (W3C standard), Apache-2.0 licensed, published on npm/PyPI/Maven Central. Auto-launches a background daemon and auto-downloads Chrome for Testing on first use.

**Why Vibium, not Playwright?**
- 10MB binary vs ~300MB Playwright install
- WebDriver BiDi standard (not CDP) — future-proof for Firefox/Safari
- `--json` mode on every command (matches AQE structured-output rule)
- Built-in MCP server: `npx -y vibium mcp`
- First-class semantic locators: `find text|label|placeholder|testid|role|xpath|alt|title`

## Platform support (verified 2026-04-09 against Vibium v26.3.18)

| Platform | `npm install -g vibium` | `vibium go <url>` | smoke-test.sh |
|---|---|---|---|
| macOS arm64 (Apple Silicon native) | ✅ | ✅ | ✅ |
| macOS x64 (Intel) | ✅ | ✅ | ✅ |
| Linux x86_64 | ✅ | ✅ | ✅ |
| Windows x64 | ✅ | ✅ | not yet tested |
| **Linux ARM64 (aarch64)** | ✅ binary itself | ⚠️ **Workaround required** | ✅ after workaround |

### Linux ARM64 workaround

Google Chrome for Testing does not publish a `linux-arm64` build. Vibium falls back to `chrome-linux64` (x86_64) on aarch64 hosts, which fails under Rosetta with `failed to open elf at /lib64/ld-linux-x86-64.so.2`. To run qe-browser on a Linux ARM64 codespace or container:

```bash
# 1. Install Vibium normally — the vibium binary itself IS native ARM64
npm install -g vibium

# 2. Install Debian's native ARM64 chromium + chromedriver
sudo apt-get update
sudo apt-get install -y chromium chromium-driver

# 3. Symlink Vibium's broken cached binaries to the native system ones.
#    Run after `vibium install` (auto-runs on first `vibium go`).
for dir in ~/.cache/vibium/chrome-for-testing/*/; do
  # Newer Vibium layout (v26.3.x): chromedriver and chrome at the root
  if [ -e "$dir/chromedriver" ]; then
    rm -f "$dir/chromedriver" "$dir/chrome"
    ln -s /usr/bin/chromedriver "$dir/chromedriver"
    ln -s /usr/bin/chromium     "$dir/chrome"
  fi
  # Older Vibium layout: chromedriver-linux64/ and chrome-linux64/ subdirs
  if [ -e "$dir/chromedriver-linux64/chromedriver" ]; then
    rm -f "$dir/chromedriver-linux64/chromedriver" "$dir/chrome-linux64/chrome"
    ln -s /usr/bin/chromedriver "$dir/chromedriver-linux64/chromedriver"
    ln -s /usr/bin/chromium     "$dir/chrome-linux64/chrome"
  fi
done

# 4. Verify
vibium --headless go https://httpbin.org/html
vibium --headless title  # → "Herman Melville - Moby-Dick"
```

This workaround is verified working on Debian bookworm aarch64 with chromium 146.0.7680.177-1~deb12u1. Track upstream — when Vibium adds a `--browser-path` flag or Google ships `linux-arm64` Chrome for Testing, this section becomes obsolete.

## Headless mode

Helper scripts (`assert.js`, `batch.js`, `visual-diff.js`, `check-injection.js`, `intent-score.js`) automatically inject `--headless` into every `vibium` invocation because the qe-browser skill is designed for QE/CI use cases where there's no display server. **Vibium itself defaults to "visible by default"** — running `vibium go` on a headless container without `--headless` fails with `Missing X server or $DISPLAY`.

Opt out for interactive debugging:
```bash
QE_BROWSER_HEADED=1 node .claude/skills/qe-browser/scripts/assert.js --checks '...'
```

When you call `vibium` directly (not through a helper), pass `--headless` yourself if you're in a container:
```bash
vibium --headless go https://example.com
vibium --headless title
```

## Activation

- When a QE skill needs to navigate, read, interact with, or capture a web page
- When running visual regression tests against stored baselines
- When asserting page state (URL, text visibility, console errors, network failures)
- When validating exploitability of security findings (pentest)
- When scanning untrusted pages for prompt injection
- When running batch automation with explicit pass/fail gates

## Core Workflow

Every browser-driven QE task follows the same shape:

1. **Navigate** — `vibium go <url>`
2. **Map** — `vibium map` to get element refs (`@e1`, `@e2`, …)
3. **Interact** — `vibium click @e1`, `vibium fill @e2 "text"`
4. **Verify** — use this skill's `assert.js` to run typed checks, OR use `vibium diff map` to see what changed
5. **Re-map** if DOM changed

```bash
# Typical login flow verification
vibium go https://app.example.com/login
vibium map --json > /tmp/refs.json
vibium fill @e1 "$USERNAME"
vibium fill @e2 "$PASSWORD"
vibium click @e3
vibium wait url "/dashboard"
node .claude/skills/qe-browser/scripts/assert.js --checks '[
  {"kind": "url_contains", "text": "/dashboard"},
  {"kind": "no_console_errors"},
  {"kind": "no_failed_requests"}
]'
```

## Ref Lifecycle — use `diff map`

Vibium refs are invalidated when the DOM changes. Instead of versioning refs manually, Vibium gives you `vibium diff map` which shows exactly what's new, removed, or repositioned since the last `map` call. After any interaction that changes the DOM:

```bash
vibium click @e3
vibium diff map --json   # shows added/removed/moved refs
```

This is cleaner than tracking version numbers — you get a structured delta you can feed directly into the next action.

## QE Primitives (this skill's value-add)

All scripts live in `.claude/skills/qe-browser/scripts/` and shell out to `vibium`. They expect `vibium` to be on PATH (installed by `aqe init`).

### `assert.js` — Typed assertions with 16 check kinds

```bash
node scripts/assert.js --checks '[
  {"kind": "url_contains", "text": "/dashboard"},
  {"kind": "text_visible", "text": "Welcome"},
  {"kind": "selector_visible", "selector": "#user-menu"},
  {"kind": "value_equals", "selector": "input[name=email]", "value": "[email protected]"},
  {"kind": "no_console_errors"},
  {"kind": "no_failed_requests"},
  {"kind": "response_status", "url": "/api/user", "status": 200},
  {"kind": "element_count", "selector": ".result", "op": ">=", "count": 5}
]'
```

All 16 kinds: `url_contains`, `url_equals`, `text_visible`, `text_hidden`, `selector_visible`, `selector_hidden`, `value_equals`, `attribute_equals`, `no_console_errors`, `no_failed_requests`, `response_status`, `request_url_seen`, `console_message_matches`, `element_count`, `title_matches`, `page_source_contains`.

Full reference: [references/assertion-kinds.md](references/assertion-kinds.md).

Exit code is non-zero if any check fails. Output is JSON: `{ "passed": N, "failed": M, "results": [...] }`.

### `batch.js` — Multi-step execution with stop-on-failure

```bash
node scripts/batch.js --steps '[
  {"action": "go", "url": "https://example.com/login"},
  {"action": "fill", "ref": "@e1", "text": "[email protected]"},
  {"action": "fill", "ref": "@e2", "text": "secret"},
  {"action": "click", "ref": "@e3"},
  {"action": "wait_url", "pattern": "/dashboard"},
  {"action": "assert", "checks": [{"kind": "no_console_errors"}]}
]' --summary-only
```

Reduces round-trips vs calling `vibium` per step. Supports `--stop-on-failure` (default true) and `--summary-only`.

### `visual-diff.js` — Pixel diff against stored baselines

```bash
# First run — creates baseline
node scripts/visual-diff.js --name "homepage"

# Subsequent runs — compare
node scripts/visual-diff.js --name "homepage" --threshold 0.05

# Scope to an element
node scripts/visual-diff.js --name "hero" --selector "#hero"

# Reset baseline after intentional change
node scripts/visual-diff.js --name "homepage" --update-baseline
```

Baselines stored in `.aqe/visual-baselines/` (project-local, gitignored by default). Uses `pixelmatch` for pixel comparison; returns similarity % and diff image path.

### `check-injection.js` — Prompt injection scanner

Scans the current page content for known prompt-injection patterns (ignore previous instructions, system prompts in hidde

Related in AI Agents