@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.
- package/SKILL.md +59 -68
- package/bin/reticle.js +9 -2
- package/dist/command/cli/adhoc-suite.js +1 -1
- package/dist/command/cli/adhoc-verdict.d.ts +12 -0
- package/dist/command/cli/adhoc-verdict.js +62 -4
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +5 -1
- package/dist/command/cli/auth/cloud-session.d.ts +11 -19
- package/dist/command/cli/auth/cloud-session.js +23 -0
- package/dist/command/cli/auth/device-flow.d.ts +3 -37
- package/dist/command/cli/cli-doctor.js +66 -21
- package/dist/command/cli/cli-flow-commands.js +53 -11
- package/dist/command/cli/cli-kill.d.ts +8 -0
- package/dist/command/cli/cli-kill.js +43 -3
- package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
- package/dist/command/cli/cli-parse-feedback.js +13 -1
- package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
- package/dist/command/cli/cli-parse-grammar.js +1 -6
- package/dist/command/cli/cli-parse-serve.d.ts +24 -0
- package/dist/command/cli/cli-parse-serve.js +124 -0
- package/dist/command/cli/cli-parse.d.ts +12 -11
- package/dist/command/cli/cli-parse.js +100 -123
- package/dist/command/cli/cli-usage.d.ts +0 -11
- package/dist/command/cli/cli-usage.js +43 -16
- package/dist/command/cli/cli-verify.d.ts +1 -1
- package/dist/command/cli/cli-verify.js +29 -14
- package/dist/command/cli/cloud-cli.js +27 -9
- package/dist/command/cli/cloud-kit.js +3 -3
- package/dist/command/cli/cloud-link.d.ts +1 -20
- package/dist/command/cli/cloud-link.js +2 -0
- package/dist/command/cli/cloud-login.d.ts +6 -2
- package/dist/command/cli/cloud-login.js +13 -41
- package/dist/command/cli/config/checkout.d.ts +10 -0
- package/dist/command/cli/config/checkout.js +78 -0
- package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
- package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
- package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
- package/dist/command/cli/doctor/doctor-rows.js +4 -0
- package/dist/command/cli/drive/drive-attach.d.ts +5 -0
- package/dist/command/cli/drive/drive-attach.js +21 -1
- package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
- package/dist/command/cli/hook/codex-transcript.js +224 -0
- package/dist/command/cli/hook/episode-structure.d.ts +24 -0
- package/dist/command/cli/hook/episode-structure.js +138 -0
- package/dist/command/cli/hook/hook-command.d.ts +9 -0
- package/dist/command/cli/hook/hook-command.js +211 -0
- package/dist/command/cli/hook/hook-fast.d.ts +31 -0
- package/dist/command/cli/hook/hook-fast.js +136 -0
- package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
- package/dist/command/cli/hook/prompt-hook.js +199 -0
- package/dist/command/cli/hook/tool-hook.d.ts +21 -0
- package/dist/command/cli/hook/tool-hook.js +259 -0
- package/dist/command/cli/launch/cli-launch.d.ts +2 -0
- package/dist/command/cli/launch/cli-launch.js +22 -2
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
- package/dist/command/cli/mcp-command.d.ts +9 -0
- package/dist/command/cli/mcp-command.js +127 -41
- package/dist/command/cli/open-navigate.d.ts +43 -0
- package/dist/command/cli/open-navigate.js +85 -0
- package/dist/command/cli/ports/port-holder.d.ts +16 -4
- package/dist/command/cli/ports/port-holder.js +58 -12
- package/dist/command/cli/ports/resolve/cli-port.js +18 -2
- package/dist/command/cli/project-name.d.ts +1 -7
- package/dist/command/cli/project-name.js +1 -0
- package/dist/command/cli/report-command.d.ts +8 -2
- package/dist/command/cli/report-command.js +95 -18
- package/dist/command/cli/status-fields.d.ts +9 -2
- package/dist/command/cli/status-fields.js +148 -4
- package/dist/command/cli/try-command.d.ts +3 -4
- package/dist/command/cli/try-command.js +6 -11
- package/dist/command/cli/verify-results.d.ts +4 -1
- package/dist/command/cli/verify-results.js +3 -1
- package/dist/command/cli.d.ts +1 -7
- package/dist/command/cli.js +79 -160
- package/dist/command/daemon/daemon-resilience.d.ts +6 -1
- package/dist/command/daemon/daemon-resilience.js +31 -18
- package/dist/command/daemon/daemon.d.ts +11 -0
- package/dist/command/daemon/daemon.js +70 -2
- package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
- package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
- package/dist/command/daemon/wake-decision.js +4 -2
- package/dist/command/daemon/win32-escape.d.ts +32 -0
- package/dist/command/daemon/win32-escape.js +119 -0
- package/dist/command/setup/agent-configs.d.ts +9 -0
- package/dist/command/setup/agent-configs.js +9 -0
- package/dist/command/setup/auto-approve.d.ts +10 -3
- package/dist/command/setup/auto-approve.js +51 -3
- package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
- package/dist/command/setup/bringup/dev-server-wait.js +5 -1
- package/dist/command/setup/bringup/ensure-daemon.js +4 -7
- package/dist/command/setup/init/init-host.js +6 -0
- package/dist/command/setup/init/init-port.js +5 -4
- package/dist/command/setup/init/init-runtime.js +7 -1
- package/dist/command/setup/node-effects.d.ts +8 -0
- package/dist/command/setup/node-effects.js +36 -4
- package/dist/command/setup/probe/dev-port.d.ts +26 -0
- package/dist/command/setup/probe/dev-port.js +117 -0
- package/dist/command/setup/probe/page-probe.d.ts +1 -1
- package/dist/command/setup/probe/page-probe.js +11 -3
- package/dist/command/setup/remaining-steps.d.ts +0 -7
- package/dist/command/setup/remaining-steps.js +3 -2
- package/dist/command/setup/run-setup.d.ts +11 -0
- package/dist/command/setup/run-setup.js +33 -5
- package/dist/command/setup/setup-command.d.ts +2 -0
- package/dist/command/setup/setup-command.js +22 -4
- package/dist/command/update/updater.d.ts +1 -6
- package/dist/command/update/updater.js +4 -5
- package/dist/command/update/version-seen.d.ts +24 -0
- package/dist/command/update/version-seen.js +65 -0
- package/dist/command/version/peer-announce.d.ts +9 -1
- package/dist/command/version/peer-announce.js +25 -2
- package/dist/command/version/sdk-fix.d.ts +5 -6
- package/dist/command/version/sdk-fix.js +17 -32
- package/dist/command/version/version-skew.d.ts +16 -1
- package/dist/command/version/version-skew.js +84 -10
- package/dist/features/crawl/crawl-tools.js +2 -2
- package/dist/features/crawl/crawl.js +2 -0
- package/dist/features/exhaust/ledger.d.ts +15 -96
- package/dist/features/exhaust/ledger.js +3 -3
- package/dist/features/harness/drive-runs.d.ts +28 -4
- package/dist/features/harness/drive-runs.js +99 -7
- package/dist/features/harness/drivers.d.ts +1 -1
- package/dist/features/harness/drivers.js +1 -1
- package/dist/features/harness/harness.d.ts +5 -0
- package/dist/features/harness/harness.js +24 -12
- package/dist/features/harness/platform/platform-drives.d.ts +7 -1
- package/dist/features/harness/platform/platform-drives.js +12 -7
- package/dist/features/harness/platform/refusal.d.ts +1 -1
- package/dist/features/harness/platform/refusal.js +4 -4
- package/dist/features/harness/platform/remote-drive.js +70 -28
- package/dist/features/harness/platform/server-driver.js +22 -1
- package/dist/features/harness/platform-config.d.ts +1 -10
- package/dist/features/harness/platform-config.js +0 -20
- package/dist/features/license/license.d.ts +2 -14
- package/dist/features/visual/step-shots.d.ts +33 -1
- package/dist/features/visual/step-shots.js +155 -1
- package/dist/features/visual/visual-tools.js +12 -4
- package/dist/hooks/coding-agents.d.ts +6 -0
- package/dist/hooks/coding-agents.js +24 -3
- package/dist/hooks/episode-stamp.d.ts +32 -0
- package/dist/hooks/episode-stamp.js +61 -0
- package/dist/hooks/hook-commands.js +19 -9
- package/dist/index.d.ts +5 -1
- package/dist/index.js +66 -24
- package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
- package/dist/judgement/app-graph/journal-steps.js +92 -0
- package/dist/judgement/capsule/capsule-store.d.ts +2 -39
- package/dist/judgement/domain/domain-model.js +1 -10
- package/dist/judgement/domain/domain-tools.js +4 -2
- package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
- package/dist/judgement/runs/artifact/run-store.js +153 -28
- package/dist/judgement/runs/default-run-id.d.ts +3 -1
- package/dist/judgement/runs/default-run-id.js +15 -3
- package/dist/judgement/runs/drive-run.d.ts +3 -3
- package/dist/judgement/runs/drive-run.js +11 -7
- package/dist/judgement/runs/run-ledger.d.ts +21 -0
- package/dist/judgement/runs/run-ledger.js +143 -0
- package/dist/judgement/runs/runner-port.d.ts +1 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +4 -3
- package/dist/judgement/runs/verification-sync.js +27 -5
- package/dist/language/flows/affected-tools.js +2 -1
- package/dist/language/flows/annotate-notes/annotate.js +8 -3
- package/dist/language/flows/annotate-tools.js +1 -1
- package/dist/language/flows/change/affected.d.ts +8 -0
- package/dist/language/flows/change/affected.js +20 -7
- package/dist/language/flows/decision.js +19 -4
- package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
- package/dist/language/flows/fields/flow-secret-field.js +67 -5
- package/dist/language/flows/flow-anchor.d.ts +5 -0
- package/dist/language/flows/flow-anchor.js +4 -0
- package/dist/language/flows/flow-cross-step.d.ts +7 -1
- package/dist/language/flows/flow-cross-step.js +9 -0
- package/dist/language/flows/flow-expect-grammar.js +15 -10
- package/dist/language/flows/flow-intent.js +6 -1
- package/dist/language/flows/flow-journey.d.ts +8 -0
- package/dist/language/flows/flow-journey.js +13 -0
- package/dist/language/flows/flow-lease.d.ts +27 -0
- package/dist/language/flows/flow-lease.js +59 -0
- package/dist/language/flows/flow-replay-run.d.ts +1 -87
- package/dist/language/flows/flow-replay-run.js +111 -310
- package/dist/language/flows/flow-replay.js +21 -19
- package/dist/language/flows/flow-replayable.d.ts +38 -0
- package/dist/language/flows/flow-replayable.js +179 -0
- package/dist/language/flows/flow-start-path.d.ts +108 -0
- package/dist/language/flows/flow-start-path.js +313 -0
- package/dist/language/flows/flow-step-runners.d.ts +23 -2
- package/dist/language/flows/flow-step-runners.js +191 -32
- package/dist/language/flows/flow-store-for-session.d.ts +8 -1
- package/dist/language/flows/flow-store-for-session.js +6 -0
- package/dist/language/flows/flow-tools.d.ts +2 -23
- package/dist/language/flows/flow-tools.js +63 -113
- package/dist/language/flows/flows.d.ts +4 -6
- package/dist/language/flows/flows.js +90 -15
- package/dist/language/flows/heal-run.d.ts +10 -4
- package/dist/language/flows/heal-run.js +26 -9
- package/dist/language/flows/recording/flake.d.ts +3 -27
- package/dist/language/flows/recording/flake.js +1 -1
- package/dist/language/flows/recording/recording-backtrack.js +1 -4
- package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
- package/dist/language/flows/recording/tape/recordings.js +9 -3
- package/dist/language/flows/replay.d.ts +25 -5
- package/dist/language/flows/replay.js +83 -16
- package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
- package/dist/language/flows/suite/coverage.d.ts +9 -0
- package/dist/language/flows/suite/coverage.js +12 -1
- package/dist/language/flows/suite-selection.d.ts +25 -0
- package/dist/language/flows/suite-selection.js +41 -9
- package/dist/machine/git-tracks.d.ts +6 -0
- package/dist/machine/git-tracks.js +36 -0
- package/dist/memory/cloud/background-sync.d.ts +25 -0
- package/dist/memory/cloud/background-sync.js +79 -0
- package/dist/memory/cloud/cloud-config.d.ts +12 -1
- package/dist/memory/cloud/cloud-config.js +39 -13
- package/dist/memory/cloud/cloud-sync.d.ts +3 -24
- package/dist/memory/cloud/cloud-sync.js +5 -2
- package/dist/memory/cloud/harness-config.d.ts +0 -7
- package/dist/memory/cloud/memory-scope.d.ts +19 -0
- package/dist/memory/cloud/memory-scope.js +48 -0
- package/dist/memory/cloud/sync-answer.d.ts +43 -0
- package/dist/memory/cloud/sync-answer.js +42 -0
- package/dist/memory/cloud/sync-cycle.d.ts +40 -10
- package/dist/memory/cloud/sync-cycle.js +97 -144
- package/dist/memory/cloud/sync-daemon.d.ts +50 -3
- package/dist/memory/cloud/sync-daemon.js +473 -83
- package/dist/memory/cloud/sync-describe.d.ts +28 -0
- package/dist/memory/cloud/sync-describe.js +92 -0
- package/dist/memory/cloud/sync-disk.d.ts +9 -1
- package/dist/memory/cloud/sync-disk.js +137 -33
- package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
- package/dist/memory/cloud/sync-flow-versions.js +42 -0
- package/dist/memory/impact/impact-store.js +32 -15
- package/dist/memory/intent/intent-shard.d.ts +41 -266
- package/dist/memory/intent/intent-tools.js +20 -61
- package/dist/memory/intent/record-request.d.ts +27 -0
- package/dist/memory/intent/record-request.js +88 -0
- package/dist/memory/intent/settled-words.js +9 -1
- package/dist/memory/journal/drive-flow.d.ts +3 -0
- package/dist/memory/journal/drive-flow.js +11 -41
- package/dist/memory/journal/envelope-store.js +1 -1
- package/dist/memory/journal/envelope.d.ts +6 -154
- package/dist/memory/journal/episode-log.d.ts +107 -0
- package/dist/memory/journal/episode-log.js +302 -0
- package/dist/memory/journal/journal-recorder.d.ts +7 -0
- package/dist/memory/journal/journal-recorder.js +22 -9
- package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
- package/dist/memory/journal/on-disk/ambient-file.js +1 -1
- package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
- package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
- package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
- package/dist/memory/journal/self-observation.js +3 -1
- package/dist/memory/journal/session-end.js +23 -9
- package/dist/memory/journal/session-journal.js +39 -20
- package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
- package/dist/memory/project/artifact-root-resolver.js +68 -23
- package/dist/memory/project/artifact-root.d.ts +17 -3
- package/dist/memory/project/artifact-root.js +47 -9
- package/dist/memory/project/fs/fs-port.d.ts +5 -0
- package/dist/memory/project/fs/fs-port.js +13 -0
- package/dist/memory/project/learned-routes.d.ts +3 -4
- package/dist/memory/project/learned-routes.js +3 -11
- package/dist/memory/project/link-directory.js +5 -2
- package/dist/memory/project/root-claims.d.ts +3 -1
- package/dist/memory/project/root-claims.js +41 -7
- package/dist/memory/project/session-root.d.ts +1 -1
- package/dist/memory/project/session-root.js +1 -15
- package/dist/memory/project/sync-status.js +5 -6
- package/dist/memory/recall/memory-tools.js +2 -2
- package/dist/memory/recall/platform-memory.d.ts +3 -1
- package/dist/memory/recall/platform-memory.js +9 -1
- package/dist/memory/recall/project-memory.js +15 -19
- package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
- package/dist/portal/bridge/auth-failure-reason.js +19 -0
- package/dist/portal/bridge/bridge.d.ts +19 -4
- package/dist/portal/bridge/bridge.js +150 -177
- package/dist/portal/bridge/harness-request.d.ts +15 -0
- package/dist/portal/bridge/harness-request.js +19 -0
- package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
- package/dist/portal/bridge/origin/origin-follow.js +110 -0
- package/dist/portal/bridge/pairing-token.d.ts +6 -0
- package/dist/portal/bridge/pairing-token.js +47 -16
- package/dist/portal/bridge/protocol-skew.d.ts +27 -2
- package/dist/portal/bridge/protocol-skew.js +66 -2
- package/dist/portal/bridge/session-nonces.d.ts +46 -0
- package/dist/portal/bridge/session-nonces.js +72 -0
- package/dist/portal/input/viewport-tools.d.ts +31 -0
- package/dist/portal/input/viewport-tools.js +106 -15
- package/dist/portal/pool/bounded-close.d.ts +23 -0
- package/dist/portal/pool/bounded-close.js +38 -0
- package/dist/portal/pool/browser-pool.d.ts +44 -39
- package/dist/portal/pool/browser-pool.js +247 -95
- package/dist/portal/pool/context-permissions.d.ts +9 -1
- package/dist/portal/pool/context-permissions.js +26 -0
- package/dist/portal/pool/lease-emulation.d.ts +37 -0
- package/dist/portal/pool/lease-emulation.js +29 -0
- package/dist/portal/pool/playwright-launcher.d.ts +6 -0
- package/dist/portal/pool/playwright-launcher.js +74 -7
- package/dist/portal/pool/pool-contract.d.ts +23 -1
- package/dist/portal/pool/pool-lease.d.ts +128 -0
- package/dist/portal/pool/pool-lease.js +49 -0
- package/dist/portal/pool/zero-install.d.ts +8 -1
- package/dist/portal/pool/zero-install.js +24 -2
- package/dist/portal/production/production-activation.d.ts +136 -0
- package/dist/portal/production/production-activation.js +173 -0
- package/dist/portal/production/production-drive.d.ts +52 -0
- package/dist/portal/production/production-drive.js +301 -0
- package/dist/portal/production/production-hello.d.ts +23 -0
- package/dist/portal/production/production-hello.js +23 -0
- package/dist/portal/realm/web-realm.js +42 -15
- package/dist/portal/session/control-envelope.d.ts +1 -1
- package/dist/portal/session/dev-server/served-document.d.ts +0 -5
- package/dist/portal/session/dev-server/served-document.js +6 -8
- package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
- package/dist/portal/session/first-run-wiring.d.ts +3 -36
- package/dist/portal/session/first-run-wiring.js +10 -103
- package/dist/portal/session/live-control-tools.js +61 -19
- package/dist/portal/session/no-session-next-action.d.ts +11 -0
- package/dist/portal/session/no-session-next-action.js +40 -15
- package/dist/portal/session/no-session-watch.d.ts +7 -0
- package/dist/portal/session/no-session-watch.js +67 -23
- package/dist/portal/session/output-budget.d.ts +10 -0
- package/dist/portal/session/output-budget.js +16 -0
- package/dist/portal/session/presence/session-lease.d.ts +2 -0
- package/dist/portal/session/presence/session-lease.js +8 -0
- package/dist/portal/session/recorded-gaps.d.ts +15 -11
- package/dist/portal/session/recorded-gaps.js +39 -18
- package/dist/portal/session/serving-directory.d.ts +24 -2
- package/dist/portal/session/serving-directory.js +93 -5
- package/dist/portal/session/session-info.d.ts +26 -0
- package/dist/portal/session/session-info.js +20 -0
- package/dist/portal/session/session-manager.d.ts +35 -3
- package/dist/portal/session/session-manager.js +69 -14
- package/dist/portal/session/session-successor.js +1 -9
- package/dist/portal/session/session-tools.js +22 -4
- package/dist/portal/session/session.d.ts +10 -10
- package/dist/portal/session/session.js +37 -29
- package/dist/portal/session/zero-install-first-call.d.ts +7 -2
- package/dist/portal/session/zero-install-first-call.js +43 -20
- package/dist/start-wiring.d.ts +2 -2
- package/dist/start-wiring.js +17 -3
- package/dist/status-payload.d.ts +11 -1
- package/dist/status-payload.js +7 -1
- package/dist/surface/agent-presence-grace.d.ts +11 -0
- package/dist/surface/agent-presence-grace.js +34 -0
- package/dist/surface/http-server.d.ts +12 -1
- package/dist/surface/http-server.js +64 -15
- package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
- package/dist/surface/mcp/faults/mcp-outage.js +19 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
- package/dist/surface/mcp/mcp-proxy.js +194 -267
- package/dist/surface/mcp/mcp.d.ts +20 -3
- package/dist/surface/mcp/mcp.js +88 -25
- package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
- package/dist/surface/mcp/proxy/drive-calls.js +114 -5
- package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
- package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
- package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
- package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
- package/dist/surface/mcp/server-instructions.js +35 -16
- package/dist/surface/mcp/shared-params.d.ts +8 -0
- package/dist/surface/mcp/shared-params.js +15 -1
- package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
- package/dist/surface/mcp/sse-frame-parser.js +18 -0
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +13 -0
- package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
- package/dist/surface/mcp/tool-catalog-cache.js +14 -4
- package/dist/surface/tools/account-tool.d.ts +4 -3
- package/dist/surface/tools/account-tool.js +20 -31
- package/dist/surface/tools/act/act-danger.d.ts +2 -0
- package/dist/surface/tools/act/act-danger.js +41 -14
- package/dist/surface/tools/act/act-observation.d.ts +11 -0
- package/dist/surface/tools/act/act-observation.js +33 -0
- package/dist/surface/tools/act/act-preflight.js +10 -3
- package/dist/surface/tools/act/act-sequence-retry.js +2 -1
- package/dist/surface/tools/act/act-target.js +19 -5
- package/dist/surface/tools/act/durable.js +1 -1
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
- package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
- package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
- package/dist/surface/tools/act/unsettled-find.js +71 -0
- package/dist/surface/tools/act-sequence-tool.js +53 -24
- package/dist/surface/tools/act-tools.d.ts +2 -3
- package/dist/surface/tools/act-tools.js +49 -47
- package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
- package/dist/surface/tools/agent/for-the-agent.js +41 -3
- package/dist/surface/tools/assert/assert-grade.js +8 -3
- package/dist/surface/tools/assert/assert-verdict.js +4 -2
- package/dist/surface/tools/browser-tools.js +7 -4
- package/dist/surface/tools/chat-drives.js +50 -25
- package/dist/surface/tools/coverage-tools.js +1 -1
- package/dist/surface/tools/dynamic-tools.d.ts +8 -0
- package/dist/surface/tools/dynamic-tools.js +89 -34
- package/dist/surface/tools/empty-session-list.d.ts +18 -25
- package/dist/surface/tools/empty-session-list.js +67 -38
- package/dist/surface/tools/error-recovery.d.ts +17 -7
- package/dist/surface/tools/error-recovery.js +53 -20
- package/dist/surface/tools/explore-tools.d.ts +10 -0
- package/dist/surface/tools/explore-tools.js +72 -19
- package/dist/surface/tools/feedback-tools.js +23 -2
- package/dist/surface/tools/gap-novelty.d.ts +6 -0
- package/dist/surface/tools/gap-novelty.js +9 -0
- package/dist/surface/tools/gaps/capability-absences.js +4 -3
- package/dist/surface/tools/harness-explore.d.ts +1 -1
- package/dist/surface/tools/harness-explore.js +6 -4
- package/dist/surface/tools/harness-gate.d.ts +43 -21
- package/dist/surface/tools/harness-gate.js +55 -81
- package/dist/surface/tools/harness-script.d.ts +2 -0
- package/dist/surface/tools/harness-script.js +11 -6
- package/dist/surface/tools/harness-toolset.js +3 -4
- package/dist/surface/tools/invoke-tool.d.ts +0 -8
- package/dist/surface/tools/invoke-tool.js +164 -178
- package/dist/surface/tools/lease-hint.d.ts +9 -0
- package/dist/surface/tools/lease-hint.js +22 -3
- package/dist/surface/tools/lease-permissions.d.ts +1 -1
- package/dist/surface/tools/lease-readiness.d.ts +55 -0
- package/dist/surface/tools/lease-readiness.js +150 -2
- package/dist/surface/tools/lease-tools.d.ts +3 -75
- package/dist/surface/tools/lease-tools.js +124 -188
- package/dist/surface/tools/map-tools.d.ts +20 -0
- package/dist/surface/tools/map-tools.js +145 -0
- package/dist/surface/tools/merge-tools.js +11 -7
- package/dist/surface/tools/next-step.js +6 -3
- package/dist/surface/tools/observe-tools.js +46 -35
- package/dist/surface/tools/platform-moment.d.ts +3 -12
- package/dist/surface/tools/platform-moment.js +12 -24
- package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
- package/dist/surface/tools/read/complete-snapshot.js +13 -2
- package/dist/surface/tools/read/query-paginate.js +6 -0
- package/dist/surface/tools/read/query-shape.d.ts +9 -0
- package/dist/surface/tools/read/query-shape.js +15 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
- package/dist/surface/tools/read-tools.js +5 -5
- package/dist/surface/tools/real-input-attempt.d.ts +11 -0
- package/dist/surface/tools/real-input-attempt.js +206 -38
- package/dist/surface/tools/reconcile-tools.js +21 -8
- package/dist/surface/tools/reticle-result.d.ts +3 -0
- package/dist/surface/tools/reticle-result.js +8 -1
- package/dist/surface/tools/run-report.d.ts +22 -0
- package/dist/surface/tools/run-report.js +141 -0
- package/dist/surface/tools/session-ports.d.ts +57 -0
- package/dist/surface/tools/session-ports.js +102 -0
- package/dist/surface/tools/tool-kit.d.ts +58 -4
- package/dist/surface/tools/tool-kit.js +140 -6
- package/dist/surface/tools/tool-surface.d.ts +2 -0
- package/dist/surface/tools/tool-surface.js +45 -0
- package/dist/surface/tools/tools.js +49 -87
- package/dist/telemetry/automation-hint.d.ts +5 -0
- package/dist/telemetry/automation-hint.js +7 -0
- package/dist/telemetry/cli-telemetry.d.ts +22 -0
- package/dist/telemetry/cli-telemetry.js +80 -11
- package/dist/telemetry/daemon-telemetry.d.ts +3 -1
- package/dist/telemetry/daemon-telemetry.js +9 -2
- package/dist/telemetry/feedback-cli.d.ts +1 -1
- package/dist/telemetry/feedback-cli.js +8 -3
- package/dist/telemetry/feedback.d.ts +1 -1
- package/dist/telemetry/feedback.js +51 -4
- package/dist/telemetry/harness-run.d.ts +3 -3
- package/dist/telemetry/harness-run.js +18 -7
- package/dist/telemetry/hud-events.d.ts +1 -1
- package/dist/telemetry/hud-metrics.d.ts +6 -3
- package/dist/telemetry/hud-metrics.js +20 -8
- package/dist/telemetry/install-source.js +1 -1
- package/dist/telemetry/mcp-connection.d.ts +1 -1
- package/dist/telemetry/mcp-connection.js +21 -2
- package/dist/telemetry/onboarding-firsts.d.ts +6 -1
- package/dist/telemetry/onboarding-firsts.js +41 -1
- package/dist/telemetry/proxy-telemetry.d.ts +42 -0
- package/dist/telemetry/proxy-telemetry.js +70 -1
- package/dist/telemetry/session-metrics.d.ts +1 -3
- package/dist/telemetry/session-metrics.js +16 -12
- package/dist/telemetry/telemetry.d.ts +9 -1
- package/dist/telemetry/telemetry.js +16 -1
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +7 -1
- package/dist/wire-journal.js +12 -2
- package/docs/README.md +4 -2
- package/docs/actions.mdx +7 -6
- package/docs/adapters.md +2 -1
- package/docs/agent-cheatsheet.md +19 -5
- package/docs/architecture.md +13 -10
- package/docs/autodrive.md +6 -5
- package/docs/benchmarks.md +2 -2
- package/docs/capabilities.mdx +1 -1
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +6 -6
- package/docs/cli/doctor.mdx +3 -1
- package/docs/cli/feedback.mdx +11 -7
- package/docs/cli/gate.mdx +1 -1
- package/docs/cli/help.mdx +1 -1
- package/docs/cli/init.mdx +20 -16
- package/docs/cli/mcp.mdx +5 -2
- package/docs/cli/open.mdx +5 -2
- package/docs/cli/report.mdx +1 -1
- package/docs/cli/restart.mdx +1 -1
- package/docs/cli/rollback.mdx +4 -4
- package/docs/cli/serve.mdx +7 -5
- package/docs/cli/setup.mdx +1 -1
- package/docs/cli/status.mdx +6 -2
- package/docs/cli/stop.mdx +3 -3
- package/docs/cli/telemetry.mdx +5 -1
- package/docs/cli/try.mdx +8 -8
- package/docs/cli/update.mdx +8 -5
- package/docs/cli/verify.mdx +12 -5
- package/docs/cli/version.mdx +1 -1
- package/docs/cli.mdx +10 -6
- package/docs/debugging.md +1 -1
- package/docs/deploy-checks.md +8 -6
- package/docs/desktop.mdx +14 -18
- package/docs/enterprise.md +6 -6
- package/docs/environment.mdx +5 -3
- package/docs/faq.mdx +9 -6
- package/docs/first-drive.md +19 -9
- package/docs/flows.md +3 -4
- package/docs/for-agents.md +1 -1
- package/docs/frameworks.mdx +34 -11
- package/docs/getting-started.md +46 -29
- package/docs/http-transport.md +2 -2
- package/docs/human-control.md +8 -8
- package/docs/index.mdx +2 -2
- package/docs/install-agentic.mdx +18 -19
- package/docs/install-manual.mdx +8 -4
- package/docs/integration-patterns.md +5 -5
- package/docs/multi-agent-testing.md +7 -5
- package/docs/packages/browser.mdx +34 -2
- package/docs/packages/core.mdx +2 -1
- package/docs/packages/electron.mdx +15 -3
- package/docs/packages/eslint-plugin.mdx +1 -1
- package/docs/packages/next.mdx +17 -5
- package/docs/packages/react.mdx +8 -1
- package/docs/packages/server.mdx +3 -3
- package/docs/packages/tauri.mdx +3 -3
- package/docs/packages/vite-plugin.mdx +1 -1
- package/docs/packages.mdx +19 -6
- package/docs/platform-integration.md +12 -4
- package/docs/predicates.mdx +18 -7
- package/docs/production-mode.md +108 -0
- package/docs/prompt-capture.md +99 -0
- package/docs/quickstart.mdx +14 -12
- package/docs/recipes.mdx +9 -8
- package/docs/required-checks.md +3 -2
- package/docs/skill-file.mdx +4 -3
- package/docs/skill-setup.md +2 -2
- package/docs/skill.md +62 -70
- package/docs/state-files.md +1 -0
- package/docs/state-management.mdx +11 -9
- package/docs/system-map.md +14 -13
- package/docs/telemetry.md +32 -24
- package/docs/testing.md +9 -5
- package/docs/tools/act-and-wait.mdx +17 -13
- package/docs/tools/act-sequence.mdx +40 -66
- package/docs/tools/act.mdx +7 -5
- package/docs/tools/assert.mdx +1 -1
- package/docs/tools/look.mdx +1 -1
- package/docs/tools/navigate.mdx +1 -1
- package/docs/tools/network.mdx +13 -11
- package/docs/tools/overview.mdx +3 -3
- package/docs/tools/query.mdx +3 -3
- package/docs/tools/session-and-feedback.mdx +9 -6
- package/docs/tools/sessions.mdx +7 -0
- package/docs/tools/snapshot.mdx +9 -7
- package/docs/tools/tools-and-run.mdx +11 -10
- package/docs/tools/verify.mdx +1 -1
- package/docs/troubleshooting.mdx +21 -9
- package/docs/usage.md +58 -43
- package/docs/use-cases.mdx +2 -2
- package/docs/vs-chrome-devtools-mcp.mdx +5 -5
- package/docs/vs-playwright-mcp.mdx +5 -4
- package/docs/what-is-recorded.md +12 -7
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/dev/stale-issue-guard.d.ts +0 -34
- package/dist/command/dev/stale-issue-guard.js +0 -69
package/docs/getting-started.md
CHANGED
|
@@ -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
|
|
15
|
+
- [What you set up](#what-you-set-up)
|
|
16
16
|
- [Prerequisites](#prerequisites)
|
|
17
|
-
- [Step 1: Connect your coding agent
|
|
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
|
|
22
|
-
- [Next.js](#
|
|
23
|
-
- [Plain
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
270
|
+
### Plain HTML and other frameworks
|
|
259
271
|
|
|
260
272
|
Anywhere your app boots in dev:
|
|
261
273
|
|
|
262
274
|
```ts
|
|
263
|
-
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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.
|
package/docs/http-transport.md
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
package/docs/human-control.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
- **
|
|
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
|
-
##
|
|
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
|
|
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**
|
|
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
|
|
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.
|
|
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
|
|
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">
|
package/docs/install-agentic.mdx
CHANGED
|
@@ -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
|
|
48
|
-
`/plugin marketplace add reticlehq/reticle` then `/plugin install reticle@reticlehq` on
|
|
49
|
-
Code, which registers the MCP server and the Reticle skill in one step. Then type
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
119
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
package/docs/install-manual.mdx
CHANGED
|
@@ -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
|
|
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
|
|
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.
|
|
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.
|
|
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`
|
|
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-
|
|
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
|
|
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
|
|
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
|
-
- [ ]
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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)
|
|
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
|
-
|
|
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,
|
|
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.
|