Skip to main content
Start with one command in your app’s folder: npx @reticlehq/server. It checks the running app with nothing installed and prints a verdict. Then npx @reticlehq/server init, once per project, connects your coding agent. The dashboard (reticle connect) is optional. No account is needed for steps 1 and 2. By the end of this page your agent will click a button in your app and prove what happened: the request that fired, the state that changed, and the file to open if it didn’t.
Every response on this page is real output, captured against a running app while writing it. Nothing here is illustrative.

Prerequisites

  • Node 20.11 or newer
  • A web app you can run locally, and its dev server
  • For step 2, a coding agent that speaks MCP (Claude Code, Cursor, Codex, OpenCode, Windsurf, VS Code)

Step 1. Check your app, with nothing installed

In your app’s folder:
It finds your app’s dev server. If the app does not run, it starts the dev script, and it stops that server at the end. It opens the app in a Reticle browser and installs nothing in your app. It checks that the page loads, that there is no console error and no failed request, and that each same-origin link opens (8 at most). On a small app with two links, it printed:
Then the verdict line, verified: yes with the URL it checked, and the next step, npx @reticlehq/server init. A fault gives verified: no, and one ✗ line for each fault, for example ✗ Failed request on /broken: GET http://localhost:58473/api/missing: HTTP 404. The command exits 0 only on yes. When the app sends the page to a sign-in page, Reticle verifies up to there and says so.
Not in the app’s folder? It checks the one dev server that runs on this computer. When several run, it names them and does not choose. In a folder that init already wired, the same command starts the Reticle server (reticle serve) instead.

Step 2. Connect your coding agent

In the same folder, before you open your coding agent, run the command that step 1 printed:
This installs the dev-only SDK, wires your build config, and registers Reticle with every coding agent it finds on this machine. Then it starts the dev server and checks that a browser session connected. Nothing from your project leaves your machine. If your dev server was already running, restart it once and hard-reload the tab: it read your build config before init edited it. Open your coding agent once this command finishes. If it was open while init ran, restart it once: a coding agent reads its MCP server list only when it starts. The RETICLE_INSTALL_SOURCE prefix is optional and only tells us which page you installed from. It is idempotent: run it twice and the second run reports what was already done rather than doing it again. This step is once per project. Skipping it is a common reason Reticle “does nothing”: the agent has no tools, or no app on the other end for them to see.
Skipped this step? Ask your agent to verify something in the app. Its first reticle_session call finds a project that has never connected and changes no file. It names the zero-install lease, which checks the running app now with nothing installed, and it tells the agent to ask you before it runs init. This works in Claude Code, Codex, Cursor and other MCP agents, including a second project while Reticle is already running for another one.
Useful flags for the local-only reticle init path:
Start with reticle init --dry-run if you want to see the app changes before anything is written.
In a monorepo, init run at the root lists every app it found, each with its own reticle init --app <dir> line, and stops. Run the line for the app you want: it writes that app’s files and starts nothing (add --start to boot it). With only one app, it wires that one without asking.
Prefer to wire it yourself? See Manual install. It is about ten lines, and worth reading once even if you let the agent do it, because it explains what the agent actually changed.

Other ways to connect your agent

On Claude Code, the plugin registers the MCP server and the skill in one step. Type /reload-plugins after the install and the tools load in the open session:
On Cursor, Codex, Copilot, Gemini and anything else the skills CLI supports, add the skill, then type /reticle and the agent runs the setup from the skill:
The installer puts reticle on your PATH once per machine and registers the MCP server with every coding agent it can reach: Claude Code, Cursor, Windsurf, VS Code, Zed, Gemini CLI, Copilot CLI, OpenCode, Antigravity, Warp, Kiro, Amazon Q, Cline, Roo Code, Amp, Continue and Factory Droid. It asks no questions and does not wire your app. Run it before you open your coding agent:
Prefer not to pipe a script into a shell? The same result by hand:
Codex CLI keeps a TOML config. With the codex command installed, the installer registers Reticle through codex mcp add. Without it, the installer prints the lines to paste and the file to paste them into. Reticle then adds one line, default_tools_approval_mode = "approve", under [mcp_servers.reticle] in ~/.codex/config.toml. This line approves Reticle’s own tools, so Codex does not ask before each call. Reticle changes no other line, and it keeps a mode that you set. To undo it, change that line to default_tools_approval_mode = "prompt". Reticle does not change a mode that is already there.

Step 3. Connect the dashboard (optional)

Skip this if you only want local verdicts. Everything above works without an account.
connect runs Step 2 first if this project isn’t wired yet, so you can use it in place of init. Then it:
  1. Opens a browser so you can sign in, or create a free account at app.reticle.sh. Approve the short code shown in the browser and in the terminal, and the command carries on by itself.
  2. Links this folder to the cloud project you named, creating it if it doesn’t exist. npx @reticlehq/server status shows the link.
  3. Sends the runs and flows already on this machine.
