@reticlehq/server 3.7.0 → 3.8.1

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 (578) hide show
  1. package/SKILL.md +59 -68
  2. package/bin/reticle.js +9 -2
  3. package/dist/command/cli/adhoc-suite.js +1 -1
  4. package/dist/command/cli/adhoc-verdict.d.ts +12 -0
  5. package/dist/command/cli/adhoc-verdict.js +62 -4
  6. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  7. package/dist/command/cli/answers/gate-hook-message.js +5 -1
  8. package/dist/command/cli/auth/cloud-session.d.ts +11 -19
  9. package/dist/command/cli/auth/cloud-session.js +23 -0
  10. package/dist/command/cli/auth/device-flow.d.ts +3 -37
  11. package/dist/command/cli/cli-doctor.js +66 -21
  12. package/dist/command/cli/cli-flow-commands.js +53 -11
  13. package/dist/command/cli/cli-kill.d.ts +8 -0
  14. package/dist/command/cli/cli-kill.js +43 -3
  15. package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
  16. package/dist/command/cli/cli-parse-feedback.js +13 -1
  17. package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
  18. package/dist/command/cli/cli-parse-grammar.js +1 -6
  19. package/dist/command/cli/cli-parse-serve.d.ts +24 -0
  20. package/dist/command/cli/cli-parse-serve.js +124 -0
  21. package/dist/command/cli/cli-parse.d.ts +12 -11
  22. package/dist/command/cli/cli-parse.js +100 -123
  23. package/dist/command/cli/cli-usage.d.ts +0 -11
  24. package/dist/command/cli/cli-usage.js +43 -16
  25. package/dist/command/cli/cli-verify.d.ts +1 -1
  26. package/dist/command/cli/cli-verify.js +29 -14
  27. package/dist/command/cli/cloud-cli.js +27 -9
  28. package/dist/command/cli/cloud-kit.js +3 -3
  29. package/dist/command/cli/cloud-link.d.ts +1 -20
  30. package/dist/command/cli/cloud-link.js +2 -0
  31. package/dist/command/cli/cloud-login.d.ts +6 -2
  32. package/dist/command/cli/cloud-login.js +13 -41
  33. package/dist/command/cli/config/checkout.d.ts +10 -0
  34. package/dist/command/cli/config/checkout.js +78 -0
  35. package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
  36. package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
  37. package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
  38. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  39. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  40. package/dist/command/cli/drive/drive-attach.d.ts +5 -0
  41. package/dist/command/cli/drive/drive-attach.js +21 -1
  42. package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
  43. package/dist/command/cli/hook/codex-transcript.js +224 -0
  44. package/dist/command/cli/hook/episode-structure.d.ts +24 -0
  45. package/dist/command/cli/hook/episode-structure.js +138 -0
  46. package/dist/command/cli/hook/hook-command.d.ts +9 -0
  47. package/dist/command/cli/hook/hook-command.js +211 -0
  48. package/dist/command/cli/hook/hook-fast.d.ts +31 -0
  49. package/dist/command/cli/hook/hook-fast.js +136 -0
  50. package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
  51. package/dist/command/cli/hook/prompt-hook.js +199 -0
  52. package/dist/command/cli/hook/tool-hook.d.ts +21 -0
  53. package/dist/command/cli/hook/tool-hook.js +259 -0
  54. package/dist/command/cli/launch/cli-launch.d.ts +2 -0
  55. package/dist/command/cli/launch/cli-launch.js +22 -2
  56. package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
  57. package/dist/command/cli/mcp-command.d.ts +9 -0
  58. package/dist/command/cli/mcp-command.js +127 -41
  59. package/dist/command/cli/open-navigate.d.ts +43 -0
  60. package/dist/command/cli/open-navigate.js +85 -0
  61. package/dist/command/cli/ports/port-holder.d.ts +16 -4
  62. package/dist/command/cli/ports/port-holder.js +58 -12
  63. package/dist/command/cli/ports/resolve/cli-port.js +18 -2
  64. package/dist/command/cli/project-name.d.ts +1 -7
  65. package/dist/command/cli/project-name.js +1 -0
  66. package/dist/command/cli/report-command.d.ts +8 -2
  67. package/dist/command/cli/report-command.js +95 -18
  68. package/dist/command/cli/status-fields.d.ts +9 -2
  69. package/dist/command/cli/status-fields.js +148 -4
  70. package/dist/command/cli/try-command.d.ts +3 -4
  71. package/dist/command/cli/try-command.js +6 -11
  72. package/dist/command/cli/verify-results.d.ts +4 -1
  73. package/dist/command/cli/verify-results.js +3 -1
  74. package/dist/command/cli.d.ts +1 -7
  75. package/dist/command/cli.js +79 -160
  76. package/dist/command/daemon/daemon-resilience.d.ts +6 -1
  77. package/dist/command/daemon/daemon-resilience.js +31 -18
  78. package/dist/command/daemon/daemon.d.ts +11 -0
  79. package/dist/command/daemon/daemon.js +70 -2
  80. package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
  81. package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
  82. package/dist/command/daemon/wake-decision.js +4 -2
  83. package/dist/command/daemon/win32-escape.d.ts +32 -0
  84. package/dist/command/daemon/win32-escape.js +119 -0
  85. package/dist/command/setup/agent-configs.d.ts +9 -0
  86. package/dist/command/setup/agent-configs.js +9 -0
  87. package/dist/command/setup/auto-approve.d.ts +10 -3
  88. package/dist/command/setup/auto-approve.js +51 -3
  89. package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
  90. package/dist/command/setup/bringup/dev-server-wait.js +5 -1
  91. package/dist/command/setup/bringup/ensure-daemon.js +4 -7
  92. package/dist/command/setup/init/init-host.js +6 -0
  93. package/dist/command/setup/init/init-port.js +5 -4
  94. package/dist/command/setup/init/init-runtime.js +7 -1
  95. package/dist/command/setup/node-effects.d.ts +8 -0
  96. package/dist/command/setup/node-effects.js +36 -4
  97. package/dist/command/setup/probe/dev-port.d.ts +26 -0
  98. package/dist/command/setup/probe/dev-port.js +117 -0
  99. package/dist/command/setup/probe/page-probe.d.ts +1 -1
  100. package/dist/command/setup/probe/page-probe.js +11 -3
  101. package/dist/command/setup/remaining-steps.d.ts +0 -7
  102. package/dist/command/setup/remaining-steps.js +3 -2
  103. package/dist/command/setup/run-setup.d.ts +11 -0
  104. package/dist/command/setup/run-setup.js +33 -5
  105. package/dist/command/setup/setup-command.d.ts +2 -0
  106. package/dist/command/setup/setup-command.js +22 -4
  107. package/dist/command/update/updater.d.ts +1 -6
  108. package/dist/command/update/updater.js +4 -5
  109. package/dist/command/update/version-seen.d.ts +24 -0
  110. package/dist/command/update/version-seen.js +65 -0
  111. package/dist/command/version/peer-announce.d.ts +9 -1
  112. package/dist/command/version/peer-announce.js +25 -2
  113. package/dist/command/version/sdk-fix.d.ts +5 -6
  114. package/dist/command/version/sdk-fix.js +17 -32
  115. package/dist/command/version/version-skew.d.ts +16 -1
  116. package/dist/command/version/version-skew.js +84 -10
  117. package/dist/features/crawl/crawl-tools.js +2 -2
  118. package/dist/features/crawl/crawl.js +2 -0
  119. package/dist/features/exhaust/ledger.d.ts +15 -96
  120. package/dist/features/exhaust/ledger.js +3 -3
  121. package/dist/features/harness/drive-runs.d.ts +28 -4
  122. package/dist/features/harness/drive-runs.js +99 -7
  123. package/dist/features/harness/drivers.d.ts +1 -1
  124. package/dist/features/harness/drivers.js +1 -1
  125. package/dist/features/harness/harness.d.ts +5 -0
  126. package/dist/features/harness/harness.js +24 -12
  127. package/dist/features/harness/platform/platform-drives.d.ts +7 -1
  128. package/dist/features/harness/platform/platform-drives.js +12 -7
  129. package/dist/features/harness/platform/refusal.d.ts +1 -1
  130. package/dist/features/harness/platform/refusal.js +4 -4
  131. package/dist/features/harness/platform/remote-drive.js +70 -28
  132. package/dist/features/harness/platform/server-driver.js +22 -1
  133. package/dist/features/harness/platform-config.d.ts +1 -10
  134. package/dist/features/harness/platform-config.js +0 -20
  135. package/dist/features/license/license.d.ts +2 -14
  136. package/dist/features/visual/step-shots.d.ts +33 -1
  137. package/dist/features/visual/step-shots.js +155 -1
  138. package/dist/features/visual/visual-tools.js +12 -4
  139. package/dist/hooks/coding-agents.d.ts +6 -0
  140. package/dist/hooks/coding-agents.js +24 -3
  141. package/dist/hooks/episode-stamp.d.ts +32 -0
  142. package/dist/hooks/episode-stamp.js +61 -0
  143. package/dist/hooks/hook-commands.js +19 -9
  144. package/dist/index.d.ts +5 -1
  145. package/dist/index.js +66 -24
  146. package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
  147. package/dist/judgement/app-graph/journal-steps.js +92 -0
  148. package/dist/judgement/capsule/capsule-store.d.ts +2 -39
  149. package/dist/judgement/domain/domain-model.js +1 -10
  150. package/dist/judgement/domain/domain-tools.js +4 -2
  151. package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
  152. package/dist/judgement/runs/artifact/run-store.js +153 -28
  153. package/dist/judgement/runs/default-run-id.d.ts +3 -1
  154. package/dist/judgement/runs/default-run-id.js +15 -3
  155. package/dist/judgement/runs/drive-run.d.ts +3 -3
  156. package/dist/judgement/runs/drive-run.js +11 -7
  157. package/dist/judgement/runs/run-ledger.d.ts +21 -0
  158. package/dist/judgement/runs/run-ledger.js +143 -0
  159. package/dist/judgement/runs/runner-port.d.ts +1 -1
  160. package/dist/judgement/runs/runner-port.js +8 -2
  161. package/dist/judgement/runs/verification-sync.d.ts +4 -3
  162. package/dist/judgement/runs/verification-sync.js +27 -5
  163. package/dist/language/flows/affected-tools.js +2 -1
  164. package/dist/language/flows/annotate-notes/annotate.js +8 -3
  165. package/dist/language/flows/annotate-tools.js +1 -1
  166. package/dist/language/flows/change/affected.d.ts +8 -0
  167. package/dist/language/flows/change/affected.js +20 -7
  168. package/dist/language/flows/decision.js +19 -4
  169. package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
  170. package/dist/language/flows/fields/flow-secret-field.js +67 -5
  171. package/dist/language/flows/flow-anchor.d.ts +5 -0
  172. package/dist/language/flows/flow-anchor.js +4 -0
  173. package/dist/language/flows/flow-cross-step.d.ts +7 -1
  174. package/dist/language/flows/flow-cross-step.js +9 -0
  175. package/dist/language/flows/flow-expect-grammar.js +15 -10
  176. package/dist/language/flows/flow-intent.js +6 -1
  177. package/dist/language/flows/flow-journey.d.ts +8 -0
  178. package/dist/language/flows/flow-journey.js +13 -0
  179. package/dist/language/flows/flow-lease.d.ts +27 -0
  180. package/dist/language/flows/flow-lease.js +59 -0
  181. package/dist/language/flows/flow-replay-run.d.ts +1 -87
  182. package/dist/language/flows/flow-replay-run.js +111 -310
  183. package/dist/language/flows/flow-replay.js +21 -19
  184. package/dist/language/flows/flow-replayable.d.ts +38 -0
  185. package/dist/language/flows/flow-replayable.js +179 -0
  186. package/dist/language/flows/flow-start-path.d.ts +108 -0
  187. package/dist/language/flows/flow-start-path.js +313 -0
  188. package/dist/language/flows/flow-step-runners.d.ts +23 -2
  189. package/dist/language/flows/flow-step-runners.js +191 -32
  190. package/dist/language/flows/flow-store-for-session.d.ts +8 -1
  191. package/dist/language/flows/flow-store-for-session.js +6 -0
  192. package/dist/language/flows/flow-tools.d.ts +2 -23
  193. package/dist/language/flows/flow-tools.js +63 -113
  194. package/dist/language/flows/flows.d.ts +4 -6
  195. package/dist/language/flows/flows.js +90 -15
  196. package/dist/language/flows/heal-run.d.ts +10 -4
  197. package/dist/language/flows/heal-run.js +26 -9
  198. package/dist/language/flows/recording/flake.d.ts +3 -27
  199. package/dist/language/flows/recording/flake.js +1 -1
  200. package/dist/language/flows/recording/recording-backtrack.js +1 -4
  201. package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
  202. package/dist/language/flows/recording/tape/recordings.js +9 -3
  203. package/dist/language/flows/replay.d.ts +25 -5
  204. package/dist/language/flows/replay.js +83 -16
  205. package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
  206. package/dist/language/flows/suite/coverage.d.ts +9 -0
  207. package/dist/language/flows/suite/coverage.js +12 -1
  208. package/dist/language/flows/suite-selection.d.ts +25 -0
  209. package/dist/language/flows/suite-selection.js +41 -9
  210. package/dist/machine/git-tracks.d.ts +6 -0
  211. package/dist/machine/git-tracks.js +36 -0
  212. package/dist/memory/cloud/background-sync.d.ts +25 -0
  213. package/dist/memory/cloud/background-sync.js +79 -0
  214. package/dist/memory/cloud/cloud-config.d.ts +12 -1
  215. package/dist/memory/cloud/cloud-config.js +39 -13
  216. package/dist/memory/cloud/cloud-sync.d.ts +3 -24
  217. package/dist/memory/cloud/cloud-sync.js +5 -2
  218. package/dist/memory/cloud/harness-config.d.ts +0 -7
  219. package/dist/memory/cloud/memory-scope.d.ts +19 -0
  220. package/dist/memory/cloud/memory-scope.js +48 -0
  221. package/dist/memory/cloud/sync-answer.d.ts +43 -0
  222. package/dist/memory/cloud/sync-answer.js +42 -0
  223. package/dist/memory/cloud/sync-cycle.d.ts +40 -10
  224. package/dist/memory/cloud/sync-cycle.js +97 -144
  225. package/dist/memory/cloud/sync-daemon.d.ts +50 -3
  226. package/dist/memory/cloud/sync-daemon.js +473 -83
  227. package/dist/memory/cloud/sync-describe.d.ts +28 -0
  228. package/dist/memory/cloud/sync-describe.js +92 -0
  229. package/dist/memory/cloud/sync-disk.d.ts +9 -1
  230. package/dist/memory/cloud/sync-disk.js +137 -33
  231. package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
  232. package/dist/memory/cloud/sync-flow-versions.js +42 -0
  233. package/dist/memory/impact/impact-store.js +32 -15
  234. package/dist/memory/intent/intent-shard.d.ts +41 -266
  235. package/dist/memory/intent/intent-tools.js +20 -61
  236. package/dist/memory/intent/record-request.d.ts +27 -0
  237. package/dist/memory/intent/record-request.js +88 -0
  238. package/dist/memory/intent/settled-words.js +9 -1
  239. package/dist/memory/journal/drive-flow.d.ts +3 -0
  240. package/dist/memory/journal/drive-flow.js +11 -41
  241. package/dist/memory/journal/envelope-store.js +1 -1
  242. package/dist/memory/journal/envelope.d.ts +6 -154
  243. package/dist/memory/journal/episode-log.d.ts +107 -0
  244. package/dist/memory/journal/episode-log.js +302 -0
  245. package/dist/memory/journal/journal-recorder.d.ts +7 -0
  246. package/dist/memory/journal/journal-recorder.js +22 -9
  247. package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
  248. package/dist/memory/journal/on-disk/ambient-file.js +1 -1
  249. package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
  250. package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
  251. package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
  252. package/dist/memory/journal/self-observation.js +3 -1
  253. package/dist/memory/journal/session-end.js +23 -9
  254. package/dist/memory/journal/session-journal.js +39 -20
  255. package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
  256. package/dist/memory/project/artifact-root-resolver.js +68 -23
  257. package/dist/memory/project/artifact-root.d.ts +17 -3
  258. package/dist/memory/project/artifact-root.js +47 -9
  259. package/dist/memory/project/fs/fs-port.d.ts +5 -0
  260. package/dist/memory/project/fs/fs-port.js +13 -0
  261. package/dist/memory/project/learned-routes.d.ts +3 -4
  262. package/dist/memory/project/learned-routes.js +3 -11
  263. package/dist/memory/project/link-directory.js +5 -2
  264. package/dist/memory/project/root-claims.d.ts +3 -1
  265. package/dist/memory/project/root-claims.js +41 -7
  266. package/dist/memory/project/session-root.d.ts +1 -1
  267. package/dist/memory/project/session-root.js +1 -15
  268. package/dist/memory/project/sync-status.js +5 -6
  269. package/dist/memory/recall/memory-tools.js +2 -2
  270. package/dist/memory/recall/platform-memory.d.ts +3 -1
  271. package/dist/memory/recall/platform-memory.js +9 -1
  272. package/dist/memory/recall/project-memory.js +15 -19
  273. package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
  274. package/dist/portal/bridge/auth-failure-reason.js +19 -0
  275. package/dist/portal/bridge/bridge.d.ts +19 -4
  276. package/dist/portal/bridge/bridge.js +150 -177
  277. package/dist/portal/bridge/harness-request.d.ts +15 -0
  278. package/dist/portal/bridge/harness-request.js +19 -0
  279. package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
  280. package/dist/portal/bridge/origin/origin-follow.js +110 -0
  281. package/dist/portal/bridge/pairing-token.d.ts +6 -0
  282. package/dist/portal/bridge/pairing-token.js +47 -16
  283. package/dist/portal/bridge/protocol-skew.d.ts +27 -2
  284. package/dist/portal/bridge/protocol-skew.js +66 -2
  285. package/dist/portal/bridge/session-nonces.d.ts +46 -0
  286. package/dist/portal/bridge/session-nonces.js +72 -0
  287. package/dist/portal/input/viewport-tools.d.ts +31 -0
  288. package/dist/portal/input/viewport-tools.js +106 -15
  289. package/dist/portal/pool/bounded-close.d.ts +23 -0
  290. package/dist/portal/pool/bounded-close.js +38 -0
  291. package/dist/portal/pool/browser-pool.d.ts +44 -39
  292. package/dist/portal/pool/browser-pool.js +247 -95
  293. package/dist/portal/pool/context-permissions.d.ts +9 -1
  294. package/dist/portal/pool/context-permissions.js +26 -0
  295. package/dist/portal/pool/lease-emulation.d.ts +37 -0
  296. package/dist/portal/pool/lease-emulation.js +29 -0
  297. package/dist/portal/pool/playwright-launcher.d.ts +6 -0
  298. package/dist/portal/pool/playwright-launcher.js +74 -7
  299. package/dist/portal/pool/pool-contract.d.ts +23 -1
  300. package/dist/portal/pool/pool-lease.d.ts +128 -0
  301. package/dist/portal/pool/pool-lease.js +49 -0
  302. package/dist/portal/pool/zero-install.d.ts +8 -1
  303. package/dist/portal/pool/zero-install.js +24 -2
  304. package/dist/portal/production/production-activation.d.ts +136 -0
  305. package/dist/portal/production/production-activation.js +173 -0
  306. package/dist/portal/production/production-drive.d.ts +52 -0
  307. package/dist/portal/production/production-drive.js +301 -0
  308. package/dist/portal/production/production-hello.d.ts +23 -0
  309. package/dist/portal/production/production-hello.js +23 -0
  310. package/dist/portal/realm/web-realm.js +42 -15
  311. package/dist/portal/session/control-envelope.d.ts +1 -1
  312. package/dist/portal/session/dev-server/served-document.d.ts +0 -5
  313. package/dist/portal/session/dev-server/served-document.js +6 -8
  314. package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
  315. package/dist/portal/session/first-run-wiring.d.ts +3 -36
  316. package/dist/portal/session/first-run-wiring.js +10 -103
  317. package/dist/portal/session/live-control-tools.js +61 -19
  318. package/dist/portal/session/no-session-next-action.d.ts +11 -0
  319. package/dist/portal/session/no-session-next-action.js +40 -15
  320. package/dist/portal/session/no-session-watch.d.ts +7 -0
  321. package/dist/portal/session/no-session-watch.js +67 -23
  322. package/dist/portal/session/output-budget.d.ts +10 -0
  323. package/dist/portal/session/output-budget.js +16 -0
  324. package/dist/portal/session/presence/session-lease.d.ts +2 -0
  325. package/dist/portal/session/presence/session-lease.js +8 -0
  326. package/dist/portal/session/recorded-gaps.d.ts +15 -11
  327. package/dist/portal/session/recorded-gaps.js +39 -18
  328. package/dist/portal/session/serving-directory.d.ts +24 -2
  329. package/dist/portal/session/serving-directory.js +93 -5
  330. package/dist/portal/session/session-info.d.ts +26 -0
  331. package/dist/portal/session/session-info.js +20 -0
  332. package/dist/portal/session/session-manager.d.ts +35 -3
  333. package/dist/portal/session/session-manager.js +69 -14
  334. package/dist/portal/session/session-successor.js +1 -9
  335. package/dist/portal/session/session-tools.js +22 -4
  336. package/dist/portal/session/session.d.ts +10 -10
  337. package/dist/portal/session/session.js +37 -29
  338. package/dist/portal/session/zero-install-first-call.d.ts +7 -2
  339. package/dist/portal/session/zero-install-first-call.js +43 -20
  340. package/dist/start-wiring.d.ts +2 -2
  341. package/dist/start-wiring.js +17 -3
  342. package/dist/status-payload.d.ts +11 -1
  343. package/dist/status-payload.js +7 -1
  344. package/dist/surface/agent-presence-grace.d.ts +11 -0
  345. package/dist/surface/agent-presence-grace.js +34 -0
  346. package/dist/surface/http-server.d.ts +12 -1
  347. package/dist/surface/http-server.js +64 -15
  348. package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
  349. package/dist/surface/mcp/faults/mcp-outage.js +19 -1
  350. package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
  351. package/dist/surface/mcp/mcp-proxy.js +194 -267
  352. package/dist/surface/mcp/mcp.d.ts +20 -3
  353. package/dist/surface/mcp/mcp.js +88 -25
  354. package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
  355. package/dist/surface/mcp/proxy/drive-calls.js +114 -5
  356. package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
  357. package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
  358. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
  359. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
  360. package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
  361. package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
  362. package/dist/surface/mcp/server-instructions.js +35 -16
  363. package/dist/surface/mcp/shared-params.d.ts +8 -0
  364. package/dist/surface/mcp/shared-params.js +15 -1
  365. package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
  366. package/dist/surface/mcp/sse-frame-parser.js +18 -0
  367. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  368. package/dist/surface/mcp/surface-vocabulary.js +13 -0
  369. package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
  370. package/dist/surface/mcp/tool-catalog-cache.js +14 -4
  371. package/dist/surface/tools/account-tool.d.ts +4 -3
  372. package/dist/surface/tools/account-tool.js +20 -31
  373. package/dist/surface/tools/act/act-danger.d.ts +2 -0
  374. package/dist/surface/tools/act/act-danger.js +41 -14
  375. package/dist/surface/tools/act/act-observation.d.ts +11 -0
  376. package/dist/surface/tools/act/act-observation.js +33 -0
  377. package/dist/surface/tools/act/act-preflight.js +10 -3
  378. package/dist/surface/tools/act/act-sequence-retry.js +2 -1
  379. package/dist/surface/tools/act/act-target.js +19 -5
  380. package/dist/surface/tools/act/durable.js +1 -1
  381. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
  382. package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
  383. package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
  384. package/dist/surface/tools/act/unsettled-find.js +71 -0
  385. package/dist/surface/tools/act-sequence-tool.js +53 -24
  386. package/dist/surface/tools/act-tools.d.ts +2 -3
  387. package/dist/surface/tools/act-tools.js +49 -47
  388. package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
  389. package/dist/surface/tools/agent/for-the-agent.js +41 -3
  390. package/dist/surface/tools/assert/assert-grade.js +8 -3
  391. package/dist/surface/tools/assert/assert-verdict.js +4 -2
  392. package/dist/surface/tools/browser-tools.js +7 -4
  393. package/dist/surface/tools/chat-drives.js +50 -25
  394. package/dist/surface/tools/coverage-tools.js +1 -1
  395. package/dist/surface/tools/dynamic-tools.d.ts +8 -0
  396. package/dist/surface/tools/dynamic-tools.js +89 -34
  397. package/dist/surface/tools/empty-session-list.d.ts +18 -25
  398. package/dist/surface/tools/empty-session-list.js +67 -38
  399. package/dist/surface/tools/error-recovery.d.ts +17 -7
  400. package/dist/surface/tools/error-recovery.js +53 -20
  401. package/dist/surface/tools/explore-tools.d.ts +10 -0
  402. package/dist/surface/tools/explore-tools.js +72 -19
  403. package/dist/surface/tools/feedback-tools.js +23 -2
  404. package/dist/surface/tools/gap-novelty.d.ts +6 -0
  405. package/dist/surface/tools/gap-novelty.js +9 -0
  406. package/dist/surface/tools/gaps/capability-absences.js +4 -3
  407. package/dist/surface/tools/harness-explore.d.ts +1 -1
  408. package/dist/surface/tools/harness-explore.js +6 -4
  409. package/dist/surface/tools/harness-gate.d.ts +43 -21
  410. package/dist/surface/tools/harness-gate.js +55 -81
  411. package/dist/surface/tools/harness-script.d.ts +2 -0
  412. package/dist/surface/tools/harness-script.js +11 -6
  413. package/dist/surface/tools/harness-toolset.js +3 -4
  414. package/dist/surface/tools/invoke-tool.d.ts +0 -8
  415. package/dist/surface/tools/invoke-tool.js +164 -178
  416. package/dist/surface/tools/lease-hint.d.ts +9 -0
  417. package/dist/surface/tools/lease-hint.js +22 -3
  418. package/dist/surface/tools/lease-permissions.d.ts +1 -1
  419. package/dist/surface/tools/lease-readiness.d.ts +55 -0
  420. package/dist/surface/tools/lease-readiness.js +150 -2
  421. package/dist/surface/tools/lease-tools.d.ts +3 -75
  422. package/dist/surface/tools/lease-tools.js +124 -188
  423. package/dist/surface/tools/map-tools.d.ts +20 -0
  424. package/dist/surface/tools/map-tools.js +145 -0
  425. package/dist/surface/tools/merge-tools.js +11 -7
  426. package/dist/surface/tools/next-step.js +6 -3
  427. package/dist/surface/tools/observe-tools.js +46 -35
  428. package/dist/surface/tools/platform-moment.d.ts +3 -12
  429. package/dist/surface/tools/platform-moment.js +12 -24
  430. package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
  431. package/dist/surface/tools/read/complete-snapshot.js +13 -2
  432. package/dist/surface/tools/read/query-paginate.js +6 -0
  433. package/dist/surface/tools/read/query-shape.d.ts +9 -0
  434. package/dist/surface/tools/read/query-shape.js +15 -0
  435. package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
  436. package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
  437. package/dist/surface/tools/read-tools.js +5 -5
  438. package/dist/surface/tools/real-input-attempt.d.ts +11 -0
  439. package/dist/surface/tools/real-input-attempt.js +206 -38
  440. package/dist/surface/tools/reconcile-tools.js +21 -8
  441. package/dist/surface/tools/reticle-result.d.ts +3 -0
  442. package/dist/surface/tools/reticle-result.js +8 -1
  443. package/dist/surface/tools/run-report.d.ts +22 -0
  444. package/dist/surface/tools/run-report.js +141 -0
  445. package/dist/surface/tools/session-ports.d.ts +57 -0
  446. package/dist/surface/tools/session-ports.js +102 -0
  447. package/dist/surface/tools/tool-kit.d.ts +58 -4
  448. package/dist/surface/tools/tool-kit.js +140 -6
  449. package/dist/surface/tools/tool-surface.d.ts +2 -0
  450. package/dist/surface/tools/tool-surface.js +45 -0
  451. package/dist/surface/tools/tools.js +49 -87
  452. package/dist/telemetry/automation-hint.d.ts +5 -0
  453. package/dist/telemetry/automation-hint.js +7 -0
  454. package/dist/telemetry/cli-telemetry.d.ts +22 -0
  455. package/dist/telemetry/cli-telemetry.js +80 -11
  456. package/dist/telemetry/daemon-telemetry.d.ts +3 -1
  457. package/dist/telemetry/daemon-telemetry.js +9 -2
  458. package/dist/telemetry/feedback-cli.d.ts +1 -1
  459. package/dist/telemetry/feedback-cli.js +8 -3
  460. package/dist/telemetry/feedback.d.ts +1 -1
  461. package/dist/telemetry/feedback.js +51 -4
  462. package/dist/telemetry/harness-run.d.ts +3 -3
  463. package/dist/telemetry/harness-run.js +18 -7
  464. package/dist/telemetry/hud-events.d.ts +1 -1
  465. package/dist/telemetry/hud-metrics.d.ts +6 -3
  466. package/dist/telemetry/hud-metrics.js +20 -8
  467. package/dist/telemetry/install-source.js +1 -1
  468. package/dist/telemetry/mcp-connection.d.ts +1 -1
  469. package/dist/telemetry/mcp-connection.js +21 -2
  470. package/dist/telemetry/onboarding-firsts.d.ts +6 -1
  471. package/dist/telemetry/onboarding-firsts.js +41 -1
  472. package/dist/telemetry/proxy-telemetry.d.ts +42 -0
  473. package/dist/telemetry/proxy-telemetry.js +70 -1
  474. package/dist/telemetry/session-metrics.d.ts +1 -3
  475. package/dist/telemetry/session-metrics.js +16 -12
  476. package/dist/telemetry/telemetry.d.ts +9 -1
  477. package/dist/telemetry/telemetry.js +16 -1
  478. package/dist/telemetry/verification-of.d.ts +3 -1
  479. package/dist/telemetry/verification-of.js +7 -1
  480. package/dist/wire-journal.js +12 -2
  481. package/docs/README.md +4 -2
  482. package/docs/actions.mdx +7 -6
  483. package/docs/adapters.md +2 -1
  484. package/docs/agent-cheatsheet.md +19 -5
  485. package/docs/architecture.md +13 -10
  486. package/docs/autodrive.md +6 -5
  487. package/docs/benchmarks.md +2 -2
  488. package/docs/capabilities.mdx +1 -1
  489. package/docs/cli/affected.mdx +1 -1
  490. package/docs/cli/cloud.mdx +6 -6
  491. package/docs/cli/doctor.mdx +3 -1
  492. package/docs/cli/feedback.mdx +11 -7
  493. package/docs/cli/gate.mdx +1 -1
  494. package/docs/cli/help.mdx +1 -1
  495. package/docs/cli/init.mdx +20 -16
  496. package/docs/cli/mcp.mdx +5 -2
  497. package/docs/cli/open.mdx +5 -2
  498. package/docs/cli/report.mdx +1 -1
  499. package/docs/cli/restart.mdx +1 -1
  500. package/docs/cli/rollback.mdx +4 -4
  501. package/docs/cli/serve.mdx +7 -5
  502. package/docs/cli/setup.mdx +1 -1
  503. package/docs/cli/status.mdx +6 -2
  504. package/docs/cli/stop.mdx +3 -3
  505. package/docs/cli/telemetry.mdx +5 -1
  506. package/docs/cli/try.mdx +8 -8
  507. package/docs/cli/update.mdx +8 -5
  508. package/docs/cli/verify.mdx +12 -5
  509. package/docs/cli/version.mdx +1 -1
  510. package/docs/cli.mdx +10 -6
  511. package/docs/debugging.md +1 -1
  512. package/docs/deploy-checks.md +8 -6
  513. package/docs/desktop.mdx +14 -18
  514. package/docs/enterprise.md +6 -6
  515. package/docs/environment.mdx +5 -3
  516. package/docs/faq.mdx +9 -6
  517. package/docs/first-drive.md +19 -9
  518. package/docs/flows.md +3 -4
  519. package/docs/for-agents.md +1 -1
  520. package/docs/frameworks.mdx +34 -11
  521. package/docs/getting-started.md +46 -29
  522. package/docs/http-transport.md +2 -2
  523. package/docs/human-control.md +8 -8
  524. package/docs/index.mdx +2 -2
  525. package/docs/install-agentic.mdx +18 -19
  526. package/docs/install-manual.mdx +8 -4
  527. package/docs/integration-patterns.md +5 -5
  528. package/docs/multi-agent-testing.md +7 -5
  529. package/docs/packages/browser.mdx +34 -2
  530. package/docs/packages/core.mdx +2 -1
  531. package/docs/packages/electron.mdx +15 -3
  532. package/docs/packages/eslint-plugin.mdx +1 -1
  533. package/docs/packages/next.mdx +17 -5
  534. package/docs/packages/react.mdx +8 -1
  535. package/docs/packages/server.mdx +3 -3
  536. package/docs/packages/tauri.mdx +3 -3
  537. package/docs/packages/vite-plugin.mdx +1 -1
  538. package/docs/packages.mdx +19 -6
  539. package/docs/platform-integration.md +12 -4
  540. package/docs/predicates.mdx +18 -7
  541. package/docs/production-mode.md +108 -0
  542. package/docs/prompt-capture.md +99 -0
  543. package/docs/quickstart.mdx +14 -12
  544. package/docs/recipes.mdx +9 -8
  545. package/docs/required-checks.md +3 -2
  546. package/docs/skill-file.mdx +4 -3
  547. package/docs/skill-setup.md +2 -2
  548. package/docs/skill.md +62 -70
  549. package/docs/state-files.md +1 -0
  550. package/docs/state-management.mdx +11 -9
  551. package/docs/system-map.md +14 -13
  552. package/docs/telemetry.md +32 -24
  553. package/docs/testing.md +9 -5
  554. package/docs/tools/act-and-wait.mdx +17 -13
  555. package/docs/tools/act-sequence.mdx +40 -66
  556. package/docs/tools/act.mdx +7 -5
  557. package/docs/tools/assert.mdx +1 -1
  558. package/docs/tools/look.mdx +1 -1
  559. package/docs/tools/navigate.mdx +1 -1
  560. package/docs/tools/network.mdx +13 -11
  561. package/docs/tools/overview.mdx +3 -3
  562. package/docs/tools/query.mdx +3 -3
  563. package/docs/tools/session-and-feedback.mdx +9 -6
  564. package/docs/tools/sessions.mdx +7 -0
  565. package/docs/tools/snapshot.mdx +9 -7
  566. package/docs/tools/tools-and-run.mdx +11 -10
  567. package/docs/tools/verify.mdx +1 -1
  568. package/docs/troubleshooting.mdx +21 -9
  569. package/docs/usage.md +58 -43
  570. package/docs/use-cases.mdx +2 -2
  571. package/docs/vs-chrome-devtools-mcp.mdx +5 -5
  572. package/docs/vs-playwright-mcp.mdx +5 -4
  573. package/docs/what-is-recorded.md +12 -7
  574. package/docs/what-is-reticle.mdx +2 -2
  575. package/docs/why-reticle.mdx +1 -1
  576. package/package.json +9 -12
  577. package/dist/command/dev/stale-issue-guard.d.ts +0 -34
  578. package/dist/command/dev/stale-issue-guard.js +0 -69
