Skip to main content
Two halves, and they are independent. Your agent needs the MCP server registered so the reticle_* tools exist. Your app needs the SDK so there is something for those tools to talk to. Do one and the tools appear but every call reports no session. Do the other and your app connects to a daemon nobody is asking questions. You want both. Take them in that order.
You only need this page for steps reticle init marked , or for an agent it doesn’t register automatically. It handles Claude Code and Cursor on its own.

Part 1. Register the MCP server

There is no config file that all agents share. Each harness has its own path and its own schema, so write only the one you actually use.

Claude Code

Register once, globally, and every project has it:
Confirm with claude mcp list. reticle should be there. If the claude CLI isn’t available, merge one key into mcpServers in ~/.claude.json. It is a large stateful file, so merge, never rewrite:

Cursor, VS Code, Windsurf

Same shape, different file and root key. Cursor and Windsurf use mcpServers; VS Code uses servers:

Codex CLI

TOML, in .codex/config.toml. This is the one init cannot write for you:

OpenCode

Note the flat command array and the required type:
Restart your agent afterwards. It read its server list at startup and nothing re-reads it. /mcp manages servers that are already loaded, so it cannot discover a new one. Restart Claude Code, reload the Cursor window, or press Start in .vscode/mcp.json.

Part 2. Wire the SDK into your app

Vite

That’s the whole web install. The plugin stamps source locations onto elements. The thing that turns a DOM node into src/components/Login.tsx:81. And injects connect() so you can’t forget it.

Anything without the plugin

If you’re not on Vite or Next, call connect() yourself, guarded so it never reaches production:
connect() is dev-only by design. Guard it with whatever your bundler gives you: import.meta.env.DEV, process.env.NODE_ENV !== 'production', or a build flag. Reticle also self-guards, but two locks on a door that leads to your users is a reasonable number.

Tauri. and the step whose failure is silent

The frontend is identical to any web app. The CSP is not optional:
Tauri’s default CSP blocks the bridge WebSocket before it opens. Your app runs perfectly and simply never connects, with no error to go on. Keep ipc: http://ipc.localhost in connect-src, Tauri v2 needs it for invoke itself. And drop the ws:// entries from your release config.
Screenshots and headless mode need the Rust crate, which is versioned independently of the npm packages:
IPC observation needs nothing on the Rust side. An invoke('load_todos') already reaches Reticle as ipc://load_todos.

Electron, and the rest of desktop

Main-process and renderer wiring, IPC observation, and what differs from the web install.

Part 3. Prove it

A session in the output means the app connected. That. Not a tick in a checklist, is the install finished. If it says nothing connected, the usual cause is a port disagreement between your app and the daemon. The browser console will name the exact port it tried; set it explicitly with VITE_RETICLE_WS_URL=ws://localhost:4400/reticle or reticle.connect({ url }). Still stuck? npx reticle doctor checks Chromium, the daemon and the port in one command.

Instrument your app

Register stores, signals and testids so your verdicts get stronger than “the DOM changed”.

Quickstart

Drive your first flow and read a real verdict.
Last modified on August 14, 2026