Claude
Skills
Sign in
Back

qa-use

Included with Lifetime
$97 forever

E2E testing and browser automation with qa-use CLI. Use when the user needs to run tests, verify features, automate browser interactions, or debug test failures.

Code Review

What this skill does


# qa-use

E2E testing and browser automation for AI-driven development workflows.

## Critical Insight: Plugin Commands as Shortcuts

**For AI Harnesses (codex, opencode, etc.):**

Plugin commands (slash commands like `/qa-use:verify`) are **convenience shortcuts** that wrap CLI workflows. Harnesses with only the Bash tool can access ALL functionality via CLI commands documented below.

**Pattern throughout this document:**
- **CLI Workflow**: Step-by-step CLI commands (works for ALL harnesses)
- **Plugin Shortcut**: Optional slash command (convenience)

## Setup & Configuration

Before using any qa-use commands, verify configuration is in place:

```bash
# Check current configuration (no-op if already configured)
qa-use setup

# Configure with API key (validates against server)
qa-use setup --api-key <key>

# View full configuration details
qa-use info
```

**Environment Variables (alternative to config file):**

| Variable | Description |
|----------|-------------|
| `QA_USE_API_KEY` | API key for authentication |
| `QA_USE_REGION` | Region: `us` (default) or `auto` |
| `QA_USE_API_URL` | Override API base URL |

**Config file:** `.qa-use.json` in the project directory or `~/.qa-use.json` in the home directory. Precedence: env vars > project `.qa-use.json` > `~/.qa-use.json`.

**If you encounter "API key not configured", 401, or auth errors:** Run `qa-use setup` to check config state. NEVER fabricate or guess API keys.

## Core Workflow

### 1. Browser Control & Session Lifecycle

**CLI Workflow:**
```bash
# Create browser session (returns immediately — runs detached in the background)
qa-use browser create --viewport desktop

# For localhost testing — auto-tunnels when base URL is localhost and API is remote.
# No flag needed for the common case:
qa-use browser create --no-headless http://localhost:3000

# Force a tunnel even in dev mode:
qa-use browser create --tunnel on --no-headless

# Opt out of auto-tunnel (e.g. backend is also local):
qa-use browser create --no-tunnel

# Navigate
qa-use browser goto https://example.com

# Snapshot to get element refs (ALWAYS do this before interacting)
qa-use browser snapshot

# Interact by ref
qa-use browser click e3
qa-use browser fill e5 "text"

# Close
qa-use browser close
```

**Background session management:**

`qa-use browser create` returns immediately — the actual browser + tunnel run in a detached child process so your terminal stays free. Manage sessions with:

```bash
qa-use browser status --list   # Show all active sessions across processes
qa-use browser status           # Details for the auto-resolved session
qa-use browser close <id>       # Close a specific session
qa-use doctor                   # Reap stale sessions/tunnels (dead PIDs)
qa-use doctor --dry-run         # Preview what would be cleaned
```

**Tunnel commands:**

Cross-process tunnel registry — multiple commands share a single tunnel per target:

```bash
qa-use tunnel start <url>         # Acquire a tunnel (released immediately unless --hold)
qa-use tunnel start <url> --hold  # Keep the tunnel up until Ctrl+C
qa-use tunnel ls                  # List active tunnels (target, public URL, refcount)
qa-use tunnel status <target>     # Detail for a single tunnel
qa-use tunnel close <target>      # Force-release a tunnel (kills detached holders)
```

**Plugin Shortcut:**
```
/qa-use:explore https://example.com
```
(Wraps create + goto + snapshot with autonomous exploration)

**Critical:** Always run `snapshot` before your **first** interaction on a page. Never guess element refs.

**Snapshot Diff Feature (use it to avoid unnecessary snapshots):**
After each action (goto, click, fill, etc.), the browser automatically shows DOM changes:
- **Summary**: "5 elements added, 1 element modified"
- **Added elements**: `+ [e54] generic "Thanks for agreeing!"` (green)
- **Modified elements**: `~ [e18] checkbox "I agree..."` with `+attrs: checked, active` (yellow)
- **Removed elements**: `- [e99] button "Submit"` (red)

