@reticlehq/server 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +130 -813
- package/dist/bridge/bridge.d.ts +23 -0
- package/dist/bridge/bridge.js +80 -2
- package/dist/bridge/bridge.test-harness.d.ts +5 -0
- package/dist/bridge/bridge.test-harness.js +6 -4
- package/dist/capsule/capsule-store.d.ts +2 -2
- package/dist/capsule/causal-summary.d.ts +16 -1
- package/dist/capsule/causal-summary.js +2 -1
- package/dist/cli/cli-doctor.js +41 -13
- package/dist/cli/cli-flow-commands.js +8 -8
- package/dist/cli/cli-launch.d.ts +0 -17
- package/dist/cli/cli-launch.js +0 -28
- package/dist/cli/cli-parse.d.ts +1 -1
- package/dist/cli/cli-parse.js +1 -1
- package/dist/cli/cli-port.d.ts +24 -0
- package/dist/cli/cli-port.js +66 -35
- package/dist/cli/cli-verify.d.ts +21 -0
- package/dist/cli/cli-verify.js +45 -1
- package/dist/cli/config-discovery.d.ts +35 -0
- package/dist/cli/config-discovery.js +163 -0
- package/dist/cli/doctor-daemon-line.js +4 -1
- package/dist/cli/doctor-project-line.d.ts +37 -0
- package/dist/cli/doctor-project-line.js +35 -0
- package/dist/cli/doctor-rows.d.ts +51 -0
- package/dist/cli/doctor-rows.js +54 -0
- package/dist/cli/doctor-sessions-line.js +6 -3
- package/dist/cli/drive-attach.d.ts +99 -0
- package/dist/cli/drive-attach.js +203 -0
- package/dist/cli/drive-command.d.ts +13 -0
- package/dist/cli/drive-command.js +103 -0
- package/dist/cli/open-note.d.ts +20 -0
- package/dist/cli/open-note.js +37 -0
- package/dist/cli/status-next-action.d.ts +37 -0
- package/dist/cli/status-next-action.js +61 -0
- package/dist/cli.js +65 -70
- package/dist/crawl/crawl.d.ts +7 -2
- package/dist/crawl/crawl.js +52 -9
- package/dist/ee/audit-log.js +2 -2
- package/dist/events/body-failures.d.ts +2 -2
- package/dist/events/contradiction-folds.d.ts +45 -0
- package/dist/events/contradiction-folds.js +42 -0
- package/dist/events/contradictions.d.ts +51 -1
- package/dist/events/contradictions.js +26 -7
- package/dist/events/declared.d.ts +45 -0
- package/dist/events/declared.js +73 -0
- package/dist/events/echo-mismatch.d.ts +9 -3
- package/dist/events/echo-mismatch.js +33 -5
- package/dist/events/event-filters.d.ts +1 -1
- package/dist/events/event-filters.js +7 -4
- package/dist/events/predicate-eval.d.ts +17 -91
- package/dist/events/predicate-eval.js +85 -326
- package/dist/events/predicate-parse.js +31 -3
- package/dist/events/predicate-route.d.ts +32 -0
- package/dist/events/predicate-route.js +102 -0
- package/dist/events/predicate-schema.d.ts +99 -0
- package/dist/events/predicate-schema.js +309 -0
- package/dist/events/predicate.d.ts +8 -0
- package/dist/events/predicate.js +127 -5
- package/dist/events/stale-response.d.ts +2 -3
- package/dist/events/stale-response.js +49 -2
- package/dist/events/unit-mismatch.d.ts +2 -2
- package/dist/flows/annotate-tools.js +3 -0
- package/dist/flows/annotate.js +18 -4
- package/dist/flows/coverage.d.ts +38 -5
- package/dist/flows/coverage.js +30 -4
- package/dist/flows/decision.d.ts +15 -0
- package/dist/flows/decision.js +1 -1
- package/dist/flows/flow-replay-run.js +8 -1
- package/dist/flows/flow-tools.js +9 -1
- package/dist/flows/replay.js +3 -0
- package/dist/flows/verify-change-tools.js +1 -1
- package/dist/honesty/accepted-write.d.ts +3 -0
- package/dist/honesty/accepted-write.js +8 -3
- package/dist/honesty/already-true.js +15 -0
- package/dist/honesty/blind-spots.js +4 -0
- package/dist/honesty/honesty.d.ts +11 -0
- package/dist/honesty/honesty.js +1 -0
- package/dist/honesty/uncaptured-bodies.d.ts +4 -2
- package/dist/honesty/uncaptured-bodies.js +9 -2
- package/dist/honesty/unread-outcome.d.ts +8 -0
- package/dist/honesty/unread-outcome.js +36 -9
- package/dist/honesty/unsettled.d.ts +9 -0
- package/dist/honesty/unsettled.js +7 -3
- package/dist/honesty/verified.d.ts +29 -3
- package/dist/honesty/verified.js +67 -8
- package/dist/http-server.d.ts +19 -0
- package/dist/http-server.js +202 -4
- package/dist/impact/impact-recorder.d.ts +23 -0
- package/dist/impact/impact-recorder.js +76 -0
- package/dist/impact/impact-store.d.ts +47 -0
- package/dist/impact/impact-store.js +171 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +60 -10
- package/dist/init/agent-rules.d.ts +20 -0
- package/dist/init/agent-rules.js +36 -0
- package/dist/init/astro-patch.js +27 -1
- package/dist/init/confirm.d.ts +21 -3
- package/dist/init/confirm.js +32 -5
- package/dist/init/connect-steps.d.ts +2 -0
- package/dist/init/connect-steps.js +50 -0
- package/dist/init/csp-check.d.ts +38 -0
- package/dist/init/csp-check.js +92 -0
- package/dist/init/csp-doctor.d.ts +25 -0
- package/dist/init/csp-doctor.js +49 -0
- package/dist/init/cursor.js +6 -9
- package/dist/init/detect.d.ts +8 -0
- package/dist/init/detect.js +33 -3
- package/dist/init/mcp-clients.d.ts +1 -0
- package/dist/init/mcp-clients.js +51 -7
- package/dist/init/mcp.d.ts +16 -2
- package/dist/init/mcp.js +23 -1
- package/dist/init/plan-framework.d.ts +10 -0
- package/dist/init/plan-framework.js +25 -1
- package/dist/init/plan.d.ts +7 -2
- package/dist/init/plan.js +66 -30
- package/dist/init/run.js +11 -5
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/slash-command.js +12 -4
- package/dist/init/snippets.d.ts +1 -1
- package/dist/init/snippets.js +35 -7
- package/dist/init/vite-config.js +24 -2
- package/dist/input/network-mock-tools.js +8 -1
- package/dist/input/scroll-find.d.ts +6 -0
- package/dist/input/scroll-find.js +17 -2
- package/dist/input/scroll-tools.js +4 -0
- package/dist/journal/attach-journal.d.ts +9 -1
- package/dist/journal/attach-journal.js +13 -2
- package/dist/journal/journal-query.d.ts +13 -0
- package/dist/journal/journal-query.js +28 -3
- package/dist/journal/workspace-gitignore.d.ts +10 -0
- package/dist/journal/workspace-gitignore.js +59 -0
- package/dist/license/license.d.ts +69 -4
- package/dist/license/license.js +84 -15
- package/dist/mcp/mcp-proxy.d.ts +7 -93
- package/dist/mcp/mcp-proxy.js +183 -250
- package/dist/mcp/mcp.d.ts +27 -2
- package/dist/mcp/mcp.js +77 -36
- package/dist/mcp/proxy-daemon-probe.d.ts +8 -0
- package/dist/mcp/proxy-daemon-probe.js +48 -0
- package/dist/mcp/proxy-handshake.d.ts +82 -1
- package/dist/mcp/proxy-handshake.js +110 -3
- package/dist/mcp/proxy-lifecycle.d.ts +10 -1
- package/dist/mcp/proxy-lifecycle.js +11 -2
- package/dist/mcp/proxy-log.d.ts +63 -0
- package/dist/mcp/proxy-log.js +132 -0
- package/dist/mcp/server-instructions.d.ts +17 -0
- package/dist/mcp/server-instructions.js +56 -0
- package/dist/mcp/shared-params.d.ts +27 -0
- package/dist/mcp/shared-params.js +36 -0
- package/dist/mcp/sse-frame-parser.d.ts +19 -0
- package/dist/mcp/sse-frame-parser.js +41 -0
- package/dist/project/reticle-dir.d.ts +2 -0
- package/dist/project/reticle-dir.js +1 -0
- package/dist/session/connection-memory.d.ts +59 -0
- package/dist/session/connection-memory.js +108 -0
- package/dist/session/dev-command.d.ts +26 -0
- package/dist/session/dev-command.js +89 -0
- package/dist/session/dev-server-probe.d.ts +68 -0
- package/dist/session/dev-server-probe.js +102 -7
- package/dist/session/last-act.d.ts +26 -0
- package/dist/session/last-act.js +35 -1
- package/dist/session/live-control-tools.js +42 -5
- package/dist/session/no-session-diagnosis.d.ts +55 -2
- package/dist/session/no-session-diagnosis.js +199 -22
- package/dist/session/no-session-next-action.d.ts +46 -0
- package/dist/session/no-session-next-action.js +85 -0
- package/dist/session/no-session-watch.d.ts +40 -1
- package/dist/session/no-session-watch.js +172 -11
- package/dist/session/pending-commands.d.ts +12 -0
- package/dist/session/pending-commands.js +13 -1
- package/dist/session/session-manager.d.ts +4 -0
- package/dist/session/session-manager.js +35 -5
- package/dist/session/session-readiness.js +1 -1
- package/dist/session/session.d.ts +10 -1
- package/dist/session/session.js +146 -5
- package/dist/telemetry/app-instrumented.d.ts +8 -0
- package/dist/telemetry/app-instrumented.js +10 -0
- package/dist/telemetry/bug-found.d.ts +18 -0
- package/dist/telemetry/bug-found.js +14 -0
- package/dist/telemetry/daemon-telemetry.js +29 -0
- package/dist/telemetry/install-source.d.ts +20 -0
- package/dist/telemetry/install-source.js +34 -0
- package/dist/telemetry/instrumentation-stall.d.ts +57 -0
- package/dist/telemetry/instrumentation-stall.js +103 -0
- package/dist/telemetry/license-activation.d.ts +48 -0
- package/dist/telemetry/license-activation.js +57 -0
- package/dist/telemetry/session-metrics.d.ts +8 -0
- package/dist/telemetry/session-metrics.js +10 -0
- package/dist/telemetry/telemetry.d.ts +3 -1
- package/dist/telemetry/telemetry.js +23 -3
- package/dist/tools/act-tools.js +166 -29
- package/dist/tools/assert-verdict.js +32 -7
- package/dist/tools/browser-tools.js +10 -0
- package/dist/tools/dynamic-tools.js +17 -8
- package/dist/tools/error-recovery.js +10 -6
- package/dist/tools/feedback-tools.js +31 -6
- package/dist/tools/invoke-tool.d.ts +1 -1
- package/dist/tools/invoke-tool.js +30 -8
- package/dist/tools/lease-hint.d.ts +30 -8
- package/dist/tools/lease-hint.js +65 -14
- package/dist/tools/lease-tools.d.ts +11 -0
- package/dist/tools/lease-tools.js +141 -96
- package/dist/tools/observe-tools.js +9 -3
- package/dist/tools/react-grace.d.ts +4 -0
- package/dist/tools/react-grace.js +6 -3
- package/dist/tools/read-tools.js +47 -1
- package/dist/tools/resolve-target.d.ts +33 -0
- package/dist/tools/resolve-target.js +53 -0
- package/dist/tools/settle-in-flight.d.ts +15 -0
- package/dist/tools/settle-in-flight.js +42 -2
- package/dist/tools/snapshot-delta.d.ts +3 -0
- package/dist/tools/snapshot-delta.js +67 -6
- package/dist/tools/tool-kit.d.ts +38 -3
- package/dist/tools/tool-names.d.ts +2 -0
- package/dist/tools/tool-names.js +2 -0
- package/dist/tools/tool-surface.d.ts +60 -0
- package/dist/tools/tool-surface.js +84 -19
- package/dist/tools/tools.js +61 -5
- package/dist/tools/unadvertised-help.js +9 -6
- package/docs/README.md +1 -2
- package/docs/actions.mdx +41 -8
- package/docs/agent-cheatsheet.md +6 -4
- package/docs/architecture.md +6 -0
- package/docs/benchmarks.md +60 -12
- package/docs/best-practices.mdx +11 -6
- package/docs/capabilities.mdx +204 -57
- package/docs/cli/affected.mdx +6 -4
- package/docs/cli/capsules.mdx +9 -8
- package/docs/cli/cloud.mdx +30 -4
- package/docs/cli/doctor.mdx +41 -8
- package/docs/cli/drive.mdx +34 -15
- package/docs/cli/gate.mdx +6 -6
- package/docs/cli/help.mdx +8 -6
- package/docs/cli/hunt.mdx +20 -4
- package/docs/cli/identify.mdx +16 -2
- package/docs/cli/init.mdx +35 -8
- package/docs/cli/kill.mdx +5 -5
- package/docs/cli/license.mdx +1 -1
- package/docs/cli/open.mdx +6 -0
- package/docs/cli/restart.mdx +6 -6
- package/docs/cli/serve.mdx +10 -3
- package/docs/cli/status.mdx +29 -5
- package/docs/cli/stop.mdx +8 -0
- package/docs/cli/verify.mdx +20 -1
- package/docs/cli/version.mdx +1 -1
- package/docs/cli/watch.mdx +9 -2
- package/docs/cli.mdx +44 -22
- package/docs/debugging.md +3 -1
- package/docs/deploy-checks.md +31 -2
- package/docs/desktop.mdx +276 -80
- package/docs/docs.json +13 -12
- package/docs/enterprise.md +9 -3
- package/docs/faq.mdx +49 -35
- package/docs/fixtures.md +2 -0
- package/docs/flows.md +7 -5
- package/docs/for-agents.md +3 -3
- package/docs/frameworks.mdx +46 -7
- package/docs/gate-plan.md +4 -2
- package/docs/gates.md +8 -6
- package/docs/getting-started.md +53 -12
- package/docs/human-control.md +2 -0
- package/docs/index.mdx +43 -1
- package/docs/install-agentic.mdx +13 -4
- package/docs/install-manual.mdx +6 -4
- package/docs/instrumentation.mdx +7 -1
- package/docs/integration-patterns.md +3 -1
- package/docs/local-registry.md +4 -2
- package/docs/multi-agent-testing.md +3 -1
- package/docs/packages/babel-plugin.mdx +15 -6
- package/docs/packages/browser.mdx +2 -2
- package/docs/packages/core.mdx +26 -16
- package/docs/packages/electron.mdx +5 -7
- package/docs/packages/eslint-plugin.mdx +5 -3
- package/docs/packages/next.mdx +3 -5
- package/docs/packages/react.mdx +3 -3
- package/docs/packages/server.mdx +2 -2
- package/docs/packages/tauri.mdx +6 -6
- package/docs/packages/test.mdx +18 -7
- package/docs/packages/vite-plugin.mdx +4 -6
- package/docs/packages.mdx +14 -13
- package/docs/platform-integration.md +2 -0
- package/docs/predicates.mdx +76 -7
- package/docs/quickstart.mdx +51 -5
- package/docs/recipes.mdx +63 -23
- package/docs/skill-file.mdx +3 -1
- package/docs/state-management.mdx +2 -0
- package/docs/system-map.md +3 -1
- package/docs/telemetry-contract.md +33 -5
- package/docs/telemetry-events.mdx +63 -18
- package/docs/telemetry.md +8 -5
- package/docs/testing.md +35 -1
- package/docs/token-efficiency.md +8 -2
- package/docs/tools-act-and-wait.mdx +64 -14
- package/docs/tools-act-sequence.mdx +34 -17
- package/docs/tools-act.mdx +24 -11
- package/docs/tools-assert.mdx +69 -10
- package/docs/tools-console.mdx +11 -7
- package/docs/tools-inspect.mdx +11 -8
- package/docs/tools-navigate.mdx +41 -5
- package/docs/tools-network.mdx +42 -9
- package/docs/tools-observe.mdx +66 -10
- package/docs/tools-overview.mdx +26 -23
- package/docs/tools-query.mdx +52 -8
- package/docs/tools-session-and-feedback.mdx +35 -9
- package/docs/tools-sessions.mdx +39 -10
- package/docs/tools-snapshot.mdx +57 -3
- package/docs/tools-state.mdx +24 -1
- package/docs/tools-tools-and-run.mdx +55 -24
- package/docs/tools-wait-for.mdx +34 -15
- package/docs/troubleshooting.mdx +80 -10
- package/docs/usage.md +46 -24
- package/docs/vs-chrome-devtools-mcp.mdx +41 -0
- package/docs/vs-playwright-mcp.mdx +42 -2
- package/docs/vs-screenshots.mdx +42 -1
- package/docs/what-is-reticle.mdx +1 -1
- package/docs/why-reticle.mdx +3 -1
- package/package.json +5 -5
- package/docs/desktop-apps.md +0 -265
package/docs/cli/doctor.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: reticle doctor
|
|
3
|
-
description: Diagnose the Reticle setup in one command: Chromium, daemon, bridge port, logs, and desktop wiring.
|
|
3
|
+
description: 'Diagnose the Reticle setup in one command: Chromium, daemon, bridge port, logs, and desktop wiring.'
|
|
4
4
|
icon: stethoscope
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -23,14 +23,28 @@ Human-readable lines on stdout, not the JSON log. Real capture:
|
|
|
23
23
|
```
|
|
24
24
|
reticle doctor
|
|
25
25
|
node v22.14.0
|
|
26
|
-
chromium ✓ installed (chromium-
|
|
27
|
-
daemon ✓ running on :4400 (pid
|
|
26
|
+
chromium ✓ installed (chromium-1234)
|
|
27
|
+
daemon ✓ running on :4400 (pid 72698, v2.8.0)
|
|
28
28
|
sessions ✓ 1 page connected
|
|
29
29
|
bridge port 4400 (your app must dial THIS port, not your dev-server port)
|
|
30
30
|
daemon log /Users/you/.reticle/daemon-4400.log
|
|
31
31
|
tracing RETICLE_TRACE=1 on the daemon for per-stage timings in that log
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
When nothing has connected, the `sessions` line fails and the daemon's own diagnosis is appended under the checklist. Real capture, against a daemon on a scratch port that no app had dialled, with the diagnosis wrapped for width and trimmed at the ellipsis:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
sessions ✗ no page has connected to this daemon
|
|
38
|
+
bridge port 4499 (your app must dial THIS port, not your dev-server port)
|
|
39
|
+
daemon log /Users/you/.reticle/daemon-4499.log
|
|
40
|
+
tracing RETICLE_TRACE=1 on the daemon for per-stage timings in that log
|
|
41
|
+
|
|
42
|
+
nothing has connected. What the daemon can tell from here:
|
|
43
|
+
no browser session connected. Two things to weigh, and neither of them is proof. (1) Nothing is
|
|
44
|
+
listening on the ports Reticle scans (3000, 3001, 4200, 4321, 5000, 5173, 5174, 8000, 8080, 8100,
|
|
45
|
+
9000, 1420, 3100, 4173, 5175, 7860, 8501), so the dev server may not be running ...
|
|
46
|
+
```
|
|
47
|
+
|
|
34
48
|
| Line | What it checks |
|
|
35
49
|
| --- | --- |
|
|
36
50
|
| `node` | The Node version running the CLI |
|
|
@@ -38,6 +52,7 @@ reticle doctor
|
|
|
38
52
|
| `daemon` | Whether the port holds a Reticle daemon, a foreign process (named where possible), or nothing. Adds a `version` line when the daemon's version or contract fingerprint disagrees with the CLI's |
|
|
39
53
|
| `sessions` | Whether any page has actually connected. Zero is a FAILING check rather than a neutral note, because it is the state the setup most often stalls in: wired correctly, daemon up, nothing dialled in. When it is zero the daemon's own no-session diagnosis prints below the checklist |
|
|
40
54
|
| `bridge port` | The port your app must dial, spelled out because mixing it up with the dev server port is the most common setup failure |
|
|
55
|
+
| `port check` | Only when your project's configured port disagrees with the one the daemon is on. Prints the mismatch rather than leaving you to spot it across two lines |
|
|
41
56
|
| `daemon log` | Where the structured daemon log lives |
|
|
42
57
|
| `tracing` | How to turn that log into a per-stage trace |
|
|
43
58
|
| `desktop` | Only on a desktop project. Every Electron and Tauri misconfiguration here fails silently, so it is diagnosed explicitly |
|
|
@@ -46,11 +61,29 @@ reticle doctor
|
|
|
46
61
|
|
|
47
62
|
Playwright pins one Chromium revision per version, and the daemon launches that one and no other. So the check is not "is a Chromium there" but "is _this_ revision there", and the three answers have three different fixes.
|
|
48
63
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
All three captures below are real, taken by pointing `PLAYWRIGHT_BROWSERS_PATH` at a full root, a stale root, and an empty one.
|
|
65
|
+
|
|
66
|
+
**`✓ installed`** means the wanted revision is on disk. Nothing to do.
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
chromium ✓ installed (chromium-1234)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**`✗ wrong revision`** means builds are installed and none of them is the wanted one. One pinned download away. The line names the revision Playwright wants, then every revision the root actually holds, then the exact command:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
chromium ✗ wrong revision ... the bundled playwright wants chromium-1234;
|
|
76
|
+
/tmp/pwroot holds chromium-1194, chromium-1208. run: npx playwright@1.62.1 install chromium
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**`✗ missing`** means the browsers root holds no Chromium at all. It prints the full executable path it looked for, so you can see which root it searched. If that is not where your browsers live, `PLAYWRIGHT_BROWSERS_PATH` is what moves it:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
chromium ✗ missing ... looked for /tmp/emptyroot/chromium-1234/chrome-mac-arm64/Google Chrome
|
|
83
|
+
for Testing.app/Contents/MacOS/Google Chrome for Testing; run: npx playwright@1.62.1 install chromium
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Both failing lines are one line in the terminal, wrapped here for width, and the punctuation that separates the verdict from its explanation is shown as `...`. The revision number and the pinned Playwright version come from the build you are running, so yours may differ from these; use the ones your own `doctor` prints.
|
|
54
87
|
|
|
55
88
|
The wanted revision and the root are both read back off the path Playwright itself resolves, so `PLAYWRIGHT_BROWSERS_PATH` and every platform default (including `%LOCALAPPDATA%\ms-playwright` on Windows) are honoured without this command keeping its own table of roots.
|
|
56
89
|
|
package/docs/cli/drive.mdx
CHANGED
|
@@ -22,34 +22,53 @@ npx @reticlehq/server drive <url> [--headless] [--headed]
|
|
|
22
22
|
|
|
23
23
|
## What it prints
|
|
24
24
|
|
|
25
|
-
`reticle_started` with the port on success, `reticle_start_failed` with the error otherwise.
|
|
25
|
+
`reticle_started` with the port on success, `reticle_start_failed` with the error otherwise. When a daemon already owns the port it prints `reticle_drive_attached` with the session it opened instead. See [When a daemon already has the port](#when-a-daemon-already-has-the-port).
|
|
26
26
|
|
|
27
|
-
Omitting the URL is a usage error. Real capture:
|
|
27
|
+
Omitting the URL is a usage error. Real capture, with the usage block that follows it trimmed:
|
|
28
28
|
|
|
29
29
|
```
|
|
30
|
-
{"t":"2026-08-
|
|
30
|
+
{"t":"2026-08-15T18:43:06.977Z","event":"reticle_usage_error","message":"drive needs a url"}
|
|
31
31
|
drive needs a url
|
|
32
32
|
|
|
33
|
-
usage:
|
|
34
|
-
|
|
33
|
+
usage: npx @reticlehq/server <command> (or `reticle <command>` once the bin is on your PATH)
|
|
34
|
+
...
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
<Note>
|
|
38
|
+
`drive` takes **no `--port` flag**. Any flag other than `--headed` or `--headless` is rejected as
|
|
39
|
+
`unknown argument '--port'`. To drive on a different port, set `RETICLE_PORT` or put the port in
|
|
40
|
+
`.reticle.json`.
|
|
41
|
+
</Note>
|
|
42
|
+
|
|
37
43
|
## Exit codes
|
|
38
44
|
|
|
39
|
-
| Code | Meaning
|
|
40
|
-
| ---- |
|
|
41
|
-
| `0` | Running in the foreground
|
|
42
|
-
| `1` | No URL, an unknown flag,
|
|
45
|
+
| Code | Meaning |
|
|
46
|
+
| ---- | --------------------------------------------------------------------- |
|
|
47
|
+
| `0` | Running in the foreground, or attached with a connected session |
|
|
48
|
+
| `1` | No URL, an unknown flag, the engine failed to start, or attach failed |
|
|
49
|
+
|
|
50
|
+
## When a daemon already has the port
|
|
51
|
+
|
|
52
|
+
A daemon on `:4400` is the normal state the moment any agent connects, and `drive` does not fight it for the port: it **asks that daemon** for a browser instead. The daemon opens a fresh isolated, never-throttled context, the same one `reticle_lease` hands an agent, and `drive` prints the session id and exits.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
$ npx @reticlehq/server drive http://localhost:5173
|
|
56
|
+
{"event":"reticle_drive_attached","port":4400,"url":"http://localhost:5173","sessionId":"lease-9f2b…","ready":true}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
A plain-text line follows it naming the same session, how long it survives untouched (any tool call against it resets that), and, if the page never dialled the bridge, why.
|
|
60
|
+
|
|
61
|
+
That session lives in the daemon, so the tools your agent already has open can address it by id. You do **not** need `reticle stop` first, and should not use it: the MCP proxy respawns a daemon as soon as the next tool call arrives, which is a race a manual `stop` loses.
|
|
62
|
+
|
|
63
|
+
Attaching means the browser is the daemon's pooled, headless one, so `--headed` cannot apply. To watch a browser instead, drive on a port no daemon owns (`RETICLE_PORT=4460`).
|
|
43
64
|
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
</Warning>
|
|
65
|
+
<Note>
|
|
66
|
+
If the port is held by something that is **not** a Reticle daemon, `drive` refuses and names the
|
|
67
|
+
holder. It can neither bind nor attach. [`reticle verify`](/cli/verify) still binds its own port.
|
|
68
|
+
</Note>
|
|
49
69
|
|
|
50
70
|
## Worked example
|
|
51
71
|
|
|
52
72
|
```bash
|
|
53
|
-
npx @reticlehq/server stop
|
|
54
73
|
npx @reticlehq/server drive http://localhost:5173
|
|
55
74
|
```
|
package/docs/cli/gate.mdx
CHANGED
|
@@ -32,16 +32,16 @@ One `reticle_gate` line. Real capture from this repository, with the flow lists
|
|
|
32
32
|
|
|
33
33
|
```json
|
|
34
34
|
{
|
|
35
|
-
"t": "2026-08-
|
|
35
|
+
"t": "2026-08-15T18:42:58.434Z",
|
|
36
36
|
"event": "reticle_gate",
|
|
37
37
|
"pass": false,
|
|
38
|
-
"uncovered": ["deploy-journey", "verify-route", "verify-500"],
|
|
39
|
-
"quarantined": ["asserted-demo", "blast-radius-compose"],
|
|
40
|
-
"coverage": { "pct":
|
|
38
|
+
"uncovered": ["WEB-flow", "deploy-journey", "verify-route", "verify-500"],
|
|
39
|
+
"quarantined": ["asserted-demo", "blast-radius-compose", "drift-demo", "qa2-flow"],
|
|
40
|
+
"coverage": { "pct": 0, "covered": 0, "total": 47 }
|
|
41
41
|
}
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
`downgraded` and `deletedCoverage` appear only when they are non-empty.
|
|
44
|
+
`downgraded` and `deletedCoverage` appear only when they are non-empty, and neither was present in that run. The CLI prints this as a single line of JSON; it is pretty-printed here to be readable.
|
|
45
45
|
|
|
46
46
|
## Exit codes
|
|
47
47
|
|
|
@@ -50,7 +50,7 @@ One `reticle_gate` line. Real capture from this repository, with the flow lists
|
|
|
50
50
|
| `0` | Every affected, non-flaky flow has a passing artifact and nothing was weakened or deleted |
|
|
51
51
|
| `1` | Something is uncovered, downgraded or deleted. Also `1` on any internal fault: the gate fails closed |
|
|
52
52
|
|
|
53
|
-
Measured on this repository, `npx @reticlehq/server gate --since HEAD~1` exited `1` with the output above.
|
|
53
|
+
Measured on this repository, `npx @reticlehq/server gate --since HEAD~1` exited `1` with the output above: 0 of 47 flows covered, 39 uncovered and 8 quarantined.
|
|
54
54
|
|
|
55
55
|
## Worked example
|
|
56
56
|
|
package/docs/cli/help.mdx
CHANGED
|
@@ -16,8 +16,8 @@ All three are the same command.
|
|
|
16
16
|
|
|
17
17
|
<Warning>
|
|
18
18
|
There is no per-command help. `reticle init --help` is not a help request, it is an unknown
|
|
19
|
-
argument: the parser rejects it, prints `unknown argument '--help'
|
|
20
|
-
the rest of this section are the per-command reference.
|
|
19
|
+
argument: the parser rejects it, prints `unknown argument '--help'` followed by this same block,
|
|
20
|
+
and exits `1`. This page and the rest of this section are the per-command reference.
|
|
21
21
|
</Warning>
|
|
22
22
|
|
|
23
23
|
## What it prints
|
|
@@ -33,7 +33,9 @@ usage: npx @reticlehq/server <command> (or `reticle <command>` once the bin i
|
|
|
33
33
|
(CLAUDE.md / AGENTS.md / .cursor) and the /reticle command, because all three
|
|
34
34
|
only make sense once the tools are reachable.
|
|
35
35
|
reticle serve [--port N] [--drive <url>] [--headless] [--http] [--http-port N] [--http-token T]
|
|
36
|
-
reticle stop [--port N] [--quiet]
|
|
36
|
+
reticle stop [--port N] [--quiet] (stop the daemon we started, by its recorded pid)
|
|
37
|
+
reticle kill [--port N] [--force] (free the port by its LISTENER, never the agent's mcp proxy)
|
|
38
|
+
reticle restart [--port N] [--force] (kill, then start a daemon and wait for a real bind)
|
|
37
39
|
reticle status [--port N]
|
|
38
40
|
reticle doctor [--port N] (one command to diagnose setup: Chromium, daemon, port)
|
|
39
41
|
reticle open [url] [--port N] (show the app: reuse the connected tab, else open one)
|
|
@@ -71,11 +73,11 @@ and the spec runner: batch work). --headed opts any of them in, --headless hides
|
|
|
71
73
|
Any usage error prints the offending thing first, then this same block on stderr, and exits `1`:
|
|
72
74
|
|
|
73
75
|
```
|
|
74
|
-
{"t":"2026-08-
|
|
76
|
+
{"t":"2026-08-15T18:42:48.476Z","event":"reticle_usage_error","message":"unknown command 'nonsense-cmd'"}
|
|
75
77
|
unknown command 'nonsense-cmd'
|
|
76
78
|
|
|
77
|
-
usage:
|
|
78
|
-
...
|
|
79
|
+
usage: npx @reticlehq/server <command> (or `reticle <command>` once the bin is on your PATH)
|
|
80
|
+
... the whole block above ...
|
|
79
81
|
```
|
|
80
82
|
|
|
81
83
|
Two audiences, two channels: the structured line for logs and scripts, the plain text for the person who just typed the command.
|
package/docs/cli/hunt.mdx
CHANGED
|
@@ -4,7 +4,7 @@ description: Aggregate many crawl reports into one false-green rate across alrea
|
|
|
4
4
|
icon: crosshairs
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
`reticle hunt` is arithmetic, not driving. You point it at a directory of crawl reports (one JSON file per checkout, each produced by `
|
|
7
|
+
`reticle hunt` is arithmetic, not driving. You point it at a directory of crawl reports (one JSON file per checkout, each produced by `reticle_verify {action:"crawl"}`) and it turns the pile into the one number the core claim needs: across N already-merged, already-green changes, how many carried a candidate false green?
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npx @reticlehq/server hunt <dir-of-crawl-reports>
|
|
@@ -22,7 +22,22 @@ Each input file is read for `label` (falling back to the filename), `anomalies[]
|
|
|
22
22
|
|
|
23
23
|
## What it prints
|
|
24
24
|
|
|
25
|
-
One `reticle_hunt` line with the summary:
|
|
25
|
+
One `reticle_hunt` line with the summary. Real capture over a directory of two reports, one of them carrying a contradiction and a console error, with the `headline` sentence trimmed at the ellipsis:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"t": "2026-08-15T18:43:18.333Z",
|
|
30
|
+
"event": "reticle_hunt",
|
|
31
|
+
"runs": 2,
|
|
32
|
+
"runsWithCoverage": 2,
|
|
33
|
+
"runsWithContradictions": 1,
|
|
34
|
+
"contradictions": 1,
|
|
35
|
+
"singleChannelFaults": 1,
|
|
36
|
+
"byKind": { "ui-advanced-request-failed": 1, "console-error": 1 },
|
|
37
|
+
"flagged": ["abc123"],
|
|
38
|
+
"headline": "1 of 2 merged, already-green changes carried a candidate false green (1 contradictions) ..."
|
|
39
|
+
}
|
|
40
|
+
```
|
|
26
41
|
|
|
27
42
|
| Field | Meaning |
|
|
28
43
|
| --- | --- |
|
|
@@ -40,7 +55,8 @@ One `reticle_hunt` line with the summary:
|
|
|
40
55
|
Always `0`. A read failure is logged as `reticle_hunt_failed`. Omitting the directory is a usage error:
|
|
41
56
|
|
|
42
57
|
```
|
|
43
|
-
{"t":"2026-08-
|
|
58
|
+
{"t":"2026-08-15T18:43:06.525Z","event":"reticle_usage_error","message":"usage: reticle hunt <dir-of-crawl-reports>"}
|
|
59
|
+
usage: reticle hunt <dir-of-crawl-reports>
|
|
44
60
|
```
|
|
45
61
|
|
|
46
62
|
That path exits `1`.
|
|
@@ -50,7 +66,7 @@ That path exits `1`.
|
|
|
50
66
|
```bash
|
|
51
67
|
for sha in $(git log --format=%H -n 30 main); do
|
|
52
68
|
git checkout "$sha" && npm run dev &
|
|
53
|
-
# drive
|
|
69
|
+
# drive reticle_verify {action:"crawl"} over the app, write the JSON:
|
|
54
70
|
# .../reports/$sha.json
|
|
55
71
|
done
|
|
56
72
|
npx @reticlehq/server hunt ./reports
|
package/docs/cli/identify.mdx
CHANGED
|
@@ -4,7 +4,9 @@ description: Opt in to telling the Reticle maintainers who you are, and undo it
|
|
|
4
4
|
icon: id-card
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
`reticle identify`
|
|
7
|
+
`reticle identify` attaches a name, a company, an email and a usage context to this machine's Reticle install and sends them to the maintainers, so support or an enterprise trial has someone to talk to. It is off unless you run it, and `reticle identify --forget` undoes it.
|
|
8
|
+
|
|
9
|
+
It is opt-in and deliberately not interactive. A prompt in the middle of someone's work is pressure, and this is the one command where the choice has to be free. You type what you want to share, or you never run it at all.
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
12
|
npx @reticlehq/server identify --context <company|side_project|open_source|learning> [--company "Acme"] [--email you@acme.com] [--forget]
|
|
@@ -39,7 +41,19 @@ forgotten the local identity file is deleted; nothing further is sent.
|
|
|
39
41
|
to have what was already sent removed, email support@reticlehq.com
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
Run with no valid `--context`, it prints the current identity (if any), the usage, and the full consent notice
|
|
44
|
+
Run with no valid `--context`, it prints the current identity (if any), the usage, and the full consent notice, and exits `1`. Real capture on a machine with no identity on file:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
usage: reticle identify --context <company|side_project|open_source|learning>
|
|
48
|
+
[--company "Acme"] [--email you@acme.com] [--forget]
|
|
49
|
+
|
|
50
|
+
This sends the details you type here to the Reticle maintainers, so we can contact you and
|
|
51
|
+
understand how teams use Reticle. It is linked to this machine's anonymous id, which means it
|
|
52
|
+
also connects the anonymous usage already recorded from this machine to what you enter now.
|
|
53
|
+
Nothing about your app, your code, or your repository is included, and nothing else changes.
|
|
54
|
+
Undo it any time with `reticle identify --forget` (that stops future sends and deletes the local file;
|
|
55
|
+
email support@reticlehq.com to have what was already sent removed).
|
|
56
|
+
```
|
|
43
57
|
|
|
44
58
|
<Warning>
|
|
45
59
|
Identifying links this machine's anonymous id to what you type, which also connects the anonymous
|
package/docs/cli/init.mdx
CHANGED
|
@@ -17,7 +17,7 @@ npx @reticlehq/server init [--dry-run] [--port N] [--no-mcp] [--no-install] [--a
|
|
|
17
17
|
| `--dry-run` | boolean | `false` | Print the full plan and write nothing |
|
|
18
18
|
| `--port N` | number | unset (resolves to `4400`) | Bridge port to write into the config |
|
|
19
19
|
| `--no-mcp` | boolean | `false` (MCP is registered) | Skip the MCP registration **and** the agent rule files (`CLAUDE.md`, `AGENTS.md`, `.cursor`) and the `/reticle` command |
|
|
20
|
-
| `--no-install` | boolean | `false` (deps are installed) |
|
|
20
|
+
| `--no-install` | boolean | `false` (deps are installed) | Do not run the install. The step becomes `[⚠]` and prints the `add -D` command for you to run by hand, rather than vanishing from the plan |
|
|
21
21
|
| `--app <dir>` | string | unset | Pick which app to wire in a monorepo, without changing directory |
|
|
22
22
|
| `--yes` | boolean | `false` | Accepted for scripting. `init` has no interactive prompts today, so it is a no-op |
|
|
23
23
|
|
|
@@ -28,7 +28,7 @@ npx @reticlehq/server init [--dry-run] [--port N] [--no-mcp] [--no-install] [--a
|
|
|
28
28
|
|
|
29
29
|
## What it prints
|
|
30
30
|
|
|
31
|
-
A plan, one line per step, each with a status mark: `✓` written, `·` already in place or left alone, `⚠` needs a hand. Captured from a real run inside `apps/bench-app`:
|
|
31
|
+
A plan, one line per step, each with a status mark: `✓` written, `·` already in place or left alone, `⚠` needs a hand, `–` deliberately skipped by a flag. Captured from a real `--dry-run` inside `apps/bench-app`:
|
|
32
32
|
|
|
33
33
|
```
|
|
34
34
|
reticle init (dry run, no files written)
|
|
@@ -46,6 +46,10 @@ reticle init (dry run, no files written)
|
|
|
46
46
|
|
|
47
47
|
[✓] Agent verification rule → CLAUDE.md
|
|
48
48
|
teach the agent to verify features with Reticle after building them
|
|
49
|
+
[✓] Agent verification rule → AGENTS.md
|
|
50
|
+
teach the agent to verify features with Reticle after building them
|
|
51
|
+
[✓] Full agent rules → RETICLE.md
|
|
52
|
+
the reference the always-loaded rule points at (when NOT to verify, recovery, feedback)
|
|
49
53
|
[✓] The /reticle command → .claude/commands/reticle.md
|
|
50
54
|
type /reticle to verify one flow in the browser
|
|
51
55
|
[✓] Install dependencies → package.json
|
|
@@ -60,7 +64,16 @@ reticle init (dry run, no files written)
|
|
|
60
64
|
Restart `vite`.
|
|
61
65
|
```
|
|
62
66
|
|
|
63
|
-
|
|
67
|
+
Below the plan it also prints the two things that actually finish the install: restart your agent so it re-reads its MCP server list, then run `npx @reticlehq/server status` to confirm the app connected.
|
|
68
|
+
|
|
69
|
+
With `--no-mcp`, the whole MCP and rules group collapses into one skipped line:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
[–] MCP server (global) → global (claude user scope)
|
|
73
|
+
--no-mcp ... also skips the agent rule files (CLAUDE.md / AGENTS.md / .cursor) and the /reticle command
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Run from a workspace root with several apps, it refuses to guess, names them, and exits `1`:
|
|
64
77
|
|
|
65
78
|
```
|
|
66
79
|
Several apps found in this workspace. Re-run `reticle init` inside the one you want:
|
|
@@ -68,17 +81,31 @@ Several apps found in this workspace. Re-run `reticle init` inside the one you w
|
|
|
68
81
|
packages/vite-plugin
|
|
69
82
|
apps/atlas
|
|
70
83
|
apps/bench-app
|
|
71
|
-
|
|
84
|
+
apps/electron-smoke
|
|
85
|
+
apps/large-dom-bench
|
|
86
|
+
apps/next-smoke
|
|
87
|
+
apps/tauri-smoke
|
|
88
|
+
apps/vibe-builder-demo
|
|
72
89
|
|
|
73
90
|
Or name one without changing directory: reticle init --app packages/next
|
|
74
91
|
```
|
|
75
92
|
|
|
93
|
+
Given `--app`, it says which directory it moved to before printing the plan:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
No app in this directory ... wiring apps/bench-app instead.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
In the two captures above, the punctuation that separates the two halves of the sentence is shown as `...`.
|
|
100
|
+
|
|
76
101
|
## Exit codes
|
|
77
102
|
|
|
78
|
-
| Code | Meaning
|
|
79
|
-
| ---- |
|
|
80
|
-
| `0` | The plan ran. Steps marked `⚠` still need a hand, and do not change the code
|
|
81
|
-
| `1` | Init failed,
|
|
103
|
+
| Code | Meaning |
|
|
104
|
+
| ---- | --------------------------------------------------------------------------------------- |
|
|
105
|
+
| `0` | The plan ran. Steps marked `⚠` still need a hand, and do not change the code |
|
|
106
|
+
| `1` | Init failed, an unknown flag was passed, or several apps were found and none was chosen |
|
|
107
|
+
|
|
108
|
+
An unknown flag is rejected by name: `reticle init --bogus` prints `unknown argument '--bogus'`, then the full usage block, and exits `1`.
|
|
82
109
|
|
|
83
110
|
## Worked example
|
|
84
111
|
|
package/docs/cli/kill.mdx
CHANGED
|
@@ -47,24 +47,24 @@ Reach for `stop` in a script that shuts down a daemon it started. Reach for `kil
|
|
|
47
47
|
|
|
48
48
|
## What it prints
|
|
49
49
|
|
|
50
|
-
Real captures.
|
|
50
|
+
Real captures, taken against a daemon started on a scratch port. The long `note` and `reason` strings are trimmed at the ellipsis. Measured exit codes: `0` for killed and nothing-to-do, `1` for refused.
|
|
51
51
|
|
|
52
52
|
Killed:
|
|
53
53
|
|
|
54
54
|
```
|
|
55
|
-
{"event":"reticle_killed","port":4499,"pid":
|
|
55
|
+
{"t":"2026-08-15T18:43:43.590Z","event":"reticle_killed","port":4499,"pid":78621,"escalated":false,"listenerIdentified":true,"note":"only the listener was signalled. Any `reticle mcp` proxy on this port holds a client connection, not the port, and was left alone ..."}
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
Refused, because the listener is not ours:
|
|
58
|
+
Refused, because the listener is not ours. This one was captured with `python3 -m http.server 4498` holding the port:
|
|
59
59
|
|
|
60
60
|
```
|
|
61
|
-
{"event":"reticle_kill_refused","port":4498,"reason":"pid
|
|
61
|
+
{"t":"2026-08-15T18:43:57.128Z","event":"reticle_kill_refused","port":4498,"reason":"pid 78795 (\"Python\") is listening, and it is not a Reticle daemon ... it never answered /status and it is not the pid Reticle recorded. Killing it would be killing someone else's process. Run it again with --force if that is what you meant, or start Reticle on another port.","holder":"Python"}
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
Nothing to free:
|
|
65
65
|
|
|
66
66
|
```
|
|
67
|
-
{"event":"reticle_kill_nothing_to_do","port":4499,"presence":"free"}
|
|
67
|
+
{"t":"2026-08-15T18:43:43.784Z","event":"reticle_kill_nothing_to_do","port":4499,"presence":"free"}
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
| Event | When |
|
package/docs/cli/license.mdx
CHANGED
|
@@ -18,7 +18,7 @@ One `reticle_license` line. Real capture on a checkout with no issuer key config
|
|
|
18
18
|
|
|
19
19
|
```json
|
|
20
20
|
{
|
|
21
|
-
"t": "2026-08-
|
|
21
|
+
"t": "2026-08-15T18:42:26.758Z",
|
|
22
22
|
"event": "reticle_license",
|
|
23
23
|
"status": "eval",
|
|
24
24
|
"detail": "evaluation mode: enterprise features run free (no issuer key configured)"
|
package/docs/cli/open.mdx
CHANGED
|
@@ -40,6 +40,12 @@ One `reticle_open` line, whose fields say which of four things happened.
|
|
|
40
40
|
{"event":"reticle_open","port":4499,"error":"could not launch a browser: spawn open ENOENT","recovery":"Nothing was opened. This command asks the OS to open a url in your default browser (`open` on this platform) and that failed, so the fix is on the OS side: open the url yourself, or set a default browser."}
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
Calling it with no URL when nothing has connected is the other `error` shape. It exits `0`, because reporting "there is nothing to show you" is a complete answer. Real capture, with the sentence break shown as `...`:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
{"t":"2026-08-15T18:43:41.651Z","event":"reticle_open","port":4499,"error":"no app connected ... pass a url: reticle open <url>. Desktop app (Electron/Tauri)? There is no url to open: start it as you normally would and it connects to this bridge itself."}
|
|
47
|
+
```
|
|
48
|
+
|
|
43
49
|
</Note>
|
|
44
50
|
|
|
45
51
|
<Warning>
|
package/docs/cli/restart.mdx
CHANGED
|
@@ -21,18 +21,18 @@ npx @reticlehq/server restart [--port N] [--force]
|
|
|
21
21
|
|
|
22
22
|
A restart that killed the old daemon and then could not start a new one leaves you somewhere quite different from one that could not kill anything at all, and a single `ok: false` cannot tell you which happened. So each half prints its own line.
|
|
23
23
|
|
|
24
|
-
Real capture, restarting over a running daemon:
|
|
24
|
+
Real capture, restarting over a running daemon (exit `0`), with the long `note` trimmed at the ellipsis:
|
|
25
25
|
|
|
26
26
|
```
|
|
27
|
-
{"event":"reticle_killed","port":4499,"pid":
|
|
28
|
-
{"event":"reticle_daemon_spawned","port":4499}
|
|
27
|
+
{"t":"2026-08-15T18:43:41.949Z","event":"reticle_killed","port":4499,"pid":78137,"escalated":false,"listenerIdentified":true,"note":"only the listener was signalled. Any `reticle mcp` proxy on this port holds a client connection, not the port, and was left alone ..."}
|
|
28
|
+
{"t":"2026-08-15T18:43:42.258Z","event":"reticle_daemon_spawned","port":4499}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Real capture, when the port is held by something that is not ours:
|
|
31
|
+
Real capture, when the port is held by something that is not ours (exit `1`). Both `reason` strings are trimmed at the ellipsis:
|
|
32
32
|
|
|
33
33
|
```
|
|
34
|
-
{"event":"reticle_kill_refused","port":4498,"reason":"pid
|
|
35
|
-
{"event":"reticle_restart_aborted","port":4498,"reason":"the port was not freed, so nothing was started
|
|
34
|
+
{"t":"2026-08-15T18:43:57.317Z","event":"reticle_kill_refused","port":4498,"reason":"pid 78795 (\"Python\") is listening, and it is not a Reticle daemon ... it never answered /status and it is not the pid Reticle recorded. Killing it would be killing someone else's process. Run it again with --force if that is what you meant, or start Reticle on another port.","holder":"Python"}
|
|
35
|
+
{"t":"2026-08-15T18:43:57.318Z","event":"reticle_restart_aborted","port":4498,"reason":"the port was not freed, so nothing was started ... the old holder is still there"}
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
<Note>
|
package/docs/cli/serve.mdx
CHANGED
|
@@ -29,13 +29,20 @@ Most people never type this. Your agent runs [`reticle mcp`](/cli/mcp), which st
|
|
|
29
29
|
One structured line. When a daemon already owns the port, it says so and does nothing:
|
|
30
30
|
|
|
31
31
|
```json
|
|
32
|
-
{ "t": "2026-08-
|
|
32
|
+
{ "t": "2026-08-15T18:43:33.065Z", "event": "reticle_daemon_already_running", "port": 4499 }
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
A successful spawn logs `reticle_daemon_spawned` with the port
|
|
35
|
+
A successful spawn logs `reticle_daemon_spawned` with the port:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{ "t": "2026-08-15T18:43:32.604Z", "event": "reticle_daemon_spawned", "port": 4499 }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A port held by something that is not a Reticle daemon is refused up front rather than spawned into. The reason is repeated as plain text on stderr for the person who typed the command. Real capture, with `python3 -m http.server 4498` holding the port and the punctuation between the two halves of the reason shown as `...`:
|
|
36
42
|
|
|
37
43
|
```
|
|
38
|
-
reticle_daemon_start_refused
|
|
44
|
+
{"t":"2026-08-15T18:43:57.478Z","event":"reticle_daemon_start_refused","port":4498,"presence":"foreign","reason":"port 4498 is held by another process that is not a Reticle daemon ... a daemon cannot bind it. Stop that process, or run Reticle on a different port (`--port`), then retry."}
|
|
45
|
+
port 4498 is held by another process that is not a Reticle daemon ... a daemon cannot bind it. Stop that process, or run Reticle on a different port (`--port`), then retry.
|
|
39
46
|
```
|
|
40
47
|
|
|
41
48
|
## Exit codes
|
package/docs/cli/status.mdx
CHANGED
|
@@ -22,23 +22,47 @@ One JSON line on stdout. Real capture, daemon up and no app connected:
|
|
|
22
22
|
|
|
23
23
|
```json
|
|
24
24
|
{
|
|
25
|
-
"t": "2026-08-
|
|
25
|
+
"t": "2026-08-15T18:43:33.724Z",
|
|
26
26
|
"event": "reticle_status",
|
|
27
|
-
"port":
|
|
27
|
+
"port": 4499,
|
|
28
28
|
"running": true,
|
|
29
|
-
"pid":
|
|
29
|
+
"pid": 78137,
|
|
30
30
|
"sessionCount": 0,
|
|
31
31
|
"sessions": [],
|
|
32
|
-
"why": "no browser session connected. Two things to weigh, and neither of them is proof. (1) Nothing is listening on the ports Reticle scans ... (2) There is no `.reticle.json` in the directory this daemon is running in ..."
|
|
32
|
+
"why": "no browser session connected. Two things to weigh, and neither of them is proof. (1) Nothing is listening on the ports Reticle scans (3000, 3001, 4200, 4321, 5000, 5173, 5174, 8000, 8080, 8100, 9000, 1420, 3100, 4173, 5175, 7860, 8501), so the dev server may not be running ... (2) There is no `.reticle.json` in the directory this daemon is running in ..."
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
With an app connected, `why` is absent and each session carries its own fields:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"t": "2026-08-15T18:45:58.190Z",
|
|
41
|
+
"event": "reticle_status",
|
|
42
|
+
"port": 4400,
|
|
43
|
+
"running": true,
|
|
44
|
+
"pid": 72698,
|
|
45
|
+
"sessionCount": 1,
|
|
46
|
+
"sessions": [
|
|
47
|
+
{
|
|
48
|
+
"sessionId": "s223e0fad-e012-43f9-a23d-6d585470c90d",
|
|
49
|
+
"url": "http://localhost:4310/",
|
|
50
|
+
"throttled": false,
|
|
51
|
+
"stale": false,
|
|
52
|
+
"pendingMarks": 0
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Both are one line of JSON in the terminal, pretty-printed here, with `why` trimmed at the ellipses.
|
|
59
|
+
|
|
36
60
|
| Field | Meaning |
|
|
37
61
|
| --- | --- |
|
|
38
62
|
| `running` | Whether a usable daemon owns the port |
|
|
39
63
|
| `presence` | Present when the pid file is dead: `daemon`, `foreign`, or `absent`. The port is asked, not just the pid file |
|
|
40
64
|
| `pid` | The daemon process |
|
|
41
|
-
| `sessionCount` / `sessions` | Connected app sessions, each with `sessionId`, `url`, `throttled`, `stale` |
|
|
65
|
+
| `sessionCount` / `sessions` | Connected app sessions, each with `sessionId`, `url`, `throttled`, `stale`, `pendingMarks` |
|
|
42
66
|
| `why` | Present when zero sessions connected. Names the two likely causes and refuses to assert either |
|
|
43
67
|
| `updateAvailable` | Present when a newer server version is on the registry |
|
|
44
68
|
|
package/docs/cli/stop.mdx
CHANGED
|
@@ -31,6 +31,14 @@ npx @reticlehq/server stop [--port N] [--quiet]
|
|
|
31
31
|
| `reticle_daemon_not_running` | No live pid for that port. The stale pid file is removed |
|
|
32
32
|
| `reticle_daemon_stop_timeout` | It survived everything. Exits `1` |
|
|
33
33
|
|
|
34
|
+
Real capture, stopping a port with no live pid recorded for it. It exits `0`, because "already not running" is the state you asked for:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
{"t":"2026-08-15T18:43:43.943Z","event":"reticle_daemon_not_running","port":4499}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
With `--quiet` that same run prints nothing at all and still exits `0`.
|
|
41
|
+
|
|
34
42
|
## Exit codes
|
|
35
43
|
|
|
36
44
|
| Code | Meaning |
|
package/docs/cli/verify.mdx
CHANGED
|
@@ -27,17 +27,36 @@ The rendered run report on stdout. On failure it names the cause on stderr inste
|
|
|
27
27
|
|
|
28
28
|
```
|
|
29
29
|
No app connected: Reticle drove the URL but no @reticlehq/browser session dialed back.
|
|
30
|
-
Make sure the SDK is in the build and reticle.connect() runs on the preview page
|
|
30
|
+
Make sure the SDK is in the build and reticle.connect() runs on the preview page (for a non-localhost preview: allowNonLocalhost + a pairing token).
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
```
|
|
34
34
|
No saved flows to verify (.reticle/flows is empty), so refusing to report a pass for verifying nothing.
|
|
35
|
+
Flows are recorded interactively by an agent (reticle_record{action:"start"} → act → reticle_flow_save via the
|
|
36
|
+
MCP tools), then committed to .reticle/flows/. In CI, check those files in and re-run `reticle verify`.
|
|
35
37
|
```
|
|
36
38
|
|
|
37
39
|
<Warning>
|
|
38
40
|
Both of those are honesty guards, and both exit `1`. Verifying nothing is never a pass.
|
|
39
41
|
</Warning>
|
|
40
42
|
|
|
43
|
+
A URL that does not answer is not one of those two. It surfaces as the underlying Playwright error, prefixed with `verify failed:`, and also exits `1`. Real capture:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
verify failed: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:59999/
|
|
47
|
+
Call log:
|
|
48
|
+
- navigating to "http://localhost:59999/", waiting until "domcontentloaded"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
<Warning>
|
|
52
|
+
`verify` binds the bridge port itself and has **no `--port` flag**: passing one is rejected as
|
|
53
|
+
`unknown argument '--port'`. If a daemon is already on the port, `verify` dies with a raw `Error:
|
|
54
|
+
listen EADDRINUSE: address already in use 127.0.0.1:4400` stack trace before it drives anything.
|
|
55
|
+
Stop the daemon first, or move `verify` with the `RETICLE_PORT` environment variable. This bites
|
|
56
|
+
most often on a developer machine, where an agent has usually left a daemon running; in CI the
|
|
57
|
+
port is normally free.
|
|
58
|
+
</Warning>
|
|
59
|
+
|
|
41
60
|
## Exit codes
|
|
42
61
|
|
|
43
62
|
| Code | Meaning |
|
package/docs/cli/version.mdx
CHANGED
|
@@ -19,7 +19,7 @@ All three are the same command. No flags.
|
|
|
19
19
|
One `reticle_version` line. Real capture:
|
|
20
20
|
|
|
21
21
|
```json
|
|
22
|
-
{ "t": "2026-08-
|
|
22
|
+
{ "t": "2026-08-15T18:42:26.275Z", "event": "reticle_version", "version": "2.8.0" }
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Exit codes
|