@@ -12,15 +12,15 @@ icon: rocket
12
12
 
13
13
  This walks you from zero to your agent verifying your app, step by step, with real code for real frameworks. ~10 minutes.
14
14
 
15
- - [What you're setting up](#what-youre-setting-up)
15
+ - [What you set up](#what-you-set-up)
16
16
  - [Prerequisites](#prerequisites)
17
- - [Step 1: Connect your coding agent (MCP), once](#step-1-connect-your-coding-agent-mcp-once)
17
+ - [Step 1: Connect your coding agent to the MCP server](#step-1-connect-your-coding-agent-to-the-mcp-server)
18
18
  - [Wire your app: on the first run, or `reticle init`](#wire-your-app-on-the-first-run-or-reticle-init)
19
19
  - [Add a cloud dashboard: `reticle connect`](#add-a-cloud-dashboard-reticle-connect)
20
20
  - [Step 2: Embed the SDK in your app](#step-2-embed-the-sdk-in-your-app)
21
- - [Vite + React](#vite--react)
22
- - [Next.js](#nextjs)
23
- - [Plain / other frameworks](#plain--other-frameworks)
21
+ - [Vite and React](#vite-and-react)
22
+ - [Next.js](#next-js)
23
+ - [Plain HTML and other frameworks](#plain-html-and-other-frameworks)
24
24
  - [Step 3: (React) component and source-file mapping](#step-3-react-component-and-source-file-mapping)
25
25
  - [Step 4: Run it and verify the connection](#step-4-run-it-and-verify-the-connection)
26
26
  - [Step 5: Your first verification](#step-5-your-first-verification)
@@ -30,7 +30,7 @@ This walks you from zero to your agent verifying your app, step by step, with re
30
30
 
31
31
  ---
32
32
 
33
- ## What you're setting up
33
+ ## What you set up
34
34
 
35
35
  Three pieces, each tiny:
36
36
 
@@ -50,7 +50,7 @@ Three pieces, each from the package for its audience:
50
50
  2. **The SDK**: `import { reticle } from '@reticlehq/react'`, a few lines in your app's dev entry point.
51
51
  3. **(Optional) React adapter + source-mapping**, so `reticle_look { action: "element" }` can tell the agent which component/file to edit (also from `@reticlehq/react`).
52
52
 
53
- Everything is **dev-only** and **localhost-only**. It's tree-shaken out of production builds.
53
+ By default, everything is **dev-only** and **localhost-only**, and it is removed from production builds. [Production mode](/production-mode) is a separate opt-in.
54
54
 
55
55
  ## Prerequisites
56
56
 
@@ -60,7 +60,7 @@ Everything is **dev-only** and **localhost-only**. It's tree-shaken out of produ
60
60
 
61
61
  ---
62
62
 
63
- ## Step 1: Connect your coding agent (MCP), once
63
+ ## Step 1: Connect your coding agent to the MCP server
64
64
 
65
65
  You don't start the server manually; your agent starts it via MCP. Register Reticle **once, at the user (global) scope** so every project picks it up. There's nothing to add per project.
66
66
 
@@ -99,7 +99,7 @@ Other MCP clients (Windsurf, Claude Desktop, …) use the same `command`/`args`
99
99
 
100
100
  ## Wire your app: on the first run, or `reticle init`
101
101
 
102
- Installing Reticle changes nothing in your project. The first time your agent uses Reticle in a project that has never connected (its first `reticle_session { action: "list" }`), Reticle runs `init` there itself and returns the files it changed under `wired`, so you can skip straight to asking your agent to verify a flow. That call wires the project the agent is in, including a second project on a machine where Reticle is already running for another one. Run `init` yourself to wire a project ahead of time, to preview the changes, or when the agent's MCP server was started outside the project (the call then answers `run_init` with this same command).
102
+ Installing Reticle changes nothing in your project, and your agent's Reticle calls do not wire it either. In a project that has never connected, the first `reticle_session { action: "list" }` changes no file. It names the zero-install lease, which checks the running app now with nothing installed, and it tells the agent to ask you before it runs `init`. `init` changes files, so it runs only when you agree. Run `init` yourself to wire a project ahead of time or to preview the changes.
103
103
 
104
104
  From your project root:
105
105
 
@@ -116,11 +116,11 @@ It detects your framework, package manager, and React version, then:
116
116
  - **Next:** wraps `next.config` in `withReticle` and mounts a generated `<ReticleDev />` component in your root layout; on a config shape it does not recognise it prints the snippet to paste instead (it never half-edits a build config).
117
117
  - **Other frameworks:** writes or prints the connect wiring for that framework (see [Frameworks](/frameworks)).
118
118
 
119
- The bridge + MCP server is a single process that serves all your projects, so it's registered at **user scope**, not in a per-project `.mcp.json`. Only the SDK (the `reticle()` plugin / connect call) is added per project.
119
+ The MCP registration is the same command for every project, so it is registered at **user scope**, not in a per-project `.mcp.json`. Reticle starts a daemon for each project when an agent needs one. Only the SDK (the `reticle()` plugin or the connect call) is added per project.
120
120
 
121
121
  Re-running is safe: already-registered and already-patched steps are skipped, and on a wired project it goes straight to proving the app still works. Preview without writing via `npx @reticlehq/server init --dry-run`.
122
122
 
123
- `init` does not stop at writing files. It starts your dev server, opens the app, and waits for a session to connect from inside it. That connection is the whole proof that onboarding worked. If a dev server was already running without Reticle, restart it once: it read the build config before `init` edited it. It exits non-zero if nothing connected and prints what is left to do. It does NOT drive. Then prove a flow. That is the FIRST RUN, and it is a separate call: drive one journey with `reticle_act_and_wait` and an `until` on its last step. On a project linked with `reticle connect`, `reticle_verify { action: "explore", persona: "<who does what>" }` lets the Reticle Harness drive it on the platform instead (every plan includes Harness credits, Free too). Either way what was driven is saved as a flow, so later checks replay it with no model in the loop.
123
+ `init` does not stop at writing files. It starts your dev server, opens the app, and waits for a session to connect from inside it. That connection is the whole proof that onboarding worked. If a dev server was already running without Reticle, restart it once: it read the build config before `init` edited it. It exits non-zero if nothing connected and prints what is left to do. It does NOT drive. Then prove a flow. That is the FIRST RUN, and it is a separate call: drive one journey with `reticle_act_and_wait` and an `until` on its last step. On a project linked with `reticle connect`, `reticle_verify { action: "explore", persona: "<who does what>" }` lets the Reticle Harness drive it on the platform instead (every plan includes credits, Free too). Either way what was driven is saved as a flow, so later checks replay it with no model in the loop.
124
124
 
125
125
  These carry what the command cannot work out for itself:
126
126
 
@@ -144,7 +144,7 @@ Optional. Instead of, or after, `init`, run this in your app directory:
144
144
  npx @reticlehq/server connect --project "My App"
145
145
  ```
146
146
 
147
- Approve the short browser code if Reticle asks you to sign in. The browser asks you to sign in, or to create a free account at app.reticle.sh. A new account gets 10 free credits to try the Harness. What syncs, and how to switch each part off, is in [What is recorded](what-is-recorded.md). The command then links this folder and sends any history already on the machine. Open or restart your coding agent and ask it to verify one real journey. For a new project, the dashboard has no result until that first run is recorded.
147
+ The browser opens. Sign in with Google or GitHub, or create a free account at app.reticle.sh, then approve the short code that the browser and the terminal show. A new account gets free credits to try the Harness. What syncs, and how to switch each part off, is in [What is recorded](what-is-recorded.md). The command then links this folder and sends any history already on the machine. Open or restart your coding agent and ask it to verify one real journey. For a new project, the dashboard has no result until that first run is recorded.
148
148
 
149
149
  ## Step 2: Embed the SDK in your app
150
150
 
@@ -157,7 +157,7 @@ npm i -D @reticlehq/react @reticlehq/vite-plugin # Vite; or: pnpm add -D …
157
157
 
158
158
  Then call `reticle.connect()` once, in dev only. Where you put it depends on your framework.
159
159
 
160
- ### Vite + React
160
+ ### Vite and React
161
161
 
162
162
  **Recommended: the Vite plugin (one line, does everything).** Add `reticle()` to your `vite.config.ts`:
163
163
 
@@ -206,12 +206,24 @@ On React 19 you then also need the source-mapping Babel plugin from Step 3. The
206
206
  The daemon auto-generates a **pairing token** on first run and stores it at `~/.reticle/pairing-token` (owner-only, `0600`). The bridge requires it, so another app running on `http://localhost:<some-other-port>` can't quietly register or drive your session. Only code that can read that file (your dev server, not a web page) can present it.
207
207
 
208
208
  - **Vite plugin users:** nothing to do. The plugin reads the token server-side and injects it into `connect()` for you.
209
- - **Next.js / hand-wired `connect()`:** your `connect()` runs in the browser and can't read the file, so pass the token in yourself. The simplest path is a shared secret: set `RETICLE_TOKEN` for the daemon (it uses that instead of auto-generating) and expose the same value to the client as `NEXT_PUBLIC_RETICLE_TOKEN`, then pass it to `connect({ token })` (see below). On a single-user machine you can also just read `~/.reticle/pairing-token` in your dev tooling and forward it the same way.
209
+ - **Next.js:** wrap `next.config` in `withReticle` from `@reticlehq/next` (see [Next.js](#next-js) below). It reads the token on the server and gives it to the browser as `NEXT_PUBLIC_RETICLE_TOKEN`, which the `ReticleDev` component passes to `connect()`. You do not set the token yourself.
210
+ - **Hand-wired `connect()` (no plugin):** run `npx @reticlehq/server init`. It writes the token to a git-ignored `reticle.local.js` and prints a snippet that imports it (see [Plain HTML and other frameworks](#plain-html-and-other-frameworks)).
210
211
  - **Keep the token out of `.env` files.** Pass it on the dev command (`VITE_RETICLE_TOKEN="$(cat ~/.reticle/pairing-token)" npm run dev`). A production build reads `.env` too, and would write the token into the JavaScript it ships.
211
212
 
212
213
  ### Next.js
213
214
 
214
- Create a tiny client component and mount it in your root layout, dev-only:
215
+ First wrap `next.config` in `withReticle`. It reads the pairing token on the server and passes it to the browser. Without it, the bridge refuses the connect:
216
+
217
+ ```ts
218
+ // next.config.ts
219
+ import { withReticle } from '@reticlehq/next';
220
+ import type { NextConfig } from 'next';
221
+
222
+ const nextConfig: NextConfig = {};
223
+ export default withReticle(nextConfig); // no-op in production
224
+ ```
225
+
226
+ Then create a small client component and mount it in your root layout, in development only:
215
227
 
216
228
  ```tsx
217
229
  // app/reticle-dev.tsx
@@ -253,26 +265,31 @@ export default function RootLayout({ children }: { children: React.ReactNode })
253
265
 
254
266
  Streamlit owns the top-level HTML document, so it has no template where the plain script tag below can be added. Scripts passed through `st.markdown(..., unsafe_allow_html=True)` are rendered but do not execute.
255
267
 
256
- With Streamlit 1.63 or newer, run `npx @reticlehq/server init` from the project. It detects a `streamlit` dependency or import and prints a copy-pasteable `st.html(..., unsafe_allow_javascript=True)` helper that loads Reticle once in the app document. Keep that helper development-only and do not commit the pairing token printed inside it.
268
+ With Streamlit 1.63 or newer, run `npx @reticlehq/server init` from the project. It detects a `streamlit` dependency or import and prints a copy-pasteable `st.html(..., unsafe_allow_javascript=True)` helper that loads Reticle once in the app document. The helper reads this machine's pairing token from `~/.reticle/pairing-token` when the page is served, so the token is not in the code you paste. Keep the helper development-only.
257
269
 
258
- ### Plain / other frameworks
270
+ ### Plain HTML and other frameworks
259
271
 
260
272
  Anywhere your app boots in dev:
261
273
 
262
274
  ```ts
263
- import { reticle, SESSION_AUTO } from '@reticlehq/react';
264
- // A dev-only guard the bundler strips from production builds (Vite shown), and the pairing token
265
- // (see "The pairing token" above) passed in on the dev command line only.
266
- if (import.meta.env.DEV) {
267
- reticle.connect({ session: SESSION_AUTO, token: import.meta.env.VITE_RETICLE_TOKEN });
275
+ // What `reticle init` prints for a bundled app with no Vite or Next plugin.
276
+ // reticle.local.js holds this machine's pairing token. Init writes it and adds it to .gitignore.
277
+ if (process.env.NODE_ENV !== 'production') {
278
+ void Promise.all([
279
+ import('@reticlehq/react'),
280
+ import('./reticle.local.js').catch(() => ({})),
281
+ ]).then(([{ reticle, install }, local]) => {
282
+ install();
283
+ reticle.connect({ token: local.token });
284
+ });
268
285
  }
269
286
  ```
270
287
 
271
- Not on Vite? Use your bundler's dev-only flag and its way of passing a value to the browser at dev time. Or run `npx @reticlehq/server init`, which wires the token for every supported stack.
288
+ Change the `./reticle.local.js` path so that it points to the project root from your entry module. Do not commit `reticle.local.js`: the token is for this machine only. A teammate runs `reticle init` to get their own.
272
289
 
273
290
  Plain HTML with no build step: run `npx @reticlehq/server init` in the folder that holds `index.html`. It adds a dev-only snippet that connects only on localhost, and puts this machine's pairing token in a gitignored `reticle.local.js` beside the page, so the token never lands in anything you publish. A hand-written script tag without that token is refused by the bridge.
274
291
 
275
- > **Want to watch the agent work?** Add `present: true` to `reticle.connect()` for a glowing border, a synthetic cursor that flies to targets, click/hover effects, and a narration HUD. See [usage §16](usage.md#16-presenter-mode-narration--fake-clock-watch--control).
292
+ > **Want to watch the agent work?** Add `present: true` to `reticle.connect()` for a glowing border, a synthetic cursor that flies to targets, click/hover effects, and a narration HUD. See [usage §16](usage.md#16-presenter-mode-narration-&-fake-clock-watch-+-control).
276
293
 
277
294
  ### Running multiple apps at once
278
295
 
@@ -442,9 +459,9 @@ registerCapabilities({
442
459
 
443
460
  > **Multi-domain apps:** prefer `registerReticleDomain({ testids, signals, stores })` co-located in one `reticle.ts` per domain. Each self-registers and `reticle_run({ tool: "reticle_capabilities", args: {} })` assembles the union, so there's no central map to forget. See [integration-patterns.md](integration-patterns.md).
444
461
 
445
- > Watch the agent work: pass `present: true` to `reticle.connect()` for a glowing border, a cursor that flies to targets, and a HUD; the agent can call `reticle_session({ action: "narrate", text })` to show its intent. See [usage §16](usage.md#16-presenter-mode-narration--fake-clock-watch--control).
462
+ > Watch the agent work: pass `present: true` to `reticle.connect()` for a glowing border, a cursor that flies to targets, and a HUD; the agent can call `reticle_session({ action: "narrate", text })` to show its intent. See [usage §16](usage.md#16-presenter-mode-narration-&-fake-clock-watch-+-control).
446
463
 
447
- > **Hover-gated UI (tooltips, hover menus, pointer drag)?** Synthetic events can't trigger native `onMouseEnter`. Enable **real input** by launching your browser with `--remote-debugging-port=9222` and setting `RETICLE_CDP_URL` in the MCP server `env`. Reticle then drives real pointer input and `reticle_act` reports `inputMode:"real"`. See [usage §18](usage.md#18-real-input-mode-native-hover--drag).
464
+ > **Hover-gated UI (tooltips, hover menus, pointer drag)?** Synthetic events can't trigger native `onMouseEnter`. Enable **real input** by launching your browser with `--remote-debugging-port=9222` and setting `RETICLE_CDP_URL` in the MCP server `env`. Reticle then drives real pointer input and `reticle_act` reports `inputMode:"real"`. See [usage §18](usage.md#18-real-input-mode-native-hover-&-drag).
448
465
 
449
466
  ---
450
467
 
@@ -494,7 +511,7 @@ Everything below comes from the `@reticlehq/react` kit plus your framework's bui
494
511
  - Port mismatch? If you set `RETICLE_PORT`, pass the same URL to `reticle.connect({ url: 'ws://localhost:<port>/reticle' })`.
495
512
  - Need to restart the daemon? **`reticle stop`** cleans it up, no `pkill` needed.
496
513
 
497
- The errors Reticle returns to the agent now carry a `recovery` hint for this exact situation (and for multiple/unknown sessions, a throttled tab, a missing baseline), so the agent knows the next move.
514
+ The errors that Reticle returns to the agent carry a `recovery` hint for this case, and for several or unknown sessions, a throttled tab and a missing baseline. The hint tells the agent what to do next.
498
515
 
499
516
  **The agent can't find an element**
500
517
 
@@ -539,7 +556,7 @@ A handful of files, none of them mysterious: a `.reticle.json` project config, y
539
556
 
540
557
  ### Do I have to re-register the MCP server for every project?
541
558
 
542
- No. The bridge and MCP server are a single process serving all your projects, so `init` registers it at user scope. Every later project starts with the tools already there. Only the SDK wiring is per project.
559
+ No. The registration is one command, `npx @reticlehq/server mcp`, for every project, so `init` registers it at user scope. Every later project starts with the tools already there. Only the SDK wiring is per project.
543
560
 
544
561
  ### Why do the Reticle tools not appear after installing?
545
562
 
@@ -563,4 +580,4 @@ No. Keep `connect()` behind a dev guard (`import.meta.env.DEV` or a `NODE_ENV` c
563
580
 
564
581
  ### Why is my install failing with `ERESOLVE`?
565
582
 
566
- You are almost certainly on a Next.js canary or a React RC. That is npm's semver rule for prereleases, not a Reticle restriction. Install with `--legacy-peer-deps`, or use pnpm, whose peer resolution does not hard-fail here. See [Installing alongside a Next.js or React prerelease](#installing-alongside-a-nextjs-or-react-prerelease) above.
583
+ You are almost certainly on a Next.js canary or a React RC. That is npm's semver rule for prereleases, not a Reticle restriction. Install with `--legacy-peer-deps`, or use pnpm, whose peer resolution does not hard-fail here. See [Installing alongside a Next.js or React prerelease](#installing-alongside-a-next-js-or-react-prerelease) above.
@@ -17,7 +17,7 @@ It is the same tool surface. Not a subset, not a simplified one. `reticle_look {
17
17
  | `GET` | `/mcp/sse` | Opens a session. The response is an SSE stream that stays open, and every reply the server sends comes back on it. |
18
18
  | `POST` | `/mcp/message?sessionId=<id>` | Sends one JSON-RPC message into an open session. |
19
19
 
20
- The daemon listens on port **4400** by default (`RETICLE_PORT`, or `reticle serve --port N`). Run `reticle status` to confirm which port is live.
20
+ The daemon port comes from `reticle serve --port N`, else `RETICLE_PORT`, else `port` in `.reticle.json`, else **4400**. Run `reticle status` to see which port is live.
21
21
 
22
22
  ## The handshake
23
23
 
@@ -64,7 +64,7 @@ Authorization: Bearer <token>
64
64
  /mcp/sse?token=<token>
65
65
  ```
66
66
 
67
- Set it with `RETICLE_TOKEN`. With no token configured, the daemon binds loopback-only and non-local requests are refused outright rather than falling back to trust.
67
+ The daemon uses `RETICLE_TOKEN` when it is set. Otherwise it uses the token it writes to `~/.reticle/pairing-token` (or `$RETICLE_PAIRING_TOKEN_DIR/pairing-token`). Read the token from there for a remote client, and do not paste it into a file that git tracks.
68
68
 
69
69
  ## A minimal client
70
70
 
@@ -4,9 +4,9 @@ description: 'Watch the agent’s live transcript, steer it mid-run, or end the
4
4
  icon: hand
5
5
  ---
6
6
 
7
- With the presenter on (`reticle.connect({ present: true })`), the floating panel in your page lets you watch the agent's live transcript and steer it: **pause** it (its next action tool refuses until you resume) or **end** the session. You can also point at a broken element with **Flag a bug** and hand the agent the element plus its source `file:line`.
7
+ With the presenter on (`reticle.connect({ present: true })`), the floating panel in your page lets you watch the agent's live transcript and steer it: **pause** it (its next action tool refuses until you resume) or **end** the session. You can also open **Notes**, select **Add notes**, and click a broken element. The agent gets the element and its source `file:line`.
8
8
 
9
- When you run with the presenter on (`reticle.connect({ present: true })`), the floating panel is a **two-way control surface**. You watch the agent's live transcript _and_ can steer it (pause it or end the session) without leaving the page. To tell the agent something, talk to it in its own window: the panel sends it no text. There's also a clean, unmistakable "session ended" signal for both you and the agent.
9
+ When you run with the presenter on (`reticle.connect({ present: true })`), the floating panel is a **two-way control surface**. You watch the agent's live transcript _and_ can steer it (pause it or end the session) without leaving the page. To give the agent an instruction, talk to it in its own window. The panel sends only notes pinned to elements, and the pause and end controls. There's also a clean, unmistakable "session ended" signal for both you and the agent.
10
10
 
11
11
  ## Watch the testing score climb (the live verdict tally)
12
12
 
@@ -28,16 +28,16 @@ The floating panel (bottom-center, `present: true`) gives you:
28
28
  - **Coding agent.** The Agent Log names the coding agent attached to Reticle (`Claude Code connected`, read from the MCP handshake). With no agent attached it says `No coding agent connected` and offers **Copy prompt**, a prompt to paste into one.
29
29
  - **Run Harness**, on the Harness page, drives the page as a person you pick: First-time visitor (the default), Returning power user, On a phone, slow connection, Keyboard only, Careless user (bad and unexpected input), Admin / settings, or Custom… in your own words. The pick is remembered per project. The agent hears about the drive on its next tool call (`harness`), with the `runId` to follow it.
30
30
  - **Minimise (▾)** collapses the panel to a bar that streams only the live line; click the bar to restore.
31
- - **Flag a bug**, the button in the corner. Toggle it on, click the element that looks wrong, type what's wrong (⌘/Ctrl+Enter to send, Esc to back out). Reticle pins a numbered marker, logs your flag in the panel, and hands the agent a structured mark. Notes are kept in `.reticle/notes.json` (pending and resolved), so a reload or a daemon restart does not lose them, and a linked project syncs them to the dashboard.
31
+ - **Notes.** Open the Notes page and select **Add notes**. Click the element that looks wrong and type what is wrong (⌘/Ctrl+Enter sends, Esc backs out). Reticle pins a numbered marker and gives the agent a structured mark. Notes are kept in `.reticle/notes.json` (pending and resolved), so a reload or a daemon restart does not lose them. A linked project syncs them to the dashboard.
32
32
 
33
- ## Flag a bug: annotate the mistake where you see it
33
+ ## Notes: annotate the mistake where you see it
34
34
 
35
- You don't have to describe a bug in prose. **Point at it.** The flag captures the element's re-resolvable anchor _and_ the source `file:line` (when the framework stamped one), so the agent fixes the exact element and code, not a guess. The loop:
35
+ You don't have to describe a bug in prose. **Point at it.** The note captures the element's re-resolvable anchor _and_ the source `file:line` (when the framework stamped one), so the agent fixes the exact element and code, not a guess. The loop:
36
36
 
37
- 1. **You** flag the element and type the problem → Reticle emits a `HUMAN_MARK`.
38
- 2. **The agent** drains it with `reticle_session { action: "review" }`, getting note + element label + `source: { file, line }` + a ready-to-act `fix` hint. `reticle_session { action: "list" }` also reports `pendingMarks` so the agent notices flags.
37
+ 1. **You** add a note on the element and type the problem → Reticle emits a `HUMAN_MARK`.
38
+ 2. **The agent** drains it with `reticle_session { action: "review" }`, getting note + element label + `source: { file, line }` + a ready-to-act `fix` hint. `reticle_session { action: "list" }` also reports `pendingMarks` so the agent notices notes.
39
39
  3. **The agent** opens the file, fixes it, and calls `reticle_session({ action: "review", resolve: "m1" })`.
40
- 4. **You** see **"✓ fixed: \<your note\>"** land in the panel. Flag → fix → confirmation.
40
+ 4. **You** see **"✓ fixed: \<your note\>"** land in the panel. Note → fix → confirmation.
41
41
 
42
42
  See [`reticle_session { action: "review" }` in the usage guide](/usage) for the tool shape. Suppress the button with `annotate: false` if you don't want it.
43
43
 
package/docs/index.mdx CHANGED
@@ -23,7 +23,7 @@ Four steps. Each command says what it did and is safe to run twice. Needs Node 2
23
23
  | 3. Connect _(optional)_ | `reticle connect --project "My App"` | project | `reticle status` shows this folder linked |
24
24
  | 4. Sync _(optional)_ | `reticle sync` | whenever you like | your runs show on the dashboard |
25
25
 
26
- On Windows, step 1 is `irm https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.ps1 | iex`. The installer puts `reticle` on your PATH, registers it with every coding agent it finds. It does not wire your app: that is step 2. Skip step 2 and your agent's first `reticle_session` call wires the app instead. The [quickstart](/quickstart) walks every step.
26
+ On Windows, step 1 is `irm https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.ps1 | iex`. The installer puts `reticle` on your PATH, registers it with every coding agent it finds. It does not wire your app: that is step 2. Skip step 2 and your agent can still check the app with the zero-install lease, which installs nothing. It asks you before it wires the app. The [quickstart](/quickstart) walks every step.
27
27
 
28
28
  A session listed means the SDK reached the page. Setup is finished when the first run returns a verdict.
29
29
 
@@ -39,7 +39,7 @@ The installer ends with **Next steps**. Do them in order:
39
39
  neither one touches your app, so you still run `reticle init` afterwards to instrument it. On
40
40
  Claude Code, `/plugin marketplace add reticlehq/reticle` then `/plugin install reticle@reticlehq`
41
41
  registers the MCP server and the skills in one step; on most other agents, `npx skills add
42
- reticlehq/reticle`.
42
+ reticlehq/reticle --skill reticle`.
43
43
  </Tip>
44
44
 
45
45
  <Card title="What that command actually changes" icon="wand-magic-sparkles" href="/install-agentic">
@@ -44,10 +44,10 @@ It registers Reticle with every coding agent it finds and closes with **Next ste
44
44
  The order matters. An agent reads its MCP server list when it starts, so a prompt pasted into an agent that is already running has no `reticle_*` tools to call until that agent restarts.
45
45
 
46
46
  <Tip>
47
- Prefer installing the skills instead? `npx skills add reticlehq/reticle` on most agents, or
48
- `/plugin marketplace add reticlehq/reticle` then `/plugin install reticle@reticlehq` on Claude
49
- Code, which registers the MCP server and the Reticle skill in one step. Then type `/reticle` and
50
- the agent runs this same setup from the skill.
47
+ Prefer installing the skill instead? `npx skills add reticlehq/reticle --skill reticle` on most
48
+ agents, or `/plugin marketplace add reticlehq/reticle` then `/plugin install reticle@reticlehq` on
49
+ Claude Code, which registers the MCP server and the Reticle skill in one step. Then type
50
+ `/reticle` and the agent runs this same setup from the skill.
51
51
  </Tip>
52
52
 
53
53
  <Note>
@@ -70,27 +70,18 @@ reticle init (dry run, no files written)
70
70
  in /tmp/initdemo
71
71
 
72
72
  [·] MCP server (Claude, global) → global (claude user scope)
73
- reticle already registered (install once, used by every project)
74
- [·] MCP server (Cursor, global) → /Users/you/.cursor/mcp.json
75
- reticle already in Cursor global config
73
+ [·] MCP server (Cursor) → /Users/you/.cursor/mcp.json
76
74
  [⚠] MCP server (Codex CLI) → /Users/you/.codex/config.toml
77
75
  add this to /Users/you/.codex/config.toml by hand:
78
76
  [mcp_servers.reticle]
79
77
  command = "npx"
80
78
  args = ["@reticlehq/server", "mcp"]
81
-
82
79
  [✓] Agent verification rule → CLAUDE.md
83
- teach the agent to verify features with Reticle after building them
84
80
  [✓] The /reticle command → .claude/commands/reticle.md
85
- type /reticle to verify one flow in the browser
86
81
  [✓] Install dependencies → package.json
87
- npm i -D @reticlehq/react@<version> @reticlehq/vite-plugin@<version>
88
82
  [✓] Reticle config → .reticle.json
89
- write project config (framework + port)
90
83
  [✓] Vite plugin → vite.config.ts
91
- add reticle() to plugins (also injects connect())
92
84
  [✓] Capabilities + store → src/reticle-dev.ts
93
- no data-testid values yet; no state library detected
94
85
  ```
95
86
 
96
87
  ## Reading the marks
@@ -111,15 +102,17 @@ There are five, and they mean different things. This is the part worth understan
111
102
  Codex simply never sees the tools.
112
103
  </Warning>
113
104
 
114
- That `ℹ` line is the one people skim past, so here it is in full:
105
+ An `ℹ` line is the one people skim past. Init prints this one when it finds a state library that it cannot register for you (punctuation changed to fit these docs):
115
106
 
116
107
  ```
117
108
  [ℹ] AGENT: finish the capabilities file → src/reticle-dev.ts
118
- src/reticle-dev.ts was written but registers nothing, so `hasCapabilities` stays false
119
- and reticle_look { action: "state" } has nothing to read.
109
+ This app's state lives in a library nothing in the running app points at, so it is the one thing Reticle cannot find for itself: reticle_state will not see it until you say where it is.
110
+ Do this now, before driving anything:
111
+ 1. In src/reticle-dev.ts, uncomment the suggested line and complete it: <the hint for your library>.
112
+ 2. Prove it: drive one flow and check reticle_state returns your key. An empty state read means the line is still not doing anything, whatever else went green.
120
113
  ```
121
114
 
122
- `init` wrote the file, but a brand-new Vite template has no testids and no state library, so there was nothing to register. Reticle tells you this instead of counting it as a win. See [Instrument your app](/instrumentation) for what to put in it.
115
+ Do the two steps. Reticle tells you this instead of counting the file as a win. See [Instrument your app](/instrumentation) for what to put in the file.
123
116
 
124
117
  ## What it actually changes
125
118
 
@@ -190,12 +183,17 @@ The files it writes in your project, none of them mysterious.
190
183
  </Accordion>
191
184
 
192
185
  <Accordion title="src/reticle-dev.ts (your capabilities)">
186
+ Trimmed, with the punctuation changed to fit these docs: the real file also has a comment block about where to start and a `declare global` block for the `DEV` type.
187
+
193
188
  ```ts
194
- // Dev-only. Loaded for you after connect() by @reticlehq/vite-plugin's injected connect, so you do not import it.
189
+ // Dev-only. Loaded for you after connect() (by @reticlehq/vite-plugin's injected connect, or by
190
+ // the connect file init wrote for a framework that connects itself), so you do not import it.
195
191
  // Self-guards on import.meta.env.DEV, so it is a no-op in a production build.
196
192
  import { registerCapabilities } from '@reticlehq/react';
197
193
 
198
194
  if (import.meta.env.DEV) {
195
+ // No state library detected. If you add one, register it here. See https://docs.reticle.sh/state-management
196
+
199
197
  registerCapabilities({
200
198
  testids: [], // none found; add data-testid to your key elements
201
199
  signals: [], // names you pass to reticle.signal()
@@ -219,6 +217,7 @@ The files it writes in your project, none of them mysterious.
219
217
 
220
218
  ```
221
219
  reticle init [--dry-run] [--port N] [--no-mcp] [--no-install] [--app <dir>]
220
+ [--env KEY=VALUE]... [--files-only] [--json] [--relaunch]
222
221
  --app picks WHICH app in a monorepo, when several are found
223
222
  --no-mcp skips MORE than the server registration: also the agent rule files
224
223
  (CLAUDE.md / AGENTS.md / .cursor) and the /reticle command, because all three
@@ -7,7 +7,7 @@ icon: screwdriver-wrench
7
7
 
8
8
  **Installing Reticle by hand is two independent halves: register the MCP server so your agent gets the `reticle_*` tools, then add the SDK to your app so there is something for those tools to talk to.** You need both, in that order.
9
9
 
10
- Do only the first half and the tools appear but every call reports no session. Do only the second and your app connects to a daemon nobody is asking questions. Stop after the first half and your agent's first Reticle call wires the app itself when you ask it to verify something, and offers to otherwise.
10
+ Do only the first half and the tools appear but every call reports no session. Do only the second and your app connects to a daemon nobody is asking questions. Stop after the first half and your agent can still check the running app with the zero-install lease, which installs nothing. It asks you before it runs `init`.
11
11
 
12
12
  <Warning>
13
13
  **You probably do not need this page.** Two commands do all of it:
@@ -19,7 +19,7 @@ npx @reticlehq/server init # in your project
19
19
 
20
20
  The first registers the MCP server with every agent it can reach. The second wires the app. See the [quickstart](/quickstart).
21
21
 
22
- This page is for the cases those cannot cover: a machine where piping a script is not allowed, an agent Reticle does not know, or a step the installer reported as needing a hand (Codex CLI is the usual one when the `codex` command is not installed, because its config is TOML that Reticle will not rewrite itself).
22
+ This page is for the cases those cannot cover: a machine where piping a script is not allowed, an agent Reticle does not know, or a step the installer reported as needing a hand (Codex CLI is the usual one when the `codex` command is not installed, because only `codex mcp add` registers a server in its TOML config).
23
23
 
24
24
  </Warning>
25
25
 
@@ -94,6 +94,8 @@ command = "npx"
94
94
  args = ["@reticlehq/server", "mcp"]
95
95
  ```
96
96
 
97
+ When the `[mcp_servers.reticle]` table is there, Reticle adds one line under it: `default_tools_approval_mode = "approve"`. This line approves Reticle's own tools, so Codex does not ask before each call. Reticle changes no other line, and it keeps a mode that you set. To undo it, change that line to `default_tools_approval_mode = "prompt"`. Reticle does not change a mode that is already there.
98
+
97
99
  ### OpenCode
98
100
 
99
101
  Note the flat command array and the required `type`:
@@ -141,6 +143,8 @@ Run `npx @reticlehq/server init` even here: it wires plain HTML, Angular, Remix,
141
143
 
142
144
  If you really are wiring `connect()` by hand, pass the token. The daemon writes it to `~/.reticle/pairing-token` on first start and refuses a page that does not present it, on localhost too. Without it the page console says `bridge refused the connection: authentication failed: no pairing token on the page…`.
143
145
 
146
+ `init` gives you a module for this: it writes the token to `reticle.local.js` at the project root, adds that file to `.gitignore`, and prints a snippet that imports it. To do it without `init`, pass the token yourself:
147
+
144
148
  ```ts
145
149
  import { reticle, SESSION_AUTO } from '@reticlehq/browser';
146
150
 
@@ -183,7 +187,7 @@ Screenshots and headless mode need the Rust crate, which is versioned independen
183
187
 
184
188
  ```toml
185
189
  [dependencies]
186
- reticle-tauri = "3.7"
190
+ reticle-tauri = "3.8"
187
191
  ```
188
192
 
189
193
  ```rust
@@ -192,7 +196,7 @@ tauri::Builder::default()
192
196
  .on_page_load(reticle_tauri::on_page_load)
193
197
  ```
194
198
 
195
- **Dev builds only.** In a release build the crate is inert: `reticle_capture` refuses and `on_page_load` does nothing, so the binary you sign and ship carries no Reticle capability. A release build you test with Reticle (a CI fixture) turns it on with `reticle-tauri = { version = "3.7", features = ["in-release"] }`.
199
+ **Dev builds only.** In a release build the crate is inert: `reticle_capture` refuses and `on_page_load` does nothing, so the binary you sign and ship carries no Reticle capability. A release build you test with Reticle (a CI fixture) turns it on with `reticle-tauri = { version = "3.8", features = ["in-release"] }`.
196
200
 
197
201
  IPC observation needs nothing on the Rust side. An `invoke('load_todos')` already reaches Reticle as `ipc://load_todos`.
198
202
 
@@ -4,7 +4,7 @@ description: 'The recommended shape for a real codebase: a minimal production fo
4
4
  icon: shapes
5
5
  ---
6
6
 
7
- The recommended shape for a real codebase is three decisions: put `createReticleEmitter()` in one `app/emit.ts` so components depend on an interface and `@reticlehq/browser` is imported in exactly one place; emit signals from the **store layer** rather than from N call sites; and let each feature self-register its testids and signals with `registerReticleDomain`. Then turn on `reticle/require-signal-on-mutation` so the signal layer cannot silently rot.
7
+ The recommended shape for a real codebase is three decisions: put `createReticleEmitter()` in one `app/emit.ts` so components depend on an interface and `@reticlehq/browser` stays out of your components; emit signals from the **store layer** rather than from N call sites; and let each feature self-register its testids and signals with `registerReticleDomain`. Then turn on `reticle/require-signal-on-mutation` so the signal layer cannot silently rot.
8
8
 
9
9
  The basics in [Getting Started](getting-started.md) work with **zero app changes**. This doc is the _recommended_ shape for a real codebase: a minimal production footprint, a signal layer that can't silently drift, and an adoption path that starts paying off on day one, with no rewrite required.
10
10
 
@@ -12,7 +12,7 @@ The basics in [Getting Started](getting-started.md) work with **zero app changes
12
12
  - [2. Inject the emitter (zero prod bundle)](#2-inject-the-emitter-zero-prod-bundle)
13
13
  - [3. Emit signals from the store layer, not N call sites](#3-emit-signals-from-the-store-layer-not-n-call-sites)
14
14
  - [4. Self-registering domains (`registerReticleDomain`)](#4-self-registering-domains-registerreticledomain)
15
- - [5. Keep the signal layer from rotting (`@reticlehq/eslint-plugin`)](#5-keep-the-signal-layer-from-rotting-reticleeslint-plugin)
15
+ - [5. Keep the signal layer from rotting (`@reticlehq/eslint-plugin`)](#5-keep-the-signal-layer-from-rotting-@reticlehq/eslint-plugin)
16
16
  - [6. Limitation: un-scriptable tabs, use `reticle drive`](#6-limitation-un-scriptable-tabs-use-reticle-drive)
17
17
  - [Checklist](#checklist)
18
18
 
@@ -158,17 +158,17 @@ export default [
158
158
  ];
159
159
  ```
160
160
 
161
- Or turn it on with the shipped preset: `plugin.configs.recommended`, which sets `reticle/require-signal-on-mutation` to `warn` (with empty no-op defaults you then configure) and the plugin's other two rules, `reticle/no-internal-tags` and `reticle/no-runaway-comment`, to `error`. A function that calls a mutator and a signal together passes; a mutator with no signal reports `store mutation without a mapped Reticle signal`. The documented view-level exceptions from §3 simply don't list those view callees as `mutators`, so they never fire.
161
+ Or turn it on with the shipped preset: `plugin.configs.recommended`, which sets `reticle/require-signal-on-mutation` to `warn` (with empty no-op defaults you then configure) and the plugin's other two rules to `error`. `reticle/no-internal-tags` reports design-document codes (such as `N5` or `§4.3`) and version strings (such as `v2.2.0`) in comments, test names and file names. `reticle/no-runaway-comment` reports a block comment of more than 60 lines. If your code base uses either pattern, turn the rule off in your config, or enable only `reticle/require-signal-on-mutation`. A function that calls a mutator and a signal together passes; a mutator with no signal reports `store mutation without a mapped Reticle signal`. The documented view-level exceptions from §3 simply don't list those view callees as `mutators`, so they never fire.
162
162
 
163
163
  ## 6. Limitation: un-scriptable tabs, use `reticle drive`
164
164
 
165
165
  Reticle observes and drives a tab through the in-page SDK plus (optionally) CDP. It **cannot bring to front or recover a browser tab the OS won't let it script**: a backgrounded tab, say, or a non-default browser (Dia, etc.) reporting `hidden:true` / `throttled:true`.
166
166
 
167
- When that happens, `reticle_session { action: "list" }` and every act/assert result carry a `session.recommendation` saying so. The escape hatch is **`reticle drive <url>`**, which opens in the foreground (`--headless` hides it). Reticle launches and owns a guaranteed-scriptable browser. See [usage §18](usage.md#18-real-input-mode-native-hover--drag) for the full note.
167
+ When that happens, `reticle_session { action: "list" }` and every act/assert result carry a `session.recommendation` saying so. The agent's way out is a lease: `reticle_run({ tool: "reticle_lease", args: { action: "acquire", url } })` opens a tab that Reticle owns. A person can run **`reticle drive <url>`**, which opens a browser in the foreground (`--headless` hides it). The person who watches sees nothing of a lease, so prefer the open tab while someone follows along. See [usage §18](usage.md#18-real-input-mode-native-hover-&-drag) for the full note.
168
168
 
169
169
  ## Checklist
170
170
 
171
- - [ ] One `app/emit.ts` is the **only** module importing `@reticlehq/browser`; components import the emitter.
171
+ - [ ] Components import the emitter from `app/emit.ts`, never `@reticlehq/browser`. Only `app/emit.ts`, the store layer and the `reticle.ts` domain files import the SDK.
172
172
  - [ ] `reticle.connect()` is dev-gated; the prod bundle has no `@reticlehq/browser`.
173
173
  - [ ] Signals fire from the store layer (middleware or `commitAndSignal`); view-level exceptions are explicit.
174
174
  - [ ] Each domain self-registers via `registerReticleDomain`; `reticle_run({ tool: "reticle_capabilities", args: {} })` returns the full surface.
@@ -4,15 +4,15 @@ description: 'Several apps at once, ports that shift between runs, and many agen
4
4
  icon: users
5
5
  ---
6
6
 
7
- Many agents can drive the same app at once without a browser each: `reticle_run { tool: "reticle_lease", args: { action: "acquire" } }` hands each one an **isolated context** (its own cookies, storage and DOM) from a single shared headless Chromium. One daemon per machine, and identity is the **app** (a stable `projectId` stamped by the build plugin), not the port, so an app that boots on `:3001` today is still the same app.
7
+ Many agents can drive the same app at once without a browser each: `reticle_run { tool: "reticle_lease", args: { action: "acquire" } }` hands each one an **isolated context** (its own cookies, storage and DOM) from a single shared headless Chromium. One daemon for each project, and identity is the **app** (a stable `projectId` stamped by the build plugin), not the port, so an app that boots on `:3001` today is still the same app.
8
8
 
9
9
  Reticle is built for the messy real world: several apps running at once, ports that shift between runs, and many agents driving different flows of the same app in parallel, without each one spinning up its own Chromium. This page explains how that works and how to use it.
10
10
 
11
11
  ## The mental model
12
12
 
13
- - **One daemon per machine.** `reticle mcp` discovers a running daemon (via `~/.reticle`) or starts one. A crashed daemon's stale pidfile is reclaimed automatically, so you never chase "port already in use" or a zombie server.
13
+ - **One daemon for each project.** `reticle mcp` finds this project's daemon through `~/.reticle`, or starts one. When another project's daemon holds the port, it starts one on a free port. A crashed daemon's stale pidfile is reclaimed automatically, so you never chase "port already in use" or a zombie server.
14
14
  - **Identity is the app, not the port.** The build plugin stamps a stable `projectId` that travels in every connection. If your Next app usually runs on `:3000` but boots on `:3001` today, Reticle still knows which app it is, and an agent scoped to project A will never accidentally drive project B's tab. Origin is only a fallback hint.
15
- - **One browser, many contexts.** When agents need their own headless tabs, the daemon's **browser pool** launches a single Chromium and hands out isolated contexts (one per flow). They are cheap, and capped so a big fan-out can't exhaust the machine. Over-cap requests queue.
15
+ - **One browser, many contexts.** When agents need their own headless tabs, the daemon's **browser pool** launches a single Chromium and hands out isolated contexts (one per flow). They are cheap, and capped so a big fan-out can't exhaust the machine. An acquire over the cap is refused at once and names the cap.
16
16
  - **Attach-only daemon.** The daemon never starts your dev server. It connects to an app that is running (or opens a headless tab pointed at it). When nothing is running, the agent starts your project's own dev script in the background and tells you. A build process spawned by a background daemon would be invisible, unconsented, and orphaned when the daemon exits.
17
17
 
18
18
  ## Manual testing: ~5 minutes
@@ -20,7 +20,7 @@ Reticle is built for the messy real world: several apps running at once, ports t
20
20
  1. Add the plugin (Vite/Next) or one `reticle.connect()` call. (See [getting-started](./getting-started.md).)
21
21
  2. Start your app as you normally do.
22
22
  3. Open it in a browser; the in-page panel shows Reticle is connected.
23
- 4. Click around; flag anything that looks wrong with the "Flag a bug" annotator. The agent drains those with `reticle_session { action: "review" }`.
23
+ 4. Click around. To report something that looks wrong, open **Notes** in the panel, select **Add notes**, and click the element. The agent drains those with `reticle_session { action: "review" }`.
24
24
 
25
25
  ## Agent testing: ~2 minutes
26
26
 
@@ -36,6 +36,8 @@ reticle_run { tool: "reticle_lease", args: { action: "release", sessionId } }
36
36
 
37
37
  `reticle_run { tool: "reticle_lease", args: { action: "acquire" } }` opens a fresh isolated headless context against your **already-running** app, stamps the lease identity into the URL so the app's own SDK registers under a sessionId you can target, and waits until that tab has connected (`ready: true`) before returning, so the sessionId is usable immediately. Release when the flow finishes.
38
38
 
39
+ **Lease the exact host that the dev server binds.** `http://localhost:3000` and `http://127.0.0.1:3000` are two origins, and they are not the same address. A dev server that binds only `::1` (Vite can do this for `localhost`) refuses a lease on `127.0.0.1`, and a server that binds only `127.0.0.1` does not answer on `::1`. The two origins also have their own cookies and storage, and a lease is reused for each origin. Copy the url that the dev server prints, host and port included.
40
+
39
41
  ## Permissions
40
42
 
41
43
  A lease starts with every permission undecided. Pass `permissions` to grant some on the app's origin before the first navigation, so the first render already sees them:
@@ -59,7 +61,7 @@ The headless shell has no notification support, so a notifications grant never r
59
61
  This is the design target, and it needs no special setup:
60
62
 
61
63
  - Each agent calls `reticle_run { tool: "reticle_lease", args: { action: "acquire" } }` for the same dashboard URL → its own isolated context (own cookies/storage) in the **one** shared Chromium.
62
- - The pool caps simultaneous contexts (`RETICLE_MAX_CONTEXTS`, default scales with CPU under a ceiling); extra acquires queue and proceed as slots free.
64
+ - The pool caps simultaneous contexts (`RETICLE_MAX_CONTEXTS`, default scales with CPU under a ceiling). An acquire, or a `reticle drive`, that finds every slot taken is refused at once with `all N lease slots are in use`, naming the release and the override, so an agent knows to release a lease or wait rather than retry into the same full pool. The parallel flow runner queues instead, since it holds its own slots and frees them as each flow ends.
63
65
  - Flows can't bleed into each other: contexts are isolated and every session is scoped by `projectId`.
64
66
  - A single crashed page is reclaimed on its own, and if an agent crashes or hangs its lease stops being touched and the **lease reaper** reclaims the context after a TTL, freeing the slot. One dead agent never starves the others.
65
67
 
@@ -24,9 +24,31 @@ npm i -D @reticlehq/browser
24
24
 
25
25
  ```ts
26
26
  import { reticle } from '@reticlehq/browser';
27
- if (import.meta.env.DEV) reticle.connect();
27
+
28
+ if (import.meta.env.DEV) {
29
+ // reticle.local.js holds this machine's pairing token. Do not commit it.
30
+ import('./reticle.local.js')
31
+ .catch(() => ({}))
32
+ .then((local) => reticle.connect({ token: local.token }));
33
+ }
34
+ ```
35
+
36
+ The bridge refuses a connect without the pairing token, also on localhost. `reticle init` writes `reticle.local.js` at the project root and adds it to `.gitignore`. Change the import path so that it points to that file. If you did not run `reticle init`, make the file yourself from the token that the daemon keeps in `~/.reticle/pairing-token`:
37
+
38
+ ```bash
39
+ printf "export const token = '%s';\n" "$(cat ~/.reticle/pairing-token)" > reticle.local.js
40
+ echo reticle.local.js >> .gitignore
28
41
  ```
29
42
 
43
+ With the Vite plugin and `inject: false`, pass `token: __RETICLE_TOKEN__` instead. See [the Vite plugin](/packages/vite-plugin).
44
+
45
+ ## Subpaths
46
+
47
+ | Subpath | What it is |
48
+ | --- | --- |
49
+ | `./activate` | `activate({ publicKey })`. Connects the SDK on a staging or production deployment, but only when the page URL carries a valid signed ticket in the `reticle_activate` parameter. Without the parameter it does nothing. See [Production mode](/production-mode) |
50
+ | `./inject` | The SDK build that a hosted verifier puts into a page from outside. An app does not import it |
51
+
30
52
  ## The `reticle` singleton
31
53
 
32
54
  One instance, memoized on `globalThis` so hot module replacement does not create a second one.
@@ -36,6 +58,8 @@ One instance, memoized on `globalThis` so hot module replacement does not create
36
58
  | `connect` | `(options?: ReticleConnectOptions) => void` |
37
59
  | `connected` | `get connected(): boolean` |
38
60
  | `signal` | `(name: string, data?: Record<string, unknown>) => void` |
61
+ | `routes` | `(patterns: readonly string[]) => void` |
62
+ | `busy` | `<T>(work: Promise<T>) => Promise<T>` |
39
63
  | `state` | `(name: string, value: unknown) => void` |
40
64
  | `renderCommit` | `(commits: number) => void` |
41
65
  | `describe` | `(input: CapabilitiesInput) => void` |
@@ -43,8 +67,12 @@ One instance, memoized on `globalThis` so hot module replacement does not create
43
67
  | `disconnect` | `() => void` |
44
68
  | `observeHotUpdates` | `(hot: unknown) => void` (called by the build integration) |
45
69
 
70
+ `routes` declares the app's route patterns (`/runs/:id`, `*` for the rest), so each route change names its screen. `busy` declares work that only the app can see, such as a debounced save. A settle waits for it, and it returns `work`.
71
+
46
72
  Everything else on the class is private. `Reticle` itself is exported for typing.
47
73
 
74
+ `trackShortTimers(maxMs?: number): () => void` is a separate export. It counts every short `setTimeout` (one second or less by default) as busy work, so a settle waits through a debounce. It returns the function that turns it off. It is off until you call it.
75
+
48
76
  ## `ReticleConnectOptions`
49
77
 
50
78
  Every field is optional.
@@ -54,9 +82,11 @@ Every field is optional.
54
82
  | `url` | `string` | Bridge URL, when you are not on the default port |
55
83
  | `session` | `string` | Session id. Defaults to the auto id (`SESSION_AUTO` is re-exported here) |
56
84
  | `projectId` | `string` | Project identity stamped on the handshake |
57
- | `token` | `string` | Pairing token, required for a non-loopback page |
85
+ | `token` | `string` | Pairing token. Required on every page, also on localhost, because the daemon makes one on its first start. The build plugins pass it for you |
58
86
  | `allowNonLocalhost` | `boolean` | Opt in to connecting from a non-localhost origin |
59
87
  | `allowInProduction` | `boolean` | Opt in to connecting from a production build. Desktop apps need this |
88
+ | `env` | `'development' \| 'production'` | Where the page runs. `production` needs a session nonce as `token`. Absent: development. The [production loader](/production-mode) sets it |
89
+ | `scope` | `'observe' \| 'act'` | What a drive may do. Required with `env: 'production'` |
60
90
  | `testIdAttribute` | `string` | The attribute the app marks controls with, when it is not `data-testid` |
61
91
  | `overlay` | `boolean` | The in-page overlay |
62
92
  | `captureNetworkBodies` | `boolean` | Record request and response bodies |
@@ -77,6 +107,8 @@ Every field is optional.
77
107
  | `idleEndMs` | `number` | Idle timeout before the session ends itself |
78
108
  | `redact` | `RedactionConfig` | Redaction policy, from core |
79
109
 
110
+ Reticle itself sets two more fields, `injected` and `lease`. Do not set them in an app.
111
+
80
112
  ## Capabilities
81
113
 
82
114
  Declaring a capability surface is what lets an agent discover what your app can do without guessing.