Install Arguseye for your agent or editor
Everything runs through one MCP server: npx @ayushniroula/arguseye mcp (started in the project directory, or with --root <dir>). The install command writes the server entry and the skill where each client reads them; it merges into existing config and can be run again safely.
npx @ayushniroula/arguseye install all # every client below
npx @ayushniroula/arguseye install claude # one client
npx @ayushniroula/arguseye install codex --project /path/to/app --dry-run
| Client | What install writes |
Alternative |
|---|---|---|
| Claude Code | .mcp.json in the project; skill in ~/.claude/skills/arguseye |
claude mcp add arguseye -- npx -y @ayushniroula/arguseye mcp, or the plugin: claude plugin marketplace add DarkWorldCoder/arguseye then claude plugin install arguseye |
| Codex | [mcp_servers.arguseye] in ~/.codex/config.toml; skill in ~/.agents/skills/arguseye |
codex mcp add arguseye -- npx -y @ayushniroula/arguseye mcp |
| Gemini CLI | mcpServers.arguseye in .gemini/settings.json; skill in .gemini/skills/arguseye |
gemini mcp add arguseye npx -y @ayushniroula/arguseye mcp --root . |
| Cursor | ~/.cursor/mcp.json; skill in .cursor/skills/arguseye |
Settings → MCP → add the JSON |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
|
| VS Code (Copilot agent mode) | .vscode/mcp.json (servers) |
|
| Antigravity (CLI and IDE) | .agents/mcp_config.json and .agents/skills/arguseye in the workspace |
plugin: agy plugin install https://github.com/DarkWorldCoder/arguseye |
Prerequisites
Use Node.js 22 or later and install the dependencies in the project you want to preview. Headless renders need a Playwright-compatible Chromium browser or Google Chrome. If neither is available, install Chromium:
npx playwright install chromium
Vue projects use their own Vue 3 runtime and vue/compiler-sfc. Server-only Next.js behavior and Nuxt application context are outside the isolated runtime.
VS Code extension (the human panel)
Marketplace listing: Arguseye. Compatible editors can install a platform-specific VSIX; an Open VSX release has not been verified. To install a local build: npm run package then code --install-extension arguseye-*.vsix.
Skill only (no MCP)
The skill at skills/arguseye/SKILL.md follows the Agent Skills format and also works on its own: it tells the agent to use the CLI (npx @ayushniroula/arguseye shot …) when the MCP tools are not available. Copy it to ~/.claude/skills/, ~/.agents/skills/ or .cursor/skills/.
Verified end to end
Checked on 2026-10-29 against the React fixture, each agent calling render_component through the MCP server and reading back the image, the accessibility tree and errors[]:
| Agent | Result | Note |
|---|---|---|
Claude Code (claude -p … --mcp-config) |
works | allow the tools with --allowedTools "mcp__arguseye__*" in headless runs |
Codex (codex exec) |
works | non-interactive runs need --approve-for-me (or an interactive session) because MCP tool calls ask for approval; -a never refuses them |
| Gemini CLI | config written, not run | the Gemini CLI on the test machine required an Antigravity account |
Product: why Arguseye exists
Arguseye is eyes for coding agents and developers: see a component, change it, and inspect the consequences without starting the application or writing stories.
What is implemented
- Your actual React/Next.js browser component or Vue 3 SFC, using the project's packages and Chromium.
- Literal props from real JSX and Vue template usages, including aliases and local barrel re-exports. Runtime values remain explicitly unresolved.
- Global styles, Tailwind v3/v4, PostCSS, Sass, CSS modules, assets, and statically reconstructable layout wrappers. Incomplete context is reported.
- Warm browser pages and per-module compilation. Unsaved editor buffers update the live page; React refresh and Vue template/style updates preserve state. Vue script edits reset state with a warning.
- MCP and CLI render evidence: PNG, accessibility snapshot, resolved inputs, source fingerprint, timing, warnings and errors. Responses can omit images.
- Immutable baselines and before/after comparisons of pixels, dimensions, accessibility snapshots and errors. Comparisons report change or incomplete evidence, never automatic correctness.
- Paginated usage rendering, with a maximum of 12 isolated variants per batch and an incremental source index.
- A VS Code panel with export/usage selection, typed React prop controls, viewport presets, capture and comparison controls. Verification uses the shared renderer and unsaved source.
- Imported root Next Google font variables can reuse matching cached font faces from the project’s
.next/staticbuild. Missing font assets remain unresolved; fonts are not downloaded or compiled.
Product constraints
Warm render p95 must stay at or below 100 ms over 20 measured renders on a documented machine. The edit-to-pixels target is 50 ms; current live-edit tests enforce a looser 100 ms bound. New work on either path needs a timing assertion.
App modules are transformed with oxc; Vue SFCs use the project's matching compiler. Dependencies are pre-bundled by Rolldown. CSS processing uses the project's toolchain and Lightning CSS where appropriate. Browser pages stay warm. Chromium provides the rendering engine; the VS Code webview is the interactive human view.
Render failures return errors: string[]. Invalid IDs and inputs name the offending value. Source fingerprints describe files read by this preview session, not the whole application's external state. Successful rendering can still be incomplete because of runtime props, provider gaps, or unsettled assets.
Where this competes
Storybook's MCP exposes component discovery, previews and testing. Playwright MCP provides browser interaction, snapshots and screenshots. Preview.js established the instant editor-preview workflow. MCP support or unsaved previewing alone is not a unique claim.
Our focus is the combination of direct source rendering, discovered usage inputs, low-latency local feedback, compact evidence, and edit verification without authored stories or an application server. These are product goals to validate against real projects, not claims of universal compatibility or competitive superiority.
References checked on 2026-10-27:
- https://storybook.js.org/docs/ai/mcp/api
- https://playwright.dev/docs/getting-started-mcp
- https://previewjs.com/docs/faq
- https://vuejs.org/guide/scaling-up/tooling.html#lower-level-packages
Validation and next boundaries
npm test covers server HTTP, updates/timing, headless rendering, MCP contracts and installed fixtures. npm run test:vscode checks the panel workflow in the real extension host. npm run benchmark records the same fixture-edit task through our MCP and Playwright MCP plus Vite. Raw results and limitations live in benchmarks/latest.json; no fixed speedup or token saving is promised.
The MVP is local. Next.js server execution, Nuxt application context, arbitrary provider reconstruction, backend/auth-dependent states, agent interaction scripting, cloud review and team dashboards remain outside this release. See README.md for the exact compatibility limits and setup commands.
State (2026-10-29)
Added: render inside the call site's parent box (list_usages context, render_component in_context, frame), states before capture (actions, storage), function props ($fn), NEXT_PUBLIC_* env, Next app-router previews on Next's vendored React canary, settled-frame capture (fonts, images). Verified on WiseAdmit: Footer, Navbar and the 641-line AIEcosystem section render with no errors. Cold starts on a large provider chain are 7–32 s per new package set: next is a one-time project-wide package warm-up at server start, then automatic changes on re-render, layout facts with refs, element→source. See docs/agent-wishlist.md.
Performance (2026-10-29, WiseAdmit latest-front, 1,197 files)
Before: warm-up 32 s and skipped, first render 11–13 s, server 1.8–2.8 GB. After: ready 2–11 s, first render 1.5 s, section 0.9 s, warm 0.3 s, server ~500–750 MB. Levers: crawl once per file version, bundle worker process, cjs-module-lexer, package CSS inlined, minified bundles, modulepreload graph, route page pre-warm, usage index in warm-up, barrel rewrite, eager lazy images. Still open: server memory (transform cache + usage index + bundles in memory), V8 code cache via a persistent browser profile, HTTP/2 for module fetches.
Mirror rendering: how Arguseye shows a component as the app shows it
No dev server, no stories, no mocks. The technique has five parts; each is ours, and together they are what no other tool does. The pixels come from Chromium, on purpose: "exactly as in the app" is only true when the same engine draws it.
1. Real props from the code that already exists
Every JSX call site of the component is found by parsing the project (oxc), following imports and barrel re-exports back to the file. Literal props are read as values; props that depend on runtime data are reported as "unresolved" text. The first call site with props is what the preview shows by default, so the component appears the way the app already uses it. When nothing uses it yet, the TypeScript parameter type is read (aliases, interfaces with extends, imported types, enums, nested objects, defaults from destructuring) and sample props are made for the required ones.
2. The app's context, reconstructed statically
The root layout (app/layout.tsx, pages/_app.tsx, src/main.tsx) is parsed once: its global stylesheets, <html>/<body> classes, and the chain of providers around {children} with the literal props the layout passes. A generated wrapper module nests the component inside that same chain, so themes, contexts, fonts and host elements match. Stylesheets are compiled the way the app's bundler would: Sass, then the project's own Tailwind (v4 directly with its theme, v3 through its PostCSS config), then CSS modules via Lightning CSS. Framework modules that cannot run outside the app (next/link, next/image, next/navigation) are replaced by shims that render Next's markup.
3. One build, one React
Project files are transformed one module at a time (oxc, about 1 ms each) and served as native ES modules. Packages are bundled once by Rolldown from the project's own node_modules into shared chunks and cached on disk by package set, lockfile and bundler version. Before the first paint, the component's import graph and the providers' are crawled so every package is in that single build; if a later edit introduces a new package, the build generation changes and the page reloads instead of mixing two copies of React. ESM-or-CommonJS is decided from the file the bundler actually uses, and Node built-ins become empty modules.
4. A warm page that swaps targets
The preview page stays open. A new component, new props or a new usage is swapped in with show(target), not a navigation. Unsaved editor buffers overlay the disk; an edit re-transforms only that file and React Fast Refresh swaps the component in place, so its state survives (about 35 ms from keystroke to pixels). CSS edits re-apply their <style>. Files changed on disk by an agent are picked up by comparing served mtimes before each render.
5. The settled frame, cheaply
For agents, the capture is the DevTools protocol directly: a clip to the component's box, transitions ended, finite animations jumped to their end state, caret hidden, and the screenshot and accessibility snapshot taken in parallel (about 40 ms warm). The result is token-cheap: a cropped PNG, a text tree, and errors[] with real file paths, including the server's reason when a module could not be served.
Measured component-edit workflow
Run npm run benchmark after installing the root and React fixture dependencies. The script copies the installed fixture into temporary projects and uses real stdio MCP clients. Source edits never touch the fixture itself. Raw results are in latest.json.
The task is to capture ProductCard with title Desk and price 3, edit its button label, and inspect the rendered result. Playwright receives a minimal Vite app with a known URL and no login. Arguseye renders the source directly and also returns an automated pixel/semantic comparison.
Result: 2026-10-27
Linux x64; Intel Core i5-1235U; 12 logical CPUs; Node v24.21.0. All four workflows verified the expected result.
| Workflow | Tool calls | Startup | Workflow | Total | Response bytes |
|---|---|---|---|---|---|
| Arguseye, cold | 2 | 1,172 ms | 933 ms | 2,105 ms | 49,076 |
| Playwright MCP + Vite, cold | 6 | 576 ms | 1,128 ms | 1,704 ms | 28,006 |
| Arguseye, warm | 2 | 0 ms | 145 ms | 145 ms | 48,669 |
| Playwright MCP + Vite, warm | 4 | 0 ms | 217 ms | 217 ms | 27,298 |
Arguseye returned four images across the two calls: initial capture, before, after, and highlighted changes. Playwright returned two component screenshots. The response sizes therefore compare different evidence bundles. Both workflows included accessibility text; Arguseye also included structured provenance and comparison metadata.
Twenty additional warm Arguseye renders measured p95 50 ms against the 100 ms gate. Every sample is retained in the JSON result.
This run shows fewer tool calls and a shorter warm workflow, alongside larger default responses and a slower total cold path. It does not establish a general performance ranking. Cold means a fresh process/browser, with packages installed and OS caches potentially warm. Text-token estimates use characters/4, include text blocks and structured JSON, and exclude image tokens. No LLM reasoning, model billing, login journey, or full Next.js startup was measured. Summary-only output is available but was not used for these workflow measurements.
If I were the agent: what I'd want from this tool
Written from the point of view of a coding agent that just edited a component and has one tool call to spend.
1. "Did my change look right?" in one call
After an edit, calling render_component again should tell me what changed, without me keeping baseline ids: changed-pixel ratio, the regions that changed, and a text diff of the accessibility tree. render_diff with a captureId exists; the automatic version (changes on every re-render of the same target) is the ergonomic one.
2. The state I care about, not the default one
A dropdown closed, a form empty, a card not hovered: that is rarely the state I'm fixing. I want actions before capture (click, hover, fill, press, scroll, wait) addressed by role/text/ref, plus storage/cookies for logged-in or feature-flagged states, viewport, colorScheme and prefersReducedMotion, all in the same call.
3. The box it lives in
A component alone on white lies: width, height and background come from the parent. in_context renders inside the call site's ancestors; frame is the stand-in when there is no usage yet.
4. Layout facts as text
Pixels cost tokens and I can't measure them. I want [ref=e3] button "Add" 120×36 at (24,180), and flags I would otherwise miss: text truncated, element overflowing its parent, zero-size element, low contrast, image failed to load.
5. From pixel to file
inspect ref returning in ProductCard (components/ProductCard.tsx:19) and the computed styles that matter, so a wrong margin becomes a line to change.
6. Errors that say what to do
Cannot resolve "./Icon" from components/Card.tsx with the file and the line, missing NEXT_PUBLIC_X, a provider that threw: each with the fix it suggests, not a browser's "failed to fetch".
7. Every usage, only the ones that differ
After a change to a shared component, render it at every call site but group identical outcomes, and show pixels changed per usage, so the blast radius is three lines, not twelve screenshots.
8. Captures I can trust to diff
Fonts loaded, images loaded, animations settled (done), and also Date.now and Math.random frozen, so "changed" means my edit changed it.
9. Speed that lets me iterate
Warm renders under 50 ms (done) and a cold start under a second, with the server living across tool calls (done).
10. The tool telling me the next step
"3 usages exist, 2 with runtime props; call render_usages" or "required prop price missing; describe_props lists it". Hints in results, so I don't have to remember the tool surface.
Order of building: 2 (actions + storage) and 1 (automatic changes) first, then 4 and 5 (facts and source), then 8, 7, 10.
Arguseye
Render component source in Chromium with the project's packages, styles, assets and statically reconstructable layouts. Inspect a cropped PNG, accessibility snapshot, resolved inputs, warnings and errors. The application server and authored stories are unnecessary; project dependencies and a compatible Chromium browser are still required. Startup and warm render times vary with the project; read the returned timings.
When to use it
- After editing a component: render it again; the result says what changed (
changes) since the last render of the same target. - For a shared component: inspect relevant call-site variants with
render_usages, following pagination when broader coverage is needed. Useusageplusin_context: trueto reconstruct its parent elements. - When a component needs a state: pass
actions(click, hover, fill, press, scroll, wait) andstorage(localStorage/sessionStorage flags). Storage seeds do not reconstruct a backend or an authenticated application journey. - When a component has no usage yet:
describe_propsgives the schema and sample props;framegives it a parent box of a chosen size and background.
Tools (MCP server arguseye)
| Tool | Use |
|---|---|
render_component {file, export?, usage?, props?, viewport?, in_context?, frame?, actions?, storage?, output?} |
Render with a discovered usage or explicit props. viewport: mobile, tablet, desktop or WxH. Without supplied inputs, required props may be generated from TypeScript samples. |
list_usages {file, export?} |
Every call site with literal props, unresolved runtime props, and the JSX ancestors (context). |
render_usages {file, export?, viewport?, cursor?, limit?, output?} |
A page of isolated literal-prop variants, not full-page integration tests. limit is 1–12; pass the returned nextCursor as cursor until it is null. |
describe_props {file, export?} |
Props from the TypeScript type, with sample values. |
render_diff {baselineId, output?} |
Compare current code with a successful render's captureId, reusing resolved props and viewport. Returns before/after/highlighted images and change evidence. |
Function props are passed as { "$fn": "(x) => ..." }. Paths are relative to the project root the server was started with.
For render tools, output is "image", "summary" or "both" (default). Use summary for a compact text response, image for visual inspection, or both when needed. Structured evidence remains available separately from image bytes.
Reading a result
errors[]are real: a resolve error names the import and the importer; a render error carries the component stack. Fix them before trusting the pixels.- Read
warnings[],unresolved[],propsSourceandcompletebefore trusting context. Generated samples are not real application data; provider gaps, runtime values or unsettled assets can make a successful render incomplete. changesand explicit diffs reportunchanged,changedorincomplete, with pixel, accessibility and error evidence. None of these establishes that the intended behavior is correct.timings(prepare, show, settle, capture) tell you whether a slow render is loading, rendering or waiting for images.layoutsAppliedandcontextAppliedlist the layouts/templates and the call-site ancestors the component was wrapped in.sourceRevisionfingerprints files read by this preview session, not the whole application's external state or a Git commit.
Baselines and comparison limits
Successful renders return an immutable captureId. The renderer retains the latest 64 captures per session; restarting the server or eviction makes an old ID unavailable. Capture again when the error names an unknown or expired baseline.
An explicit render_diff reuses the file, export, resolved props and viewport. It does not replay actions, storage, frame or call-site parent context. For stateful/contextual comparisons, render again with the same explicit inputs and inspect changes; do not assume a saved baseline restores the live editor's interaction state. Next.js server execution, Nuxt context and arbitrary runtime providers require the application environment.
Without MCP (CLI)
npx @ayushniroula/arguseye shot src/components/Card.tsx --export Card --usage app/page.tsx:12 --in-context --out card.png
npx @ayushniroula/arguseye usages src/components/Card.tsx --export Card
npx @ayushniroula/arguseye serve src/components/Card.tsx --export Card --port 4321
Use shot --json for structured metadata and --output summary to omit the ordinary PNG output. CLI baselines survive separate commands when explicitly saved in a chosen directory:
npx @ayushniroula/arguseye shot src/components/Card.tsx --export Card --capture-dir /tmp/arguseye-before --json --output summary
# Edit the component in the same project, then compare:
npx @ayushniroula/arguseye diff --baseline /tmp/arguseye-before --out /tmp/arguseye-diff --json
The baseline directory contains capture.json and capture.png; comparison writes before.png, after.png, diff.png and diff.json. The same replay limits apply to saved CLI baselines.
Workflow
list_usagesfor the component you changed.render_componentwith the first usage andin_context: true; readerrors, then the snapshot, then the PNG.- Edit; render the same target again and read
changes. - Inspect relevant
render_usagespages when the component is shared; report incomplete context and the variants actually checked.
Contributing to Arguseye
Thanks for helping agents see. This page is the short version; the rules every change follows are in AGENTS.md (they apply to humans too).
Set up
git clone https://github.com/DarkWorldCoder/arguseye && cd arguseye
npm install
for d in test/fixtures/*/; do (cd "$d" && npm install); done
npx playwright-core install chromium-headless-shell # or have Chrome installed
npm test # unit + headless browser tests
npm run test:vscode # the panel in a real VS Code (downloads one on first run)
Node 22 or newer. Linux, macOS and Windows should all work; the native pieces (oxc, Rolldown, Lightning CSS) ship binaries for each.
How changes land
- Open an issue first for anything bigger than a fix, so the approach is agreed before code.
- Work test-first at one of the agreed seams (preview server HTTP, update timing, headless render, MCP contract, VS Code suite). A failing test comes before the code that makes it pass.
- Keep the speed budgets: a warm render stays under 100 ms in the test, and anything on the per-render or per-keystroke path ships with a timing assertion.
- Fidelity first: render the user's real code with the user's real packages. Shims are for framework modules that cannot run outside the app, and they mirror the real module's exports.
- One slice per pull request,
npm testandnpm run typecheckgreen, a one-line commit message saying what the user gets.
Good first contributions
- A framework shim that is missing (
next/font,next/script, Vue router stubs). - A barrel package to add to the per-member import rewrite.
- A fixture app that reproduces a styling setup we don't cover yet (CSS-in-JS libraries, Less, UnoCSS).
- Items from docs/agent-wishlist.md: layout facts with refs, element → source, a frozen clock for deterministic diffs.
Reporting a bug
Use the bug template. The most useful report includes the component file, how it is used (list_usages output), the errors[] and warnings[] from the render result, and the framework versions from your package.json.
Security
Arguseye runs your project's code in a local Chromium and starts a local HTTP server bound to 127.0.0.1. It never sends your code anywhere. Rendering a component executes that component and its imports, so treat untrusted repositories as you would when running their dev server.
Reporting a vulnerability
Please do not open a public issue. Email tech@wiseadmit.io with the details and, if possible, a reproduction. You will get an acknowledgement within three working days and a fix or mitigation plan as soon as the issue is confirmed. Credit is given in the release notes unless you prefer otherwise.
Scope
In scope: the arguseye npm package (MCP server, CLI, preview server), the VS Code extension, and the skill and plugin manifests in this repository. Out of scope: vulnerabilities in the frameworks or packages of the project being previewed.
Code of Conduct
Everyone taking part in this project, in issues, pull requests, discussions and reviews, agrees to:
- Be direct and kind. Critique code and ideas, never people.
- Assume good intent, and ask before concluding.
- Welcome newcomers and the questions that come with them.
- Keep private information private.
Harassment, personal attacks, discriminatory remarks and sustained disruption are not accepted. The maintainers may edit or remove contributions and may block repeat offenders. Report concerns to the maintainer at tech@wiseadmit.io; reports are handled confidentially.
This policy is adapted from the Contributor Covenant, version 2.1.
MIT License
Copyright (c) 2026 Ayush Niroula
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.