npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

openqa

v0.0.10

Published

Agent Harness for Browser Test Automation — write tests in natural language, powered by Claude Code or OpenCode

Readme

OpenQA

AI Powered Natural Language Browser Test Automation

No selectors. No flake. Just plain English.

npm version License: MIT

Features

  • 🗣️ Write Tests in Plain English — Describe what you want, not how to find it. "Add laptop to cart" just works.
  • 📝 BDD & YAML Support — Works with Playwright-BDD, Cucumber.js, or simple YAML files.
  • ⚡ 2-Minute Setupnpx openqa init scaffolds a fully configured .openqa/ in your existing project.
  • 🔒 No API Keys Required Locally — Uses your existing claude login session (Claude Code) or opencode auth login (OpenCode). API keys only needed for CI.

Powered by: Claude Code SDKOpenCode SDKPlaywright MCPPlaywright-BDDCucumber.jsVarlock


Quick Start

Run this from your existing project root:

npx openqa init

The interactive wizard will ask you:

  1. Agent — Claude Code (@anthropic-ai/claude-agent-sdk) or OpenCode (@opencode-ai/sdk)
  2. Modelclaude-haiku-4-5 (default), claude-sonnet-4-6, claude-opus-4-7, or custom (OpenCode supports anthropic/..., openai/..., google/...)
  3. Framework — Playwright-BDD or Cucumber.js
  4. Feature files path — Where feature files live, relative to .openqa/ (default: features)

This scaffolds a .openqa/ directory in your project containing:

  • playwright.config.ts or cucumber.js — pre-configured and pointing at your feature files
  • steps/steps.ts (or .js) — a single AI step definition that handles all Gherkin steps
  • steps/fixtures.ts — the Playwright-BDD fixture extension (Playwright-BDD only)
  • features/ — two example feature files to get started (todomvc.feature, getting-started.feature)
  • .env.example — copy this to .env and fill in your values
  • .env.schema — committed schema: documents every variable, types, and defaults; secrets are redacted from logs automatically

Then:

cd .openqa
cp .env.example .env
# Local: run `claude login` or `opencode auth login` — no API key needed
# CI: add the relevant API key to .env
npm run test:headed

How It Works

  1. Your BDD step definitions call runAgent(claudeCode('model'), 'natural language step', page).
  2. OpenQA creates a Playwright MCP server in-process and exposes it over HTTP/SSE on a random localhost port.
  3. The chosen AI provider SDK connects to that MCP URL and receives your natural language instruction.
  4. The agent drives the real browser using Playwright MCP tools (browser_navigate, browser_click, etc.).
  5. The step passes or fails based on what the agent reports back.
  • True browser sharing — the agent drives the exact same page object your test holds.
  • Parallel-safe — each test worker gets its own HTTP port. No shared config files.
  • Session resumption — within a scenario, the agent resumes its conversation across steps.
  • Multi-provider — swap claudeCode for openCode to use any model from OpenAI, Google, Anthropic, etc.

Environment Variables

The .openqa/ directory uses varlock for environment variable management. Variables are defined in .env.schema (committed to git) and values go in .env (gitignored). Secrets are automatically redacted from logs.

| Variable | Default | Description | |----------|---------|-------------| | BASE_URL | — | App URL — sets Playwright baseURL and is injected into every agent prompt | | APP_USERNAME | — | Username — injected into agent prompt for login steps | | APP_PASSWORD | — | Password — injected into agent prompt; always redacted from logs | | OPENQA_VERBOSE | true | Set false to suppress step-by-step agent logs | | HEADLESS | true | Set false to watch the browser | | ANTHROPIC_API_KEY | — | Anthropic API key — only needed for CI (use claude login locally) | | OPENAI_API_KEY | — | OpenAI API key — only needed for CI via OpenCode | | GOOGLE_API_KEY | — | Google API key — only needed for CI via OpenCode |

Adding your own variables — edit .openqa/.env.schema to declare them, then add values to .env:

# .openqa/.env.schema (add to the bottom)

# @sensitive=false
ENVIRONMENT = staging

# Your test account credentials for the staging environment
STAGING_USER =
# @sensitive
STAGING_PASSWORD =

Then use them in your steps or anywhere in the test process via process.env.ENVIRONMENT, etc.


Authentication

No API key needed for local development — just log in with the CLI once:

# Claude Code
claude login

# OpenCode (supports GitLab Duo, GitHub Copilot, Anthropic, OpenAI, Google, …)
opencode auth login

For CI (or if you prefer an API key), set the relevant key in .openqa/.env:

# Claude Code
ANTHROPIC_API_KEY=your_key

# OpenCode — use whichever provider you're connecting to
ANTHROPIC_API_KEY=your_key
# OPENAI_API_KEY=your_key
# GOOGLE_API_KEY=your_key

Customizing Your Setup

openqa init creates a working starting point — everything in .openqa/ is yours to edit. Common customizations:

Playwright config.openqa/playwright.config.ts is a standard Playwright config. Add projects, change timeouts, add reporters, enable retries for CI:

// .openqa/playwright.config.ts
export default defineConfig({
  timeout: 120000,
  retries: process.env.CI ? 2 : 0,
  use: {
    baseURL: process.env.BASE_URL,
    locale: 'en-US',
    timezoneId: 'America/New_York',
  },
});

Step definitions.openqa/steps/steps.ts is a regular Playwright-BDD or Cucumber.js step file. Add custom (non-AI) steps alongside the AI step, or add Before/After hooks:

