interface-built-right
Visual regression testing for Claude Code. Capture baselines, compare changes, iterate automatically.
Quick Start
npm install github:tyroneross/interface-built-right
npx ibr start http://localhost:3000/dashboard --name my-feature
npx ibr check
npx ibr serve
Installation
From GitHub:
npm install github:tyroneross/interface-built-right
From local path:
npm install /path/to/interface-built-right
After install, verify it works:
npx ibr --help
CLI Commands
npx ibr start <url> | Capture baseline screenshot |
npx ibr check [sessionId] | Compare current state against baseline |
npx ibr serve | Open web UI at localhost:4200 |
npx ibr list | List all sessions |
npx ibr update [sessionId] | Update baseline with current screenshot |
npx ibr clean --older-than 7d | Clean old sessions |
npx ibr login <url> | Save auth state for protected pages |
npx ibr logout | Clear saved auth state |
Workflow Example
cd my-app && npm run dev
npx ibr start http://localhost:3000/settings --name settings-redesign
npx ibr check
npx ibr serve
npx ibr update
Authenticated Pages
For pages behind login:
npx ibr login http://localhost:3000/login
npx ibr start http://localhost:3000/dashboard
npx ibr logout
Security notes:
- Auth state is stored per-user (
auth.{username}.json)
- 7-day expiration with auto-cleanup
- Blocked in CI/CD and deployed environments
- Add
.ibr/ to your .gitignore
Claude Code Plugin
Add to your project's .claude/settings.json:
{
"plugins": [
"node_modules/interface-built-right/plugin"
]
}
Then restart Claude Code. You'll have these commands:
/ibr:ui | Launch web UI dashboard |
/ibr:snapshot | Capture baseline (prompts for URL) |
/ibr:compare | Compare against baseline |
Programmatic API
import { InterfaceBuiltRight } from 'interface-built-right';
const ibr = new InterfaceBuiltRight({
baseUrl: 'http://localhost:3000',
outputDir: './.ibr',
threshold: 1.0,
});
const { sessionId } = await ibr.startSession('/dashboard', {
name: 'dashboard-update',
});
const report = await ibr.check(sessionId);
console.log(report.analysis.verdict);
await ibr.close();
Configuration
Create .ibrrc.json in your project root:
{
"baseUrl": "http://localhost:3000",
"outputDir": "./.ibr",
"viewport": "desktop",
"threshold": 1.0,
"fullPage": true
}
Comparison Report
Reports are structured for Claude to read and act on:
{
"sessionId": "sess_abc123",
"comparison": {
"match": false,
"diffPercent": 8.2,
"diffPixels": 6560
},
"analysis": {
"verdict": "EXPECTED_CHANGE",
"summary": "Header background changed. Layout intact."
}
}
Verdicts:
MATCH - No visual changes (within threshold)
EXPECTED_CHANGE - Changes detected, appear intentional
UNEXPECTED_CHANGE - Changes in unexpected areas
LAYOUT_BROKEN - Significant structural issues
File Structure
Sessions are stored in .ibr/sessions/:
.ibr/
├── auth.{username}.json # Auth state (per-user)
└── sessions/
└── sess_abc123/
├── session.json # Session metadata
├── baseline.png # Original screenshot
├── current.png # After-changes screenshot
└── diff.png # Visual diff
Troubleshooting
"Command not found: ibr"
npx ibr --help
npm run ibr -- --help
"Playwright browsers not installed"
npx playwright install chromium
"Auth state expired"
npx ibr login http://localhost:3000/login
"Session not found"
npx ibr list
Requirements
- Node.js 18+
- Playwright (installed automatically)
License
MIT