> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reticle.sh/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Reticle is a dev-only, localhost-only verification layer for AI coding agents. It reads program truth (network, state, console, routing, animations, framework state) from inside a running web app and returns a deterministic verdict with evidence. It is not a screenshot tool and not a browser automation library.
> Only `reticle_act_and_wait` and `reticle_assert` produce a verdict. Every other tool moves or reads the app and proves nothing. A drive that ends without one of those two has no result, however many tools it used.
> A verdict of `verified: "unknown"` is not a pass. It means Reticle drove the app and could not tell what happened. Report it as unknown; never weaken a check to make it pass.
> Package names are scoped `@reticlehq/*` and the CLI is `reticle`. Install with `npx reticle init`. The complete tool surface is on the `/usage` page; `/agent-cheatsheet` is the one-screen version.

# reticle_state

> Read live framework state directly from the running app. What it believes, not just what it rendered, without the app broadcasting anything.

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

```json theme={"dark"}
{ "depth": 2 }
```

Real response:

```json theme={"dark"}
{
  "found": true,
  "value": {
    "stores": {
      "__reticle_renders": "{…1 keys}",
      "app": "{…30 keys}",
      "queries": "{…0 keys}"
    },
    "storeNames": ["__reticle_renders", "app", "queries"]
  },
  "storeNames": ["__reticle_renders", "app", "queries"]
}
```

`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

| Argument | What it does                                                 |
| -------- | ------------------------------------------------------------ |
| `store`  | A registered store name, e.g. `app`                          |
| `path`   | Dot-path into a store, e.g. `cart.items.0.qty`               |
| `depth`  | Collapse anything deeper than N levels to a size marker      |
| `ref`    | Best-effort read of the nearest React component's hook state |

Drill in once you know what you want:

```json theme={"dark"}
{ "store": "app", "path": "auth" }
```

## 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.

```ts theme={"dark"}
registerCapabilities({
  stores: [{ name: 'app', store: appStore }],
});
```

<Warning>
  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".
</Warning>

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`](/quickstart) reports

```json theme={"dark"}
"stateDiffs": [{ "path": "auth", "from": null, "to": "{\"email\":\"admin@reticle.dev\"}" }]
```

that is the app itself saying the login took. A mock that returns `200` without touching state gets caught right there, and nowhere else.

<Card title="Instrument your app" icon="wrench" href="/instrumentation">
  Registering one store for your most important flow is the highest-value line you can write.
</Card>