// .openqa/steps/steps.ts — add a manual step alongside the AI one
import { createBdd } from 'playwright-bdd';
const { Given } = createBdd();

Given('I am on the home page', async ({ page }) => {
  await page.goto(process.env.BASE_URL!);
});

Writing Feature Files

openqa init places two example feature files in .openqa/features/todomvc.feature (2 scenarios) and getting-started.feature (1 scenario). Edit or replace them with your own.

Feature files use standard Gherkin syntax. We recommend using * (asterisk) for steps instead of Given/When/Then — it reads more naturally for AI-driven tests:

Feature: TodoMVC

  Scenario: Add a todo item
    * I navigate to "https://demo.playwright.dev/todomvc/"
    * I add a new todo item "Buy groceries"
    * I should see "Buy groceries" in the todo list

  Scenario: Filter completed todos
    * I navigate to "https://demo.playwright.dev/todomvc/"
    * I add three todo items: "Task 1", "Task 2", and "Task 3"
    * I mark the first todo as completed
    * I click the Active filter
    * I should see 2 active todos

You can still use Given/When/Then — both work identically.

Moving feature files elsewhere — if your feature files live outside .openqa/ (e.g. features/ in the project root), update the path in your config:

For Playwright-BDD, edit .openqa/playwright.config.ts:

const testDir = defineBddConfig({
  featuresRoot: '../features',
  features: '../features/**/*.feature',
  steps: 'steps/*.ts',
});

For Cucumber.js, edit .openqa/cucumber.js:

paths: ['../features/**/*.feature'],

Changing Model or Provider

After running openqa init, your model is set in one line inside .openqa/steps/steps.ts (or steps.js for Cucumber.js). Open that file and edit the provider call:

Change the Claude Code model:

// .openqa/steps/steps.ts
import { runAgent, claudeCode } from 'openqa';

// Before
await runAgent(claudeCode('claude-haiku-4-5'), action, page);

// After — switch to a more capable model
await runAgent(claudeCode('claude-sonnet-4-6'), action, page);

Switch from Claude Code to OpenCode (GitLab Duo, GitHub Copilot, etc.):

// .openqa/steps/steps.ts
import { runAgent, openCode } from 'openqa';  // swap the import

// GitLab Duo
await runAgent(openCode('gitlab/duo-chat-haiku-4-5'), action, page);

// GitHub Copilot
await runAgent(openCode('github-copilot/gpt-5.4'), action, page);

// Anthropic via OpenCode
await runAgent(openCode('anthropic/claude-sonnet-4-6'), action, page);

// OpenAI
await runAgent(openCode('openai/gpt-4o'), action, page);

// Google
await runAgent(openCode('google/gemini-2.0-flash'), action, page);

That's the only change needed — one import swap and one string update.


Using runAgent Directly

For custom Playwright tests (without BDD):

import { test } from "@playwright/test";
import { runAgent, claudeCode } from "openqa";

test("AI agent fills form", async ({ page }) => {
  await page.goto("https://example.com/form");

  await runAgent(claudeCode('claude-haiku-4-5'), "Fill in the form with test data", page, { verbose: true });

  await expect(page.locator('input[name="email"]')).toHaveValue("[email protected]");
});

API Reference

runAgent(provider, prompt, pageOrContext, options?)

Runs the AI agent with a natural language instruction.

| Parameter | Type | Description | |---|---|---| | provider | object | Agent provider, e.g. claudeCode('claude-haiku-4-5') | | prompt | string | Natural language instruction | | pageOrContext | Page \| BrowserContext | Playwright page or browser context | | options.verbose | boolean | Enable logging (default: true) | | options.returnUsage | boolean | Return token usage stats (default: false) |

Returns: Promise<string> — the agent's final response.

claudeCode(model?)

import { claudeCode } from 'openqa';
const provider = claudeCode('claude-haiku-4-5'); // default

| Model | Description | |---|---| | claude-haiku-4-5 | Fast, cost-efficient (default) | | claude-sonnet-4-6 | Balanced performance | | claude-opus-4-7 | Most capable |

Requires @anthropic-ai/claude-agent-sdk to be installed.

openCode(model?)

import { openCode } from 'openqa';
const provider = openCode('gitlab/duo-chat-haiku-4-5'); // GitLab Duo (default in init)
// or: openCode('github-copilot/gpt-5.4')
// or: openCode('anthropic/claude-haiku-4-5'), openCode('openai/gpt-4o'), openCode('google/gemini-2.0-flash')

Model format: provider/model. Supports any provider configured in your OpenCode installation.

| Model | Provider | |-------|----------| | gitlab/duo-chat-haiku-4-5 | GitLab Duo (default) | | github-copilot/gpt-5.4 | GitHub Copilot | | anthropic/claude-haiku-4-5 | Anthropic | | openai/gpt-4o | OpenAI | | google/gemini-2.0-flash | Google |

Requires @opencode-ai/sdk to be installed.

runAgent.resetSession(browserContext)

Resets the Claude Code conversation session for a specific browser context. Useful when you want to start a fresh conversation mid-test.


Examples


Requirements

  • openqa library: Node.js 18+
  • Scaffolded .openqa/ project: Node.js 22+ (required by varlock)
  • @playwright/test ^1.57.0
  • One of: @anthropic-ai/claude-agent-sdk (for claudeCode) or @opencode-ai/sdk (for openCode)

Links

  • Website: https://openqa.io/
  • NPM: https://www.npmjs.com/package/openqa
  • GitHub: https://github.com/openqa-labs/openqa

License

MIT