argus-qa
Sends rich audit reports to Slack channels, with issue severity classification and routing.
Argus — AI-Powered Dev Testing Tool
Argus Panoptes — the all-seeing giant of Greek mythology with a hundred eyes who never slept.
Automated browser testing pipeline that catches bugs, compares environments, and sends rich reports to Slack (or generates a self-contained HTML dashboard when Slack is not configured) — powered by Chrome DevTools MCP and Claude Code.
MCP Quick Start
Add to your .mcp.json (or ask Claude Code: claude mcp add argus -- npx -y argusqa-os):
{
"mcpServers": {
"argus": {
"command": "npx",
"args": ["-y", "argusqa-os"]
}
}
}Then ask Claude (or any MCP client):
Run argus_audit on http://localhost:3000Four tools are exposed:
Tool | What it does |
| Fast QA pass — JS errors, network failures, accessibility, SEO, security, CSS, content |
| Deep QA pass — adds Lighthouse scoring, responsive layout checks across 4 viewports, memory leak detection via heap snapshot, hover-state bug detection, and accessibility tree snapshot |
| Diff dev vs staging side-by-side — screenshots, findings delta, environment regressions |
| Return the last saved report JSON from the most recent audit |
Requires: Node.js ≥ 20.19, Chrome running with
--remote-debugging-port=9222, and thechrome-devtools-mcpMCP server registered alongside Argus.
The landing/ directory contains the product landing page (React + Vite + Tailwind + Framer Motion) with Supabase-backed waitlist and enterprise contact forms. Live at argus-qa.com (deployed via Cloudflare Pages; background video served from Cloudflare R2). See landing/README.md for setup.
🔴 Critical / 🟡 Warning / 🔵 Info | ⚙️ | 🧪 | 📋 |
114 distinct issue types detected | 24 analysis engines | 348 test assertions | 82 test blocks |
What Argus Catches
Argus runs 24 analysis engines per run and detects 114 distinct issue types across JavaScript runtime, network, CSS, performance, accessibility, SEO, security, content quality, responsive layout, memory, runtime anti-patterns, hover-state interactions, accessibility tree snapshots, keyboard focus, and Chrome DevTools issues panel — plus flakiness detection, historical baselines, user flow assertions, and environment comparison as cross-cutting layers. Every finding is classified by severity (critical / warning / info) and routed to the right Slack channel — or rendered as a local report.html when Slack is not configured.
JavaScript Runtime
Severity | Bug / Issue | Detection Method |
🔴 Critical | Uncaught exceptions — |
|
🔴 Critical | Unhandled Promise rejections |
|
🟡 Warning |
| Chrome DevTools |
🔴 Critical |
| Chrome DevTools |
🔵 Info |
| Chrome DevTools |
Network & API
Severity | Bug / Issue | Detection Method |
🔴 Critical | HTTP 5xx server errors on any request |
|
🔴 Critical | 401 / 403 auth failures — user is being kicked out |
|
🔴 Critical | API endpoint called 5+ times in one page load — likely an infinite loop | Network frequency grouping by normalized URL + method |
🟡 Warning | HTTP 4xx client errors (404, 422, 429, etc.) |
|
🟡 Warning | API endpoint called 3–4 times — likely a double-fetch bug | Frequency grouping → 3 ≤ count ≤ 4 (check |
🔵 Info | API endpoint called twice — may be intentional prefetch | Frequency grouping → count = 2 |
🔵 Info | API call summary per page load (total calls, unique endpoints, duplicates) | Aggregated network analysis |
🟡 Warning | Redirect chain longer than 2 hops — extra round-trips inflate load time | Navigation Timing |
🟡 Warning | Broken internal link — |
|
Page Health
Severity | Bug / Issue | Detection Method |
🔴 Critical | Blank or near-empty page — less than 50 characters of body text |
|
🟡 Warning | Expected element never appeared — page may have crashed mid-load |
|
CSS & Styling
Severity | Bug / Issue | Detection Method |
🟡 Warning |
| CSS rule walk: property declared with |
🟡 Warning | Component style leak — BEM selector found in the wrong stylesheet |
|
🟡 Warning | React inline style overriding a stylesheet declaration on the same element |
|
🔵 Info | CSS property declared by multiple rules on the same element (cascade override) | Computed style walk across all matched rules per key element |
🔵 Info | Unused CSS rules — selectors matching no element on the page (> 10 flagged) |
|
🔵 Info | CSS Modules detected — hashed class names found on DOM elements | Pattern |
🔵 Info | SCSS source map found — compiled CSS traced back to |
|
Performance
Severity | Bug / Issue | Detection Method |
🟡 Warning | LCP > 2500ms — largest element took too long to paint | Chrome performance trace → |
🟡 Warning | CLS > 0.1 — layout shifted significantly after initial render | Chrome performance trace |
🟡 Warning | FID / TBT > 100ms — main thread was blocked during interaction | Chrome performance trace |
🟡 Warning | TTFB > 800ms — server took too long to send the first byte | Chrome performance trace |
Accessibility
Severity | Bug / Issue | Detection Method |
🔴 Critical | Lighthouse accessibility score below 50 / 100 | Lighthouse audit via |
🟡 Warning | Lighthouse accessibility score 50–89 / 100 | Lighthouse audit |
🟡 Warning | Missing alt text on images | Individual Lighthouse audit check |
🟡 Warning | Insufficient color contrast ratio | Individual Lighthouse audit check |
🟡 Warning | Missing ARIA labels on interactive elements | Individual Lighthouse audit check |
🟡 Warning | Keyboard navigation broken or unreachable elements | Individual Lighthouse audit check |
SEO
Severity | Bug / Issue | Detection Method |
🟡 Warning | Missing | DOM inspection via |
🟡 Warning | Missing Open Graph tags ( | DOM inspection via |
🟡 Warning |
| DOM inspection + URL prefix check ( |
🟡 Warning | Multiple | DOM inspection — |
🟡 Warning | Zero | DOM inspection — |
🟡 Warning | Generic page title (less than 10 characters, or default placeholder) | DOM inspection + length check |
🟡 Warning | Missing | DOM inspection via |
🟡 Warning | Missing | DOM inspection via |
Security
Severity | Bug / Issue | Detection Method |
🔴 Critical | Auth token found in |
|
🔴 Critical | Sensitive token in the page URL (query param or hash) | URL pattern match against current |
🔴 Critical |
|
|
🔴 Critical | CSP violation — inline script or external resource blocked by Content-Security-Policy | Chrome DevTools Issues panel ( |
🟡 Warning | Sensitive data ( |
|
🟡 Warning | Missing |
|
🟡 Warning | Missing | Same headers fetch |
🟡 Warning | Cross-origin |
|
🟡 Warning | Page served over plain HTTP with no HTTPS upgrade redirect | URL protocol check ( |
🔵 Info | Cookie present without |
|
🔵 Info | Deprecated browser API usage (e.g. | Chrome DevTools Issues panel |
Content Quality
Severity | Bug / Issue | Detection Method |
🟡 Warning |
| DOM text scan for literal "null" / "undefined" strings |
🟡 Warning | Lorem ipsum / placeholder copy still in production | DOM text scan for "lorem ipsum" and common placeholder strings |
🟡 Warning | Broken image (404 or failed to load) |
|
🔵 Info | Empty data list — | DOM structure check |
Responsive / Mobile
Severity | Bug / Issue | Detection Method |
🔴 Critical | Horizontal overflow at mobile / tablet viewport (≤ 768px) |
|
🟡 Warning | Touch target smaller than 44×44 px at mobile or tablet viewport | CSS computed size check on interactive elements at 375px and 768px |
🔵 Info | Responsive screenshot grid — snapshots at 375 / 768 / 1024 / 1440px |
|
Network Performance
Severity | Bug / Issue | Detection Method |
🔴 Critical | API response time > 3000ms |
|
🟡 Warning | API response time > 1000ms | Same observer, lower threshold |
🔴 Critical | API response payload > 2 MB |
|
🟡 Warning | API response payload > 500 KB | Same, lower threshold |
🟡 Warning | Cross-origin (third-party) script TTFB > 2000ms — blocking render or late interactivity | HAR |
Network Request Origin Tagging
All network findings carry an origin field ('first-party' / 'third-party') so operators can triage critical first-party failures separately from third-party noise.
Lighthouse Audits
Severity | Bug / Issue | Detection Method |
🔴 Critical | Lighthouse accessibility score < 50 / 100 |
|
🟡 Warning | Lighthouse accessibility score 50–89 / 100 |
|
🟡 Warning | Lighthouse performance score < 90 / 100 |
|
🟡 Warning | Lighthouse SEO score < 90 / 100 |
|
🟡 Warning | Lighthouse best-practices score < 90 / 100 |
|
🟡 Warning | Individual failing Lighthouse audit items | Surfaced per-audit from the full Lighthouse report |
Memory Leaks
Severity | Bug / Issue | Detection Method |
🔴 Critical | > 100 detached DOM nodes in V8 heap — severe leak |
|
🟡 Warning | > 10 detached DOM nodes in V8 heap — probable leak | Same snapshot parse, lower threshold |
🟡 Warning | Heap grew > 2 MB after navigate-away + navigate-back — probable per-load leak |
|
Runtime Anti-Patterns
Severity | Bug / Issue | Detection Method |
🟡 Warning | Synchronous |
|
🟡 Warning |
|
|
🟡 Warning | Long task > 50ms on the main thread — blocks user interaction |
|
🔴 Critical | CORS policy violation — cross-origin fetch blocked by the browser |
|
🟡 Warning | Service worker registration failure — SW script returns 4xx or is invalid |
|
🔵 Info | Same-origin static asset ( |
|
Historical Baselines & Trends
Severity | Bug / Issue | Detection Method |
🔴 Critical | New critical finding not present in the saved baseline — regression introduced since last run |
|
🟡 Warning | New warning finding not present in the baseline | Same key comparison, warning severity |
🔵 Info | Pre-existing finding still present — no change since last run | Suppressed from real-time alerts; included in info digest only |
🔵 Info | Run trend summary — new vs resolved counts, saved per run | Appended to |
Hover-State Bugs
Severity | Bug / Issue | Detection Method |
🟡 Warning / 🔴 Critical |
|
|
🟡 Warning |
| Same hover + |
Accessibility Snapshot Analysis
Severity | Bug / Issue | Detection Method |
🟡 Warning | Interactive element ( |
|
🟡 Warning | Form control ( |
|
🟡 Warning | Landmark role appearing more than once without distinct |
|
🟡 Warning | Heading level skip — h1→h3 or h4→h6 jumps more than one level, breaking WCAG 1.3.1 document outline | DOM walk of |
🟡 Warning |
|
|
Keyboard Accessibility
Severity | Bug / Issue | Detection Method |
🟡 Warning | Button or focusable element has |
|
Flakiness Detection
Severity | Bug / Issue | Detection Method |
original | Confirmed finding — present in both crawl runs |
|
🔵 Info | Flaky finding — appeared in only one of two crawl runs | Present in run1 or run2 but not both; downgraded to |
User Flow Assertions
Severity | Bug / Issue | Detection Method |
🔴 Critical | Flow step failed — navigate/fill/click/waitFor threw mid-flow (page state unknown) |
|
🔴 Critical |
| Polled via |
🟡 Warning |
| Baseline snapshot of |
🟡 Warning |
| Baseline snapshot of |
🟡 Warning |
|
|
🟡 Warning |
|
|
🔴 Critical |
| Script parses the injected error buffer |
Environment Regressions (dev vs staging)
Severity | Bug / Issue | Detection Method |
🔴 Critical | API status regressed — request that returned 2xx in dev now returns 5xx in staging | Network diff between both environments |
🟡 Warning | Visual change > 0.5% pixels different between dev and staging screenshots |
|
🟡 Warning | New console error in staging that doesn't exist in dev | Console message diff |
🟡 Warning | New network request in staging — unexpected endpoint appeared | Network request URL diff |
🟡 Warning | Request present in dev is missing in staging — endpoint removed or broken | Network request URL diff |
🟡 Warning | API status changed between environments (any non-5xx change) | Network status diff |
🔵 Info | DOM structural change — element count differs between dev and staging | HTML tag count comparison across snapshots |
What It Does
Argus watches your running application and automatically surfaces issues that test suites miss: visual regressions, API loops, CSS drift, console noise, and accessibility failures — all with screenshots delivered directly to Slack.
Feature | Description |
Error Detection | Crawls your app's routes; captures JS exceptions, console errors, failed API calls, redirect chains, and broken internal links |
Environment Comparison | Diffs dev vs staging: screenshots, DOM structure, network requests, console errors |
CSS Analysis | Detects cascade overrides, component style leaks, unused rules, React inline style conflicts |
API Frequency Analysis | Flags endpoints called more than once per page load (double-fetch, missing |
Network Performance |
|
SEO Checks | Missing meta description, OG tags, canonical, viewport, h1 — DOM-inspected on every route |
Security Checks | localStorage tokens, token-in-URL, |
Content Quality |
|
Responsive Analysis | Overflow + touch target checks at 375/768px; screenshot grid at 4 breakpoints dispatched to Slack |
Memory Leak Detection | V8 heap snapshot → detached DOM node count; heap growth across navigate-away + navigate-back |
Runtime Anti-Patterns | Synchronous XHR, |
Hover-State Bug Detection | Fires |
Accessibility Snapshot Analysis | Calls |
Keyboard Focus Analysis | Tab-walks every focusable element (up to 20 steps); detects |
Chrome DevTools Issues Panel | Queries |
Mobile CPU Throttling | Applies 4× CPU throttle ( |
Origin-Tagged Network Findings | All network error and timing findings carry |
Historical Baselines | Saves finding keys after each run; subsequent runs only alert on new issues; trend summary in Slack digest |
Flakiness Detection | Crawls each route twice per run; findings in both runs are confirmed (original severity); findings in only one run are marked flaky ( |
User Flow Assertions | Named multi-step flows ( |
API Contract Validation | Define |
Severity Policy Overrides | Define |
Auth Token Refresh |
|
Slack-optional mode | When |
Codebase Cross-Reference | Points |
GitHub PR Integration | Posts a structured Markdown findings table as a PR comment (updates in-place — one comment per PR, no spam); sets an |
Auto Route Discovery | Augments manual |
| |
Watch Mode |
|
Full Lighthouse Suite | All 4 Lighthouse categories (performance, SEO, best-practices, accessibility) with per-audit items |
Performance Budgets | Enforces LCP < 2500ms, CLS < 0.1, FID < 100ms, TTFB < 800ms per route |
Slack Notifications | Rich Block Kit reports with inline screenshots routed to |
Slash Command |
|
CI Integration | GitHub Actions workflow runs daily at 6 AM UTC and on every push to |
MCP Server (AI-callable Argus) | Register Argus as an MCP server via |
Works with React + SCSS, CSS Modules, CSS-in-JS (styled-components / emotion), and plain HTML/CSS apps.
How It Works
Three components run against the same Chrome instance:
Claude Code (Terminal / VS Code)
├── MCP Protocol → Chrome DevTools MCP Server → Chrome
└── Writes → Orchestration Layer → Slack Bot APIChrome DevTools MCP Server — programmatic access to Chrome: network traffic, console, screenshots, DOM, performance traces
Claude Code — orchestration hub: reads codebase, drives the MCP tools, classifies findings, posts to Slack
Slack Bot (BugBot) — receives reports, exposes
/argus-retestslash command, handles Acknowledge / Retest button actions
In interactive mode (running from Claude Code), MCP tools are called natively. In CI mode (GitHub Actions), src/utils/mcp-client.js spawns chrome-devtools-mcp as a child process and communicates via JSON-RPC over stdio.
Prerequisites
Requirement | Version | Notes |
Node.js | v20.19+ | Required by Chrome DevTools MCP |
Chrome | Stable (current) | Must be installed |
Claude Code | Latest |
|
Slack workspace | — | Optional — only needed if you want Slack reports. Without it, Argus generates a local |
One-Time Setup
1. Clone and install
git clone <your-repo-url>
cd argus
npm install
npm run setup # creates reports/ directory2. Configure environment variables
Recommended: use the interactive setup wizard
npm run initThe wizard prompts for your dev and staging URLs, detects your framework (Next.js / React Router), auto-discovers routes from sitemap.xml and your file structure, and optionally collects Slack and GitHub credentials. It writes a populated .env and a pre-filled src/config/targets.js — no manual editing required.
Alternative: manual setup
cp .env.example .envOpen .env and fill in:
# Your app URLs (required)
TARGET_DEV_URL=http://localhost:3000
TARGET_STAGING_URL=https://staging.yourapp.com # leave blank → CSS-only analysis mode
# Slack — OPTIONAL. Omit to get a local report.html instead of Slack messages.
# Get from: api.slack.com/apps → BugBot → OAuth & Permissions
# SLACK_BOT_TOKEN=xoxb-...
# SLACK_SIGNING_SECRET=...
# Channel IDs — only needed when SLACK_BOT_TOKEN is set
# SLACK_CHANNEL_CRITICAL=C0000000000
# SLACK_CHANNEL_WARNINGS=C0000000001
# SLACK_CHANNEL_DIGEST=C00000000023. Configure your routes
If you used npm run init in Step 2, this file was generated for you — skip to Step 4.
Otherwise, edit src/config/targets.js — add every key page of your app:
export const routes = [
{ path: '/', name: 'Home', critical: true, waitFor: 'main' },
{ path: '/login', name: 'Login', critical: true, waitFor: 'form' },
{ path: '/dashboard', name: 'Dashboard', critical: true, waitFor: '[data-testid="dashboard"]' },
{ path: '/settings', name: 'Settings', critical: false, waitFor: null },
];critical: true— any error on this route goes to#bugs-criticalwaitFor— CSS selector Argus waits for before capturing (signals the page is ready)
4. Connect Chrome DevTools MCP to Claude Code
claude mcp add chrome-devtools -- npx chrome-devtools-mcp@latestVerify it's working — in Claude Code, ask:
"List all open Chrome pages"
You should see a list of tabs. If you do, the MCP connection is live.
5. Set up the Slack App (BugBot) (optional)
Skip this step if you don't need Slack notifications. Argus will generate a local
report.htmland open it in the browser instead.
Go to api.slack.com/apps → Create New App → From scratch → name it BugBot
OAuth & Permissions → Bot Token Scopes: add
chat:write,files:write,files:readClick Install to Workspace → Authorize
Copy the Bot User OAuth Token (
xoxb-...) into.envasSLACK_BOT_TOKENBasic Information → copy Signing Secret into
.envasSLACK_SIGNING_SECRETCreate channels:
#bugs-critical,#bugs-warnings,#bugs-digestIn each channel:
/invite @BugBot
Running Argus
Option A: From Claude Code (interactive — recommended)
Open Claude Code in this project directory. With Chrome DevTools MCP connected, ask:
Run the Argus error detection crawl on localhost:3000Claude calls runCrawl(mcp) with live MCP tools — navigates pages, captures errors, posts to Slack.
Run the Argus environment comparison between localhost:3000 and stagingClaude calls runComparison(mcp) — screenshots both, diffs them, posts results.
Option B: From the terminal (CI / headless)
# Error detection crawl
npm run crawl
# Generate a self-contained HTML report from the latest JSON (offline-friendly)
npm run report:html
# Environment comparison (or CSS analysis if no staging URL)
npm run compare
# Start the Slack interaction server
npm run serverReports are saved to reports/ as JSON files. Screenshots saved alongside. Run npm run report:html after any crawl to get a portable reports/report.html with all screenshots inlined — useful for sharing with designers, PMs, or reviewing offline.
Option C: Watch Mode (passive monitoring)
Watch mode attaches to whatever page Chrome already has open and polls for new issues at a 3-second interval — without navigating anywhere. Use this for real-time reporting while you develop.
Requires 2 terminals:
Terminal | Command | Purpose |
1 |
| Your application |
2 |
| Argus passive monitor |
Sequential steps:
Open Chrome and navigate to your app's local URL
Terminal 1: start your application
Terminal 2:
npm run watch— Argus begins pollingDevelop normally — any new console errors, network failures (4xx/5xx), CORS blocks, or auth failures are printed in Terminal 2 in real time
Ctrl+Cin Terminal 2 — stops the monitor and writesreports/report.htmlif any issues were found
To target a specific URL:
npm run watch http://localhost:4000Environment variables:
Variable | Default | Description |
|
| Poll interval in milliseconds |
|
| URL attributed to findings when none passed as argument |
Watch mode uses the same Slack integration as npm run crawl — if SLACK_BOT_TOKEN is configured, new findings are posted to Slack in real time. On Ctrl+C, the HTML report is generated from all accumulated findings for the session.
Option D: From Slack (on-demand)
/argus-retest https://staging.yourapp.com/checkoutBugBot responds immediately, runs the test, and posts results back to the channel. Detailed bug reports go to #bugs-critical.
CSS Analysis Mode
When TARGET_STAGING_URL is not set in .env, npm run compare automatically switches to CSS analysis mode instead of comparing two environments.
What it analyzes on your dev environment:
Check | What it catches |
Cascade overrides | Same CSS property declared multiple times on an element; |
Component style leaks | BEM selector ( |
Unused rules | CSS selectors that match no element on the current page |
CSS Modules | Detects hashed class names; extracts readable component names ( |
React inline style conflicts |
|
SCSS source maps | Traces compiled CSS back to original |
API frequency analysis also runs automatically:
Call count | Severity | Likely cause |
2 calls | info | Possible prefetch + actual — verify intentional |
3–4 calls | warning | Double-fetch — check |
5+ calls | critical | Runaway loop — missing cleanup, infinite re-render |
Performance Budgets
Argus enforces these thresholds on every crawl:
Metric | Threshold | Severity |
LCP (Largest Contentful Paint) | < 2500ms | warning |
CLS (Cumulative Layout Shift) | < 0.1 | warning |
FID / TBT (interaction latency) | < 100ms | warning |
TTFB (Time to First Byte) | < 800ms | warning |
Violations are reported as individual warning bugs with the measured value.
Lighthouse Suite
Runs all four Lighthouse categories on every route:
Accessibility — score < 50 →
critical; score < 90 →warningPerformance — score < 90 →
warningSEO — score < 90 →
warningBest Practices — score < 90 →
warning
Individual failing audit items (e.g., missing alt text, low contrast, render-blocking resources) are surfaced as separate findings alongside the category score.
Slack Channel Routing
Slack is optional. When
SLACK_BOT_TOKENis not set, Argus skips Slack entirely and auto-generates a localreport.html(all findings + inline screenshots) and opens it in the default browser. No Slack setup needed to start using Argus.
When Slack is configured, findings are routed by severity:
Severity | Channel | When |
|
| JS exceptions, HTTP 5xx, blank page, auth failure, API called 5+ times, Lighthouse accessibility < 50, auth token in storage/URL, responsive overflow, slow API > 3s, payload > 2MB, > 100 detached DOM nodes, CORS policy violations, |
|
| Visual regression > 0.5%, HTTP 4xx, CSS overrides with |
|
| Console warnings, unused CSS rules, API summaries, CSS Modules detection, empty data lists, responsive screenshot grid, missing cache headers on static assets |
Each message includes:
Severity badge + affected URL + timestamp
AI-generated description
Inline screenshot (uploaded directly to Slack — no external hosting)
View Page, Acknowledge, and Retest action buttons
Slack Slash Command Setup
To use /argus-retest from Slack, you need to expose the Argus server publicly.
Step 1 — Start the server
npm run serverServer runs on port 3001.
Step 2 — Expose with Cloudflare Tunnel
Download cloudflared (free, no account needed), then:
cloudflared tunnel --url http://localhost:3001Alternatively, with no install at all (SSH tunnel):
ssh -R 80:localhost:3001 nokey@localhost.runCopy the public HTTPS URL that appears.
Step 3 — Configure Slack App
api.slack.com/apps → BugBot → Slash Commands → Create New Command:
Command:
/argus-retestRequest URL:
https://your-public-url/slack/commandsDescription:
Run Argus regression test on a URLUsage hint:
<url>
Interactivity & Shortcuts → Enable → Request URL:
https://your-public-url/slack/interactionsOAuth & Permissions → Reinstall to Workspace
Step 4 — Test
/argus-retest http://localhost:3000BugBot should reply within 3 seconds with a "running" acknowledgement, then post results.
GitHub Actions CI Setup
Add secrets to your repository
Go to GitHub repo → Settings → Secrets and variables → Actions → add:
Secret name | Required | Value |
| No | Your |
| No* | From Slack App → Basic Information (only needed for |
| No* | Channel ID (required when Slack is configured) |
| No* | Channel ID (required when Slack is configured) |
| No* | Channel ID (required when Slack is configured) |
| Yes | Your staging base URL |
| No | For C2 PR integration — auto-injected by GitHub Actions as |
| No | For C2 PR integration — |
C2 PR integration: when
GITHUB_TOKENandGITHUB_REPOSITORYare set, Argus posts a PR comment and commit status check for every crawl.GITHUB_PR_NUMBERis injected automatically by the workflow fromgithub.event.pull_request.number. The included workflow does not wire these up by default — add them to theenv:block in.github/workflows/argus.ymlif you want PR-level comments.
The workflow at .github/workflows/argus.yml runs:
On every push to
main/masterDaily at 6 AM UTC (before the team starts work)
Manually via Actions → Run workflow (with optional URL override)
If critical issues are found, the pipeline fails — preventing silent regressions from being missed.
Project Structure
argus/
├── .env # Your secrets (never commit this)
├── .env.example # Template — copy to .env
├── .gitignore
├── package.json
├── README.md
├── .claude/
│ └── settings.json # Claude Code permission config (auto-approve node/npm/reports)
├── .github/
│ └── workflows/
│ └── argus.yml # CI pipeline
├── .vscode/
│ └── mcp.json # Chrome DevTools MCP config for VS Code
├── .mcp.json # Argus MCP server registration — exposes argus_audit/argus_audit_full/argus_compare/argus_last_report to Claude
├── src/
│ ├── argus.js # Single-page audit entry point
│ ├── batch-runner.js # Multi-page batch audit
│ ├── mcp-server.js # Argus MCP server — argus_audit / argus_audit_full / argus_compare / argus_last_report
│ ├── adapters/
│ │ └── browser.js # CdpBrowserAdapter — facade over all chrome-devtools-mcp calls
│ ├── domain/
│ │ └── finding.js # createFinding() factory — canonical finding shape
│ ├── registry.js # Analyzer plugin registry — registerExpensive/getCheap/getExpensive
│ ├── config/
│ │ ├── targets.js # Routes to test, thresholds, config
│ │ └── schema.js # Zod validation schema; validateConfig() called inside runCrawl()
│ ├── orchestration/
│ │ ├── crawl-and-report.js # Backward-compat re-export shell → orchestrator + report-processor + dispatcher
│ │ ├── orchestrator.js # Crawl loop, route/flow crawl, runCrawl()
│ │ ├── report-processor.js # Dedup → severity overrides → baseline → JSON write
│ │ ├── dispatcher.js # Slack / GitHub / HTML dispatch
│ │ ├── env-comparison.js # Dev vs staging diff + CSS analysis mode
│ │ ├── watch-mode.js # Passive browser monitoring (WatchSession + runWatchMode)
│ │ └── slack-notifier.js # Slack Block Kit dispatcher
│ ├── server/
│ │ ├── index.js # Express server (port 3001)
│ │ ├── slash-command-handler.js # /argus-retest handler
│ │ └── interaction-handler.js # Acknowledge + Retest button handler
│ ├── utils/
│ │ ├── css-analyzer.js # CSS analysis script injected into the browser
│ │ ├── seo-analyzer.js # SEO checks: meta, OG tags, h1, canonical, viewport
│ │ ├── security-analyzer.js # Security: localStorage tokens, eval(), headers, cookies
│ │ ├── content-analyzer.js # Content quality: null text, placeholders, broken images
│ │ ├── responsive-analyzer.js # Responsive: overflow + touch targets at 4 breakpoints
│ │ ├── memory-analyzer.js # Memory leaks: V8 heap snapshot + heap growth
│ │ ├── logger.js # Pino structured logger — childLogger(module)│ │ ├── retry.js # withRetry() exponential backoff — navigate/fill only; Number.isFinite guard│ │ ├── telemetry.js # OTel tracing + metrics — startSpan() / recordFinding() / recordFlaky() / recordNewFindings(); no-op default│ │ ├── session-manager.js # Auth: backward-compat re-export barrel│ │ ├── session-persistence.js # Auth: saveSession (mkdirSync+atomic write), restoreSession, hasSession, clearSession│ │ ├── login-orchestrator.js # Auth: runLoginFlow, refreshSession + lock file│ │ ├── baseline-manager.js # Baselines: loadBaseline, saveBaseline, applyBaseline, appendTrend
│ │ ├── flakiness-detector.js # Flakiness: mergeRunResults — confirmed vs flaky per double-crawl
│ │ ├── flow-runner.js # User flow assertions: runFlow / runAllFlows — assert DSL
│ │ ├── html-reporter.js # HTML dashboard: generateHtmlReport() + npm run report:html (D7.1 / D7.7)
│ │ ├── parallel-crawler.js # chunkArray sharding utility (ARGUS_CONCURRENCY=N parallel crawl)
│ │ ├── contract-validator.js # API contract validation: validateSchema, matchesContract (D7.4)
│ │ ├── severity-overrides.js # Severity policy overrides: applyOverrides (D7.5)
│ │ ├── slack-guard.js # Slack-optional guard: isSlackConfigured() (D7.7)
│ │ ├── hover-analyzer.js # Hover-state bug detection — aria-haspopup + data-tooltip (D8.1)
│ │ ├── snapshot-analyzer.js # Accessibility tree snapshot — missing names, labels, landmarks, heading hierarchy, ARIA state (D8.2 + v6)
│ │ ├── issues-analyzer.js # Chrome DevTools Issues panel — CSP/deprecated/cookie issues
│ │ ├── network-timing-analyzer.js # HAR timing analysis — slow third-party detection
│ │ ├── keyboard-analyzer.js # Keyboard Tab-walk — focus_visible_missing, focus_lost
│ │ ├── codebase-analyzer.js # Codebase cross-reference — env vars, feature flags, dead routes (C1)
│ │ ├── github-reporter.js # GitHub PR comment + commit status integration (C2)
│ │ ├── route-discoverer.js # Auto route discovery — sitemap + Next.js + React Router (C3)
│ │ ├── diff.js # pixelmatch screenshot + DOM/network diff utilities
│ │ ├── mcp-parsers.js # Text-format parsers for list_console_messages + list_network_requests (v9)
│ │ └── mcp-client.js # Headless JSON-RPC MCP client for CI mode
│ └── cli/
│ └── init.js # argus init setup wizard — detect framework, discover routes, write .env + targets.js (C4)
├── test/
│ └── unit/ # Vitest unit tests — no Chrome required
│ ├── finding.test.js # createFinding() — fields, throws, frozen, extra fields (8 tests)
│ ├── config-schema.test.js # validateConfig() + ConfigSchema.safeParse (8 tests)
│ ├── report-processor.test.js # deduplicateFindings + rebuildSummary (11 tests)
│ ├── flakiness-detector.test.js # findingKey normalization + mergeRunResults (13 tests)
│ ├── baseline-manager.test.js # loadBaseline/saveBaseline/applyBaseline (9 tests)
│ └── flow-runner.test.js # normalizeArray (pure) + runFlow mock browser (11 tests)
├── landing/ # Product landing page (React 18 + Vite + Tailwind + Framer Motion)
│ ├── src/
│ │ ├── App.jsx # Single-page app — hero, features, comparison, waitlist + enterprise modals
│ │ └── supabase.js # Supabase client factory (null-safe when env vars missing)
│ ├── public/
│ │ ├── favicon.svg # SVG favicon — purple ring + dot
│ │ ├── argus-poster.png # Video poster fallback (1918×1078)
│ │ ├── og-image-v2.jpg # OG social card — 1200×630 JPEG, branded overlay, black-outlined stat numbers
│ │ ├── robots.txt # Allows all crawlers; Sitemap reference
│ │ └── sitemap.xml # Canonical URL for argus-qa.com/
│ ├── index.html # Vite entry; OG/Twitter/JSON-LD SEO tags; canonical; favicon
│ ├── package.json
│ ├── .env.example # VITE_SUPABASE_URL + VITE_SUPABASE_ANON_KEY template
│ └── README.md # Setup guide, Supabase SQL schema, env vars, deployment
├── scripts/
│ └── dispatch-report.js # Standalone Slack re-dispatch script (re-posts last report.json to Slack)
├── test-harness/ # Fixture server + test runner (82 blocks, 348 hard assertions, 54 fixture pages)
│ ├── README.md
│ ├── server.js # Express fixture server (ports 3100 dev / 3101 staging)
│ ├── harness-config.js # Route definitions + expected findings
│ ├── validate.js # Test runner — 82 numbered blocks ([80] MCP server, [81] createFinding, [82] withRetry)
│ ├── pages/ # 54 fixture pages (one per detection category)
│ ├── nextjs-fixture/ # Next.js app structure for C3 discovery tests (10 files)
│ ├── source-fixture/ # Minimal app.js for C1 codebase-analyzer tests (env var audit)
│ └── static/
│ └── button-styles.css # BEM card selectors in button file → component leak
└── reports/ # Output: JSON reports + screenshots (gitignored)
├── baselines/
│ ├── <branch>.json # Per-route finding keys — per git branch (D7.2)
│ └── <branch>-trends.json # Append-only run history per branch (D7.2)
└── .gitkeepKey Technical Decisions
Decision | Choice | Reason |
Screenshot comparison | pixelmatch + AI classification | pixelmatch is fast and deterministic; Claude removes false positives from anti-aliasing and dynamic content |
Slack API | Bot API, not Incoming Webhooks | Bot API supports file uploads, message updates, interactive buttons, and threads |
File uploads |
|
|
CSS analysis | Script injected via | Runs in page context so it sees the live computed styles, CSS Modules hashes, and React fiber properties |
Responsive viewport |
|
|
Viewport width measurement |
| After |
V8 heap snapshot |
| The MCP tool writes JSON to disk (not inline); parse with |
Detached DOM detection | Walk flat | Chrome serializes detached elements as "Detached HTMLDivElement" etc.; secondary check on |
Baseline finding key |
| Excludes timestamps and dynamic URL path IDs; message truncated to 100 chars to handle slight wording variations; |
Baseline alert filter |
| Only findings explicitly marked new by |
Flakiness routing |
| Downgrading severity means existing |
Private | Each of | Avoids coupling two independently-useful modules via a shared export for a trivial 3-line function |
Runtime anti-pattern injection |
| Scripts registered this way run in the new page context before any page script — intercepts |
CORS error detection |
| CORS errors are generated by the browser itself, not by page JS — |
Long task detection |
| Only the duration is included in the finding message (not |
CI MCP client | JSON-RPC over stdio | In CI there's no Claude Code agent — the headless client replaces it with the same API surface |
Node.js | v20.19+ | Minimum required by Chrome DevTools MCP |
Known MCP Tool Limitations
The Chrome DevTools MCP behavioral constraints below cause 3 permanent test failures in the harness (345/348 pass). These are MCP-layer restrictions — they cannot be fixed in Argus code.
type_textclarification:type_textdoes fire DOMinputevents when the element is properly focused first withmcp.click({ uid }). Always use uid-based focus — passing{ selector }tomcp.clicksilently does nothing.
Tool | Constraint | Impact |
| Uses mouse simulation, not HTML5 DnD API |
|
| Issues panel returns empty even when violations exist | CSP and deprecated-API detection is unreliable |
These constraints are documented with workarounds in SKILL.md §10.
Environment Variables Reference
Variable | Required | Description |
| No |
|
| No* | Verifies slash command / interaction requests from Slack (required only when using |
| No* | Channel ID for critical bugs (required when Slack is configured) |
| No* | Channel ID for warnings (required when Slack is configured) |
| No* | Channel ID for info / daily digest (required when Slack is configured) |
| Yes | Base URL of your dev environment |
| No | Base URL of staging. If blank → CSS analysis mode |
| No | Pixel diff % to flag (default: |
| No | Where to write reports (default: |
| No | Number of parallel MCP clients for route crawling (default: |
| No | Server port (default: |
| No | Pino log level — |
| No | Set to |
| No | Max retry attempts for |
| No | OTLP collector endpoint — enables span/metric export to Jaeger, Grafana Tempo, Datadog, etc. |
| No | Set to |
| No | Watch mode poll interval in milliseconds (default: |
| No | Path to your app's source directory — enables codebase cross-reference (env var detection, feature flag leakage, dead routes) |
| No | Path to your app's |
| No | GitHub personal access token — required for PR comment + commit status integration |
| No | Repository in |
| No | Commit SHA for the commit status check — injected automatically by GitHub Actions ( |
| No | PR number for comment targeting — set via |
| No | Full URL to the hosted HTML report — linked from the GitHub commit status check |
Troubleshooting
Chrome DevTools MCP not connecting
claude mcp add chrome-devtools -- npx chrome-devtools-mcp@latest
# Then restart Claude CodeSlack messages not posting
Confirm
SLACK_BOT_TOKENstarts withxoxb-(notxoxp-,xoxe-, orxapp-)Verify BugBot is invited to each channel:
/invite @BugBotCheck token scopes:
chat:write,files:write,files:read
Screenshots not appearing in Slack messages
The upload uses a pre-signed URL that requires
PUT, notPOST— if you see a broken image, check that the Slack token hasfiles:writescope and the channel is correct
Slash command returns "dispatch_failed"
Your tunnel URL has changed (Cloudflare Tunnel / localhost.run URLs change on restart)
Update the Request URL in Slack App → Slash Commands and reinstall
CSS analysis returns empty results
Page may be behind auth — make sure you're logged in on the Chrome instance Argus is controlling
Cross-origin stylesheets (CDN fonts, third-party widgets) can't be read due to browser security restrictions — this is expected
Screenshots are blank
Page hasn't finished loading — increase
pageSettleMsinsrc/config/targets.jsAdd a
waitForselector for that route
CI pipeline fails immediately
Chrome may not be starting fast enough — increase the
sleep 3after Chrome launch tosleep 5in.github/workflows/argus.yml
How Argus Differs From Playwright / Cypress
Argus is not a replacement for unit or E2E tests. It's a complementary layer:
Playwright / Cypress | Argus | |
Tests | Your logic and API contracts | What the user actually sees |
Catches | Regression in behaviour | CSS drift, visual regressions, API redundancy, console noise, perf budgets |
Runs | In your test suite | Continuously, on the live running app |
Setup | Write test files | Configure routes in |
Output | Pass / fail | Structured Slack reports with screenshots and action buttons |
They complement each other — Argus catches what test suites miss.
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/ironclawdevs27/Argus'
If you have feedback or need assistance with the MCP directory API, please join our Discord server