Vibe Testing
Integrates with Windsurf (powered by Codeium) to provide browser testing capabilities: codebase scanning, scenario execution, and automated report generation.
Enables GitHub Copilot (VS Code) to perform browser-based testing of web applications, including login, element exploration, and full test run.
vibe-test
Code-aware browser testing agent for AI-powered editors.
Reads your codebase, understands every route and form, opens a real Playwright browser, explores every element, and reports what works and what breaks — with screenshots.
Works as an MCP server that gives your AI editor (Claude Code, Cursor, Windsurf, VS Code Copilot) 13 browser testing tools — or as a standalone CLI.
Install in Any Project (One Command)
cd /path/to/your/project
npx vibe-testing@latest initThis command:
Detects which AI editors you have installed
Registers vibe-test in global editor configs (
~/.claude/settings.json,~/.cursor/mcp.json, etc.) so the tools are available in every project, every sessionCreates 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
Then open your editor and say:
"Scan this codebase and test it against http://localhost:3000"
Your AI will pick up the tools automatically and start testing.
Contents
How It Works
npx vibe-testing@latest init
↓
Registers 13 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 stepNo 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.
MCP Setup
Option 1 — Automatic (recommended)
npx vibe-testing@latest initDetects and configures all installed editors. Done.
Option 2 — Manual per editor
Claude Code
Add to ~/.claude/settings.json (global — works in every project):
{
"mcpServers": {
"vibe-test": {
"command": "npx",
"args": ["-y", "vibe-testing@latest", "--mcp"]
}
}
}Or add to .mcp.json in your project root (project-level only):
{
"mcpServers": {
"vibe-test": {
"command": "npx",
"args": ["-y", "vibe-testing@latest", "--mcp"]
}
}
}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": {
"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
13 tools available to your AI editor after setup:
Tool | When to call | Returns |
| Always first. Reads source code, finds routes/forms/tests/gaps | Routes, forms, coverage map, generated scenarios |
| Before writing test steps. Returns source files for a feature | Actual source code with real field names and selectors |
| When app requires authentication | Post-login screenshot, token state, API calls observed |
| To see all interactive elements on a page | Element list with selectors + page screenshot |
| Broad "does everything work?" testing | Interaction results, API calls, errors, screenshot |
| Run specific test steps | Step-by-step logs + screenshots |
| View coverage map and untested routes | Coverage entries, gaps, available scenarios |
| Find coverage gaps after exploration | Prioritized, ready-to-run scenarios with steps |
| Quick visual verification | Screenshot of any URL |
| Build HTML report (auto-opens) | Report path + summary |
| One-shot: scan → execute → explore → report | Full results |
| Iterative testing until thresholds | Summary across all rounds |
| Close browsers, free resources | — |
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": "test@example.com",
"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
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 test@example.com / pass123. Explore the dashboard and
settings pages, run the suggested tests, and generate a report.The AI will:
scan_codebase— understand routes, forms, existing testsget_context("login")— read actual login form source codelogin— authenticate in a real browserexplore_page("/dashboard")— click everything, observe what breaksexplore_page("/settings")— samesuggest_tests— find coverage gapsexecute_scenario× N — run targeted test flowsgenerate_report— HTML report opens automaticallycleanup— close 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")— readCheckoutForm.tsx,api/orders/route.tsetc.login— authenticateexecute_scenario— fill 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— test the login flowtake_screenshot— visual confirmation of the post-login stateReport 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 |
| Project root | Claude Code MCP config (project-level) |
| Global | Claude Code MCP config (all projects) |
| Project root | Cursor MCP config |
| Global | Cursor MCP config (all projects) |
| Project | Cursor rules — |
| Project | Windsurf instructions |
| Global | Windsurf MCP config (all projects) |
| Project | VS Code Copilot MCP config |
| Project | GitHub Copilot instructions |
| Project | Roo Code MCP config |
| Project | Claude Code session instructions |
| Project | Universal agent instructions (Codex, Devin, Zed) |
| Project | Test guidance — edit with your credentials |
| 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 --editor cursor # only configure Cursor
npx vibe-testing@latest init --editor claude-code windsurfAfter init, edit VIBE.md with your login URL and test credentials.
CLI Commands
# Set up in current project
npx vibe-testing@latest init
# 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
# 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 resetrun options
Option | Default | Description |
|
|
|
| — | Run browser headless (default: visible) |
| cwd | Path to project root |
| all | Test only specific routes |
|
| Config file path |
converge options
Option | Default | Description |
|
| Max follow-up rounds after baseline |
|
| Stop when pass rate ≥ this (0–1) |
|
| Stop when critical+important gaps ≤ this |
VIBE.md — Project Guidance
Create VIBE.md in your project root. Vibe Test reads it automatically on every run.
## Login URL
/login
## Test Credentials
- Email: test@example.com
- 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 admin@example.com / adminpass
- Dashboard data loads async — wait for [data-loaded="true"]
- Profile page: click "Edit Profile" before form fields appearSee 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": "test@example.com",
"password": "TestPass123!"
}
},
"never_interact": [
"delete account",
"cancel subscription",
"[data-testid='danger-zone']"
],
"scope": {
"include": ["/**"],
"exclude": ["/admin/**", "/api/**"],
"max_routes": 30
},
"browser": {
"headed": true,
"slowMo": 40,
"timeout": 30000
}
}Key | Description |
| App URL — localhost or staging. Auto-detected by |
|
|
|
|
| Login credentials — persisted across runs once used |
| Text patterns or CSS selectors to skip during exploration |
| Route patterns to exclude from testing |
| Cap how many routes are tested per run |
|
|
| Milliseconds between actions (useful for debugging) |
Supported Frameworks
Framework | Routes | API endpoints | Forms |
Next.js App Router | ✅ | ✅ | ✅ |
Next.js Pages Router | ✅ | ✅ | ✅ |
Next.js (src/ variant) | ✅ | ✅ | ✅ |
React SPA (react-router) | ✅ | — | ✅ |
Vue + Vite (vue-router) | ✅ | — | ✅ |
Nuxt | ✅ | ✅ | ✅ |
SvelteKit | ✅ | ✅ | ✅ |
Express / Fastify | — | ✅ | ✅ |
Monorepos (Turborepo, pnpm, Lerna) | ✅ | ✅ | ✅ |
Existing test files are also read to build a coverage map:
Test runner | Supported |
Jest / Vitest | ✅ |
Playwright | ✅ |
Cypress | ✅ |
Self-Improvement
Vibe Test learns across runs and stores intelligence in .vibe/:
Working selectors — remembers
[name='email']worked on/login, uses it next runRoute 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
Reset with npx vibe-testing@latest reset to start fresh.
How the AI Uses These Tools
When you ask your editor to "test the login flow", here is exactly 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 email, password fields, name="email", name="password")
→ Returns src/app/api/auth/login/route.ts (POST handler, returns { token })
→ AI now knows the REAL selectors: [name='email'], [name='password']
login({ email: "test@example.com", password: "pass123" })
→ Opens Chromium, navigates to /login
→ Fills email and password fields
→ 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",
steps: [
{ action: "navigate", url: "/login" },
{ action: "fill", selector: "[name='email']", value: "test@example.com" },
{ action: "fill", selector: "[name='password']", value: "wrongpassword" },
{ action: "click", selector: "button[type='submit']" }
],
expected_outcome: "Error message shown"
}
})
→ Returns screenshot showing error state
generate_report()
→ Writes .vibe/report.html
→ Opens in browser automatically
AI reports: "Login works. Invalid password shows an error. All 3 login scenarios passed."FAQ
Does vibe-test use an AI/LLM internally? No. It uses heuristic verification (URL changes, toast detection, API errors). Your editor's AI (Claude, GPT-4, etc.) is the brain — it sees screenshots and decides what to test next.
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, etc.) 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 ≥ 18
Playwright Chromium — install once with:
npx playwright install chromium(vibe-test will prompt you if it's missing)
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 buildingSee CHANGELOG.md for version history.
License
MIT — Aishwary Shrivastav
Links
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/AishwaryShrivastav/vibe-testing'
If you have feedback or need assistance with the MCP directory API, please join our Discord server