复制安装命令
用 Codex 或 Claude 安装复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它先审查 Skill 页面再帮你安装。
复制前请先查看来源、License 和安全提示。
Your AI agent says "done." Reticle checks whether that's true.
用 Codex 或 Claude 安装复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它先审查 Skill 页面再帮你安装。
复制前请先查看来源、License 和安全提示。
来源文件:README.md
Your AI agent says "done." Reticle checks whether that's true.
It drives your real running app, reads what actually happened, and hands back pass · fail · couldn't tell with the file:line to fix.
Install · Use it · How it works · vs Playwright · Benchmarks · Limits · Docs
▶ Two minutes. An agent finds a bug the screen was hiding, and proves the fix.
Three steps. The first one is the whole install.
macOS · Linux
curl -fsSL https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.sh | sh
Windows (PowerShell)
irm https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.ps1 | iex
It puts reticle on your PATH and registers the MCP server with every coding agent it can reach: Claude Code, Cursor, Windsurf, VS Code, Zed, Gemini CLI, Copilot CLI, OpenCode, Warp, Kiro, Amazon Q, Cline, Amp, Continue and Factory Droid. Nothing is asked. Nothing is written outside your agent configs and ~/.reticle.
Codex CLI keeps a TOML config we don't rewrite, so the installer prints the four lines to paste and where they go. It tells you; it doesn't pretend.
That's it. The tools are already there, because the installer wrote the config before your agent started.
Run the installer first, in a terminal. A coding agent reads its MCP server list once at startup. Install while it's closed and there is nothing to restart. If it was already open, quit and reopen it once.
In your project, let your agent run:
RETICLE_INSTALL_SOURCE=readme npx @reticlehq/server init
Like npm init or git init, this is the per-project step. It installs the dev-only SDK, wires your build config, restarts your dev server, and then opens your app and proves a session connected. A config file is not an install, so init doesn't stop until it has seen your app.
Step 1 is once per machine. This step is once per project.
npx @reticlehq/server doctor
Or just ask your agent: "Is Reticle connected to my app?"
npm install -g @reticlehq/server # 1. the CLI
npx @reticlehq/server setup mcp # 2. register it with your agents
Step 2 registers the same agents as the installer, and writes the /reticle skill where the agent supports one. On Claude Code it also pre-approves the Reticle tools, so there is no Accept prompt on every call.
Any other MCP client: point it at npx @reticlehq/server mcp.
{ "mcpServers": { "reticle": { "command": "npx", "args": ["@reticlehq/server", "mcp"] } } }
Then continue at step 2 above: open your agent, and run npx @reticlehq/server init in your project.
The RETICLE_INSTALL_SOURCE prefix above is optional. It tells us which page somebody installed from, so we know which docs are working.
Requires Node 20.11+.
/plugin marketplace add reticlehq/reticle
/plugin install reticle@reticlehq
Registers the MCP server and installs the Reticle skill together. Reopen Claude Code once and the tools are there.
For other agents that support the skills CLI:
npx skills add reticlehq/reticle
You never write test syntax. You say what should be true, in plain English.
Verify what you just built
"I changed checkout. Verify it with Reticle before you tell me it's done."
Find what the screen is hiding
"The page looks fine but something's off. Use Reticle to check what's happening underneath."
Prove a bug is fixed
"Reproduce the bug with Reticle, fix it, then prove the fix with the same steps."
Lock a flow so it can't break
"Record the login flow with Reticle, then re-verify it after every change."
Sweep before you ship
"Walk the main routes with Reticle. Tell me anything broken."
Reticle answers with evidence: the request that fired, the state that changed, the console line, and the file to open.
Playwright, DevTools and browser agents all stand outside the browser looking in. For a site you don't own, that's right. For the app you're building, the bugs that matter never reach the pixels.
| Bug | Looks fine on screen? | Reticle reads |
|---|---|---|
Pay button silently returns 500 | yes | the network response, tied to the click |
Badge shows "12", the store holds 0 | yes | your app's state |
| The form fired the request twice | yes | request count |
| "Deploy succeeded", the deploy failed | yes | the store's real status |
| A console error slipped in | yes | the console since the action |
| Component re-renders 60×/sec | yes | the React commit stream |
Use both. Playwright for sites you don't own, many browsers, real pixels. Reticle for the app you're building, inside your agent's loop.
Your agent writes code, assumes it worked, and moves on. It never opens the app.
So the broken modal, the silent 500, the "Deploy succeeded" over a failed deploy: they all ship, and you find them by clicking around afterwards. You've become your agent's QA.
The truth was in the running app the whole time. It just never reached the screen.
This isn't something your agent forgot. A coding agent is built to produce a change, and it's optimistic by construction. Verification is the opposite motion: going to find out, and being willing to come back with no.
You: "Verify login works."
Agent, via Reticle: clicks Sign in →
POST /api/login → 200 (14 ms)→ dashboard rendered → store holdsauth: { email: "admin@…" }→ PASS, evidence attached.
flowchart LR
A["Your agent<br/>(Claude Code, Cursor…)"] -->|"look · act · observe · assert"| B(("Reticle"))
B <-->|"structured events,<br/>not pixels"| C["Your running app<br/>DOM · network · console<br/>store · React fiber"]
B -->|"verdict + evidence<br/>+ file:line"| A
style B fill:#8b7bff,stroke:#5b4bd0,color:#fff
style A fill:#15131f,stroke:#3a3550,color:#fff
style C fill:#1c2433,stroke:#2f3d57,color:#fff
One call checks many things at once. Say "save that as a flow" and it replays on every later edit with no model in the loop, so today's fix can't quietly break last week's feature.
// The agent clicked "Pay". Did the right things actually happen?
reticle_assert({
predicate: { allOf: [
{ kind: "net", method: "POST", urlContains: "/api/order", status: 200 },
{ kind: "element", query: { role: "dialog", name: "Order confirmed" }, state: "visible" },
{ kind: "signal", name: "order:saved" }, // the charge actually committed
{ kind: "console", level: "error", absent: true } // …and nothing errored
]}
})
// → { pass: false,
// failureReason: "POST /api/order returned 500, expected 200",
// source: { file: "src/checkout/PayButton.tsx", line: 42 } }
88 real regressions injected into a controlled app, Reticle against a Playwright script. Every number comes from a committed harness. Reproduce it with pnpm bench.
Re-verification has no model in the loop, so a recorded suite is a fixed, tiny read. Reticle is ahead from the second run even when charged a full LLM drive to author the suite.
Faster for a structural reason rather than a browser-speed one: a time-gated transition is verified from the event stream instead of waited out, and a batch of flows runs as a batch.
A verification tool that oversells its reach is worse than none.
| Strong | silent failed requests, state that disagrees with the screen, stale caches, double-submits, a write that failed while the UI moved on |
| Partial | races around a single action. It detects request-never-settled and duplicate-request; it is not a scheduler-level race analyser |
| Not the tool | cross-browser rendering, visual regressions, sites you don't own. That's Playwright |
| Can't see yet | IndexedDB, Web Workers, closed shadow roots, cross-origin iframes |
When Reticle can't see something, it says so. A verdict is yes, no, or unknown, where unknown means the evidence couldn't decide. Never a quiet pass.
Cost: zero bytes in production. The SDK sits behind import.meta.env.DEV and is dead-code eliminated; a runtime guard refuses to connect under NODE_ENV=production. No app data leaves your machine.
| Web | Next.js (App + Pages), Vite + React, CRA, SvelteKit, Svelte, Astro, Vue 3, Preact, plain HTML |
| Desktop | Electron, Tauri, including the IPC boundary a browser-only tool can't see |
| Agents | anything that speaks MCP. Config written automatically for Claude Code, Cursor, Windsurf, VS Code, Zed, Gemini CLI, Copilot CLI, OpenCode, Warp, Kiro, Amazon Q, Cline, Amp, Continue, Factory Droid. Codex CLI is a printed four-line paste |
| Browsers | Chrome, Edge, Arc, Brave, Opera, Firefox, Safari, plus Electron and Tauri webviews |
| State | zustand and Redux need no adapter. Shipped: TanStack Query, Jotai, XState, Valtio, MobX, Recoil, Svelte stores, Pinia |
| OS | macOS, Linux, Windows |
Routing verification flows with TypeSafe AI's Jev. A verification run makes a lot of small decisions — is this page settled, is this finding worth chasing, does this failure warrant a full capture — and today an LLM answers each one at LLM latency and LLM cost. Jev is a System One model: it returns a typed, probabilistic choice from a fixed set instead of prose, in 70–500ms. That is the exact shape of a routing decision inside Reticle's infra, so when we build that layer, Jev is what decides which flow a run takes. Nothing ships against it yet.
docs.reticle.sh — a page per tool, a page per command, every example captured from a real run.
Quickstart · Frameworks · Troubleshooting · Architecture · Contributing
Join the Discord → Where the work happens in the open: what's being built, what's up for grabs, and design calls before they land.
If Reticle proves useful, a ⭐ helps other developers find it.
SDK and adapters are Apache-2.0. The server is FSL (source-available, converts to Apache-2.0 after two years). See LICENSE.
dev-only · localhost-only · your app data stays local
name: verify-ui-change
description: Check that a change to a web app actually works in the running app before calling it done. Drives the real page and returns a pass/fail verdict with the request that fired, the state that moved, and the file:line to fix. Use after editing a component, a form, a route, or an API call; when you have said "fixed" but have not opened the app; when the user asks "does it actually work?"; or when a change looks right on screen and you cannot prove it.
license: Apache-2.0
metadata:
version: 3.1.0
homepage: https://www.reticle.sh
repository: https://github.com/reticlehq/reticleYou edited something a user can see. Nothing is proven until the real app has done it and something other than the DOM agrees.
This uses Reticle, which embeds a dev-only SDK in the user's running app and exposes it as reticle_* MCP tools. No screenshots, no browser download for the verify loop, no dev server of its own.
reticle_session({ action: "list" })
RETICLE_INSTALL_SOURCE=npx_skill npx @reticlehq/server@latest init, then keep going without the tools: fix every ⚠ it printed, start the project's own dev script in the background if nothing is serving the app, and open it with npx @reticlehq/server open <the url the dev server is serving>. Only once the app is running and connected, ask for the one thing you cannot do yourself: a client restart, so it picks up the MCP server. Stopping at the init command leaves the user with config files and an uninstrumented page. Full setup is in the install-and-verify skill.why field on the response. It distinguishes "no app running" from "an app is running that never dialled this daemon" from "a tab was here and closed", and each has a different fix. If no app is running, start the project's own dev script from package.json in the background yourself and tell the user in one line that it is running and how to stop it: never a second one, never a guessed command, never kill anything, and the permission prompt is your host's. If one IS running, the app is not the missing piece and the SDK is; do not send the user to start what they already started.This is the whole method. An expectation written after you see the result can be talked into agreeing with whatever happened; one written before cannot.
reticle_look({ action: "page", sessionId, mode: "interactive" }) // controls only, with refs
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "allOf", predicates: [
{ kind: "net", method: "POST", urlContains: "/api/...", status: 200 },
{ kind: "element", query: { testid: "..." } },
{ kind: "console", level: "error", absent: true },
]}})
Multi-step journey? Drive it in one call with reticle_act { steps: [...] }, then assert the outcome once. Do not act → snapshot → act → snapshot: it proves the same thing at several times the cost.
Only reticle_act_and_wait and reticle_assert produce a verdict. reticle_act, snapshot, query, navigate, network and console move or read the app and prove nothing. A drive that ends without one of the first two has no result, however many calls it made.
verified | means | do |
|---|---|---|
yes | the consequence you named happened | report it, with the evidence |
no | it did not happen, or a channel contradicted the UI | a real finding: report it with because |
unknown | Reticle drove the app and could not tell | not a pass. Say unknown and say why |
On unknown / unsettled, re-assert rather than re-driving: reticle_assert({ predicate, since, timeout_ms: 8000 }) using the since from the act result. Re-driving repeats a side effect that already happened.
Never weaken a check to turn a verdict green. An assertion edited until it passes proves nothing.
reticle_run({ tool: "reticle_verify", sessionId, args: { action: "coverage" } }) // { total, exercised, untouched }
If untouched still holds controls your change affects, the drive is unfinished. One call, and it is the cheapest guard against reporting a pass over the half you never opened.
State what you drove, what the verdict was, and the evidence: the request and status, the state that changed, the app's own signal. If something failed, reticle_look({ action: "element", sessionId, ref }) on the failing element gives the file:line: put it in the report.
Then reticle_session({ action: "yield", mode: "waiting" }) so the human's panel stops reading "live".
More detail, fetchable one page at a time: curl https://docs.reticle.sh/llms.txt for the index, then the single page you need (tools/act-and-wait.md, predicates.md, troubleshooting.md). If Reticle itself misbehaves, file it with reticle_session { action: "feedback" }: one call, then carry on.
评论 (0)
暂无评论,成为第一个评论者吧!