Skip to main content
reticle_state is not advertised. The default surface is the merged nine, so an agent does not see this name. Call reticle_look { action: "state" } instead. Everything below describes what that call does; only the spelling changed. A call to the old name is answered with the new one, but an allowedTools allowlist or an MCP permission rule naming it refuses before Reticle is asked.
reticle_state reads live framework state straight out of the running app, without the app broadcasting anything. Reach for it when the DOM looks right and you want to know whether the application actually accepted the change, which is where false greens live. The DOM tells you what the app drew. reticle_state tells you what it believes. The gap between those two is where false greens live: a row appears in the table, the store never changed, and a reload makes the row vanish.

Example

Real response:
depth: 2 collapsed the contents to size markers: {…30 keys} rather than thirty keys of JSON. On a large store this is the difference between a cheap look and a very expensive one.

Arguments

Drill in once you know what you want:
A wrong path comes back { "found": false, "availableKeys": [...] } rather than an empty value, so a typo is diagnosable instead of looking like an empty store.
reticle_state asks the page and waits. On a backgrounded tab the page may never answer, and you get "command 'state_read' timed out after 8000ms" with a recovery note pointing at reticle_sessions. That is a fact about the tab, not a Reticle failure. Bring it to the front, or drive your own browser.

You have to register stores first

reticle_state reads what your app registered in src/reticle-dev.ts. With nothing registered, storeNames comes back empty and this tool has nothing to say.
Pass the store, not () => store.getState(). The store form wires subscribe too, so every mutation emits a state diff. The getter form is read-only and silently produces empty diffs, which looks like “nothing changed” and is really “I was never watching”.
That distinction is the single most common instrumentation mistake, and its failure mode is a verdict that passes when it should not.

Why this is the strongest evidence you have

A POST returning 200 proves the server was reachable. A row in the DOM proves React rendered something. Neither proves your application accepted the change. State does. When reticle_act_and_wait reports
that is the app itself saying the login took. A mock that returns 200 without touching state gets caught right there, and nowhere else.

Instrument your app

Registering one store for your most important flow is the highest-value line you can write.
Last modified on September 18, 2026