After that, every verified run syncs on its own. To sync right now, for example before showing a teammate:
A new account gets free credits to try the Harness. What syncs, and how to switch each part off (reticle config --runs/--memory/--flows on|off), is in What is recorded. In CI, set RETICLE_API_KEY instead of signing in.

Step 4. Check the setup

doctor diagnoses the whole setup in one command: Chromium, the daemon, the port. If something is wrong this is the page you want before you start debugging your app instead.

Step 5. Open your app again when you need it

init (or connect) already started the dev server and opened the app. On a later day, start your dev server as usual, then:
This reuses the tab you already have open, or opens one if you don’t. The SDK connects to the local daemon over a WebSocket, and your agent can now see the app.
If the browser console says [Reticle] this page could not open a websocket to …, your app and the daemon disagree about the port. Set it explicitly: RETICLE_PORT=4400 pnpm dev (Vite plugin), reticle({ port: 4400 }) in vite.config, or reticle.connect({ url: 'ws://localhost:4400/reticle' }) by hand. The console message names the exact address it tried.

Step 6. Look at the page

Ask your agent to take a snapshot. This is what came back from a real app:
Three things to notice. The password is already [REDACTED]. Reticle redacts credential-shaped values before they leave the page, so your agent’s context never holds your test password, let alone your real one. The whole snapshot cost 61 tokens. This is mode: "interactive", which returns only the controls. A full accessibility-tree dump of a comparable page runs to thousands. Reticle is built to ask narrow questions, because the answer gets re-sent to the model on every turn. Each control has a ref like e5. That’s the handle for the next step, and it stays valid until the element leaves the DOM, so you don’t re-snapshot between actions.

Step 7. Act, and prove it

Here is the whole idea of Reticle in one call. Your agent names the expected consequence before it acts:
Stating the expectation up front is the difference between a check and a rationalisation. An agent that clicks first and then decides what counts as success will always find something that counts. The real response, trimmed for length:
A real act_and_wait verdict, annotated. The verdict, the source pointer, the request evidence, the request count, the state diff, and the app's own signal Read what that actually proves:

What “verified” can say

yes

The consequence you named actually happened, and the evidence is attached.

no

It did not happen. This is a finding, with the source pointer to go fix it.

unknown

Reticle drove the app and could not tell. This is not a pass. Report it as unknown.

no-fault

Nothing was declared to prove, so nothing was checked. Not a pass either: add an until.
That third state is the one that matters. Most tools have two outcomes and quietly file “I couldn’t tell” under “fine”. A verification layer that cannot admit uncertainty is just a very confident random number generator.

Frequently asked questions

Two commands in your app’s folder. npx @reticlehq/server gives a first verdict with nothing installed. Then npx @reticlehq/server init wires the project, registers Reticle with every coding agent on the machine, starts your dev server and opens the app for you. Run them before you open your agent, and it needs no restart. For most agents the MCP registration is global, so a later project starts with the tools already there.
No. You talk to your agent in plain language and it calls the tools. There is no spec file, no selector language and no test runner involved in the loop on this page. If you later want the same flow to block a bad merge, you can save it and run it in CI, but that is a separate step.
No, not unless you add it on purpose. The SDK is dev-only. A production vite build with the Vite plugin injects nothing and replaces the SDK with an inert stub, and connect() disables itself when the build reports NODE_ENV=production. The recommended wiring also guards the call behind import.meta.env.DEV, so there are two independent locks. The one exception is Production mode: you add its loader to your production build yourself, and it loads nothing until a signed ticket activates it.
Not unless you link a project. The daemon runs on your machine and the SDK runs in your browser. Nothing from your app leaves the machine until you link a project (reticle connect, or RETICLE_API_KEY in CI). After that, what syncs is set by reticle config, and when the Harness drives, the platform sees the steps it drives. Secret values never leave. Anonymous product analytics are sent unless you opt out with npx @reticlehq/server telemetry disable, and they never include your code or your app’s data.
The core is framework-neutral, so DOM, network, console, routing and source mapping work anywhere JavaScript runs. What varies is how connect() gets into your app and whether you get component identity on top. See Frameworks for the exact wiring per stack and an honest table of what is gated in CI versus wired but unverified.
Run npx @reticlehq/server doctor. If it shows the daemon running but sessions at zero, your app is not reaching the bridge, and the usual cause is a port mismatch. The bridge port is not your dev-server port. See Troubleshooting.

Where to go next

Instrument your app

Emit signals like auth:granted so your verdicts get stronger than “the DOM changed”.

Every tool

The 10 tools your agent sees by default, and the rest it reaches through reticle_tools and reticle_run.

Run it in CI

Turn this session into a suite that blocks a bad merge.

Why Reticle

The false-green problem, and the measured case that this fixes it.
Last modified on October 29, 2026