@reticlehq/server 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -5
- package/SKILL.md +64 -29
- package/dist/capsule/causal-summary.d.ts +20 -0
- package/dist/capsule/causal-summary.js +31 -6
- package/dist/capsule/divergence.js +7 -1
- package/dist/cli/chromium-hint.d.ts +33 -5
- package/dist/cli/chromium-hint.js +82 -12
- package/dist/cli/cli-doctor.js +28 -25
- package/dist/cli/cli-kill.d.ts +58 -0
- package/dist/cli/cli-kill.js +162 -0
- package/dist/cli/cli-launch.d.ts +17 -0
- package/dist/cli/cli-launch.js +28 -0
- package/dist/cli/cli-parse.d.ts +16 -1
- package/dist/cli/cli-parse.js +32 -9
- package/dist/cli/cli-port.d.ts +8 -0
- package/dist/cli/cli-port.js +16 -0
- package/dist/cli/cli-verify.js +2 -2
- package/dist/cli/doctor-sessions-line.d.ts +12 -0
- package/dist/cli/doctor-sessions-line.js +66 -0
- package/dist/cli/port-holder.d.ts +10 -0
- package/dist/cli/port-holder.js +26 -2
- package/dist/cli.js +99 -14
- package/dist/crawl/crawl-tools.js +12 -2
- package/dist/crawl/crawl.d.ts +13 -0
- package/dist/crawl/crawl.js +50 -2
- package/dist/events/contradictions.d.ts +14 -0
- package/dist/events/contradictions.js +26 -17
- package/dist/events/predicate-eval.d.ts +20 -1
- package/dist/events/predicate-eval.js +125 -3
- package/dist/events/predicate.js +170 -18
- package/dist/flows/flow-classify.js +1 -1
- package/dist/flows/flow-tools.js +12 -4
- package/dist/flows/heal-run.js +1 -1
- package/dist/honesty/blind-spots.js +6 -2
- package/dist/honesty/unsettled.d.ts +40 -0
- package/dist/honesty/unsettled.js +78 -0
- package/dist/honesty/verified.d.ts +7 -0
- package/dist/honesty/verified.js +3 -3
- package/dist/index.js +3 -0
- package/dist/init/agent-rules.d.ts +16 -0
- package/dist/init/agent-rules.js +96 -22
- package/dist/init/astro-patch.d.ts +2 -1
- package/dist/init/astro-patch.js +11 -5
- package/dist/init/capabilities.d.ts +22 -0
- package/dist/init/capabilities.js +76 -0
- package/dist/init/confirm.d.ts +96 -0
- package/dist/init/confirm.js +138 -0
- package/dist/init/cra.js +3 -2
- package/dist/init/non-js-project.js +29 -5
- package/dist/init/plan-framework.js +53 -15
- package/dist/init/plan.d.ts +40 -4
- package/dist/init/plan.js +163 -40
- package/dist/init/run.d.ts +24 -2
- package/dist/init/run.js +148 -42
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/slash-command.js +46 -6
- package/dist/init/snippets.d.ts +44 -4
- package/dist/init/snippets.js +161 -37
- package/dist/init/vite-config.js +29 -3
- package/dist/input/network-mock-tools.d.ts +19 -0
- package/dist/input/network-mock-tools.js +29 -4
- package/dist/license/license.js +1 -1
- package/dist/mcp/mcp-proxy.d.ts +69 -3
- package/dist/mcp/mcp-proxy.js +205 -20
- package/dist/mcp/mcp.js +23 -7
- package/dist/mcp/proxy-lifecycle.d.ts +1 -1
- package/dist/mcp/proxy-lifecycle.js +1 -1
- package/dist/pool/browser-pool.d.ts +22 -2
- package/dist/pool/browser-pool.js +44 -4
- package/dist/project/learned-routes.d.ts +24 -0
- package/dist/project/learned-routes.js +63 -0
- package/dist/project/project-store.d.ts +6 -0
- package/dist/project/project-store.js +25 -1
- package/dist/session/no-session-diagnosis.d.ts +19 -0
- package/dist/session/no-session-diagnosis.js +71 -18
- package/dist/session/no-session-watch.js +12 -0
- package/dist/session/ref-provenance.d.ts +54 -0
- package/dist/session/ref-provenance.js +61 -0
- package/dist/session/session-lease.js +1 -1
- package/dist/telemetry/automation-hint.d.ts +17 -0
- package/dist/telemetry/automation-hint.js +71 -0
- package/dist/telemetry/bug-found.d.ts +0 -20
- package/dist/telemetry/bug-found.js +38 -21
- package/dist/telemetry/cli-telemetry.js +7 -1
- package/dist/telemetry/feedback.js +1 -1
- package/dist/telemetry/init-telemetry.js +9 -1
- package/dist/telemetry/install-source.d.ts +36 -0
- package/dist/telemetry/install-source.js +40 -0
- package/dist/telemetry/run-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.js +5 -0
- package/dist/telemetry/telemetry.d.ts +5 -1
- package/dist/telemetry/telemetry.js +15 -2
- package/dist/telemetry/tool-refused.d.ts +19 -0
- package/dist/telemetry/tool-refused.js +55 -0
- package/dist/telemetry/verification-of.js +46 -7
- package/dist/temp-dir.d.ts +27 -0
- package/dist/temp-dir.js +46 -0
- package/dist/tools/act-tools.js +45 -1
- package/dist/tools/assert-grade.d.ts +1 -1
- package/dist/tools/assert-grade.js +27 -5
- package/dist/tools/assert-verdict.js +18 -1
- package/dist/tools/contract-tools.js +4 -0
- package/dist/tools/dynamic-tools.js +1 -1
- package/dist/tools/error-recovery.d.ts +10 -0
- package/dist/tools/error-recovery.js +64 -4
- package/dist/tools/feedback-invite.js +1 -1
- package/dist/tools/invoke-tool.js +139 -23
- package/dist/tools/lease-tools.d.ts +29 -1
- package/dist/tools/lease-tools.js +58 -5
- package/dist/tools/navigate-result.js +1 -1
- package/dist/tools/observe-tools.js +1 -1
- package/dist/tools/observed-nothing.js +1 -1
- package/dist/tools/react-grace.d.ts +48 -0
- package/dist/tools/react-grace.js +87 -0
- package/dist/tools/read-tools.js +20 -4
- package/dist/tools/settle-in-flight.d.ts +79 -0
- package/dist/tools/settle-in-flight.js +106 -0
- package/dist/tools/snapshot-delta.d.ts +7 -0
- package/dist/tools/snapshot-delta.js +130 -6
- package/dist/tools/tool-surface.js +19 -0
- package/dist/tools/tools.js +16 -4
- package/docs/README.md +56 -11
- package/docs/actions.mdx +87 -0
- package/docs/agent-cheatsheet.md +93 -29
- package/docs/architecture.md +46 -35
- package/docs/benchmarks.md +76 -72
- package/docs/best-practices.mdx +211 -0
- package/docs/capabilities.mdx +387 -0
- package/docs/cli/affected.mdx +51 -0
- package/docs/cli/capsules.mdx +69 -0
- package/docs/cli/cloud.mdx +127 -0
- package/docs/cli/doctor.mdx +76 -0
- package/docs/cli/drive.mdx +55 -0
- package/docs/cli/feedback.mdx +67 -0
- package/docs/cli/gate.mdx +64 -0
- package/docs/cli/help.mdx +92 -0
- package/docs/cli/hunt.mdx +57 -0
- package/docs/cli/identify.mdx +62 -0
- package/docs/cli/init.mdx +94 -0
- package/docs/cli/kill.mdx +91 -0
- package/docs/cli/license.mdx +48 -0
- package/docs/cli/mcp.mdx +61 -0
- package/docs/cli/open.mdx +68 -0
- package/docs/cli/restart.mdx +60 -0
- package/docs/cli/rollback.mdx +35 -0
- package/docs/cli/serve.mdx +62 -0
- package/docs/cli/status.mdx +64 -0
- package/docs/cli/stop.mdx +56 -0
- package/docs/cli/telemetry.mdx +57 -0
- package/docs/cli/update.mdx +52 -0
- package/docs/cli/verify.mdx +57 -0
- package/docs/cli/version.mdx +39 -0
- package/docs/cli/watch.mdx +55 -0
- package/docs/cli.mdx +219 -0
- package/docs/debugging.md +13 -9
- package/docs/deploy-checks.md +15 -11
- package/docs/desktop-apps.md +49 -40
- package/docs/desktop.mdx +188 -0
- package/docs/docs.json +363 -0
- package/docs/enterprise.md +20 -16
- package/docs/faq.mdx +88 -0
- package/docs/fixtures.md +11 -7
- package/docs/flows.md +26 -22
- package/docs/for-agents.md +71 -0
- package/docs/frameworks.mdx +199 -0
- package/docs/gate-plan.md +45 -41
- package/docs/gates.md +22 -18
- package/docs/getting-started.md +76 -65
- package/docs/human-control.md +22 -18
- package/docs/index.mdx +101 -0
- package/docs/install-agentic.mdx +215 -0
- package/docs/install-manual.mdx +194 -0
- package/docs/instrumentation.mdx +232 -0
- package/docs/integration-patterns.md +38 -34
- package/docs/local-registry.md +16 -12
- package/docs/multi-agent-testing.md +16 -12
- package/docs/packages/babel-plugin.mdx +70 -0
- package/docs/packages/browser.mdx +111 -0
- package/docs/packages/core.mdx +106 -0
- package/docs/packages/electron.mdx +87 -0
- package/docs/packages/eslint-plugin.mdx +84 -0
- package/docs/packages/next.mdx +91 -0
- package/docs/packages/react.mdx +91 -0
- package/docs/packages/server.mdx +98 -0
- package/docs/packages/tauri.mdx +63 -0
- package/docs/packages/test.mdx +108 -0
- package/docs/packages/vite-plugin.mdx +96 -0
- package/docs/packages.mdx +217 -0
- package/docs/platform-integration.md +33 -26
- package/docs/predicates.mdx +179 -0
- package/docs/quickstart.mdx +211 -0
- package/docs/recipes.mdx +242 -0
- package/docs/skill-file.mdx +105 -0
- package/docs/state-management.mdx +197 -0
- package/docs/style.css +14 -0
- package/docs/system-map.md +47 -32
- package/docs/telemetry-contract.md +93 -50
- package/docs/telemetry-events.mdx +430 -0
- package/docs/telemetry.md +57 -52
- package/docs/testing.md +10 -6
- package/docs/token-efficiency.md +30 -26
- package/docs/tools-act-and-wait.mdx +123 -0
- package/docs/tools-act-sequence.mdx +120 -0
- package/docs/tools-act.mdx +82 -0
- package/docs/tools-assert.mdx +70 -0
- package/docs/tools-console.mdx +59 -0
- package/docs/tools-inspect.mdx +85 -0
- package/docs/tools-navigate.mdx +63 -0
- package/docs/tools-network.mdx +86 -0
- package/docs/tools-observe.mdx +89 -0
- package/docs/tools-overview.mdx +157 -0
- package/docs/tools-query.mdx +82 -0
- package/docs/tools-session-and-feedback.mdx +91 -0
- package/docs/tools-sessions.mdx +65 -0
- package/docs/tools-snapshot.mdx +75 -0
- package/docs/tools-state.mdx +81 -0
- package/docs/tools-tools-and-run.mdx +125 -0
- package/docs/tools-wait-for.mdx +66 -0
- package/docs/troubleshooting.mdx +193 -0
- package/docs/usage.md +175 -153
- package/docs/vs-chrome-devtools-mcp.mdx +82 -0
- package/docs/vs-playwright-mcp.mdx +85 -0
- package/docs/vs-screenshots.mdx +96 -0
- package/docs/what-is-reticle.mdx +63 -0
- package/docs/why-reticle.mdx +107 -0
- package/package.json +2 -2
- package/docs/matrix/2.5.0/claude-code-machine.json +0 -19
- package/docs/matrix/2.5.0/codex-machine.json +0 -20
- package/docs/matrix/2.5.0/cursor-machine.json +0 -22
- package/docs/matrix/2.5.0/gemini-machine.json +0 -22
- package/docs/matrix/2.5.0/opencode-machine.json +0 -22
- package/docs/matrix/2.5.0/vscode-machine.json +0 -22
- package/docs/matrix/2.5.0/windsurf-machine.json +0 -22
- package/docs/matrix/MATRIX.md +0 -26
- package/docs/matrix/README.md +0 -59
- package/docs/mint.json +0 -61
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle doctor
|
|
3
|
+
description: Diagnose the Reticle setup in one command: Chromium, daemon, bridge port, logs, and desktop wiring.
|
|
4
|
+
icon: stethoscope
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle doctor` collapses the setup failure modes into one command. It is the first thing to run when something is wrong.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server doctor [--port N]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Flags
|
|
14
|
+
|
|
15
|
+
| Flag | Type | Default | What it does |
|
|
16
|
+
| --- | --- | --- | --- |
|
|
17
|
+
| `--port N` | number | `4400` (or `RETICLE_PORT`, or the port in `.reticle.json`) | Which bridge port to diagnose |
|
|
18
|
+
|
|
19
|
+
## What it prints
|
|
20
|
+
|
|
21
|
+
Human-readable lines on stdout, not the JSON log. Real capture:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
reticle doctor
|
|
25
|
+
node v22.14.0
|
|
26
|
+
chromium ✓ installed (chromium-1223)
|
|
27
|
+
daemon ✓ running on :4400 (pid 4795, v2.8.0)
|
|
28
|
+
sessions ✓ 1 page connected
|
|
29
|
+
bridge port 4400 (your app must dial THIS port, not your dev-server port)
|
|
30
|
+
daemon log /Users/you/.reticle/daemon-4400.log
|
|
31
|
+
tracing RETICLE_TRACE=1 on the daemon for per-stage timings in that log
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
| Line | What it checks |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| `node` | The Node version running the CLI |
|
|
37
|
+
| `chromium` | Whether the exact Chromium revision the bundled Playwright wants is on disk. The most common silent failure |
|
|
38
|
+
| `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
|
+
| `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
|
+
| `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 |
|
|
41
|
+
| `daemon log` | Where the structured daemon log lives |
|
|
42
|
+
| `tracing` | How to turn that log into a per-stage trace |
|
|
43
|
+
| `desktop` | Only on a desktop project. Every Electron and Tauri misconfiguration here fails silently, so it is diagnosed explicitly |
|
|
44
|
+
|
|
45
|
+
## The chromium line
|
|
46
|
+
|
|
47
|
+
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
|
+
|
|
49
|
+
| Verdict | Real capture | What it means |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| installed | `chromium ✓ installed (chromium-1223)` | The wanted revision is on disk. Nothing to do |
|
|
52
|
+
| wrong revision | `chromium ✗ wrong revision — the bundled playwright wants chromium-1223; /tmp/pwroot holds chromium-1194, chromium-1208. run: npx playwright@1.60.0 install chromium` | Builds are installed, none of them the wanted one. One pinned download away |
|
|
53
|
+
| missing | `chromium ✗ missing — looked for /tmp/emptyroot/chromium-1223/chrome-mac-arm64/…; run: npx playwright@1.60.0 install chromium` | The browsers root holds no Chromium at all. If that root is not where your browsers live, `PLAYWRIGHT_BROWSERS_PATH` is what moves it |
|
|
54
|
+
|
|
55
|
+
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
|
+
|
|
57
|
+
<Warning>
|
|
58
|
+
Run the command `doctor` prints, not `npx playwright install chromium`. The unpinned form resolves
|
|
59
|
+
the newest Playwright, downloads *its* revision, and leaves the check saying exactly what it said
|
|
60
|
+
before. That loop is why the line names the version to pin to.
|
|
61
|
+
</Warning>
|
|
62
|
+
|
|
63
|
+
## Exit codes
|
|
64
|
+
|
|
65
|
+
Always `0`. `doctor` reports; it does not gate.
|
|
66
|
+
|
|
67
|
+
## Worked example
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx @reticlehq/server doctor
|
|
71
|
+
# then run the chromium command doctor printed, verbatim
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
<Card title="Deeper debugging" icon="bug" href="/debugging">
|
|
75
|
+
Reading the daemon log, and what `RETICLE_TRACE=1` adds to it.
|
|
76
|
+
</Card>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle drive
|
|
3
|
+
description: Run Reticle in the foreground against a URL, with the browser visible, for debugging.
|
|
4
|
+
icon: gauge-high
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle drive` runs the engine in the foreground and launches a browser at the URL you give it. It exists for debugging: you watch the run happen.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server drive <url> [--headless] [--headed]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Arguments and flags
|
|
14
|
+
|
|
15
|
+
| Argument | Type | Default | What it does |
|
|
16
|
+
| ------------ | -------------------------------- | ------------------------ | ----------------- |
|
|
17
|
+
| `url` | string, positional, **required** | none | The page to drive |
|
|
18
|
+
| `--headed` | boolean | on by default outside CI | Show the browser |
|
|
19
|
+
| `--headless` | boolean | on when `CI` is set | Hide it |
|
|
20
|
+
|
|
21
|
+
`drive` is the one interactive command in the family, so it is the one that shows the browser by default. `serve`, `mcp` and the internal daemon own the pooled browser behind leases, which is batch work, and hide theirs.
|
|
22
|
+
|
|
23
|
+
## What it prints
|
|
24
|
+
|
|
25
|
+
`reticle_started` with the port on success, `reticle_start_failed` with the error otherwise.
|
|
26
|
+
|
|
27
|
+
Omitting the URL is a usage error. Real capture:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
{"t":"2026-08-14T19:38:46.975Z","event":"reticle_usage_error","message":"drive needs a url"}
|
|
31
|
+
drive needs a url
|
|
32
|
+
|
|
33
|
+
usage:
|
|
34
|
+
reticle init [--dry-run] [--port N] ...
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Exit codes
|
|
38
|
+
|
|
39
|
+
| Code | Meaning |
|
|
40
|
+
| ---- | ------------------------------------------------------ |
|
|
41
|
+
| `0` | Running in the foreground |
|
|
42
|
+
| `1` | No URL, an unknown flag, or the engine failed to start |
|
|
43
|
+
|
|
44
|
+
<Warning>
|
|
45
|
+
`drive` binds the bridge port itself. If a daemon is already listening, it fails with an
|
|
46
|
+
`EADDRINUSE` stack trace, which is the normal state once your agent has started one. [`reticle
|
|
47
|
+
mcp`](/cli/mcp) reuses a running daemon; `drive` does not.
|
|
48
|
+
</Warning>
|
|
49
|
+
|
|
50
|
+
## Worked example
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx @reticlehq/server stop
|
|
54
|
+
npx @reticlehq/server drive http://localhost:5173
|
|
55
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle feedback
|
|
3
|
+
description: Send a report to the Reticle maintainers from the shell, including from a setup that never finished.
|
|
4
|
+
icon: comment
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle feedback` is the feedback channel as a command: no prompts, no editor, no account. It exists so the cost of telling the maintainers something is lower than the cost of shrugging and moving on.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server feedback [--rating 1-5] [--bug] "what worked, what didn't"
|
|
11
|
+
npx @reticlehq/server feedback --agent --kind <bug|gap|ambiguity|feature_request|improvement> "what happened"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The `--agent` form is for an agent that cannot reach the `reticle_feedback` tool: during `init`, while instrumentation is half wired, or when the daemon will not start. Those are the reports that are hardest to hear and most needed, because every other path requires the tool surface to already work.
|
|
15
|
+
|
|
16
|
+
## Flags
|
|
17
|
+
|
|
18
|
+
| Flag | Type | Default | What it does |
|
|
19
|
+
| --- | --- | --- | --- |
|
|
20
|
+
| `--rating N` | integer 1 to 5 | unset | A human's overall take. A bare rating with no words is a valid report |
|
|
21
|
+
| `--bug` | boolean | `false` | Shorthand for `--kind bug` |
|
|
22
|
+
| `--kind K` | one of `bug`, `gap`, `ambiguity`, `feature_request`, `improvement`, `experience` | `experience`, or `bug` with `--bug` | The report's class. Wins over `--bug` |
|
|
23
|
+
| `--agent` | boolean | `false` | File as the agent, so agent reports never dilute the human rating signal |
|
|
24
|
+
|
|
25
|
+
Everything that is not a flag or a flag's value becomes the message, joined with spaces. Quoting is still your job for shell reasons.
|
|
26
|
+
|
|
27
|
+
## What it prints
|
|
28
|
+
|
|
29
|
+
The payload is printed **before** it is sent, every time. A channel that carries free text and does not show you what it sends is asking for trust it has not earned.
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
sending {"source":"human","kind":"experience","stack":"vite","runtime":"web"}
|
|
33
|
+
redacted email (removed before sending)
|
|
34
|
+
thanks your feedback is in. it genuinely changes what gets built next.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`not sent` replaces the last line when the send failed or telemetry is off, and names the reason. Humans who have never identified also get an offer of a reply route, printed after the receipt rather than as a prompt.
|
|
38
|
+
|
|
39
|
+
Run with no message and no rating, it prints usage and exits `1`. Real capture:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
usage: reticle feedback [--rating 1-5] [--bug] "what worked, what didn't"
|
|
43
|
+
agents: reticle feedback --agent --kind <bug|gap|ambiguity|feature_request|improvement|experience> "what happened"
|
|
44
|
+
your words go to the maintainers; nothing from your app is ever included.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Exit codes
|
|
48
|
+
|
|
49
|
+
| Code | Meaning |
|
|
50
|
+
| ---- | --------------------------------------------------------------- |
|
|
51
|
+
| `0` | The report was submitted, or attempted and reported as not sent |
|
|
52
|
+
| `1` | No message and no rating, or an invalid `--rating` or `--kind` |
|
|
53
|
+
|
|
54
|
+
## Worked example
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx @reticlehq/server feedback --agent --kind gap \
|
|
58
|
+
"no way to drive a contenteditable rich-text editor; had to skip the flow"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
<Card
|
|
62
|
+
title="The same channel from inside a session"
|
|
63
|
+
icon="comments"
|
|
64
|
+
href="/tools-session-and-feedback"
|
|
65
|
+
>
|
|
66
|
+
`reticle_feedback` when the tools are reachable.
|
|
67
|
+
</Card>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle gate
|
|
3
|
+
description: Exit non-zero unless passing verification artifacts cover every flow the changed files affect.
|
|
4
|
+
icon: shield-halved
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle gate` is what makes verification unavoidable. It computes the [affected](/cli/affected) flows, looks for a passing artifact for each, and fails the command if any is missing. An agent that edits a covered file cannot call itself finished without re-verifying.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server gate [--since <ref>] [file...]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Arguments and flags
|
|
14
|
+
|
|
15
|
+
| Argument | Type | Default | What it does |
|
|
16
|
+
| --- | --- | --- | --- |
|
|
17
|
+
| `file...` | strings, positional | none | Explicit changed files |
|
|
18
|
+
| `--since <ref>` | string | `HEAD` when no files are given | Also include files git reports as changed since this ref |
|
|
19
|
+
|
|
20
|
+
## What blocks and what does not
|
|
21
|
+
|
|
22
|
+
| Category | Blocking | Why |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| `uncovered` | Yes | An affected flow with no passing artifact |
|
|
25
|
+
| `downgraded` | Yes | A flow whose assertions were weakened since its last passing run. A green bought by weakening the test is the gaming move this exists to stop |
|
|
26
|
+
| `deletedCoverage` | Yes | A flow that covered a changed file and has since vanished. Coverage deleted, not satisfied |
|
|
27
|
+
| `quarantined` | No | Flows the flake ledger has quarantined. Surfaced, never blocking, because one unexplained flake that blocks a merge destroys trust in the red |
|
|
28
|
+
|
|
29
|
+
## What it prints
|
|
30
|
+
|
|
31
|
+
One `reticle_gate` line. Real capture from this repository, with the flow lists trimmed for length:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"t": "2026-08-14T19:38:56.353Z",
|
|
36
|
+
"event": "reticle_gate",
|
|
37
|
+
"pass": false,
|
|
38
|
+
"uncovered": ["deploy-journey", "verify-route", "verify-500"],
|
|
39
|
+
"quarantined": ["asserted-demo", "blast-radius-compose"],
|
|
40
|
+
"coverage": { "pct": 28, "covered": 13, "total": 47 }
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`downgraded` and `deletedCoverage` appear only when they are non-empty.
|
|
45
|
+
|
|
46
|
+
## Exit codes
|
|
47
|
+
|
|
48
|
+
| Code | Meaning |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `0` | Every affected, non-flaky flow has a passing artifact and nothing was weakened or deleted |
|
|
51
|
+
| `1` | Something is uncovered, downgraded or deleted. Also `1` on any internal fault: the gate fails closed |
|
|
52
|
+
|
|
53
|
+
Measured on this repository, `npx @reticlehq/server gate --since HEAD~1` exited `1` with the output above.
|
|
54
|
+
|
|
55
|
+
## Worked example
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
- run: npx @reticlehq/server verify http://localhost:4173
|
|
59
|
+
- run: npx @reticlehq/server gate --since ${{ github.event.pull_request.base.sha }}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
<Card title="Wiring this into CI" icon="rocket" href="/deploy-checks">
|
|
63
|
+
Where the gate sits relative to build, verify, and merge.
|
|
64
|
+
</Card>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle help
|
|
3
|
+
description: Print the complete Reticle command grammar, every command and every flag, on one screen.
|
|
4
|
+
icon: circle-question
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle help` prints the whole usage block to stdout and exits `0`.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server help
|
|
11
|
+
npx @reticlehq/server --help
|
|
12
|
+
npx @reticlehq/server -h
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
All three are the same command.
|
|
16
|
+
|
|
17
|
+
<Warning>
|
|
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'`, and exits `1`. This page and
|
|
20
|
+
the rest of this section are the per-command reference.
|
|
21
|
+
</Warning>
|
|
22
|
+
|
|
23
|
+
## What it prints
|
|
24
|
+
|
|
25
|
+
Real capture, in full:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
usage: npx @reticlehq/server <command> (or `reticle <command>` once the bin is on your PATH)
|
|
29
|
+
|
|
30
|
+
reticle init [--dry-run] [--port N] [--no-mcp] [--no-install] [--app <dir>] (wire Reticle into the project in this directory)
|
|
31
|
+
--app picks WHICH app in a monorepo, when several are found
|
|
32
|
+
--no-mcp skips MORE than the server registration: also the agent rule files
|
|
33
|
+
(CLAUDE.md / AGENTS.md / .cursor) and the /reticle command, because all three
|
|
34
|
+
only make sense once the tools are reachable.
|
|
35
|
+
reticle serve [--port N] [--drive <url>] [--headless] [--http] [--http-port N] [--http-token T]
|
|
36
|
+
reticle stop [--port N] [--quiet]
|
|
37
|
+
reticle status [--port N]
|
|
38
|
+
reticle doctor [--port N] (one command to diagnose setup: Chromium, daemon, port)
|
|
39
|
+
reticle open [url] [--port N] (show the app: reuse the connected tab, else open one)
|
|
40
|
+
reticle verify <url> [--headed] [--timeout N] [--storage-state <file>] (one-shot: drive the URL, verify saved flows, exit 0=pass)
|
|
41
|
+
reticle affected [--since <ref>] [file...] (which saved flows must re-verify for the changed files)
|
|
42
|
+
reticle gate [--since <ref>] [file...] (exit non-zero unless passing artifacts cover the affected flows)
|
|
43
|
+
reticle watch [url] (on save, report which saved flows must re-verify)
|
|
44
|
+
reticle drive <url> [--headless] (foreground mode, for debugging)
|
|
45
|
+
reticle mcp [--port N] [--drive <url>] [--headless] (MCP stdio proxy; auto-starts daemon if needed)
|
|
46
|
+
reticle update (install the latest server version and restart)
|
|
47
|
+
reticle rollback (restore the previous server version and restart)
|
|
48
|
+
reticle license (show enterprise license status: active | eval | missing)
|
|
49
|
+
reticle telemetry [status|enable|disable] (anonymous usage metrics; status shows what's sent + the policy)
|
|
50
|
+
reticle feedback [--rating 1-5] [--bug] "message" (tell us what worked and what didn't; prints exactly what it sends)
|
|
51
|
+
reticle feedback --agent --kind <bug|gap|ambiguity|feature_request|improvement> "message"
|
|
52
|
+
(agents: file from anywhere, including a setup that never finished)
|
|
53
|
+
reticle identify --context company|side_project|open_source|learning [--company N] [--email E] [--forget]
|
|
54
|
+
(OPT-IN: tell us who you are, e.g. for support or an enterprise trial)
|
|
55
|
+
|
|
56
|
+
Cloud (link this project to Reticle Cloud; runs/flows recorded on the dashboard):
|
|
57
|
+
reticle login --email <e> [--code <c>] [--org <n>] (sign in: mails a code, then exchanges it)
|
|
58
|
+
reticle link [--project <name|id>] (bind this repo: mints a scoped key, writes .reticle/cloud.json)
|
|
59
|
+
reticle whoami (who am I signed in as, and is this repo attached?)
|
|
60
|
+
reticle project <ls|create <name>> (list or create cloud projects)
|
|
61
|
+
reticle config [--runs on|off] [--memory on|off] [--flows on|off] [--verify local|server]
|
|
62
|
+
reticle push (send local run artifacts to the dashboard)
|
|
63
|
+
reticle runs | regression | share <runId> (read cloud state; regression exits 3 if any flow broke)
|
|
64
|
+
|
|
65
|
+
'drive' shows the browser; everything else is hidden (serve/mcp own the pool behind leases, replay
|
|
66
|
+
and the spec runner: batch work). --headed opts any of them in, --headless hides drive, CI hides it.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Errors print it too
|
|
70
|
+
|
|
71
|
+
Any usage error prints the offending thing first, then this same block on stderr, and exits `1`:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
{"t":"2026-08-14T19:38:47.402Z","event":"reticle_usage_error","message":"unknown command 'nonsense-cmd'"}
|
|
75
|
+
unknown command 'nonsense-cmd'
|
|
76
|
+
|
|
77
|
+
usage:
|
|
78
|
+
...
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Two audiences, two channels: the structured line for logs and scripts, the plain text for the person who just typed the command.
|
|
82
|
+
|
|
83
|
+
## Exit codes
|
|
84
|
+
|
|
85
|
+
| Code | Meaning |
|
|
86
|
+
| ---- | ------------------------------------------------- |
|
|
87
|
+
| `0` | Help was requested |
|
|
88
|
+
| `1` | Help was printed because something else was wrong |
|
|
89
|
+
|
|
90
|
+
<Note>
|
|
91
|
+
A bare `reticle` with no arguments is **not** help. It is [`reticle serve`](/cli/serve).
|
|
92
|
+
</Note>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle hunt
|
|
3
|
+
description: Aggregate many crawl reports into one false-green rate across already-merged changes.
|
|
4
|
+
icon: crosshairs
|
|
5
|
+
---
|
|
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 `reticle_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
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server hunt <dir-of-crawl-reports>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
No control arm is needed. Those changes shipped, so the counterfactual is already established.
|
|
14
|
+
|
|
15
|
+
## Arguments
|
|
16
|
+
|
|
17
|
+
| Argument | Type | Default | What it does |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| `<dir>` | string, positional, **required** | none | Directory of `*.json` crawl reports. Each file is one crawl over one checkout |
|
|
20
|
+
|
|
21
|
+
Each input file is read for `label` (falling back to the filename), `anomalies[]`, and `stepsRun`.
|
|
22
|
+
|
|
23
|
+
## What it prints
|
|
24
|
+
|
|
25
|
+
One `reticle_hunt` line with the summary:
|
|
26
|
+
|
|
27
|
+
| Field | Meaning |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| `runs` | Report files read |
|
|
30
|
+
| `runsWithCoverage` | Runs that drove at least one control. The only honest denominator: a run that drove nothing is not evidence of cleanliness |
|
|
31
|
+
| `runsWithContradictions` | Runs with at least one cross-channel contradiction |
|
|
32
|
+
| `contradictions` | Total contradictions. The kinds are `ui-advanced-request-failed`, `signal-contradicted`, `response-ignored`, `duplicate-request`, `request-never-settled`, `failure-misattributed` |
|
|
33
|
+
| `singleChannelFaults` | Everything else: console errors, failed requests, dead controls. Context, not the claim |
|
|
34
|
+
| `byKind` | Counts per anomaly kind |
|
|
35
|
+
| `flagged` | The labels with contradictions, so each can be confirmed by hand |
|
|
36
|
+
| `headline` | A sentence phrased so it cannot overstate itself. It says "candidate", because every flag still needs manual confirmation |
|
|
37
|
+
|
|
38
|
+
## Exit codes
|
|
39
|
+
|
|
40
|
+
Always `0`. A read failure is logged as `reticle_hunt_failed`. Omitting the directory is a usage error:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
{"t":"2026-08-14T19:38:47.116Z","event":"reticle_usage_error","message":"usage: reticle hunt <dir-of-crawl-reports>"}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
That path exits `1`.
|
|
47
|
+
|
|
48
|
+
## Worked example
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
for sha in $(git log --format=%H -n 30 main); do
|
|
52
|
+
git checkout "$sha" && npm run dev &
|
|
53
|
+
# drive reticle_crawl over the app, write the JSON:
|
|
54
|
+
# .../reports/$sha.json
|
|
55
|
+
done
|
|
56
|
+
npx @reticlehq/server hunt ./reports
|
|
57
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle identify
|
|
3
|
+
description: Opt in to telling the Reticle maintainers who you are, and undo it at any time.
|
|
4
|
+
icon: id-card
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle identify` 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
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server identify --context <company|side_project|open_source|learning> [--company "Acme"] [--email you@acme.com] [--forget]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Flags
|
|
14
|
+
|
|
15
|
+
| Flag | Type | Default | What it does |
|
|
16
|
+
| --- | --- | --- | --- |
|
|
17
|
+
| `--context K` | one of `company`, `side_project`, `open_source`, `learning` | none. Required unless `--forget` | What Reticle is being used for |
|
|
18
|
+
| `--company N` | string | unset | Your company name. Optional |
|
|
19
|
+
| `--email E` | string | unset | An address to reach you on. Optional |
|
|
20
|
+
| `--forget` | boolean | `false` | Delete the local identity file and stop sending it |
|
|
21
|
+
|
|
22
|
+
Every field except the context is optional, so you can say "this is a company" without saying which, or name the company without leaving an address.
|
|
23
|
+
|
|
24
|
+
## What it prints
|
|
25
|
+
|
|
26
|
+
The consent notice, then the exact payload, then the result:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
sending {"context":"company","company":"Acme","email":"you@acme.com"}
|
|
30
|
+
thanks saved and sent. we may reach out; `reticle identify --forget` undoes this.
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`not sent` replaces the last line when telemetry is disabled on the machine, in which case the identity is saved locally only.
|
|
34
|
+
|
|
35
|
+
With `--forget`:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
forgotten the local identity file is deleted; nothing further is sent.
|
|
39
|
+
to have what was already sent removed, email support@reticlehq.com
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Run with no valid `--context`, it prints the current identity (if any), the usage, and the full consent notice.
|
|
43
|
+
|
|
44
|
+
<Warning>
|
|
45
|
+
Identifying links this machine's anonymous id to what you type, which also connects the anonymous
|
|
46
|
+
usage already recorded from this machine to that identity. The command says so before it sends
|
|
47
|
+
anything. Nothing about your app, your code, or your repository is ever included.
|
|
48
|
+
</Warning>
|
|
49
|
+
|
|
50
|
+
## Exit codes
|
|
51
|
+
|
|
52
|
+
| Code | Meaning |
|
|
53
|
+
| ---- | ------------------------------------------------------------------------------ |
|
|
54
|
+
| `0` | Identity saved, or forgotten, or usage printed when an identity already exists |
|
|
55
|
+
| `1` | No valid `--context` and no identity on file |
|
|
56
|
+
|
|
57
|
+
## Worked example
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx @reticlehq/server identify --context open_source --email maintainer@example.com
|
|
61
|
+
npx @reticlehq/server identify --forget
|
|
62
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle init
|
|
3
|
+
description: Wire Reticle into the project in the current directory, registering the MCP server and installing the SDK.
|
|
4
|
+
icon: wand-magic-sparkles
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle init` is the one command a person runs before anything else. It inspects the directory it is standing in, works out the framework, and writes every piece of wiring Reticle needs: the MCP server registration, the agent rule files, the dev dependencies, `.reticle.json`, and the bundler plugin.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server init [--dry-run] [--port N] [--no-mcp] [--no-install] [--app <dir>] [--yes]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Flags
|
|
14
|
+
|
|
15
|
+
| Flag | Type | Default | What it does |
|
|
16
|
+
| --- | --- | --- | --- |
|
|
17
|
+
| `--dry-run` | boolean | `false` | Print the full plan and write nothing |
|
|
18
|
+
| `--port N` | number | unset (resolves to `4400`) | Bridge port to write into the config |
|
|
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) | Skip the dependency install step |
|
|
21
|
+
| `--app <dir>` | string | unset | Pick which app to wire in a monorepo, without changing directory |
|
|
22
|
+
| `--yes` | boolean | `false` | Accepted for scripting. `init` has no interactive prompts today, so it is a no-op |
|
|
23
|
+
|
|
24
|
+
<Warning>
|
|
25
|
+
`--no-mcp` skips more than the server registration. The agent rule files and the `/reticle`
|
|
26
|
+
command go with it, because all three only make sense once the tools are reachable.
|
|
27
|
+
</Warning>
|
|
28
|
+
|
|
29
|
+
## What it prints
|
|
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`:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
reticle init (dry run, no files written)
|
|
35
|
+
in /Users/you/reticle/apps/bench-app
|
|
36
|
+
|
|
37
|
+
[·] MCP server (Claude, global) → global (claude user scope)
|
|
38
|
+
reticle already registered (install once, used by every project)
|
|
39
|
+
[·] MCP server (Cursor, global) → /Users/you/.cursor/mcp.json
|
|
40
|
+
reticle already in Cursor global config
|
|
41
|
+
[⚠] MCP server (Codex CLI) → /Users/you/.codex/config.toml
|
|
42
|
+
add this to /Users/you/.codex/config.toml by hand:
|
|
43
|
+
[mcp_servers.reticle]
|
|
44
|
+
command = "npx"
|
|
45
|
+
args = ["@reticlehq/server", "mcp"]
|
|
46
|
+
|
|
47
|
+
[✓] Agent verification rule → CLAUDE.md
|
|
48
|
+
teach the agent to verify features with Reticle after building them
|
|
49
|
+
[✓] The /reticle command → .claude/commands/reticle.md
|
|
50
|
+
type /reticle to verify one flow in the browser
|
|
51
|
+
[✓] Install dependencies → package.json
|
|
52
|
+
pnpm add -D @reticlehq/react@2.8.0 @reticlehq/vite-plugin@2.8.0
|
|
53
|
+
[✓] Reticle config → .reticle.json
|
|
54
|
+
write project config (framework + port)
|
|
55
|
+
[✓] Vite plugin → vite.config.ts
|
|
56
|
+
add reticle() to plugins (also injects connect())
|
|
57
|
+
[·] Capabilities + store → src/reticle-dev.ts
|
|
58
|
+
file exists, left alone, it is yours to edit
|
|
59
|
+
|
|
60
|
+
Restart `vite`.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Run from a workspace root with several apps, it refuses to guess and names them instead:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Several apps found in this workspace. Re-run `reticle init` inside the one you want:
|
|
67
|
+
packages/next
|
|
68
|
+
packages/vite-plugin
|
|
69
|
+
apps/atlas
|
|
70
|
+
apps/bench-app
|
|
71
|
+
...
|
|
72
|
+
|
|
73
|
+
Or name one without changing directory: reticle init --app packages/next
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Exit codes
|
|
77
|
+
|
|
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, or an unknown flag was passed |
|
|
82
|
+
|
|
83
|
+
## Worked example
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cd apps/web
|
|
87
|
+
npx @reticlehq/server init --dry-run # read the plan first
|
|
88
|
+
npx @reticlehq/server init # then run it
|
|
89
|
+
npx @reticlehq/server status # confirm the app actually connected
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
<Card title="The install, step by step" icon="wand-magic-sparkles" href="/install-agentic">
|
|
93
|
+
What each step writes and how to read the four status marks.
|
|
94
|
+
</Card>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle kill
|
|
3
|
+
description: Free the bridge port by killing its listener, without touching the agent's own MCP proxy.
|
|
4
|
+
icon: skull
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle kill` frees the bridge port. It asks **who is listening** on the port and signals that one process, which is the whole difference between this command and the shell pipeline everybody reaches for.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @reticlehq/server kill [--port N] [--force]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
<Warning>
|
|
14
|
+
Never free the port with `lsof -ti tcp:4400 | xargs kill -9`. `reticle mcp` holds a **client**
|
|
15
|
+
socket on that port, so `-ti` lists the proxy right beside the daemon and the pipeline kills both.
|
|
16
|
+
When the proxy dies, the agent's next tool calls get no reply at all: not an error, not a timeout.
|
|
17
|
+
Nothing is written to the proxy log either, because the process that writes it is the one that
|
|
18
|
+
died. That is the mechanism behind most "my MCP disconnected" reports.
|
|
19
|
+
</Warning>
|
|
20
|
+
|
|
21
|
+
## Flags
|
|
22
|
+
|
|
23
|
+
| Flag | Type | Default | What it does |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| `--port N` | number | `4400` (or `RETICLE_PORT`, or the port in `.reticle.json`) | Which port to free |
|
|
26
|
+
| `--force` | boolean | `false` | Kill the listener even when it is not a Reticle daemon |
|
|
27
|
+
|
|
28
|
+
## kill or stop?
|
|
29
|
+
|
|
30
|
+
They target different things, and the distinction matters exactly when you are stuck.
|
|
31
|
+
|
|
32
|
+
| | `reticle stop` | `reticle kill` |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| Finds the process by | the pid recorded in Reticle's own state | the **listener** on the port |
|
|
35
|
+
| Works when the pid file is stale or was never written | no | yes |
|
|
36
|
+
| Works on a daemon from another checkout | no | yes |
|
|
37
|
+
| Works without `lsof` (Windows, slim containers) | yes | yes, falling back to the recorded pid and saying so |
|
|
38
|
+
|
|
39
|
+
Reach for `stop` in a script that shuts down a daemon it started. Reach for `kill` when the port is held and you want it back.
|
|
40
|
+
|
|
41
|
+
## How it decides
|
|
42
|
+
|
|
43
|
+
1. Look up the listener with `lsof -nP -iTCP:<port> -sTCP:LISTEN`. Client sockets are excluded by construction, so the proxy is never a candidate.
|
|
44
|
+
2. It is Reticle's if it answers `/status`, **or** if it is the pid Reticle recorded for the port. `/status` outranks the pid file, so a daemon started from another checkout is still recognised as ours.
|
|
45
|
+
3. Anything else is refused, by name, unless `--force`.
|
|
46
|
+
4. `SIGTERM`, then `SIGKILL` after 5 seconds, then report that it survived and exit `1`.
|
|
47
|
+
|
|
48
|
+
## What it prints
|
|
49
|
+
|
|
50
|
+
Real captures.
|
|
51
|
+
|
|
52
|
+
Killed:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
{"event":"reticle_killed","port":4499,"pid":84420,"escalated":true,"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 — it goes dormant and starts a fresh daemon on the next tool call."}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Refused, because the listener is not ours:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
{"event":"reticle_kill_refused","port":4498,"reason":"pid 84346 (\"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
|
+
```
|
|
63
|
+
|
|
64
|
+
Nothing to free:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
{"event":"reticle_kill_nothing_to_do","port":4499,"presence":"free"}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
| Event | When |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `reticle_killed` | The listener is gone. `escalated: true` means it took a `SIGKILL`; `forced: true` means `--force` overrode a refusal |
|
|
73
|
+
| `reticle_kill_refused` | The listener is not a Reticle daemon and `--force` was not given. Exits `1` |
|
|
74
|
+
| `reticle_kill_survived` | It survived `SIGKILL`. The port is still held. Exits `1` |
|
|
75
|
+
| `reticle_kill_nothing_to_do` | No listener, and no live recorded pid |
|
|
76
|
+
|
|
77
|
+
`listenerIdentified: false` means `lsof` could not run and the pid came from Reticle's records rather than from an observed listener. Those are different claims, so the field says which one you got.
|
|
78
|
+
|
|
79
|
+
## Exit codes
|
|
80
|
+
|
|
81
|
+
| Code | Meaning |
|
|
82
|
+
| ---- | ------------------------------------------------------------------ |
|
|
83
|
+
| `0` | The port is free |
|
|
84
|
+
| `1` | The port is still held: refused, or the process survived `SIGKILL` |
|
|
85
|
+
|
|
86
|
+
## Worked example
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npx @reticlehq/server kill # free 4400
|
|
90
|
+
npx @reticlehq/server status # confirm
|
|
91
|
+
```
|