> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reticle.sh/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Reticle is a dev-only, localhost-only verification layer for AI coding agents. It reads program truth (network, state, console, routing, animations, framework state) from inside a running web app and returns a deterministic verdict with evidence. It is not a screenshot tool and not a browser automation library.
> Only `reticle_act_and_wait` and `reticle_assert` produce a verdict. Every other tool moves or reads the app and proves nothing. A drive that ends without one of those two has no result, however many tools it used.
> A verdict of `verified: "unknown"` is not a pass. It means Reticle drove the app and could not tell what happened. Report it as unknown; never weaken a check to make it pass.
> Package names are scoped `@reticlehq/*`. Run every CLI command as `npx @reticlehq/server <command>`, for example `npx @reticlehq/server init`. `reticle` is a bin name that `@reticlehq/server` installs once it is on your PATH, NOT a package on npm: `npx reticle` fetches an unrelated package published by somebody else, so never run that. The complete tool surface is on the `/usage` page; `/agent-cheatsheet` is the one-screen version.

# reticle kill

> Free the bridge port by killing its listener, without touching the agent's own MCP proxy.

`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.

```bash theme={"dark"}
npx @reticlehq/server kill [--port N] [--force]
```

<Warning>
  Never free the port with `lsof -ti tcp:4400 | xargs kill -9`. `reticle mcp` holds a **client**
  socket on that port, so `-ti` lists the proxy right beside the daemon and the pipeline kills both.
  When the proxy dies, the agent's next tool calls get no reply at all: not an error, not a timeout.
  Nothing is written to the proxy log either, because the process that writes it is the one that
  died. That is the mechanism behind most "my MCP disconnected" reports.
</Warning>

## Flags

| Flag       | Type    | Default                                                    | What it does                                           |
| ---------- | ------- | ---------------------------------------------------------- | ------------------------------------------------------ |
| `--port N` | number  | `4400` (or `RETICLE_PORT`, or the port in `.reticle.json`) | Which port to free                                     |
| `--force`  | boolean | `false`                                                    | Kill the listener even when it is not a Reticle daemon |

## kill or stop?

They target different things, and the distinction matters exactly when you are stuck.

|                                                       | `reticle stop`                          | `reticle kill`                                      |
| ----------------------------------------------------- | --------------------------------------- | --------------------------------------------------- |
| Finds the process by                                  | the pid recorded in Reticle's own state | the **listener** on the port                        |
| Works when the pid file is stale or was never written | no                                      | yes                                                 |
| Works on a daemon from another checkout               | no                                      | yes                                                 |
| Works without `lsof` (Windows, slim containers)       | yes                                     | yes, falling back to the recorded pid and saying so |

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.

## How it decides

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.
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.
3. Anything else is refused, by name, unless `--force`.
4. `SIGTERM`, then `SIGKILL` after 5 seconds, then report that it survived and exit `1`.

## What it prints

Real captures.

Killed:

```
{"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."}
```

Refused, because the listener is not ours:

```
{"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"}
```

Nothing to free:

```
{"event":"reticle_kill_nothing_to_do","port":4499,"presence":"free"}
```

| Event                        | When                                                                                                                 |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `reticle_killed`             | The listener is gone. `escalated: true` means it took a `SIGKILL`; `forced: true` means `--force` overrode a refusal |
| `reticle_kill_refused`       | The listener is not a Reticle daemon and `--force` was not given. Exits `1`                                          |
| `reticle_kill_survived`      | It survived `SIGKILL`. The port is still held. Exits `1`                                                             |
| `reticle_kill_nothing_to_do` | No listener, and no live recorded pid                                                                                |

`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.

## Exit codes

| Code | Meaning                                                            |
| ---- | ------------------------------------------------------------------ |
| `0`  | The port is free                                                   |
| `1`  | The port is still held: refused, or the process survived `SIGKILL` |

## Worked example

```bash theme={"dark"}
npx @reticlehq/server kill            # free 4400
npx @reticlehq/server status          # confirm
```
