Code-aware browser testing for AI coding agents
Vibe testing

Code-aware browser testing for AI coding agents. 14 MCP tools, CLI workflows, regression memory, and human-readable QA reports.
# vibe-testing [](https://www.npmjs.com/package/vibe-testing) [](https://www.npmjs.com/package/vibe-testing) [](https://github.com/AishwaryShrivastav/vibe-testing/stargazers) [](https://nodejs.org) [](https://modelcontextprotocol.io) [](https://opensource.org/licenses/MIT) [](https://github.com/AishwaryShrivastav/vibe-testing/actions) **Code-aware browser testing for AI coding agents.** [Product site](https://testing.tfgstudio.com/) · [npm](https://www.npmjs.com/package/vibe-testing) · [MCP Registry](https://registry.modelcontextprotocol.io/?q=io.github.AishwaryShrivastav%2Fvibe-testing) · [Smithery](https://smithery.ai/servers/aish/vibe-testing) · [Privacy](PRIVACY.md) · [Launch status](https://github.com/AishwaryShrivastav/vibe-testing/blob/main/docs/distribution/launch-status.md) Listed in [Awesome MCP Servers](https://github.com/punkpeye/awesome-mcp-servers/pull/14575). The download badge shows npm's cumulative package downloads; `npx` package fetches contribute to that total. vibe-testing reads your codebase so tests use your real routes and field names, runs them in a real Playwright browser, remembers what broke, and tells you what your last change fixed or regressed. It works as an MCP server that gives your editor (Claude Code, Cursor, Windsurf, VS Code Copilot, Roo Code) 14 testing tools, or as a standalone CLI.
Overview
[](https://www.npmjs.com/package/vibe-testing) [](https://www.npmjs.com/package/vibe-testing) [](https://github.com/AishwaryShrivastav/vibe-testing/stargazers) [](https://nodejs.org) [](https://modelcontextprotocol.io) [](https://opensource.org/licenses/MIT) [](https://github.com/AishwaryShrivastav/vibe-testing/actions)
Connects with Agent Alley MCP · agentalley.io/mcp
Files included
README.md34.8 KB
Read README.md here
AishwaryShrivastav/
Show the full text856 lines
vibe-testing
Code-aware browser testing for AI coding agents.
Product site · npm · MCP Registry · Smithery · Privacy · Launch status
Listed in Awesome MCP Servers. The download badge shows npm's cumulative package downloads; npx package fetches contribute to that total.
vibe-testing reads your codebase so tests use your real routes and field names, runs them in a real Playwright browser, remembers what broke, and tells you what your last change fixed or regressed. It works as an MCP server that gives your editor (Claude Code, Cursor, Windsurf, VS Code Copilot, Roo Code) 14 testing tools, or as a standalone CLI.
The repository is also an Agent Plugin with a release-qa skill. Compatible agents get both the testing tools and a senior-QA workflow for coverage, evidence, regression checks, and a clear release verdict.
cd /path/to/your/project
npx vibe-testing@latest init
Then open your editor and say:
"Scan this codebase and test it against http://localhost:3000"
No source code? Point it at a URL from an empty folder and it tests the app black-box:
npx vibe-testing@latest run https://staging.example.com
It finds bugs you didn't write a test for
While it explores, vibe-testing checks for server crashes, console errors, broken values (NaN, [object Object], Invalid Date), totals that don't match their line items, saved values that never appear, a logout that doesn't end the session, and one user opening another user's pages. No scenarios to write.
Measured on intentionally buggy apps (0.5.0, details in #13):
| App | Mode | Before | 0.5.0 |
|---|---|---|---|
| react-simple-project (7 planted functional bugs) | with source code | 1 of 7 | 7 of 7 |
| react-simple-project | URL only | 0 of 7 | 7 of 7 |
| OWASP NodeGoat | with source code | 0 issues | /contributions crash, /allocations 500s, a redirect to /undefined |
| restful-booker-platform (no planted bugs) | both | 3 pages, 4 false errors | 8+ pages, 1 real bug: /api/room/:id returns 500 |
No false findings on these three apps in either mode. Run it against a test environment: exploration creates records and lists every change it made.
Using it on your project? Add the badge:
[](https://github.com/AishwaryShrivastav/vibe-testing)
What code-aware testing adds
Playwright MCP gives your agent hands. vibe-testing gives it a testing workflow: code-derived scenarios, memory across runs, and a report. Two things a stateless browser tool cannot do:
1. Run it twice and it tells you what you broke. Every run writes .vibe/run-snapshot.json and diffs it against the previous run. Every scan writes .vibe/route-manifest.json and diffs your routes. The second run prints regressions and fixes instead of a wall of results:
Changes since last run
Fixed: /login
Regression: /checkout
New: /admin/users
The same diff reaches your editor as snapshot_diff on run_full_test and run_converge, and as route_changes on scan_codebase, so the agent can flag "checkout broke after that commit" without anyone scrolling a report. Flaky routes, working selectors, and measured timeouts are also remembered between runs.
2. Zero LLM calls inside the tool. Pass/fail verification is heuristic: URL changes, toast detection, API errors. Your editor's model decides what to test; vibe-testing does the browsing and checking. No API key, no per-run cost beyond the editor subscription you already pay for.
Contents
- How it works
- MCP setup (per editor)
- MCP tools reference
- Recommended workflow
- init command
- CLI commands
- VIBE.md, project guidance
- Configuration (vibe.config.json)
- Supported frameworks
- Memory and regression detection
- FAQ
How it works
npx vibe-testing@latest init
|
Registers 14 MCP tools in your editor
|
You ask: "Test the checkout flow"
|
AI calls: scan_codebase -> get_context("checkout") -> login -> explore_page -> execute_scenario -> generate_report
|
HTML report opens in browser with screenshots of every step
No test cases to write. The AI reads your source code to understand real field names and routes, opens a browser, tests everything, and shows you what's broken.
init also:
- Detects which AI editors you have installed
- Registers vibe-test in global editor configs (
~/.claude.json,~/.cursor/mcp.json,~/.codex/config.toml, and so on) so the tools are available in every project, every session - Creates project-level MCP configs and AI instruction files
- Auto-detects your app's URL (reads
.env,vite.config, framework defaults) - Creates
VIBE.md(edit with your test credentials) andvibe.config.json - Installs the matching Playwright Chromium build
MCP setup
Agent Plugin
Install this repository as a plugin when your agent supports the Agent Plugins standard. It includes the portable release-qa skill and starts the published npm MCP server with no API key.
Cursor: submit or install
https://github.com/AishwaryShrivastav/vibe-testingas an Agent Plugin.Claude Code:
claude plugin marketplace add AishwaryShrivastav/vibe-testing claude plugin install vibe-testing@vibe-testingOther compatible agents: load the repository root containing
plugin.json,skills/, andmcp.json.
The direct MCP and CLI setup below remains available for editors without plugin support.
MCPB bundle
Claude Desktop and other MCPB hosts can install one local bundle. Build and validate it from this repository:
npm ci
npm run build:mcpb
The artifact is written to artifacts/vibe-testing-<version>.mcpb. See the MCPB distribution guide for the bundle contents, validation steps, Smithery handoff, and the one-time Playwright Chromium prerequisite.
Option 1: automatic (recommended)
npx vibe-testing@latest init
Detects Claude Code, Cursor, Codex, Windsurf, VS Code and Roo Code, registers vibe-test in each, and prints what to do next in each editor. It never overwrites a config file it cannot parse, and running it twice changes nothing.
Option 2: one command per editor
| Editor | Run this | Then |
|---|---|---|
| Claude Code | claude mcp add --scope user vibe-test -- npx -y vibe-testing@latest --mcp |
Start a new claude session. /mcp shows vibe-test as connected. |
| Codex (CLI, IDE extension, desktop app) | codex mcp add vibe-test -- npx -y vibe-testing@latest --mcp |
Start a new codex session. /mcp lists vibe-test. |
| VS Code (Copilot) | code --add-mcp '{"name":"vibe-test","type":"stdio","command":"npx","args":["-y","vibe-testing@latest","--mcp"]}' |
Use Agent mode in Copilot Chat. |
| Cursor | Add the JSON below to ~/.cursor/mcp.json |
Cursor Settings > MCP: check vibe-test is switched on. |
| Windsurf | Add the JSON below to ~/.codeium/windsurf/mcp_config.json |
Press Refresh in the Cascade MCP panel. |
Then say to your agent:
"Scan this codebase and test it against http://localhost:3000"
The first run downloads a Chromium build (one-time, roughly 150 MB). npx vibe-testing@latest install-browser does it ahead of time.
Option 3: edit the config file yourself
Claude Code
For every project, the user-scope config is ~/.claude.json (top-level mcpServers). Claude Code does not read MCP servers from ~/.claude/settings.json. For one project, use .mcp.json in the project root, which you can commit for your team:
{
"mcpServers": {
"vibe-test": {
"type": "stdio",
"command": "npx",
"args": ["-y", "vibe-testing@latest", "--mcp"]
}
}
}
Claude Code asks you to approve a project-scoped server the first time it sees it.
Codex
Add to ~/.codex/config.toml. The Codex CLI, IDE extension and desktop app share this file:
[mcp_servers.vibe-test]
command = "npx"
args = ["-y", "vibe-testing@latest", "--mcp"]
init also writes AGENTS.md, which Codex reads for project instructions.
Cursor
Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (project):
{
"mcpServers": {
"vibe-test": {
"command": "npx",
"args": ["-y", "vibe-testing@latest", "--mcp"]
}
}
}
Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"vibe-test": {
"command": "npx",
"args": ["-y", "vibe-testing@latest", "--mcp"]
}
}
}
VS Code (GitHub Copilot)
Add to .vscode/mcp.json in your project:
{
"servers": {
"vibe-test": {
"type": "stdio",
"command": "npx",
"args": ["-y", "vibe-testing@latest", "--mcp"]
}
}
}
Roo Code / Cline
Add to .roo/mcp.json:
{
"mcpServers": {
"vibe-test": {
"command": "npx",
"args": ["-y", "vibe-testing@latest", "--mcp"]
}
}
}
From local build (development)
{
"mcpServers": {
"vibe-test": {
"command": "node",
"args": ["/path/to/vibe-testing/dist/mcp-server.js"]
}
}
}
MCP tools reference
14 tools available to your AI editor after setup:
| Tool | When to call | Returns |
|---|---|---|
configure |
Start here on a new project. Detects framework, server, and authentication | Structured setup result and idempotent project files |
scan_codebase |
Always first. Reads source code, finds routes/forms/tests/gaps | Routes, forms, coverage map, generated scenarios, route_changes since last scan |
get_context |
Before writing test steps. Returns source files for a feature | Actual source code with real field names and selectors |
login |
When app requires authentication | Post-login screenshot, token state, API calls observed |
scan_page_elements |
To see all interactive elements on a page | Element list with selectors plus page screenshot |
explore_page |
Broad "does everything work?" testing | Interaction results, API calls, problems, diagnostics, warnings, changes_made_to_app, screenshot. isError when problems is non-empty |
execute_scenario |
Run specific test steps | Step-by-step logs plus screenshots |
get_coverage |
View coverage map and untested routes | Coverage entries, gaps, available scenarios |
suggest_tests |
Find coverage gaps after exploration | Prioritized, ready-to-run scenarios with steps |
take_screenshot |
Quick visual verification | Screenshot of any URL |
generate_report |
Build HTML report (auto-opens) | Report path plus summary |
run_full_test |
One-shot: scan, execute, explore, report | Full results, summary.failed_scenarios (name, route, reason) plus snapshot_diff vs last run |
run_converge |
Iterative testing until thresholds | Summary across all rounds (incl. summary.failed_scenarios) plus snapshot_diff vs last run |
cleanup |
Close browsers, free resources | - |
explore_page replaces the old errors field with problems (real app failures: server errors, console errors, broken values, functional failures) and diagnostics (vibe-test's own notes, such as navigation or discovery issues). It also returns warnings (possible missing data such as "Category: Unknown"; not failures) and changes_made_to_app (data-changing requests it sent, per explore.writes), and sets isError when there are problems.
Run results (run_full_test, run_converge, generate_report) carry summary.failed_scenarios, a list of { name, route, status, reason } for every failed or errored scenario, alongside explorer_failures, explorer_warnings, retry_findings and app_changes. The Markdown and HTML reports list the same findings.
Tool inputs
scan_codebase
{
"codebase_path": "/path/to/project",
"url": "http://localhost:3000",
"mode": "deep"
}
get_context
{ "feature": "login" }
{ "feature": "/checkout" }
{ "feature": "user profile form" }
login
{
"email": "[email protected]",
"password": "TestPass123!",
"login_url": "/login"
}
scan_page_elements / explore_page
{
"route": "/dashboard",
"authenticated": true
}
execute_scenario
{
"scenario": {
"id": "create-item",
"name": "Create a new item",
"route": "/items",
"steps": [
{ "action": "navigate", "url": "/items", "description": "Open items page" },
{ "action": "click", "selector": "text=Add Item", "description": "Open create form" },
{ "action": "fill", "selector": "[name='title']", "value": "Test Item", "description": "Fill title" },
{ "action": "fill", "selector": "[name='description']", "value": "Test description", "description": "Fill description" },
{ "action": "click", "selector": "button[type='submit']", "description": "Submit form" }
],
"expected_outcome": "New item appears in the list",
"requires_auth": true
}
}
Step actions: navigate, fill, click, select, wait, assert, upload
CLI and MCP use the same scenario runner. An assert step evaluates every
supplied condition:
selector: the target must be visible. CSS,text=,label=, andplaceholder=are supported; the named locators match exactly.value: visible text must contain this string, on the selected element or on the page body when no selector is supplied.url: the current URL must exactly match this absolute URL or path resolved against the configured base URL, including query and fragment.
For example:
{ "action": "assert", "selector": "#confirmation", "value": "Saved", "url": "/settings", "timeout": 5000, "description": "Check saved settings" }
These checks wait up to the step timeout (default 15000 ms per check). A failed
assertion stops the scenario, records a failed step and reason, and returns
status: "fail"; MCP also sets isError: true. Explicit conditions are used as
the verdict after the existing authentication and form API checks. The
description and expected_outcome prose are not executable assertions.
Without selector, value, or url, assert only checks page health: at least
10 characters of visible body text and no nonempty visible error indicators.
This compatibility check does not prove a described business outcome.
upload requires a file-input selector and a nonempty file path in value.
Relative paths resolve against the codebase root. Hidden file inputs are
supported. A missing file, directory, missing target, or target that is not a
file input returns status: "error". The action selects one file using
Playwright; add an assertion of the resulting UI to verify application-side
processing. It does not automate native file-picker dialogs.
Scenarios must contain at least one step. Unknown actions are errors.
take_screenshot
{ "url": "/settings", "authenticated": true, "full_page": false }
run_full_test
{ "url": "http://localhost:3000", "codebase_path": "/path/to/project", "mode": "deep" }
run_converge
{
"url": "http://localhost:3000",
"max_followup_rounds": 4,
"target_pass_rate": 0.92,
"max_high_severity_gaps": 2
}
Recommended workflow
Full test session
Tell your AI editor:
Scan this codebase and test it against http://localhost:3000.
Log in with [email protected] / pass123. Explore the dashboard and
settings pages, run the suggested tests, and generate a report.
The AI will:
scan_codebase, to understand routes, forms, existing testsget_context("login"), to read the actual login form source codelogin, to authenticate in a real browserexplore_page("/dashboard"), clicking everything and observing what breaksexplore_page("/settings"), samesuggest_tests, to find coverage gapsexecute_scenariox N, running targeted test flowsgenerate_report, HTML report opens automaticallycleanup, closing browsers
Test a specific feature
Test the checkout flow using vibe-test. Get context for checkout,
then run the full purchase flow with card number 4242424242424242.
The AI will:
scan_codebase(if not already done)get_context("checkout"), readingCheckoutForm.tsx,api/orders/route.tsand so onloginexecute_scenario, filling the real form fields from source codegenerate_report
Verify a bug fix
I fixed the login redirect bug. Use vibe-test to confirm it's working.
The AI will:
login, testing the login flowtake_screenshot, visual confirmation of the post-login state- Report back what it sees
Find what's broken
Explore every page and tell me what's broken.
The AI will run explore_page on every route, collecting API errors, broken elements, and failed interactions, then suggest_tests with the broken items marked as high priority.
init command
npx vibe-testing@latest init [options]
What it creates:
| File | Where | Purpose |
|---|---|---|
.mcp.json |
Project root | Claude Code MCP config (project-level) |
~/.claude.json |
Global | Claude Code MCP config, user scope (all projects) |
~/.codex/config.toml |
Global | Codex MCP config (CLI, IDE extension, desktop app) |
.cursor/mcp.json |
Project root | Cursor MCP config |
~/.cursor/mcp.json |
Global | Cursor MCP config (all projects) |
.cursor/rules/vibe-test.mdc |
Project | Cursor rules, alwaysApply: true |
.windsurfrules |
Project | Windsurf instructions |
~/.codeium/windsurf/mcp_config.json |
Global | Windsurf MCP config (all projects) |
.vscode/mcp.json |
Project | VS Code Copilot MCP config |
.github/copilot-instructions.md |
Project | GitHub Copilot instructions |
.roo/mcp.json |
Project | Roo Code MCP config |
CLAUDE.md |
Project | Claude Code session instructions |
AGENTS.md |
Project | Universal agent instructions (Codex, Devin, Zed) |
VIBE.md |
Project | Test guidance, edit with your credentials |
vibe.config.json |
Project | Config, URL auto-detected from your project |
Options:
npx vibe-testing@latest init # auto-detect editors, register globally + project
npx vibe-testing@latest init --no-global # project-level only, skip global registration
npx vibe-testing@latest init --skip-browser-install
npx vibe-testing@latest init --editor cursor # only configure Cursor
npx vibe-testing@latest init --editor claude-code windsurf
npx vibe-testing@latest init --editor codex # register Codex even if ~/.codex is not there yet
After init, edit VIBE.md with your login URL and test credentials.
CLI commands
# Set up in current project
npx vibe-testing@latest init
# Install or repair the matching browser build
npx vibe-testing@latest install-browser
# Run tests against a URL
npx vibe-testing@latest run http://localhost:3000
npx vibe-testing@latest run https://staging.myapp.com --mode deep
npx vibe-testing@latest run http://localhost:3000 --codebase /path/to/project --scope /login /dashboard
# After a small change: test what changed thoroughly, everything else lightly
npx vibe-testing@latest run http://localhost:3000 --mode auto
npx vibe-testing@latest run http://localhost:3000 --mode changed --since main
# Iterative testing until coverage thresholds
npx vibe-testing@latest converge http://localhost:3000
npx vibe-testing@latest converge http://localhost:3000 --max-rounds 6 --target-pass-rate 0.95
# Open last report in browser
npx vibe-testing@latest report
# Reset memory and screenshots for a clean run
npx vibe-testing@latest reset
run options
| Option | Default | Description |
|---|---|---|
--mode fast|deep|auto|changed |
config file, else deep |
How much to test each page; see Test depth and modes |
--since <ref> |
last run | For auto/changed: compare against this branch, tag or commit |
--no-headed |
- | Run browser headless (default: visible) |
--codebase <path> |
cwd | Path to project root |
--scope <routes...> |
all | Test only specific routes |
-c <path> |
vibe.config.json |
Config file path |
run and converge fail with a nonzero exit when no scenarios are discovered
or an execution batch is empty. MCP run_full_test and run_converge return
isError: true for these cases. Empty runs do not write a successful run
snapshot or replace the prior report.
converge options
| Option | Default | Description |
|---|---|---|
--max-rounds <n> |
4 |
Max follow-up rounds after baseline |
--target-pass-rate <r> |
0.92 |
Stop when pass rate reaches this (0-1) |
--max-gaps <n> |
2 |
Stop when critical plus important gaps fall to this |
VIBE.md, project guidance
Create VIBE.md in your project root. vibe-testing reads it automatically on every run.
## Login URL
/login
## Test Credentials
- Email: [email protected]
- Password: TestPass123!
## Never Automate
- delete account
- cancel subscription
- [data-testid="danger-zone"]
- .billing-section
## Known Flaky
- /notifications (WebSocket dependent, skip or expect retry)
- /live-feed
## Notes
- Admin panel at /admin, use [email protected] / adminpass
- Dashboard data loads async, wait for [data-loaded="true"]
- Profile page: click "Edit Profile" before form fields appear
See VIBE.example.md for the full template.
Configuration
vibe.config.json
Created automatically by init with auto-detected URL. Edit as needed:
{
"url": "http://localhost:3000",
"mode": "deep",
"auth": {
"strategy": "credentials",
"login_url": "/login",
"credentials": {
"email": "[email protected]",
"password": "TestPass123!"
}
},
"never_interact": [
"delete account",
"cancel subscription",
"[data-testid='danger-zone']"
],
"scope": {
"include": ["/**"],
"exclude": ["/admin/**", "/api/**"],
"max_routes": 30,
"seed_routes": ["/live/dev-mode-a-now"]
},
"browser": {
"headed": true,
"slowMo": 40,
"timeout": 30000
}
}
| Key | Description |
|---|---|
url |
App URL, localhost or staging. Auto-detected by init. |
mode |
deep (default), fast, auto or changed; see Test depth and modes |
auth.strategy |
credentials (form login), basic (HTTP Basic Auth), or skip |
auth.login_url |
Explicit login route for non-standard paths keyword matching would miss |
auth.credentials |
Login credentials, used for login and for generated scenarios, persisted across runs |
auth.accounts |
More accounts on the same login form: [{ "name": "Bob", "credentials": { "email": "bob", "password": "…" } }]. With two different accounts, each run logs in as both and checks that the second cannot open the first one's pages (e.g. /orders/42 showing the first user's data). |
never_interact |
Text patterns or CSS selectors to skip during exploration |
explore.writes |
What exploration may change in the app. safe (default): creates new records (add/create forms, "add" buttons, probes on blank forms) but never overwrites a value already in a field, and doesn't probe or create-check forms that edit existing data (settings, profile, branding). all: also overwrites existing values and tests edit forms. none: no data-changing submissions. Every data-changing request exploration made is listed under "Changes made to the app" in the run summary and the report. |
scope.include |
Route patterns to include; default /** includes / and all nested routes. * stays within one segment; a trailing /** includes the subtree root and its descendants. Other characters are literal. Applies to pages from the code and pages found by the live crawl. |
scope.exclude |
Route patterns to exclude from testing (code and crawled pages) |
scope.since |
For mode auto/changed: the branch, tag or commit "changed" is compared against. Default: the commit of the last run (.vibe/baseline.json) plus uncommitted changes. |
scope.max_routes |
Cap how many routes are tested per run |
scope.seed_routes |
Concrete URLs for dynamic-segment routes the parser can't enumerate (e.g. /live/[slug] becomes /live/dev-mode-a-now). Each seeded route inherits requires_auth and the source file from its dynamic parent. |
browser.headed |
true = visible browser. CLI default true, MCP server default false (headless) so editor sessions aren't disrupted by pop-up windows. |
browser.slowMo |
Milliseconds between actions (useful for debugging) |
routes |
Deprecated and ignored; use scope to choose pages. |
Test depth and modes
Each page is tested at one of three depths:
| Depth | What runs |
|---|---|
| light | Load the page; server errors, console errors, broken values and resources, crash text. No clicks or submissions. |
| standard | Light, plus tabs, fills, toggles, buttons that don't change data (with the empty-state check), and links checked by request. |
| thorough | Everything: data-changing buttons, the in-app journey, totals after actions, create-then-verify, boundary probes, and the logout and cross-user session checks. |
mode decides the depth per page:
mode |
Pages |
|---|---|
deep (default) |
Every page thoroughly. |
fast |
Every page lightly. |
auto |
Pages changed since scope.since (default: the last run) thoroughly, pages affected through a shared file at standard, all others lightly. The first run (no baseline yet) behaves like deep. |
changed |
Only changed and affected pages, thoroughly; nothing else. |
With source code, "changed" comes from version control: files changed since the baseline (plus uncommitted and untracked files) are followed through the import graph to the pages that use them. A page's own file or a component it imports makes it thorough; a file most pages use (layout, context, API client) makes every page standard; a style sheet asks for a light check; a server handler makes the pages that called its endpoint thorough. Without a repository, auto/changed test every page thoroughly and say why. Without source code (black-box), every page gets a light visit and pages whose structure changed since the last run (controls, links, forms, headings, API calls; data and counts are ignored) are tested thoroughly.
In every mode, pages built from one template (same route pattern such as /tutorial/:page, or the same controls under one parent path) are tested thoroughly once and lightly after that, and any page that shows a problem at light or standard depth, or whose scenario failed, is re-tested thoroughly in the same run. The run summary (summary.plan) and the report's "Test plan" section list every page's depth and the reason; nothing is skipped silently.
Supported frameworks
| Framework | Routes | API endpoints | Forms |
|---|---|---|---|
| Next.js App Router | yes | yes | yes |
| Next.js Pages Router | yes | yes | yes |
| Next.js (src/ variant) | yes | yes | yes |
| React SPA (react-router) | yes | - | yes |
| Vue + Vite (vue-router) | yes | - | yes |
| Nuxt | yes | yes | yes |
| SvelteKit | yes | yes | yes |
| Express / Fastify | - | yes | yes |
| Monorepos (Turborepo, pnpm, Lerna) | yes | yes | yes |
Existing test files are also read to build a coverage map: Jest, Vitest, Playwright, and Cypress suites are all parsed.
Memory and regression detection
vibe-testing learns across runs and stores state in .vibe/:
- Working selectors: remembers
[name='email']worked on/login, uses it next run - Route timings: adjusts timeouts based on measured load times
- Auth credentials: saved after first login, reused automatically
- Flaky routes: tracks high fail-rate routes, marks them for retry
- Skip routes: routes that consistently error (need URL params) are auto-skipped
- Route manifest (
.vibe/route-manifest.json): every scan diffs against the previous one; new and removed routes surface asroute_changesonscan_codebaseresults so the AI can cover them immediately - Run snapshot (
.vibe/run-snapshot.json): every run captures per-route pass/fail and diffs against the prior run;snapshot_diffflagsnewly_passing(fixes),newly_failing(regressions),still_failing, plus added and removed routes
{
"snapshot_diff": {
"newly_passing": ["/login"],
"newly_failing": ["/checkout"],
"still_failing": [],
"new_routes": ["/admin/users"],
"removed_routes": []
}
}
run_converge returns the same shape, so iterative runs in your editor highlight what you just broke.
Reset with npx vibe-testing@latest reset to start fresh.
What a session looks like
When you ask your editor to "test the login flow", here is what it does:
User: "Test the login flow"
AI calls:
scan_codebase({ codebase_path: ".", url: "http://localhost:3000" })
-> Finds /login route, LoginForm component, POST /api/auth/login endpoint
-> Returns 8 generated test scenarios
get_context({ feature: "login" })
-> Returns src/app/login/page.tsx (has name="email", name="password" fields)
-> Returns src/app/api/auth/login/route.ts (POST handler, returns { token })
-> AI now knows the real selectors: [name='email'], [name='password']
login({ email: "[email protected]", password: "pass123" })
-> Opens Chromium, fills the form, clicks submit
-> Returns: { success: true, final_url: "/dashboard", tokens_found: 2 }
-> Returns screenshot of post-login dashboard
execute_scenario({ scenario: { name: "Login with invalid password", ... } })
-> Returns screenshot showing error state
generate_report()
-> Writes .vibe/report.html, opens in browser
AI reports: "Login works. Invalid password shows an error. All 3 login scenarios passed."
FAQ
Does vibe-testing use an LLM internally? No. It uses heuristic verification (URL changes, toast detection, API errors). Your editor's model is the brain: it sees screenshots and decides what to test next. Runs have no API cost.
What's the difference between explore_page and execute_scenario?
explore_page is broad: it clicks every button and input it finds and reports the results. execute_scenario is precise: you give it specific steps and it follows them exactly. Use explore_page to find what's on a page, then execute_scenario to test specific flows.
What's get_context for?
It returns the actual source code for a feature, so the AI knows [name='email'] instead of guessing #email-input. Always call it before writing test steps for a specific feature.
Does it handle SPAs with client-side routing? Yes. Playwright navigates the real browser, so client-side routing (React Router, Vue Router, and the rest) works naturally.
Does it handle login / authentication?
Yes. The login tool fills credentials in a real browser, captures auth tokens from localStorage/cookies, and keeps that session alive for authenticated tests. Credentials are persisted in .vibe/memory/ and reused automatically.
Will it click "Delete Account" or other destructive buttons?
No. Set never_interact in vibe.config.json or VIBE.md to blocklist dangerous actions. Any button whose text or selector matches is skipped during exploration.
Can I use it without an AI editor?
Yes. vibe-test run https://your-app.com runs standalone. It scans, generates scenarios, executes them, and produces an HTML report without needing an editor.
How do I test a staging environment?
Set url in vibe.config.json to your staging URL, or pass it as a CLI argument: npx vibe-testing@latest run https://staging.myapp.com.
Does it work with monorepos?
Yes. init detects Turborepo/pnpm/yarn workspaces and finds the frontend app automatically.
Requirements
- Node.js >= 20 (the test suite uses vitest 4.x which requires Node 20+)
- Playwright Chromium.
initinstalls the matching build. To install or repair it directly:npx vibe-testing@latest install-browser
run and converge check for the browser before scanning your project and print the same recovery command when it is missing.
Docker
A Node 20 + Chromium image is included for environments that prefer container-based MCP servers:
docker build -t vibe-test .
# wire into your editor's MCP config:
# { "command": "docker", "args": ["run", "--rm", "-i", "vibe-test"] }
Contributing
git clone https://github.com/AishwaryShrivastav/vibe-testing.git
cd vibe-testing
npm install
npx playwright install chromium
npm run build # tsc -> dist/
npm run dev # run CLI without building
npm run mcp # run MCP server without building
npm test # unit and isolated integration tests
VIBE_REAL_BROWSER=1 npm test # also run real Chromium CLI/MCP regressions
See CHANGELOG.md for version history. Bug reports and feature requests: GitHub issues.
License
MIT, Aishwary Shrivastav
Links
- npm: https://www.npmjs.com/package/vibe-testing
- GitHub: https://github.com/AishwaryShrivastav/vibe-testing
- Issues: https://github.com/AishwaryShrivastav/vibe-testing/issues
- Official MCP registry: listed as
io.github.AishwaryShrivastav/vibe-testingat https://registry.modelcontextprotocol.io - Model Context Protocol
- Playwright
| 1 | # vibe-testing |
| 2 | |
| 3 | [![npm version]](https://www.npmjs.com/package/vibe-testing) |
| 4 | [![npm downloads]](https://www.npmjs.com/package/vibe-testing) |
| 5 | [![GitHub stars]](https://github.com/AishwaryShrivastav/vibe-testing/stargazers) |
| 6 | [![Node.js]](https://nodejs.org) |
| 7 | [![MCP]](https://modelcontextprotocol.io) |
| 8 | [![License: MIT]](https://opensource.org/licenses/MIT) |
| 9 | [![CI]](https://github.com/AishwaryShrivastav/vibe-testing/actions) |
| 10 | |
| 11 | **Code-aware browser testing for AI coding agents.** |
| 12 | |
| 13 | [Product site] · [npm] · [MCP Registry] · [Smithery] · [Privacy] · [Launch status] |
| 14 | |
| 15 | Listed in [Awesome MCP Servers]. The download badge shows npm's cumulative package downloads; `npx` package fetches contribute to that total. |
| 16 | |
| 17 | vibe-testing reads your codebase so tests use your real routes and field names, runs them in a real Playwright browser, remembers what broke, and tells you what your last change fixed or regressed. It works as an MCP server that gives your editor (Claude Code, Cursor, Windsurf, VS Code Copilot, Roo Code) 14 testing tools, or as a standalone CLI. |
| 18 | |
| 19 | The repository is also an [Agent Plugin] with a `release-qa` skill. Compatible agents get both the testing tools and a senior-QA workflow for coverage, evidence, regression checks, and a clear release verdict. |
| 20 | |
| 21 | |
| 22 | cd /path/to/your/project |
| 23 | npx vibe-testing@latest init |
| 24 | |
| 25 | |
| 26 | Then open your editor and say: |
| 27 | |
| 28 | > "Scan this codebase and test it against http://localhost:3000" |
| 29 | |
| 30 | No source code? Point it at a URL from an empty folder and it tests the app black-box: |
| 31 | |
| 32 | |
| 33 | npx vibe-testing@latest run https://staging.example.com |
| 34 | |
| 35 | |
| 36 | |
| 37 | |
| 38 | ## It finds bugs you didn't write a test for |
| 39 | |
| 40 | While it explores, vibe-testing checks for server crashes, console errors, broken values (`NaN`, `[object Object]`, `Invalid Date`), totals that don't match their line items, saved values that never appear, a logout that doesn't end the session, and one user opening another user's pages. No scenarios to write. |
| 41 | |
| 42 | Measured on intentionally buggy apps (0.5.0, [details in #13]): |
| 43 | |
| 44 | | App | Mode | Before | 0.5.0 | |
| 45 | |---|---|---|---| |
| 46 | | react-simple-project (7 planted functional bugs) | with source code | 1 of 7 | **7 of 7** | |
| 47 | | react-simple-project | URL only | 0 of 7 | **7 of 7** | |
| 48 | | OWASP NodeGoat | with source code | 0 issues | `/contributions` crash, `/allocations` 500s, a redirect to `/undefined` | |
| 49 | | restful-booker-platform (no planted bugs) | both | 3 pages, 4 false errors | 8+ pages, 1 real bug: `/api/room/:id` returns 500 | |
| 50 | |
| 51 | No false findings on these three apps in either mode. Run it against a test environment: exploration creates records and lists every change it made. |
| 52 | |
| 53 | Using it on your project? Add the badge: |
| 54 | |
| 55 | |
| 56 | [](https://github.com/AishwaryShrivastav/vibe-testing) |
| 57 | |
| 58 | |
| 59 | |
| 60 | |
| 61 | ## What code-aware testing adds |
| 62 | |
| 63 | Playwright MCP gives your agent hands. vibe-testing gives it a testing workflow: code-derived scenarios, memory across runs, and a report. Two things a stateless browser tool cannot do: |
| 64 | |
| 65 | **1. Run it twice and it tells you what you broke.** Every run writes `.vibe/run-snapshot.json` and diffs it against the previous run. Every scan writes `.vibe/route-manifest.json` and diffs your routes. The second run prints regressions and fixes instead of a wall of results: |
| 66 | |
| 67 | |
| 68 | Changes since last run |
| 69 | Fixed: /login |
| 70 | Regression: /checkout |
| 71 | New: /admin/users |
| 72 | |
| 73 | |
| 74 | The same diff reaches your editor as `snapshot_diff` on `run_full_test` and `run_converge`, and as `route_changes` on `scan_codebase`, so the agent can flag "checkout broke after that commit" without anyone scrolling a report. Flaky routes, working selectors, and measured timeouts are also remembered between runs. |
| 75 | |
| 76 | **2. Zero LLM calls inside the tool.** Pass/fail verification is heuristic: URL changes, toast detection, API errors. Your editor's model decides what to test; vibe-testing does the browsing and checking. No API key, no per-run cost beyond the editor subscription you already pay for. |
| 77 | |
| 78 | |
| 79 | |
| 80 | ## Contents |
| 81 | |
| 82 | [How it works] |
| 83 | [MCP setup (per editor)] |
| 84 | [MCP tools reference] |
| 85 | [Recommended workflow] |
| 86 | [init command] |
| 87 | [CLI commands] |
| 88 | [VIBE.md, project guidance] |
| 89 | [Configuration (vibe.config.json)] |
| 90 | [Supported frameworks] |
| 91 | [Memory and regression detection] |
| 92 | [FAQ] |
| 93 | |
| 94 | |
| 95 | |
| 96 | ## How it works |
| 97 | |
| 98 | |
| 99 | npx vibe-testing@latest init |
| 100 | | |
| 101 | Registers 14 MCP tools in your editor |
| 102 | | |
| 103 | You ask: "Test the checkout flow" |
| 104 | | |
| 105 | AI calls: scan_codebase -> get_context("checkout") -> login -> explore_page -> execute_scenario -> generate_report |
| 106 | | |
| 107 | HTML report opens in browser with screenshots of every step |
| 108 | |
| 109 | |
| 110 | No test cases to write. The AI reads your source code to understand real field names and routes, opens a browser, tests everything, and shows you what's broken. |
| 111 | |
| 112 | `init` also: |
| 113 | |
| 114 | Detects which AI editors you have installed |
| 115 | Registers vibe-test in global editor configs (`~/.claude.json`, `~/.cursor/mcp.json`, `~/.codex/config.toml`, and so on) so the tools are available in every project, every session |
| 116 | Creates project-level MCP configs and AI instruction files |
| 117 | Auto-detects your app's URL (reads `.env`, `vite.config`, framework defaults) |
| 118 | Creates `VIBE.md` (edit with your test credentials) and `vibe.config.json` |
| 119 | Installs the matching Playwright Chromium build |
| 120 | |
| 121 | |
| 122 | |
| 123 | ## MCP setup |
| 124 | |
| 125 | ### Agent Plugin |
| 126 | |
| 127 | Install this repository as a plugin when your agent supports the Agent Plugins standard. It includes the portable `release-qa` skill and starts the published npm MCP server with no API key. |
| 128 | |
| 129 | Cursor: submit or install `https://github.com/AishwaryShrivastav/vibe-testing` as an Agent Plugin. |
| 130 | Claude Code: |
| 131 | |
| 132 | |
| 133 | claude plugin marketplace add AishwaryShrivastav/vibe-testing |
| 134 | claude plugin install vibe-testing@vibe-testing |
| 135 | |
| 136 | Other compatible agents: load the repository root containing `plugin.json`, `skills/`, and `mcp.json`. |
| 137 | |
| 138 | The direct MCP and CLI setup below remains available for editors without plugin support. |
| 139 | |
| 140 | ### MCPB bundle |
| 141 | |
| 142 | Claude Desktop and other MCPB hosts can install one local bundle. Build and validate it from this repository: |
| 143 | |
| 144 | |
| 145 | npm ci |
| 146 | npm run build:mcpb |
| 147 | |
| 148 | |
| 149 | The artifact is written to `artifacts/vibe-testing-<version>.mcpb`. See the [MCPB distribution guide] for the bundle contents, validation steps, Smithery handoff, and the one-time Playwright Chromium prerequisite. |
| 150 | |
| 151 | ### Option 1: automatic (recommended) |
| 152 | |
| 153 | |
| 154 | npx vibe-testing@latest init |
| 155 | |
| 156 | |
| 157 | Detects Claude Code, Cursor, Codex, Windsurf, VS Code and Roo Code, registers vibe-test in each, and prints what to do next in each editor. It never overwrites a config file it cannot parse, and running it twice changes nothing. |
| 158 | |
| 159 | ### Option 2: one command per editor |
| 160 | |
| 161 | | Editor | Run this | Then | |
| 162 | |---|---|---| |
| 163 | | Claude Code | `claude mcp add --scope user vibe-test -- npx -y vibe-testing@latest --mcp` | Start a new `claude` session. `/mcp` shows vibe-test as connected. | |
| 164 | | Codex (CLI, IDE extension, desktop app) | `codex mcp add vibe-test -- npx -y vibe-testing@latest --mcp` | Start a new `codex` session. `/mcp` lists vibe-test. | |
| 165 | | VS Code (Copilot) | `code --add-mcp '{"name":"vibe-test","type":"stdio","command":"npx","args":["-y","vibe-testing@latest","--mcp"]}'` | Use Agent mode in Copilot Chat. | |
| 166 | | Cursor | Add the JSON below to `~/.cursor/mcp.json` | Cursor Settings > MCP: check vibe-test is switched on. | |
| 167 | | Windsurf | Add the JSON below to `~/.codeium/windsurf/mcp_config.json` | Press Refresh in the Cascade MCP panel. | |
| 168 | |
| 169 | Then say to your agent: |
| 170 | |
| 171 | > "Scan this codebase and test it against http://localhost:3000" |
| 172 | |
| 173 | The first run downloads a Chromium build (one-time, roughly 150 MB). `npx vibe-testing@latest install-browser` does it ahead of time. |
| 174 | |
| 175 | ### Option 3: edit the config file yourself |
| 176 | |
| 177 | #### Claude Code |
| 178 | |
| 179 | For every project, the user-scope config is `~/.claude.json` (top-level `mcpServers`). Claude Code does not read MCP servers from `~/.claude/settings.json`. For one project, use `.mcp.json` in the project root, which you can commit for your team: |
| 180 | |
| 181 | |
| 182 | { |
| 183 | "mcpServers": { |
| 184 | "vibe-test": { |
| 185 | "type": "stdio", |
| 186 | "command": "npx", |
| 187 | "args": ["-y", "vibe-testing@latest", "--mcp"] |
| 188 | } |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | |
| 193 | Claude Code asks you to approve a project-scoped server the first time it sees it. |
| 194 | |
| 195 | #### Codex |
| 196 | |
| 197 | Add to `~/.codex/config.toml`. The Codex CLI, IDE extension and desktop app share this file: |
| 198 | |
| 199 | |
| 200 | [mcp_servers.vibe-test] |
| 201 | command = "npx" |
| 202 | args = ["-y", "vibe-testing@latest", "--mcp"] |
| 203 | |
| 204 | |
| 205 | `init` also writes `AGENTS.md`, which Codex reads for project instructions. |
| 206 | |
| 207 | #### Cursor |
| 208 | |
| 209 | Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project): |
| 210 | |
| 211 | |
| 212 | { |
| 213 | "mcpServers": { |
| 214 | "vibe-test": { |
| 215 | "command": "npx", |
| 216 | "args": ["-y", "vibe-testing@latest", "--mcp"] |
| 217 | } |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | |
| 222 | #### Windsurf |
| 223 | |
| 224 | Add to `~/.codeium/windsurf/mcp_config.json`: |
| 225 | |
| 226 | |
| 227 | { |
| 228 | "mcpServers": { |
| 229 | "vibe-test": { |
| 230 | "command": "npx", |
| 231 | "args": ["-y", "vibe-testing@latest", "--mcp"] |
| 232 | } |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | |
| 237 | #### VS Code (GitHub Copilot) |
| 238 | |
| 239 | Add to `.vscode/mcp.json` in your project: |
| 240 | |
| 241 | |
| 242 | { |
| 243 | "servers": { |
| 244 | "vibe-test": { |
| 245 | "type": "stdio", |
| 246 | "command": "npx", |
| 247 | "args": ["-y", "vibe-testing@latest", "--mcp"] |
| 248 | } |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | |
| 253 | #### Roo Code / Cline |
| 254 | |
| 255 | Add to `.roo/mcp.json`: |
| 256 | |
| 257 | |
| 258 | { |
| 259 | "mcpServers": { |
| 260 | "vibe-test": { |
| 261 | "command": "npx", |
| 262 | "args": ["-y", "vibe-testing@latest", "--mcp"] |
| 263 | } |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | |
| 268 | #### From local build (development) |
| 269 | |
| 270 | |
| 271 | { |
| 272 | "mcpServers": { |
| 273 | "vibe-test": { |
| 274 | "command": "node", |
| 275 | "args": ["/path/to/vibe-testing/dist/mcp-server.js"] |
| 276 | } |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | |
| 281 | |
| 282 | |
| 283 | ## MCP tools reference |
| 284 | |
| 285 | 14 tools available to your AI editor after setup: |
| 286 | |
| 287 | | Tool | When to call | Returns | |
| 288 | |------|-------------|---------| |
| 289 | | `configure` | Start here on a new project. Detects framework, server, and authentication | Structured setup result and idempotent project files | |
| 290 | | `scan_codebase` | Always first. Reads source code, finds routes/forms/tests/gaps | Routes, forms, coverage map, generated scenarios, `route_changes` since last scan | |
| 291 | | `get_context` | Before writing test steps. Returns source files for a feature | Actual source code with real field names and selectors | |
| 292 | | `login` | When app requires authentication | Post-login screenshot, token state, API calls observed | |
| 293 | | `scan_page_elements` | To see all interactive elements on a page | Element list with selectors plus page screenshot | |
| 294 | | `explore_page` | Broad "does everything work?" testing | Interaction results, API calls, `problems`, `diagnostics`, `warnings`, `changes_made_to_app`, screenshot. `isError` when `problems` is non-empty | |
| 295 | | `execute_scenario` | Run specific test steps | Step-by-step logs plus screenshots | |
| 296 | | `get_coverage` | View coverage map and untested routes | Coverage entries, gaps, available scenarios | |
| 297 | | `suggest_tests` | Find coverage gaps after exploration | Prioritized, ready-to-run scenarios with steps | |
| 298 | | `take_screenshot` | Quick visual verification | Screenshot of any URL | |
| 299 | | `generate_report` | Build HTML report (auto-opens) | Report path plus summary | |
| 300 | | `run_full_test` | One-shot: scan, execute, explore, report | Full results, `summary.failed_scenarios` (name, route, reason) plus `snapshot_diff` vs last run | |
| 301 | | `run_converge` | Iterative testing until thresholds | Summary across all rounds (incl. `summary.failed_scenarios`) plus `snapshot_diff` vs last run | |
| 302 | | `cleanup` | Close browsers, free resources | - | |
| 303 | |
| 304 | `explore_page` replaces the old `errors` field with `problems` (real app failures: server errors, console errors, broken values, functional failures) and `diagnostics` (vibe-test's own notes, such as navigation or discovery issues). It also returns `warnings` (possible missing data such as "Category: Unknown"; not failures) and `changes_made_to_app` (data-changing requests it sent, per `explore.writes`), and sets `isError` when there are `problems`. |
| 305 | |
| 306 | Run results (`run_full_test`, `run_converge`, `generate_report`) carry `summary.failed_scenarios`, a list of `{ name, route, status, reason }` for every failed or errored scenario, alongside `explorer_failures`, `explorer_warnings`, `retry_findings` and `app_changes`. The Markdown and HTML reports list the same findings. |
| 307 | |
| 308 | ### Tool inputs |
| 309 | |
| 310 | **`scan_codebase`** |
| 311 | |
| 312 | { |
| 313 | "codebase_path": "/path/to/project", |
| 314 | "url": "http://localhost:3000", |
| 315 | "mode": "deep" |
| 316 | } |
| 317 | |
| 318 | |
| 319 | **`get_context`** |
| 320 | |
| 321 | { "feature": "login" } |
| 322 | { "feature": "/checkout" } |
| 323 | { "feature": "user profile form" } |
| 324 | |
| 325 | |
| 326 | **`login`** |
| 327 | |
| 328 | { |
| 329 | "email": "[email protected]", |
| 330 | "password": "TestPass123!", |
| 331 | "login_url": "/login" |
| 332 | } |
| 333 | |
| 334 | |
| 335 | **`scan_page_elements`** / **`explore_page`** |
| 336 | |
| 337 | { |
| 338 | "route": "/dashboard", |
| 339 | "authenticated": true |
| 340 | } |
| 341 | |
| 342 | |
| 343 | **`execute_scenario`** |
| 344 | |
| 345 | { |
| 346 | "scenario": { |
| 347 | "id": "create-item", |
| 348 | "name": "Create a new item", |
| 349 | "route": "/items", |
| 350 | "steps": [ |
| 351 | { "action": "navigate", "url": "/items", "description": "Open items page" }, |
| 352 | { "action": "click", "selector": "text=Add Item", "description": "Open create form" }, |
| 353 | { "action": "fill", "selector": "[name='title']", "value": "Test Item", "description": "Fill title" }, |
| 354 | { "action": "fill", "selector": "[name='description']", "value": "Test description", "description": "Fill description" }, |
| 355 | { "action": "click", "selector": "button[type='submit']", "description": "Submit form" } |
| 356 | ], |
| 357 | "expected_outcome": "New item appears in the list", |
| 358 | "requires_auth": true |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | |
| 363 | Step actions: `navigate`, `fill`, `click`, `select`, `wait`, `assert`, `upload` |
| 364 | |
| 365 | CLI and MCP use the same scenario runner. An `assert` step evaluates every |
| 366 | supplied condition: |
| 367 | |
| 368 | `selector`: the target must be visible. CSS, `text=`, `label=`, and |
| 369 | `placeholder=` are supported; the named locators match exactly. |
| 370 | `value`: visible text must contain this string, on the selected element or on |
| 371 | the page body when no selector is supplied. |
| 372 | `url`: the current URL must exactly match this absolute URL or path resolved |
| 373 | against the configured base URL, including query and fragment. |
| 374 | |
| 375 | For example: |
| 376 | |
| 377 | |
| 378 | { "action": "assert", "selector": "#confirmation", "value": "Saved", "url": "/settings", "timeout": 5000, "description": "Check saved settings" } |
| 379 | |
| 380 | |
| 381 | These checks wait up to the step timeout (default 15000 ms per check). A failed |
| 382 | assertion stops the scenario, records a failed step and reason, and returns |
| 383 | `status: "fail"`; MCP also sets `isError: true`. Explicit conditions are used as |
| 384 | the verdict after the existing authentication and form API checks. The |
| 385 | `description` and `expected_outcome` prose are not executable assertions. |
| 386 | Without `selector`, `value`, or `url`, `assert` only checks page health: at least |
| 387 | 10 characters of visible body text and no nonempty visible error indicators. |
| 388 | This compatibility check does not prove a described business outcome. |
| 389 | |
| 390 | `upload` requires a file-input `selector` and a nonempty file path in `value`. |
| 391 | Relative paths resolve against the codebase root. Hidden file inputs are |
| 392 | supported. A missing file, directory, missing target, or target that is not a |
| 393 | file input returns `status: "error"`. The action selects one file using |
| 394 | Playwright; add an assertion of the resulting UI to verify application-side |
| 395 | processing. It does not automate native file-picker dialogs. |
| 396 | |
| 397 | Scenarios must contain at least one step. Unknown actions are errors. |
| 398 | |
| 399 | |
| 400 | **`take_screenshot`** |
| 401 | |
| 402 | { "url": "/settings", "authenticated": true, "full_page": false } |
| 403 | |
| 404 | |
| 405 | **`run_full_test`** |
| 406 | |
| 407 | { "url": "http://localhost:3000", "codebase_path": "/path/to/project", "mode": "deep" } |
| 408 | |
| 409 | |
| 410 | **`run_converge`** |
| 411 | |
| 412 | { |
| 413 | "url": "http://localhost:3000", |
| 414 | "max_followup_rounds": 4, |
| 415 | "target_pass_rate": 0.92, |
| 416 | "max_high_severity_gaps": 2 |
| 417 | } |
| 418 | |
| 419 | |
| 420 | |
| 421 | |
| 422 | ## Recommended workflow |
| 423 | |
| 424 | ### Full test session |
| 425 | |
| 426 | Tell your AI editor: |
| 427 | |
| 428 | |
| 429 | Scan this codebase and test it against http://localhost:3000. |
| 430 | Log in with [email protected] / pass123. Explore the dashboard and |
| 431 | settings pages, run the suggested tests, and generate a report. |
| 432 | |
| 433 | |
| 434 | The AI will: |
| 435 | `scan_codebase`, to understand routes, forms, existing tests |
| 436 | `get_context("login")`, to read the actual login form source code |
| 437 | `login`, to authenticate in a real browser |
| 438 | `explore_page("/dashboard")`, clicking everything and observing what breaks |
| 439 | `explore_page("/settings")`, same |
| 440 | `suggest_tests`, to find coverage gaps |
| 441 | `execute_scenario` x N, running targeted test flows |
| 442 | `generate_report`, HTML report opens automatically |
| 443 | `cleanup`, closing browsers |
| 444 | |
| 445 | ### Test a specific feature |
| 446 | |
| 447 | |
| 448 | Test the checkout flow using vibe-test. Get context for checkout, |
| 449 | then run the full purchase flow with card number 4242424242424242. |
| 450 | |
| 451 | |
| 452 | The AI will: |
| 453 | `scan_codebase` (if not already done) |
| 454 | `get_context("checkout")`, reading `CheckoutForm.tsx`, `api/orders/route.ts` and so on |
| 455 | `login` |
| 456 | `execute_scenario`, filling the real form fields from source code |
| 457 | `generate_report` |
| 458 | |
| 459 | ### Verify a bug fix |
| 460 | |
| 461 | |
| 462 | I fixed the login redirect bug. Use vibe-test to confirm it's working. |
| 463 | |
| 464 | |
| 465 | The AI will: |
| 466 | `login`, testing the login flow |
| 467 | `take_screenshot`, visual confirmation of the post-login state |
| 468 | Report back what it sees |
| 469 | |
| 470 | ### Find what's broken |
| 471 | |
| 472 | |
| 473 | Explore every page and tell me what's broken. |
| 474 | |
| 475 | |
| 476 | The AI will run `explore_page` on every route, collecting API errors, broken elements, and failed interactions, then `suggest_tests` with the broken items marked as high priority. |
| 477 | |
| 478 | |
| 479 | |
| 480 | ## init command |
| 481 | |
| 482 | |
| 483 | npx vibe-testing@latest init [options] |
| 484 | |
| 485 | |
| 486 | What it creates: |
| 487 | |
| 488 | | File | Where | Purpose | |
| 489 | |------|-------|---------| |
| 490 | | `.mcp.json` | Project root | Claude Code MCP config (project-level) | |
| 491 | | `~/.claude.json` | Global | Claude Code MCP config, user scope (all projects) | |
| 492 | | `~/.codex/config.toml` | Global | Codex MCP config (CLI, IDE extension, desktop app) | |
| 493 | | `.cursor/mcp.json` | Project root | Cursor MCP config | |
| 494 | | `~/.cursor/mcp.json` | Global | Cursor MCP config (all projects) | |
| 495 | | `.cursor/rules/vibe-test.mdc` | Project | Cursor rules, `alwaysApply: true` | |
| 496 | | `.windsurfrules` | Project | Windsurf instructions | |
| 497 | | `~/.codeium/windsurf/mcp_config.json` | Global | Windsurf MCP config (all projects) | |
| 498 | | `.vscode/mcp.json` | Project | VS Code Copilot MCP config | |
| 499 | | `.github/copilot-instructions.md` | Project | GitHub Copilot instructions | |
| 500 | | `.roo/mcp.json` | Project | Roo Code MCP config | |
| 501 | | `CLAUDE.md` | Project | Claude Code session instructions | |
| 502 | | `AGENTS.md` | Project | Universal agent instructions (Codex, Devin, Zed) | |
| 503 | | `VIBE.md` | Project | Test guidance, edit with your credentials | |
| 504 | | `vibe.config.json` | Project | Config, URL auto-detected from your project | |
| 505 | |
| 506 | Options: |
| 507 | |
| 508 | |
| 509 | npx vibe-testing@latest init # auto-detect editors, register globally + project |
| 510 | npx vibe-testing@latest init --no-global # project-level only, skip global registration |
| 511 | npx vibe-testing@latest init --skip-browser-install |
| 512 | npx vibe-testing@latest init --editor cursor # only configure Cursor |
| 513 | npx vibe-testing@latest init --editor claude-code windsurf |
| 514 | npx vibe-testing@latest init --editor codex # register Codex even if ~/.codex is not there yet |
| 515 | |
| 516 | |
| 517 | After init, edit `VIBE.md` with your login URL and test credentials. |
| 518 | |
| 519 | |
| 520 | |
| 521 | ## CLI commands |
| 522 | |
| 523 | |
| 524 | # Set up in current project |
| 525 | npx vibe-testing@latest init |
| 526 | |
| 527 | # Install or repair the matching browser build |
| 528 | npx vibe-testing@latest install-browser |
| 529 | |
| 530 | # Run tests against a URL |
| 531 | npx vibe-testing@latest run http://localhost:3000 |
| 532 | npx vibe-testing@latest run https://staging.myapp.com --mode deep |
| 533 | npx vibe-testing@latest run http://localhost:3000 --codebase /path/to/project --scope /login /dashboard |
| 534 | |
| 535 | # After a small change: test what changed thoroughly, everything else lightly |
| 536 | npx vibe-testing@latest run http://localhost:3000 --mode auto |
| 537 | npx vibe-testing@latest run http://localhost:3000 --mode changed --since main |
| 538 | |
| 539 | # Iterative testing until coverage thresholds |
| 540 | npx vibe-testing@latest converge http://localhost:3000 |
| 541 | npx vibe-testing@latest converge http://localhost:3000 --max-rounds 6 --target-pass-rate 0.95 |
| 542 | |
| 543 | # Open last report in browser |
| 544 | npx vibe-testing@latest report |
| 545 | |
| 546 | # Reset memory and screenshots for a clean run |
| 547 | npx vibe-testing@latest reset |
| 548 | |
| 549 | |
| 550 | ### `run` options |
| 551 | |
| 552 | | Option | Default | Description | |
| 553 | |--------|---------|-------------| |
| 554 | | `--mode fast\|deep\|auto\|changed` | config file, else `deep` | How much to test each page; see [Test depth and modes] | |
| 555 | | `--since <ref>` | last run | For `auto`/`changed`: compare against this branch, tag or commit | |
| 556 | | `--no-headed` | - | Run browser headless (default: visible) | |
| 557 | | `--codebase <path>` | cwd | Path to project root | |
| 558 | | `--scope <routes...>` | all | Test only specific routes | |
| 559 | | `-c <path>` | `vibe.config.json` | Config file path | |
| 560 | |
| 561 | `run` and `converge` fail with a nonzero exit when no scenarios are discovered |
| 562 | or an execution batch is empty. MCP `run_full_test` and `run_converge` return |
| 563 | `isError: true` for these cases. Empty runs do not write a successful run |
| 564 | snapshot or replace the prior report. |
| 565 | |
| 566 | ### `converge` options |
| 567 | |
| 568 | | Option | Default | Description | |
| 569 | |--------|---------|-------------| |
| 570 | | `--max-rounds <n>` | `4` | Max follow-up rounds after baseline | |
| 571 | | `--target-pass-rate <r>` | `0.92` | Stop when pass rate reaches this (0-1) | |
| 572 | | `--max-gaps <n>` | `2` | Stop when critical plus important gaps fall to this | |
| 573 | |
| 574 | |
| 575 | |
| 576 | ## VIBE.md, project guidance |
| 577 | |
| 578 | Create `VIBE.md` in your project root. vibe-testing reads it automatically on every run. |
| 579 | |
| 580 | |
| 581 | ## Login URL |
| 582 | /login |
| 583 | |
| 584 | ## Test Credentials |
| 585 | - Email: [email protected] |
| 586 | - Password: TestPass123! |
| 587 | |
| 588 | ## Never Automate |
| 589 | - delete account |
| 590 | - cancel subscription |
| 591 | - [data-testid="danger-zone"] |
| 592 | - .billing-section |
| 593 | |
| 594 | ## Known Flaky |
| 595 | - /notifications (WebSocket dependent, skip or expect retry) |
| 596 | - /live-feed |
| 597 | |
| 598 | ## Notes |
| 599 | - Admin panel at /admin, use [email protected] / adminpass |
| 600 | - Dashboard data loads async, wait for [data-loaded="true"] |
| 601 | - Profile page: click "Edit Profile" before form fields appear |
| 602 | |
| 603 | |
| 604 | See [`VIBE.example.md`] for the full template. |
| 605 | |
| 606 | |
| 607 | |
| 608 | ## Configuration |
| 609 | |
| 610 | ### vibe.config.json |
| 611 | |
| 612 | Created automatically by `init` with auto-detected URL. Edit as needed: |
| 613 | |
| 614 | |
| 615 | { |
| 616 | "url": "http://localhost:3000", |
| 617 | "mode": "deep", |
| 618 | "auth": { |
| 619 | "strategy": "credentials", |
| 620 | "login_url": "/login", |
| 621 | "credentials": { |
| 622 | "email": "[email protected]", |
| 623 | "password": "TestPass123!" |
| 624 | } |
| 625 | }, |
| 626 | "never_interact": [ |
| 627 | "delete account", |
| 628 | "cancel subscription", |
| 629 | "[data-testid='danger-zone']" |
| 630 | ], |
| 631 | "scope": { |
| 632 | "include": ["/**"], |
| 633 | "exclude": ["/admin/**", "/api/**"], |
| 634 | "max_routes": 30, |
| 635 | "seed_routes": ["/live/dev-mode-a-now"] |
| 636 | }, |
| 637 | "browser": { |
| 638 | "headed": true, |
| 639 | "slowMo": 40, |
| 640 | "timeout": 30000 |
| 641 | } |
| 642 | } |
| 643 | |
| 644 | |
| 645 | | Key | Description | |
| 646 | |-----|-------------| |
| 647 | | `url` | App URL, localhost or staging. Auto-detected by `init`. | |
| 648 | | `mode` | `deep` (default), `fast`, `auto` or `changed`; see [Test depth and modes] | |
| 649 | | `auth.strategy` | `credentials` (form login), `basic` (HTTP Basic Auth), or `skip` | |
| 650 | | `auth.login_url` | Explicit login route for non-standard paths keyword matching would miss | |
| 651 | | `auth.credentials` | Login credentials, used for login and for generated scenarios, persisted across runs | |
| 652 | | `auth.accounts` | More accounts on the same login form: `[{ "name": "Bob", "credentials": { "email": "bob", "password": "…" } }]`. With two different accounts, each run logs in as both and checks that the second cannot open the first one's pages (e.g. `/orders/42` showing the first user's data). | |
| 653 | | `never_interact` | Text patterns or CSS selectors to skip during exploration | |
| 654 | | `explore.writes` | What exploration may change in the app. `safe` (default): creates new records (add/create forms, "add" buttons, probes on blank forms) but never overwrites a value already in a field, and doesn't probe or create-check forms that edit existing data (settings, profile, branding). `all`: also overwrites existing values and tests edit forms. `none`: no data-changing submissions. Every data-changing request exploration made is listed under "Changes made to the app" in the run summary and the report. | |
| 655 | | `scope.include` | Route patterns to include; default `/**` includes `/` and all nested routes. `*` stays within one segment; a trailing `/**` includes the subtree root and its descendants. Other characters are literal. Applies to pages from the code and pages found by the live crawl. | |
| 656 | | `scope.exclude` | Route patterns to exclude from testing (code and crawled pages) | |
| 657 | | `scope.since` | For mode `auto`/`changed`: the branch, tag or commit "changed" is compared against. Default: the commit of the last run (`.vibe/baseline.json`) plus uncommitted changes. | |
| 658 | | `scope.max_routes` | Cap how many routes are tested per run | |
| 659 | | `scope.seed_routes` | Concrete URLs for dynamic-segment routes the parser can't enumerate (e.g. `/live/[slug]` becomes `/live/dev-mode-a-now`). Each seeded route inherits `requires_auth` and the source file from its dynamic parent. | |
| 660 | | `browser.headed` | `true` = visible browser. CLI default `true`, MCP server default `false` (headless) so editor sessions aren't disrupted by pop-up windows. | |
| 661 | | `browser.slowMo` | Milliseconds between actions (useful for debugging) | |
| 662 | | `routes` | Deprecated and ignored; use `scope` to choose pages. | |
| 663 | |
| 664 | ### Test depth and modes |
| 665 | |
| 666 | Each page is tested at one of three depths: |
| 667 | |
| 668 | | Depth | What runs | |
| 669 | |-------|-----------| |
| 670 | | light | Load the page; server errors, console errors, broken values and resources, crash text. No clicks or submissions. | |
| 671 | | standard | Light, plus tabs, fills, toggles, buttons that don't change data (with the empty-state check), and links checked by request. | |
| 672 | | thorough | Everything: data-changing buttons, the in-app journey, totals after actions, create-then-verify, boundary probes, and the logout and cross-user session checks. | |
| 673 | |
| 674 | `mode` decides the depth per page: |
| 675 | |
| 676 | | `mode` | Pages | |
| 677 | |--------|-------| |
| 678 | | `deep` (default) | Every page thoroughly. | |
| 679 | | `fast` | Every page lightly. | |
| 680 | | `auto` | Pages changed since `scope.since` (default: the last run) thoroughly, pages affected through a shared file at standard, all others lightly. The first run (no baseline yet) behaves like `deep`. | |
| 681 | | `changed` | Only changed and affected pages, thoroughly; nothing else. | |
| 682 | |
| 683 | With source code, "changed" comes from version control: files changed since the baseline (plus uncommitted and untracked files) are followed through the import graph to the pages that use them. A page's own file or a component it imports makes it thorough; a file most pages use (layout, context, API client) makes every page standard; a style sheet asks for a light check; a server handler makes the pages that called its endpoint thorough. Without a repository, `auto`/`changed` test every page thoroughly and say why. Without source code (black-box), every page gets a light visit and pages whose structure changed since the last run (controls, links, forms, headings, API calls; data and counts are ignored) are tested thoroughly. |
| 684 | |
| 685 | In every mode, pages built from one template (same route pattern such as `/tutorial/:page`, or the same controls under one parent path) are tested thoroughly once and lightly after that, and any page that shows a problem at light or standard depth, or whose scenario failed, is re-tested thoroughly in the same run. The run summary (`summary.plan`) and the report's "Test plan" section list every page's depth and the reason; nothing is skipped silently. |
| 686 | |
| 687 | |
| 688 | |
| 689 | ## Supported frameworks |
| 690 | |
| 691 | | Framework | Routes | API endpoints | Forms | |
| 692 | |-----------|--------|---------------|-------| |
| 693 | | Next.js App Router | yes | yes | yes | |
| 694 | | Next.js Pages Router | yes | yes | yes | |
| 695 | | Next.js (src/ variant) | yes | yes | yes | |
| 696 | | React SPA (react-router) | yes | - | yes | |
| 697 | | Vue + Vite (vue-router) | yes | - | yes | |
| 698 | | Nuxt | yes | yes | yes | |
| 699 | | SvelteKit | yes | yes | yes | |
| 700 | | Express / Fastify | - | yes | yes | |
| 701 | | Monorepos (Turborepo, pnpm, Lerna) | yes | yes | yes | |
| 702 | |
| 703 | Existing test files are also read to build a coverage map: Jest, Vitest, Playwright, and Cypress suites are all parsed. |
| 704 | |
| 705 | |
| 706 | |
| 707 | ## Memory and regression detection |
| 708 | |
| 709 | vibe-testing learns across runs and stores state in `.vibe/`: |
| 710 | |
| 711 | **Working selectors**: remembers `[name='email']` worked on `/login`, uses it next run |
| 712 | **Route timings**: adjusts timeouts based on measured load times |
| 713 | **Auth credentials**: saved after first login, reused automatically |
| 714 | **Flaky routes**: tracks high fail-rate routes, marks them for retry |
| 715 | **Skip routes**: routes that consistently error (need URL params) are auto-skipped |
| 716 | **Route manifest** (`.vibe/route-manifest.json`): every scan diffs against the previous one; new and removed routes surface as `route_changes` on `scan_codebase` results so the AI can cover them immediately |
| 717 | **Run snapshot** (`.vibe/run-snapshot.json`): every run captures per-route pass/fail and diffs against the prior run; `snapshot_diff` flags `newly_passing` (fixes), `newly_failing` (regressions), `still_failing`, plus added and removed routes |
| 718 | |
| 719 | |
| 720 | { |
| 721 | "snapshot_diff": { |
| 722 | "newly_passing": ["/login"], |
| 723 | "newly_failing": ["/checkout"], |
| 724 | "still_failing": [], |
| 725 | "new_routes": ["/admin/users"], |
| 726 | "removed_routes": [] |
| 727 | } |
| 728 | } |
| 729 | |
| 730 | |
| 731 | `run_converge` returns the same shape, so iterative runs in your editor highlight what you just broke. |
| 732 | |
| 733 | Reset with `npx vibe-testing@latest reset` to start fresh. |
| 734 | |
| 735 | |
| 736 | |
| 737 | ## What a session looks like |
| 738 | |
| 739 | When you ask your editor to "test the login flow", here is what it does: |
| 740 | |
| 741 | |
| 742 | User: "Test the login flow" |
| 743 | |
| 744 | AI calls: |
| 745 | scan_codebase({ codebase_path: ".", url: "http://localhost:3000" }) |
| 746 | -> Finds /login route, LoginForm component, POST /api/auth/login endpoint |
| 747 | -> Returns 8 generated test scenarios |
| 748 | |
| 749 | get_context({ feature: "login" }) |
| 750 | -> Returns src/app/login/page.tsx (has name="email", name="password" fields) |
| 751 | -> Returns src/app/api/auth/login/route.ts (POST handler, returns { token }) |
| 752 | -> AI now knows the real selectors: [name='email'], [name='password'] |
| 753 | |
| 754 | login({ email: "[email protected]", password: "pass123" }) |
| 755 | -> Opens Chromium, fills the form, clicks submit |
| 756 | -> Returns: { success: true, final_url: "/dashboard", tokens_found: 2 } |
| 757 | -> Returns screenshot of post-login dashboard |
| 758 | |
| 759 | execute_scenario({ scenario: { name: "Login with invalid password", ... } }) |
| 760 | -> Returns screenshot showing error state |
| 761 | |
| 762 | generate_report() |
| 763 | -> Writes .vibe/report.html, opens in browser |
| 764 | |
| 765 | AI reports: "Login works. Invalid password shows an error. All 3 login scenarios passed." |
| 766 | |
| 767 | |
| 768 | |
| 769 | |
| 770 | ## FAQ |
| 771 | |
| 772 | **Does vibe-testing use an LLM internally?** |
| 773 | No. It uses heuristic verification (URL changes, toast detection, API errors). Your editor's model is the brain: it sees screenshots and decides what to test next. Runs have no API cost. |
| 774 | |
| 775 | **What's the difference between `explore_page` and `execute_scenario`?** |
| 776 | `explore_page` is broad: it clicks every button and input it finds and reports the results. `execute_scenario` is precise: you give it specific steps and it follows them exactly. Use `explore_page` to find what's on a page, then `execute_scenario` to test specific flows. |
| 777 | |
| 778 | **What's `get_context` for?** |
| 779 | It returns the actual source code for a feature, so the AI knows `[name='email']` instead of guessing `#email-input`. Always call it before writing test steps for a specific feature. |
| 780 | |
| 781 | **Does it handle SPAs with client-side routing?** |
| 782 | Yes. Playwright navigates the real browser, so client-side routing (React Router, Vue Router, and the rest) works naturally. |
| 783 | |
| 784 | **Does it handle login / authentication?** |
| 785 | Yes. The `login` tool fills credentials in a real browser, captures auth tokens from localStorage/cookies, and keeps that session alive for authenticated tests. Credentials are persisted in `.vibe/memory/` and reused automatically. |
| 786 | |
| 787 | **Will it click "Delete Account" or other destructive buttons?** |
| 788 | No. Set `never_interact` in `vibe.config.json` or `VIBE.md` to blocklist dangerous actions. Any button whose text or selector matches is skipped during exploration. |
| 789 | |
| 790 | **Can I use it without an AI editor?** |
| 791 | Yes. `vibe-test run https://your-app.com` runs standalone. It scans, generates scenarios, executes them, and produces an HTML report without needing an editor. |
| 792 | |
| 793 | **How do I test a staging environment?** |
| 794 | Set `url` in `vibe.config.json` to your staging URL, or pass it as a CLI argument: `npx vibe-testing@latest run https://staging.myapp.com`. |
| 795 | |
| 796 | **Does it work with monorepos?** |
| 797 | Yes. `init` detects Turborepo/pnpm/yarn workspaces and finds the frontend app automatically. |
| 798 | |
| 799 | |
| 800 | |
| 801 | ## Requirements |
| 802 | |
| 803 | Node.js >= 20 (the test suite uses vitest 4.x which requires Node 20+) |
| 804 | Playwright Chromium. `init` installs the matching build. To install or repair it directly: |
| 805 | |
| 806 | npx vibe-testing@latest install-browser |
| 807 | |
| 808 | |
| 809 | `run` and `converge` check for the browser before scanning your project and print the same recovery command when it is missing. |
| 810 | |
| 811 | ### Docker |
| 812 | |
| 813 | A Node 20 + Chromium image is included for environments that prefer container-based MCP servers: |
| 814 | |
| 815 | |
| 816 | docker build -t vibe-test . |
| 817 | # wire into your editor's MCP config: |
| 818 | # { "command": "docker", "args": ["run", "--rm", "-i", "vibe-test"] } |
| 819 | |
| 820 | |
| 821 | |
| 822 | |
| 823 | ## Contributing |
| 824 | |
| 825 | |
| 826 | git clone https://github.com/AishwaryShrivastav/vibe-testing.git |
| 827 | cd vibe-testing |
| 828 | npm install |
| 829 | npx playwright install chromium |
| 830 | npm run build # tsc -> dist/ |
| 831 | npm run dev # run CLI without building |
| 832 | npm run mcp # run MCP server without building |
| 833 | npm test # unit and isolated integration tests |
| 834 | VIBE_REAL_BROWSER=1 npm test # also run real Chromium CLI/MCP regressions |
| 835 | |
| 836 | |
| 837 | See [CHANGELOG.md] for version history. Bug reports and feature requests: [GitHub issues]. |
| 838 | |
| 839 | |
| 840 | |
| 841 | ## License |
| 842 | |
| 843 | MIT, [Aishwary Shrivastav] |
| 844 | |
| 845 | |
| 846 | |
| 847 | ## Links |
| 848 | |
| 849 | npm: https://www.npmjs.com/package/vibe-testing |
| 850 | GitHub: https://github.com/AishwaryShrivastav/vibe-testing |
| 851 | Issues: https://github.com/AishwaryShrivastav/vibe-testing/issues |
| 852 | Official MCP registry: listed as `io.github.AishwaryShrivastav/vibe-testing` at https://registry.modelcontextprotocol.io |
| 853 | [![mcpindex]](https://mcpindex.ai/server/io-github-aishwaryshrivastav-vibe-testing) |
| 854 | [Model Context Protocol] |
| 855 | [Playwright] |
| 856 |
Details
- Updated
- Nov 13, 2026
- License
- MIT
- Stars on the repo
- ★ 18
- Checked
- Source
- AishwaryShrivastav/vibe-testing ↗
- Creator
- AishwaryShrivastav · 1 listing
Similar MCP servers
See all →
Skill29 production-ready scripts for iOS app testing, buildingIos simulator skill
SkillMoAI unified orchestrator for autonomous development
SkillWrite Android unit, Compose UI, and Hilt-integrated testsAndroid Testing Standards
SkillImplementing any feature or bugfixTest-Driven Development (TDD)
SkillToolkit for interacting with and testing local webWebapp testing
PromptGuide to fixing bugs using a test-first approachTest first bug fixing approach