> ## 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/*`. Run every CLI command as `npx @reticlehq/server <command>`, for example `npx @reticlehq/server init`. `reticle` is a bin name that `@reticlehq/server` installs once it is on your PATH, NOT a package on npm: `npx reticle` fetches an unrelated package published by somebody else, so never run that. The complete tool surface is on the `/usage` page; `/agent-cheatsheet` is the one-screen version.

# reticle_query

> Find elements by Testing-Library semantics. Role, text, label, placeholder, testid, alt, or React component, including inside open shadow roots.

<Warning>
  **reticle\_query is not advertised.** The default surface is the merged nine, so an agent does not see
  this name. Call **`reticle_look { action: "find" }`** 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.
</Warning>

`reticle_query` answers "where is the thing I mean?" without dumping the whole page into your context window. It queries the way a testing library does. By role, label, text, testid. So your agent binds to meaning rather than to DOM structure that a refactor will move.

## Example

```json theme={"dark"}
{ "by": "role", "value": "button", "limit": 6 }
```

Real response from a running app, with four of the six elements trimmed out for length:

```json theme={"dark"}
{
  "count": 7,
  "elements": [
    {
      "ref": "e118",
      "role": "button",
      "name": "Overview",
      "visible": true,
      "source": "src/components/Sidebar.tsx:41",
      "states": ["present", "visible", "enabled"]
    },
    {
      "ref": "e120",
      "role": "button",
      "name": "Compose",
      "visible": true,
      "source": "src/components/Sidebar.tsx:41",
      "states": ["present", "visible", "enabled"]
    }
  ],
  "total": 7,
  "truncated": true,
  "cost": { "bytes": 944, "tokens": 236 }
}
```

Seven buttons, each with a `ref` to act on and a source file to open, for 236 tokens.

## Arguments

| Argument     | What it does                                                               |
| ------------ | -------------------------------------------------------------------------- |
| `by`         | `role` · `text` · `label` · `placeholder` · `testid` · `alt` · `component` |
| `value`      | The query value for that strategy                                          |
| `name`       | Accessible-name filter. Narrows a broad `role` query                       |
| `scope`      | CSS selector or ref, to search inside a subtree                            |
| `limit`      | Cap the descriptors returned. Cuts tokens hard on broad queries            |
| `count_only` | Return just `{ count }`, around 30x smaller                                |
| `attrs`      | Extra attributes per match, e.g. `['href']` to inventory links             |
| `self`       | Return the `scope` element itself instead of searching inside it           |

Every argument also has a predicate spelling, so `{ "role": "button" }` works as shorthand for `{ "by": "role", "value": "button" }`.

## Use `count_only` when you only need a number

"Are there still three rows?" does not require three row descriptors:

```json theme={"dark"}
{ "by": "testid", "value": "login-submit", "count_only": true }
```

```json theme={"dark"}
{ "count": 1, "cost": { "bytes": 11, "tokens": 3 } }
```

Three tokens. Note that `total` is not emitted on this path, because `count` already is the total.

## A zero-match result tells you what *is* there

```json theme={"dark"}
{ "by": "testid", "value": "compose-prompt" }
```

```json theme={"dark"}
{
  "count": 0,
  "elements": [],
  "hint": {
    "route": "/hostile",
    "knownEmptyState": true,
    "presentTestids": [
      "brand",
      "nav-overview",
      "nav-deployments",
      "nav-compose",
      "nav-diagnostics",
      "nav-hostile",
      "session-pill",
      "cmdk-open",
      "sign-out",
      "hostile-view",
      "hostile-ticker",
      "hostile-feed-count"
    ],
    "presentRegions": [
      { "role": "list", "childCount": 0, "name": "hostile-feed", "sample": [] },
      { "role": "banner", "childCount": 0, "sample": [] }
    ]
  },
  "cost": { "bytes": 402, "tokens": 101 }
}
```

The testid existed, on another route. `hint.route` says where you actually are, `presentTestids` says what is on this page instead, and `presentRegions` distinguishes an empty list from a missing one. All of it without paying for a snapshot.

## Reading the response

`ref` is the handle for every other tool: `act`, `inspect`, `state`. It stays valid until the element leaves the DOM, so you do not need to re-snapshot between actions on the same element.

`source` appears when `@reticlehq/react` is installed. Note that both sidebar buttons above report `Sidebar.tsx:41`, and so do the three trimmed out of the example. That is the line where the component renders all five in a loop, which is exactly the line you want to edit.

`truncated: true` with `total: 7` means `limit` cut the list, not that Reticle ran out of room. Neither field is emitted when nothing was cut, so their absence is itself the signal that you are looking at every match.

`states` distinguishes `present` from `visible` from `enabled`. An element can be all three and still be covered by a modal. [`reticle_inspect`](/tools/inspect) reports `occluded` for that.

<Tip>
  Query by `testid` when you can. Role and text queries survive refactors well; testids survive
  redesigns, translations, and the day someone rewrites your button labels for the marketing team.
</Tip>