**When you can skip a full `snapshot`:** If the diff output from your last action already shows the element ref you need to interact with next, use it directly — no need for an intermediate `snapshot`. For example, if clicking a button shows `+ [e54] button "Submit"` in the diff, you can `click e54` immediately.

**When you still need a full `snapshot`:** Run `snapshot` when you need to find elements that weren't in the diff (e.g., pre-existing elements you haven't interacted with yet), or when the diff was truncated (shows "... and N more changes").

### 2. Understanding Blocks

**What are blocks?**

Blocks are atomic recorded interactions from a browser session. They are:
- Automatically captured during any browser interaction (click, fill, goto, scroll, etc.)
- Stored server-side with the session
- Retrieved via `qa-use browser get-blocks`
- The foundation for test generation

**Why blocks matter:**
- **Record-once, replay-many**: Interactive recording becomes automated test
- **AI-friendly**: Agents can analyze blocks to understand user intent
- **Version control**: Blocks stored with session enable test iteration
- **Bridge CLI → Tests**: Natural workflow from exploration to automation

**How blocks work:**

```bash
# 1. Create session and interact (auto-tunnels localhost)
qa-use browser create --no-headless
qa-use browser goto https://example.com
qa-use browser snapshot        # Returns: [ref=e1] button
qa-use browser click e1        # Records as block
qa-use browser fill e5 "text"  # Records as block

# 2. Retrieve blocks (JSON array)
qa-use browser get-blocks
# Returns:
# [
#   {"type": "goto", "url": "...", "timestamp": "..."},
#   {"type": "click", "ref": "e1", "timestamp": "..."},
#   {"type": "fill", "ref": "e5", "value": "text", "timestamp": "..."}
# ]

# 3. Generate test YAML from blocks
qa-use browser generate-test -n "my_test" -o qa-tests/my_test.yaml

# 4. Run generated test
qa-use test run my_test
```

**Plugin Shortcut:**
```
/qa-use:record start my_test
# ... perform interactions ...
/qa-use:record stop
```
(Wraps the interactive workflow with AI-powered test generation)

### 3. Test Management

**CLI Workflow:**
```bash
# Run test by name
qa-use test run login

# Run and save the (non-synced) local test to cloud
qa-use test run login --persist

# Validate syntax
qa-use test validate login

# Show test details
qa-use test info login

# List test runs
qa-use test runs --status failed
```

**Plugin Shortcut:**
```
/qa-use:test-run login
```
(Convenience shortcut for common test execution)

### 4. Test Variables (Imperative Edit)

Quick `set`/`unset` for the typed `variables:` block on a single test —
useful when you don't want to round-trip the full YAML.

**CLI Workflow:**
```bash
# Local YAML file — Document API preserves comments + key order
qa-use test vars list  qa-tests/login.yaml
qa-use test vars list  qa-tests/login.yaml --json
qa-use test vars set   qa-tests/login.yaml --key user --value alice
qa-use test vars set   qa-tests/login.yaml --key url --value https://x \
                                          --type url --lifetime all
qa-use test vars set   qa-tests/login.yaml --key password --value hunter2 --sensitive
qa-use test vars set   qa-tests/login.yaml --key password --sensitive  # preserves stored value
qa-use test vars unset qa-tests/login.yaml --key user

# Remote --id fallback — exports YAML, mutates, re-imports (best-effort RMW)
qa-use test vars list  --id <uuid>
qa-use test vars set   --id <uuid> --key user --value alice
qa-use test vars unset --id <uuid> --key user
```

**Rules:**

- **Mutual exclusion**: pass either `<file>` *or* `--id`, not both. Neither → exit 1.
- **`--id` requires a full UUID** (use `qa-use test list --query <name>` to find one).
- **Form upgrade**: passing only `--key`/`--value` writes simple form (`key: value`).
  Any of `--type`/`--lifetime`/`--context`/`--sensitive` upgrades to full form
  (`{ value, type, lifetime, context, is_sensitive }`).
- **Sensitive-preser
Files: 10
Size: 84.9 KB
Complexity: 57/100
Category: Code Review

Related in Code Review