@reticlehq/server 2.7.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/README.md +14 -5
  2. package/SKILL.md +64 -29
  3. package/dist/capsule/causal-summary.d.ts +20 -0
  4. package/dist/capsule/causal-summary.js +31 -6
  5. package/dist/capsule/divergence.js +7 -1
  6. package/dist/cli/chromium-hint.d.ts +33 -5
  7. package/dist/cli/chromium-hint.js +82 -12
  8. package/dist/cli/cli-doctor.js +28 -25
  9. package/dist/cli/cli-kill.d.ts +58 -0
  10. package/dist/cli/cli-kill.js +162 -0
  11. package/dist/cli/cli-launch.d.ts +17 -0
  12. package/dist/cli/cli-launch.js +28 -0
  13. package/dist/cli/cli-parse.d.ts +16 -1
  14. package/dist/cli/cli-parse.js +32 -9
  15. package/dist/cli/cli-port.d.ts +8 -0
  16. package/dist/cli/cli-port.js +16 -0
  17. package/dist/cli/cli-verify.js +2 -2
  18. package/dist/cli/doctor-sessions-line.d.ts +12 -0
  19. package/dist/cli/doctor-sessions-line.js +66 -0
  20. package/dist/cli/port-holder.d.ts +10 -0
  21. package/dist/cli/port-holder.js +26 -2
  22. package/dist/cli.js +99 -14
  23. package/dist/crawl/crawl-tools.js +12 -2
  24. package/dist/crawl/crawl.d.ts +13 -0
  25. package/dist/crawl/crawl.js +50 -2
  26. package/dist/events/contradictions.d.ts +14 -0
  27. package/dist/events/contradictions.js +26 -17
  28. package/dist/events/predicate-eval.d.ts +20 -1
  29. package/dist/events/predicate-eval.js +125 -3
  30. package/dist/events/predicate.js +170 -18
  31. package/dist/flows/flow-classify.js +1 -1
  32. package/dist/flows/flow-tools.js +12 -4
  33. package/dist/flows/heal-run.js +1 -1
  34. package/dist/honesty/blind-spots.js +6 -2
  35. package/dist/honesty/unsettled.d.ts +40 -0
  36. package/dist/honesty/unsettled.js +78 -0
  37. package/dist/honesty/verified.d.ts +7 -0
  38. package/dist/honesty/verified.js +3 -3
  39. package/dist/index.js +3 -0
  40. package/dist/init/agent-rules.d.ts +16 -0
  41. package/dist/init/agent-rules.js +96 -22
  42. package/dist/init/astro-patch.d.ts +2 -1
  43. package/dist/init/astro-patch.js +11 -5
  44. package/dist/init/capabilities.d.ts +22 -0
  45. package/dist/init/capabilities.js +76 -0
  46. package/dist/init/confirm.d.ts +96 -0
  47. package/dist/init/confirm.js +138 -0
  48. package/dist/init/cra.js +3 -2
  49. package/dist/init/non-js-project.js +29 -5
  50. package/dist/init/plan-framework.js +53 -15
  51. package/dist/init/plan.d.ts +40 -4
  52. package/dist/init/plan.js +163 -40
  53. package/dist/init/run.d.ts +24 -2
  54. package/dist/init/run.js +148 -42
  55. package/dist/init/slash-command.d.ts +1 -1
  56. package/dist/init/slash-command.js +46 -6
  57. package/dist/init/snippets.d.ts +44 -4
  58. package/dist/init/snippets.js +161 -37
  59. package/dist/init/vite-config.js +29 -3
  60. package/dist/input/network-mock-tools.d.ts +19 -0
  61. package/dist/input/network-mock-tools.js +29 -4
  62. package/dist/license/license.js +1 -1
  63. package/dist/mcp/mcp-proxy.d.ts +69 -3
  64. package/dist/mcp/mcp-proxy.js +205 -20
  65. package/dist/mcp/mcp.js +23 -7
  66. package/dist/mcp/proxy-lifecycle.d.ts +1 -1
  67. package/dist/mcp/proxy-lifecycle.js +1 -1
  68. package/dist/pool/browser-pool.d.ts +22 -2
  69. package/dist/pool/browser-pool.js +44 -4
  70. package/dist/project/learned-routes.d.ts +24 -0
  71. package/dist/project/learned-routes.js +63 -0
  72. package/dist/project/project-store.d.ts +6 -0
  73. package/dist/project/project-store.js +25 -1
  74. package/dist/session/no-session-diagnosis.d.ts +19 -0
  75. package/dist/session/no-session-diagnosis.js +71 -18
  76. package/dist/session/no-session-watch.js +12 -0
  77. package/dist/session/ref-provenance.d.ts +54 -0
  78. package/dist/session/ref-provenance.js +61 -0
  79. package/dist/session/session-lease.js +1 -1
  80. package/dist/telemetry/automation-hint.d.ts +17 -0
  81. package/dist/telemetry/automation-hint.js +71 -0
  82. package/dist/telemetry/bug-found.d.ts +0 -20
  83. package/dist/telemetry/bug-found.js +38 -21
  84. package/dist/telemetry/cli-telemetry.js +7 -1
  85. package/dist/telemetry/feedback.js +1 -1
  86. package/dist/telemetry/init-telemetry.js +9 -1
  87. package/dist/telemetry/install-source.d.ts +36 -0
  88. package/dist/telemetry/install-source.js +40 -0
  89. package/dist/telemetry/run-telemetry.js +4 -1
  90. package/dist/telemetry/session-metrics.js +5 -0
  91. package/dist/telemetry/telemetry.d.ts +5 -1
  92. package/dist/telemetry/telemetry.js +15 -2
  93. package/dist/telemetry/tool-refused.d.ts +19 -0
  94. package/dist/telemetry/tool-refused.js +55 -0
  95. package/dist/telemetry/verification-of.js +46 -7
  96. package/dist/temp-dir.d.ts +27 -0
  97. package/dist/temp-dir.js +46 -0
  98. package/dist/tools/act-tools.js +45 -1
  99. package/dist/tools/assert-grade.d.ts +1 -1
  100. package/dist/tools/assert-grade.js +27 -5
  101. package/dist/tools/assert-verdict.js +18 -1
  102. package/dist/tools/contract-tools.js +4 -0
  103. package/dist/tools/dynamic-tools.js +1 -1
  104. package/dist/tools/error-recovery.d.ts +10 -0
  105. package/dist/tools/error-recovery.js +64 -4
  106. package/dist/tools/feedback-invite.js +1 -1
  107. package/dist/tools/invoke-tool.js +139 -23
  108. package/dist/tools/lease-tools.d.ts +29 -1
  109. package/dist/tools/lease-tools.js +58 -5
  110. package/dist/tools/navigate-result.js +1 -1
  111. package/dist/tools/observe-tools.js +1 -1
  112. package/dist/tools/observed-nothing.js +1 -1
  113. package/dist/tools/react-grace.d.ts +48 -0
  114. package/dist/tools/react-grace.js +87 -0
  115. package/dist/tools/read-tools.js +20 -4
  116. package/dist/tools/settle-in-flight.d.ts +79 -0
  117. package/dist/tools/settle-in-flight.js +106 -0
  118. package/dist/tools/snapshot-delta.d.ts +7 -0
  119. package/dist/tools/snapshot-delta.js +130 -6
  120. package/dist/tools/tool-surface.js +19 -0
  121. package/dist/tools/tools.js +16 -4
  122. package/docs/README.md +56 -11
  123. package/docs/actions.mdx +87 -0
  124. package/docs/agent-cheatsheet.md +93 -29
  125. package/docs/architecture.md +46 -35
  126. package/docs/benchmarks.md +76 -72
  127. package/docs/best-practices.mdx +211 -0
  128. package/docs/capabilities.mdx +387 -0
  129. package/docs/cli/affected.mdx +51 -0
  130. package/docs/cli/capsules.mdx +69 -0
  131. package/docs/cli/cloud.mdx +127 -0
  132. package/docs/cli/doctor.mdx +76 -0
  133. package/docs/cli/drive.mdx +55 -0
  134. package/docs/cli/feedback.mdx +67 -0
  135. package/docs/cli/gate.mdx +64 -0
  136. package/docs/cli/help.mdx +92 -0
  137. package/docs/cli/hunt.mdx +57 -0
  138. package/docs/cli/identify.mdx +62 -0
  139. package/docs/cli/init.mdx +94 -0
  140. package/docs/cli/kill.mdx +91 -0
  141. package/docs/cli/license.mdx +48 -0
  142. package/docs/cli/mcp.mdx +61 -0
  143. package/docs/cli/open.mdx +68 -0
  144. package/docs/cli/restart.mdx +60 -0
  145. package/docs/cli/rollback.mdx +35 -0
  146. package/docs/cli/serve.mdx +62 -0
  147. package/docs/cli/status.mdx +64 -0
  148. package/docs/cli/stop.mdx +56 -0
  149. package/docs/cli/telemetry.mdx +57 -0
  150. package/docs/cli/update.mdx +52 -0
  151. package/docs/cli/verify.mdx +57 -0
  152. package/docs/cli/version.mdx +39 -0
  153. package/docs/cli/watch.mdx +55 -0
  154. package/docs/cli.mdx +219 -0
  155. package/docs/debugging.md +13 -9
  156. package/docs/deploy-checks.md +15 -11
  157. package/docs/desktop-apps.md +49 -40
  158. package/docs/desktop.mdx +188 -0
  159. package/docs/docs.json +363 -0
  160. package/docs/enterprise.md +20 -16
  161. package/docs/faq.mdx +88 -0
  162. package/docs/fixtures.md +11 -7
  163. package/docs/flows.md +26 -22
  164. package/docs/for-agents.md +71 -0
  165. package/docs/frameworks.mdx +199 -0
  166. package/docs/gate-plan.md +45 -41
  167. package/docs/gates.md +22 -18
  168. package/docs/getting-started.md +76 -65
  169. package/docs/human-control.md +22 -18
  170. package/docs/index.mdx +101 -0
  171. package/docs/install-agentic.mdx +215 -0
  172. package/docs/install-manual.mdx +194 -0
  173. package/docs/instrumentation.mdx +232 -0
  174. package/docs/integration-patterns.md +38 -34
  175. package/docs/local-registry.md +16 -12
  176. package/docs/multi-agent-testing.md +16 -12
  177. package/docs/packages/babel-plugin.mdx +70 -0
  178. package/docs/packages/browser.mdx +111 -0
  179. package/docs/packages/core.mdx +106 -0
  180. package/docs/packages/electron.mdx +87 -0
  181. package/docs/packages/eslint-plugin.mdx +84 -0
  182. package/docs/packages/next.mdx +91 -0
  183. package/docs/packages/react.mdx +91 -0
  184. package/docs/packages/server.mdx +98 -0
  185. package/docs/packages/tauri.mdx +63 -0
  186. package/docs/packages/test.mdx +108 -0
  187. package/docs/packages/vite-plugin.mdx +96 -0
  188. package/docs/packages.mdx +217 -0
  189. package/docs/platform-integration.md +33 -26
  190. package/docs/predicates.mdx +179 -0
  191. package/docs/quickstart.mdx +211 -0
  192. package/docs/recipes.mdx +242 -0
  193. package/docs/skill-file.mdx +105 -0
  194. package/docs/state-management.mdx +197 -0
  195. package/docs/style.css +14 -0
  196. package/docs/system-map.md +47 -32
  197. package/docs/telemetry-contract.md +93 -50
  198. package/docs/telemetry-events.mdx +430 -0
  199. package/docs/telemetry.md +57 -52
  200. package/docs/testing.md +10 -6
  201. package/docs/token-efficiency.md +30 -26
  202. package/docs/tools-act-and-wait.mdx +123 -0
  203. package/docs/tools-act-sequence.mdx +120 -0
  204. package/docs/tools-act.mdx +82 -0
  205. package/docs/tools-assert.mdx +70 -0
  206. package/docs/tools-console.mdx +59 -0
  207. package/docs/tools-inspect.mdx +85 -0
  208. package/docs/tools-navigate.mdx +63 -0
  209. package/docs/tools-network.mdx +86 -0
  210. package/docs/tools-observe.mdx +89 -0
  211. package/docs/tools-overview.mdx +157 -0
  212. package/docs/tools-query.mdx +82 -0
  213. package/docs/tools-session-and-feedback.mdx +91 -0
  214. package/docs/tools-sessions.mdx +65 -0
  215. package/docs/tools-snapshot.mdx +75 -0
  216. package/docs/tools-state.mdx +81 -0
  217. package/docs/tools-tools-and-run.mdx +125 -0
  218. package/docs/tools-wait-for.mdx +66 -0
  219. package/docs/troubleshooting.mdx +193 -0
  220. package/docs/usage.md +175 -153
  221. package/docs/vs-chrome-devtools-mcp.mdx +82 -0
  222. package/docs/vs-playwright-mcp.mdx +85 -0
  223. package/docs/vs-screenshots.mdx +96 -0
  224. package/docs/what-is-reticle.mdx +63 -0
  225. package/docs/why-reticle.mdx +107 -0
  226. package/package.json +2 -2
  227. package/docs/matrix/2.5.0/claude-code-machine.json +0 -19
  228. package/docs/matrix/2.5.0/codex-machine.json +0 -20
  229. package/docs/matrix/2.5.0/cursor-machine.json +0 -22
  230. package/docs/matrix/2.5.0/gemini-machine.json +0 -22
  231. package/docs/matrix/2.5.0/opencode-machine.json +0 -22
  232. package/docs/matrix/2.5.0/vscode-machine.json +0 -22
  233. package/docs/matrix/2.5.0/windsurf-machine.json +0 -22
  234. package/docs/matrix/MATRIX.md +0 -26
  235. package/docs/matrix/README.md +0 -59
  236. package/docs/mint.json +0 -61
@@ -0,0 +1,157 @@
1
+ ---
2
+ title: Tools overview: 18 up front, 30 on call
3
+ sidebarTitle: Tools overview
4
+ description: The 18 tools your agent sees every turn, the 30 more it can reach on demand, and why the surface is deliberately small.
5
+ icon: wrench
6
+ ---
7
+
8
+ Reticle ships 48 tools. Your agent is shown **18** of them.
9
+
10
+ That is not a limitation, it's the design. MCP re-sends every advertised tool definition to the model on **every single turn**, so the tool list is not a menu you pay for once. It's rent.
11
+
12
+ A wider surface costs tokens on every message. Less obviously, it makes the model wander: give it forty ways to look at a page and it will try several before doing anything useful.
13
+
14
+ The other 30 tools are one call away, never unreachable. `reticle_tools` lists them and `reticle_run` invokes them.
15
+
16
+ <Note>
17
+ Measured off the real wire on 2026-08-14, by reading `tools/list` from a fresh daemon: the default
18
+ surface is **18 tools at 21,468 bytes**, against **48 tools at 134,368 bytes**. That is 6.3x more,
19
+ charged on every message. In real tokenizer terms that is roughly **4,930** and **30,200** tokens
20
+ per turn ([measured by `bench/harness/schema-tax.mjs`](/token-efficiency), which puts every server
21
+ through one tokenizer in a single pass). Re-measure before quoting these; the surface grows.
22
+ </Note>
23
+
24
+ ## The default 18
25
+
26
+ Grouped by the job they do in the verify loop.
27
+
28
+ <CardGroup cols={2}>
29
+ <Card title="Look" icon="magnifying-glass">
30
+ `reticle_snapshot` · `reticle_query` · `reticle_inspect` · `reticle_sessions`
31
+ </Card>
32
+ <Card title="Act" icon="hand-pointer">
33
+ `reticle_act` · `reticle_act_and_wait` · `reticle_act_sequence` · `reticle_navigate`
34
+ </Card>
35
+ <Card title="Observe" icon="satellite-dish">
36
+ `reticle_observe` · `reticle_network` · `reticle_console` · `reticle_state` · `reticle_wait_for`
37
+ </Card>
38
+ <Card title="Prove & discover" icon="circle-check">
39
+ `reticle_assert` · `reticle_tools` · `reticle_run`
40
+ </Card>
41
+ <Card title="Session & feedback" icon="comment">
42
+ `reticle_session` · `reticle_feedback`
43
+ </Card>
44
+ </CardGroup>
45
+
46
+ <Warning>
47
+ Only **`reticle_act_and_wait`** and **`reticle_assert`** produce a verdict. Everything else moves
48
+ or reads the app and proves nothing. A drive that ends without one of those two has no result,
49
+ however many tools it used and however confident the summary sounds.
50
+ </Warning>
51
+
52
+ ## Why these 18 and not others
53
+
54
+ Each one earned its slot, and a couple are there because of measured mistakes.
55
+
56
+ `reticle_inspect` maps a DOM node to `src/components/Sidebar.tsx:41`. Finding a bug is half the job. Knowing which file to open is the half that makes an agent useful.
57
+
58
+ It used to sit in the cold tail, which meant an agent had to already know it existed to use it. So essentially nobody did.
59
+
60
+ `reticle_act_sequence` batches a multi-step interaction into one round trip. It was also in the cold tail, and the consequence showed up in the data: agents drove login forms one call at a time, over and over.
61
+
62
+ Those repeats were not retries. The calls succeeded and got repeated, because the batching tool was invisible. A tool an agent must already know about is a tool that never gets called.
63
+
64
+ Direct `reticle_network` and `reticle_console` stay advertised even though `reticle_observe` can filter for both, because two obvious tools beat one clever tool with a filter grammar.
65
+
66
+ <Tip>
67
+ Trimming further has a floor. An 8-tool cut measurably dropped real-agent accuracy, because the
68
+ model loses scaffolding and wanders on harder flows. That reading is old enough to be dated
69
+ evidence rather than proof, and a fresh A/B against a leaner surface is still unrun. Small is
70
+ good; empty is not.
71
+ </Tip>
72
+
73
+ ## Reaching the other 30
74
+
75
+ ```json
76
+ { "name": "reticle_flow_verify", "args": {} }
77
+ ```
78
+
79
+ `reticle_run` takes a tool name and its arguments. `reticle_tools` lists what's available and returns the full argument grammar for any of them, so your agent can discover a tool mid-task without you having pre-loaded its schema.
80
+
81
+ Notable residents of the cold tail: flow recording and replay, visual diffing and screenshots, network mocking, viewport pinning, coverage, autonomous crawling, and the human-in-the-loop session controls.
82
+
83
+ ## Every response carries its cost
84
+
85
+ Reticle tells you what each answer cost, because a verification tool that quietly eats your context window is not saving you anything:
86
+
87
+ ```json
88
+ "cost": { "bytes": 938, "tokens": 235 }
89
+ ```
90
+
91
+ That is a real `reticle_query` response: seven buttons found, with source pointers, for 235 tokens.
92
+
93
+ ## Every response tells you when not to trust it
94
+
95
+ This is the part we're proudest of and the part that makes demos slightly less shiny.
96
+
97
+ When the browser tab is backgrounded, every response says so:
98
+
99
+ ```json
100
+ "warning": "tab throttled; timer/rAF/pointer gestures may silently no-op; refocus before driving"
101
+ ```
102
+
103
+ When the event buffer has evicted old events, a negative result might be a false negative, and it says that too:
104
+
105
+ ```json
106
+ "buffer": {
107
+ "held": 15,
108
+ "dropped": 529,
109
+ "note": "event buffer evicted older events (age/size cap): a negative result here may be a false negative; the evidence may have expired. Grade sooner or widen the buffer."
110
+ }
111
+ ```
112
+
113
+ A tool that says "no requests found" when it actually means "I lost the ones you asked about" is worse than useless. It is confidently wrong. Reticle would rather tell you its memory is imperfect.
114
+
115
+ ## Reference
116
+
117
+ ### Look
118
+
119
+ | Tool | Answers |
120
+ | --- | --- |
121
+ | [`reticle_snapshot`](/tools-snapshot) | What is on this page? Three modes, from full tree to a 25-token route check |
122
+ | [`reticle_query`](/tools-query) | Where is the thing I mean? |
123
+ | [`reticle_inspect`](/tools-inspect) | Everything about one element, down to source and design tokens |
124
+ | [`reticle_sessions`](/tools-sessions) | Which tabs are connected, and can they actually be driven? |
125
+
126
+ ### Act
127
+
128
+ | Tool | Answers |
129
+ | --- | --- |
130
+ | [`reticle_act`](/tools-act) | Do this. Proves nothing, and says so |
131
+ | [`reticle_act_and_wait`](/tools-act-and-wait) | Do this, and prove the consequence. **Produces a verdict** |
132
+ | [`reticle_act_sequence`](/tools-act-sequence) | Do these three things in one round trip |
133
+ | [`reticle_navigate`](/tools-navigate) | Go here. Dispatched, not confirmed |
134
+
135
+ ### Observe
136
+
137
+ | Tool | Answers |
138
+ | ------------------------------------- | ----------------------------------------------- |
139
+ | [`reticle_observe`](/tools-observe) | Everything that happened in a window |
140
+ | [`reticle_network`](/tools-network) | Which requests fired, with bodies and timings |
141
+ | [`reticle_console`](/tools-console) | What was logged, and whether the read was real |
142
+ | [`reticle_state`](/tools-state) | What the app believes, not what it drew |
143
+ | [`reticle_wait_for`](/tools-wait-for) | Block until something you did not cause happens |
144
+
145
+ ### Prove and discover
146
+
147
+ | Tool | Answers |
148
+ | --- | --- |
149
+ | [`reticle_assert`](/tools-assert) | Did the named consequence hold? **Produces a verdict** |
150
+ | [`reticle_tools`](/tools-tools-and-run) | What else is available, and what are its arguments? |
151
+ | [`reticle_run`](/tools-tools-and-run) | Invoke any of the other 30 |
152
+ | [`reticle_session`](/tools-session-and-feedback) | Hand control back to the human |
153
+ | [`reticle_feedback`](/tools-session-and-feedback) | Tell the maintainers Reticle got something wrong |
154
+
155
+ <Card title="The complete reference" icon="book" href="/usage">
156
+ Every tool, every argument, including the 30 in the cold tail.
157
+ </Card>
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: reticle_query
3
+ description: Find elements by Testing-Library semantics. Role, text, label, placeholder, testid, alt, or React component, including inside open shadow roots.
4
+ icon: magnifying-glass
5
+ ---
6
+
7
+ `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.
8
+
9
+ ## Example
10
+
11
+ ```json
12
+ { "by": "role", "value": "button", "limit": 6 }
13
+ ```
14
+
15
+ Real response from a running app:
16
+
17
+ ```json
18
+ {
19
+ "count": 7,
20
+ "elements": [
21
+ {
22
+ "ref": "e18",
23
+ "role": "button",
24
+ "name": "Overview",
25
+ "visible": true,
26
+ "source": "src/components/Sidebar.tsx:41",
27
+ "states": ["present", "visible", "enabled"]
28
+ },
29
+ {
30
+ "ref": "e20",
31
+ "role": "button",
32
+ "name": "Compose",
33
+ "visible": true,
34
+ "source": "src/components/Sidebar.tsx:41",
35
+ "states": ["present", "visible", "enabled"]
36
+ }
37
+ ],
38
+ "total": 7,
39
+ "truncated": true,
40
+ "cost": { "bytes": 938, "tokens": 235 }
41
+ }
42
+ ```
43
+
44
+ Seven buttons, each with a `ref` to act on and a source file to open, for 235 tokens.
45
+
46
+ ## Arguments
47
+
48
+ | Argument | What it does |
49
+ | ------------ | -------------------------------------------------------------------------- |
50
+ | `by` | `role` · `text` · `label` · `placeholder` · `testid` · `alt` · `component` |
51
+ | `value` | The query value for that strategy |
52
+ | `name` | Accessible-name filter. Narrows a broad `role` query |
53
+ | `scope` | CSS selector or ref, to search inside a subtree |
54
+ | `limit` | Cap the descriptors returned. Cuts tokens hard on broad queries |
55
+ | `count_only` | Return just `{ count }`, around 30x smaller |
56
+ | `attrs` | Extra attributes per match, e.g. `['href']` to inventory links |
57
+ | `self` | Return the `scope` element itself instead of searching inside it |
58
+
59
+ Every argument also has a predicate spelling, so `{ "role": "button" }` works as shorthand for `{ "by": "role", "value": "button" }`.
60
+
61
+ ## Use `count_only` when you only need a number
62
+
63
+ "Are there still three rows?" does not require three row descriptors:
64
+
65
+ ```json
66
+ { "by": "testid", "value": "todo-row", "count_only": true }
67
+ ```
68
+
69
+ ## Reading the response
70
+
71
+ `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.
72
+
73
+ `source` appears when `@reticlehq/react` is installed. Note that all five sidebar buttons above report `Sidebar.tsx:41`. That is the line where the component renders them in a loop, which is exactly the line you want to edit.
74
+
75
+ `truncated: true` with `total: 7` means `limit` cut the list, not that Reticle ran out of room.
76
+
77
+ `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.
78
+
79
+ <Tip>
80
+ Query by `testid` when you can. Role and text queries survive refactors well; testids survive
81
+ redesigns, translations, and the day someone rewrites your button labels for the marketing team.
82
+ </Tip>
@@ -0,0 +1,91 @@
1
+ ---
2
+ title: reticle_session and reticle_feedback
3
+ description: Hand the session back to the human, end it cleanly, and tell the maintainers when Reticle got something wrong.
4
+ icon: comments
5
+ ---
6
+
7
+ Two tools that are not about your app at all. One manages the boundary between agent and human; the other is how Reticle finds out it is broken.
8
+
9
+ ## reticle_session
10
+
11
+ The presenter panel in your app shows a live transcript of what the agent is doing. It reads "live" until the agent says otherwise. So an agent that wanders off without a word leaves a panel claiming work is in progress forever.
12
+
13
+ | Action | What it does |
14
+ | ------- | ------------------------------------------------------------------------ |
15
+ | `yield` | Hand control back between turns. `mode: "waiting"` or `"ask"`. Revivable |
16
+ | `end` | The task is done. Frees the session; revives on the next action |
17
+ | `tune` | Adjust session behaviour, such as the idle-end window |
18
+
19
+ ```json
20
+ { "action": "yield", "mode": "waiting" }
21
+ ```
22
+
23
+ Reticle nudges you about this. Every response on a long-running session carries a reminder:
24
+
25
+ ```json
26
+ "session_age_warning": "Session s7fe3a790… has been open for 15 minutes. If your task is complete, call reticle_session{action:\"end\"} now."
27
+ ```
28
+
29
+ And each lease carries the rule in the payload itself:
30
+
31
+ ```json
32
+ "session_lease": {
33
+ "IMPORTANT": "When you stop driving, call reticle_session {action:\"yield\", mode:\"waiting\"|\"ask\"}. The panel reads \"live\" until you do."
34
+ }
35
+ ```
36
+
37
+ <Tip>
38
+ `yield` when you are pausing and might come back. `end` when you are finished. Both revive on your
39
+ next action, so neither is destructive. The difference is what the human watching the panel is
40
+ told.
41
+ </Tip>
42
+
43
+ ## reticle_feedback
44
+
45
+ Reticle is built for agents, which creates an unusual problem: the primary user's experience vanishes the moment its context does. If an agent hits a gap and works around it silently, nobody ever learns the gap existed.
46
+
47
+ ```json
48
+ {
49
+ "kind": "bug",
50
+ "text": "What I called, what I expected, what I got, and why Reticle is at fault.",
51
+ "currentApproach": "How I am working around it today.",
52
+ "impact": "What measurably improves if this is fixed."
53
+ }
54
+ ```
55
+
56
+ | `kind` | Use it when |
57
+ | ----------------- | ---------------------------------------------------------- |
58
+ | `bug` | A tool returned a wrong or broken result |
59
+ | `gap` | Reticle could not observe something you needed at all |
60
+ | `ambiguity` | The check ran but you could not tell what the answer meant |
61
+ | `feature_request` | You wished a capability existed |
62
+ | `improvement` | It works, but costs too many calls |
63
+
64
+ ### It will tell you when it cannot send
65
+
66
+ Feedback is not fire-and-forget, and it does not pretend to succeed:
67
+
68
+ ```json
69
+ {
70
+ "sent": false,
71
+ "accepted": false,
72
+ "reason": "this is a Reticle source checkout, where telemetry is disabled by design, so feedback has nowhere to go. Open an issue at https://github.com/reticlehq/reticle/issues instead.",
73
+ "note": "NOT accepted (see reason). Tell the human what you found so it is not lost."
74
+ }
75
+ ```
76
+
77
+ That is a real response, captured while writing these docs. The instruction in `note` is the important part: when the report cannot be delivered, say so in your answer to the human rather than letting the finding evaporate.
78
+
79
+ ### From the shell, when the tools are unreachable
80
+
81
+ The setup that failed to finish is exactly the setup that most needs reporting, and in that state the MCP tools do not exist:
82
+
83
+ ```bash
84
+ npx @reticlehq/server feedback --agent --kind gap "reticle init finished but no session ever connected"
85
+ ```
86
+
87
+ <Note>
88
+ Report defects in **Reticle**. A bug you find in the app under test is Reticle working correctly,
89
+ and belongs in your answer to the user. Not in a bug report to us. We get a surprising number of
90
+ those, and each one is quietly a compliment.
91
+ </Note>
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: reticle_sessions
3
+ description: List every connected browser tab, with the health fields that tell you whether it can actually be driven.
4
+ icon: list-check
5
+ ---
6
+
7
+ ```json
8
+ {}
9
+ ```
10
+
11
+ Real response, one session shown:
12
+
13
+ ```json
14
+ {
15
+ "sessions": [
16
+ {
17
+ "sessionId": "s7fe3a790-ab02-4ebb-82b2-24d08a76fd59",
18
+ "url": "http://localhost:4312/",
19
+ "title": "Reticle · Mission Control",
20
+ "adapters": ["react"],
21
+ "hasCapabilities": true,
22
+ "hidden": true,
23
+ "throttled": true,
24
+ "focused": false,
25
+ "lastSeenMs": 21944,
26
+ "realInputAvailable": false,
27
+ "leased": false,
28
+ "attachment": { "connectedSinceMs": 827874, "outages": 0 },
29
+ "recommendation": "tab hidden/throttled and may be un-focusable from here; refocus it, or run `reticle drive <url>` for a guaranteed scriptable context"
30
+ }
31
+ ]
32
+ }
33
+ ```
34
+
35
+ ## The fields that decide whether driving will work
36
+
37
+ | Field | Why it matters |
38
+ | --- | --- |
39
+ | `throttled` | The browser is deprioritising a background tab. Synthetic timers and pointer gestures may silently no-op |
40
+ | `hidden` / `focused` | Why it's throttled, and what to do about it |
41
+ | `hasCapabilities` | Whether the app registered testids, signals and stores. `false` means [`reticle_state`](/tools-state) has nothing to read |
42
+ | `adapters` | `["react"]` means you get component names and source pointers |
43
+ | `realInputAvailable` | `true` when native CDP input is available, under `reticle drive` |
44
+ | `outages` | How often the connection has dropped. Non-zero is worth investigating |
45
+
46
+ <Warning>
47
+ `throttled: true` is the most common cause of "the click did nothing". Focus the tab, or drive a
48
+ dedicated context. It is not your app being broken. It is the browser saving battery on a tab
49
+ nobody is looking at.
50
+ </Warning>
51
+
52
+ ## Confirm after navigating
53
+
54
+ [`reticle_navigate`](/tools-navigate) can only report that a navigation was dispatched. `sessions` is how you confirm one arrived: a session at the new URL means the page loaded **and** is instrumented. No session means one of those two is false, and you find out now rather than after three confusing failures.
55
+
56
+ ## Scoping
57
+
58
+ You rarely need to pass `sessionId` to other tools. Reticle scopes to your project, prefers the active tab, and refuses rather than guesses when the choice is ambiguous. A refusal you can act on beats a silent pick of the wrong tab.
59
+
60
+ Pass it explicitly when you genuinely mean one specific tab, such as when testing two apps at once.
61
+
62
+ <Note>
63
+ Sessions accumulate. A stale entry pointing at a dev server you have since restarted will sit there
64
+ looking plausible. `reticle_session { action: "end" }` clears one out.
65
+ </Note>
@@ -0,0 +1,75 @@
1
+ ---
2
+ title: reticle_snapshot
3
+ description: A semantic accessibility snapshot of the page or a subtree, in three sizes. From the full tree down to a 25-token route check.
4
+ icon: camera
5
+ ---
6
+
7
+ `reticle_snapshot` is how an agent gets its bearings. It returns the page as semantic structure, not pixels and not raw HTML, and it comes in three sizes so you can pay for only what you need.
8
+
9
+ ## Three modes, three prices
10
+
11
+ | Mode | Returns | Real cost on one page |
12
+ | ------------- | ------------------------------------- | --------------------- |
13
+ | `status` | Route and title only | **25 tokens** |
14
+ | `interactive` | Only clickable and focusable elements | **65 tokens** |
15
+ | `full` | Every element | Depends on the page |
16
+
17
+ ### `status`. the cheapest possible check
18
+
19
+ ```json
20
+ { "mode": "status" }
21
+ ```
22
+
23
+ ```json
24
+ {
25
+ "tree": "",
26
+ "nodes": 0,
27
+ "status": { "route": "/", "title": "Reticle · Mission Control" },
28
+ "cost": { "bytes": 98, "tokens": 25 }
29
+ }
30
+ ```
31
+
32
+ Ninety-eight bytes to answer "where am I?". Use it after a navigation instead of re-reading the page.
33
+
34
+ ### `interactive`. the default working view
35
+
36
+ ```json
37
+ { "mode": "interactive" }
38
+ ```
39
+
40
+ ```json
41
+ {
42
+ "tree": "- textbox \"Email\" (ref=e101) [value=\"admin@reticle.dev\"]\n- textbox \"Password\" (ref=e102) [value=\"[REDACTED]\"]\n- button \"Sign in\" (ref=e103)",
43
+ "nodes": 3,
44
+ "truncated": false,
45
+ "status": { "route": "/deployments", "title": "Reticle · Mission Control" },
46
+ "cost": { "bytes": 260, "tokens": 65 }
47
+ }
48
+ ```
49
+
50
+ Everything you can act on, with a `ref` for each, for 65 tokens. Note the password arrives `[REDACTED]` without anyone configuring it.
51
+
52
+ ## Arguments
53
+
54
+ | Argument | What it does |
55
+ | -------- | ---------------------------------------------------------------------------- |
56
+ | `mode` | `full` · `interactive` · `status` |
57
+ | `scope` | CSS selector or ref, to snapshot one subtree |
58
+ | `diff` | Return only what changed since your last snapshot of the same scope and mode |
59
+
60
+ ## `diff` is how you keep a long session cheap
61
+
62
+ ```json
63
+ { "mode": "interactive", "diff": true }
64
+ ```
65
+
66
+ After the first snapshot, ask only for the delta. On a page where one row appeared, you get one row rather than the whole list again.
67
+
68
+ <Tip>
69
+ Reach for [`reticle_query`](/tools-query) instead when you already know what you're looking for.
70
+ Snapshot is for orientation; query is for retrieval, and it's almost always cheaper.
71
+ </Tip>
72
+
73
+ ## Refs change across documents
74
+
75
+ Refs are stable while the element is in the DOM. A full navigation builds a new document, so refs are re-issued. The same "Sign in" button was `e5` before a navigation and `e103` after. Snapshot after navigating; don't reuse refs across one.
@@ -0,0 +1,81 @@
1
+ ---
2
+ title: reticle_state
3
+ description: Read live framework state directly from the running app. What it believes, not just what it rendered, without the app broadcasting anything.
4
+ icon: database
5
+ ---
6
+
7
+ 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.
8
+
9
+ ## Example
10
+
11
+ ```json
12
+ { "depth": 2 }
13
+ ```
14
+
15
+ Real response:
16
+
17
+ ```json
18
+ {
19
+ "found": true,
20
+ "value": {
21
+ "stores": {
22
+ "__reticle_renders": "{…1 keys}",
23
+ "app": "{…30 keys}",
24
+ "queries": "{…0 keys}"
25
+ },
26
+ "storeNames": ["__reticle_renders", "app", "queries"]
27
+ },
28
+ "storeNames": ["__reticle_renders", "app", "queries"]
29
+ }
30
+ ```
31
+
32
+ `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.
33
+
34
+ ## Arguments
35
+
36
+ | Argument | What it does |
37
+ | -------- | ------------------------------------------------------------ |
38
+ | `store` | A registered store name, e.g. `app` |
39
+ | `path` | Dot-path into a store, e.g. `cart.items.0.qty` |
40
+ | `depth` | Collapse anything deeper than N levels to a size marker |
41
+ | `ref` | Best-effort read of the nearest React component's hook state |
42
+
43
+ Drill in once you know what you want:
44
+
45
+ ```json
46
+ { "store": "app", "path": "auth" }
47
+ ```
48
+
49
+ ## You have to register stores first
50
+
51
+ `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.
52
+
53
+ ```ts
54
+ registerCapabilities({
55
+ stores: [{ name: 'app', store: appStore }],
56
+ });
57
+ ```
58
+
59
+ <Warning>
60
+ Pass the **store**, not `() => store.getState()`. The store form wires `subscribe` too, so every
61
+ mutation emits a state diff. The getter form is read-only and silently produces empty diffs, which
62
+ looks like "nothing changed" and is really "I was never watching".
63
+ </Warning>
64
+
65
+ That distinction is the single most common instrumentation mistake, and its failure mode is a verdict that passes when it should not.
66
+
67
+ ## Why this is the strongest evidence you have
68
+
69
+ 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.
70
+
71
+ State does. When [`reticle_act_and_wait`](/quickstart) reports
72
+
73
+ ```json
74
+ "stateDiffs": [{ "path": "auth", "from": null, "to": "{\"email\":\"admin@reticle.dev\"}" }]
75
+ ```
76
+
77
+ that is the app itself saying the login took. A mock that returns `200` without touching state gets caught right there, and nowhere else.
78
+
79
+ <Card title="Instrument your app" icon="wrench" href="/instrumentation">
80
+ Registering one store for your most important flow is the highest-value line you can write.
81
+ </Card>
@@ -0,0 +1,125 @@
1
+ ---
2
+ title: reticle_tools and reticle_run
3
+ description: Discover the 30 tools that are not advertised, load their argument grammar on demand, and invoke any of them by name.
4
+ icon: boxes-stacked
5
+ ---
6
+
7
+ Reticle advertises 18 tools and ships 48. These two meta-tools are how your agent reaches the other 30 without paying for their schemas on every turn.
8
+
9
+ `reticle_tools` discovers. `reticle_run` invokes. Together they cost two tool definitions instead of thirty.
10
+
11
+ ## Discovering what exists
12
+
13
+ ```json
14
+ {}
15
+ ```
16
+
17
+ Returns every tool with a one-line summary. A sample of what lives in the cold tail:
18
+
19
+ | Tool | What it does |
20
+ | ----------------------- | ---------------------------------------------------------------------- |
21
+ | `reticle_capabilities` | The app's advertised testable surface, testids, signals, stores, flows |
22
+ | `reticle_flow_verify` | Replay every saved flow, return one consolidated suite verdict |
23
+ | `reticle_screenshot` | Pixel screenshot of the driven page, saved as a visual baseline |
24
+ | `reticle_visual_diff` | Perceptually diff the live page against that baseline |
25
+ | `reticle_network_mock` | Force a 500, go offline, or delay a response |
26
+ | `reticle_viewport` | Pin the viewport so screenshots are reproducible across machines |
27
+ | `reticle_crawl` | Click every reachable control and report anomalies, with no script |
28
+ | `reticle_clock` | Freeze time or fast-forward timers, toasts, debounces, auto-dismiss |
29
+ | `reticle_storage` | localStorage, sessionStorage and readable cookies |
30
+ | `reticle_coverage` | Which controls you have driven this session, and which you have not |
31
+ | `reticle_verify_change` | Give it the files you edited; it replays the flows that cover them |
32
+ | `reticle_reconcile` | Compare what the API returned against what the page actually renders |
33
+ | `reticle_scroll_to` | Find a row in a virtualised list that has not rendered yet |
34
+
35
+ The response also tells you which surface is active:
36
+
37
+ ```json
38
+ {
39
+ "profile": {
40
+ "active": "default",
41
+ "source": "the one tool surface (RETICLE_ADVERTISE_ALL_TOOLS unset when the daemon started)",
42
+ "note": "The profile is read once at daemon startup: change it and restart the daemon, or it has no effect."
43
+ },
44
+ "next": "Load params with reticle_tools { names:[…] }, then call reticle_run { tool, args }."
45
+ }
46
+ ```
47
+
48
+ <Warning>
49
+ "Read once at daemon startup" is doing real work in that sentence. Setting the environment
50
+ variable in a shell where a daemon is already running changes nothing, and the resulting "I set it
51
+ and nothing happened" is very hard to debug from the outside.
52
+ </Warning>
53
+
54
+ ## Loading argument grammar
55
+
56
+ Summaries are enough to choose a tool, not to call one. Load the full parameters for the ones you want:
57
+
58
+ ```json
59
+ { "names": ["reticle_network_mock", "reticle_clock"] }
60
+ ```
61
+
62
+ This is the point of the design. Schemas arrive when they are needed, rather than on every turn forever.
63
+
64
+ ## Invoking
65
+
66
+ ```json
67
+ { "tool": "reticle_capabilities" }
68
+ ```
69
+
70
+ Real response from an instrumented app, trimmed:
71
+
72
+ ```json
73
+ {
74
+ "testids": [
75
+ "nav-overview",
76
+ "nav-deployments",
77
+ "login-email",
78
+ "login-password",
79
+ "login-submit",
80
+ "deploy-table",
81
+ "new-deploy",
82
+ "deploy-submit",
83
+ "…"
84
+ ],
85
+ "signals": [
86
+ "nav:changed",
87
+ "auth:granted",
88
+ "auth:denied",
89
+ "deploy:created",
90
+ "deploy:shipped",
91
+ "modal:opened",
92
+ "toast:shown",
93
+ "…"
94
+ ],
95
+ "stores": ["app"],
96
+ "flows": [
97
+ {
98
+ "name": "ship-a-deploy",
99
+ "steps": ["nav-deployments", "new-deploy", "deploy-name", "deploy-submit"]
100
+ },
101
+ { "name": "generate-a-script", "steps": ["nav-compose", "compose-prompt", "compose-generate"] }
102
+ ],
103
+ "source": "live"
104
+ }
105
+ ```
106
+
107
+ ## Start here, not with a snapshot
108
+
109
+ That `reticle_capabilities` output is the single best first call on an unfamiliar app. It is the app telling you what it considers testable: the elements worth driving, the signals that mean success, and the flows somebody already thought were important.
110
+
111
+ Compared with snapshotting the page and guessing from element names, it is both cheaper and more truthful. `auth:granted` is what the app means by "logged in", and no amount of looking at the DOM will tell you that.
112
+
113
+ ```json
114
+ {
115
+ "tool": "reticle_network_mock",
116
+ "args": { "mocks": [{ "urlContains": "/api/deploys", "status": 500 }] }
117
+ }
118
+ ```
119
+
120
+ Then drive the flow and see whether your error state actually works. Most do not, which is the point.
121
+
122
+ <Note>
123
+ `reticle_run` returns whatever the invoked tool returns, unchanged. It is a transport, not a
124
+ wrapper. So a tool that produces a verdict still produces one through `run`.
125
+ </Note>