SKILL.md and you never need to come back here.
One command. It wires the app and proves a session connected. The verdict is the first run, after it. init changes files, so run it only when the user asked you to set Reticle up, or agreed when you asked. Until then, the zero-install lease checks a running app with nothing installed: reticle_session { action: "list" } names it in next_step.
@latest is deliberate: npx caches, and a stale cached CLI is the most common silent setup failure. Never pin a version here.
That single command detects the framework and package manager, wires the build config, installs the SDK, registers the MCP server, starts the dev server, opens the app, and waits for a session to connect from inside it. It exits non-zero if nothing connected, and prints exactly what is left to do. Then prove a flow. That is the FIRST RUN, and it is a separate call: drive one journey with reticle_act_and_wait and an until on its last step. On a project linked with reticle connect, reticle_verify { action: "explore", persona: "<who does what>" } lets the Reticle Harness drive it on the platform instead. Either way what was driven is saved as a flow, so later checks replay it with no model in the loop.
What YOU decide, and pass in
The command reads the repository. It cannot read the request, and three things live only there. Decide them before you run it; do not walk any of them by hand.
Ask the user nothing else. After the user agrees to the setup, do not ask about the framework, package manager, port, editor or MCP client: the repo you are in answers each one. Read
.env.example, the README and package.json, decide, and say what you decided in one line.
Never ask about the port. There are two, and conflating them is a top setup failure. The dev-server port (3000, 5173) belongs to the project’s own dev script. The bridge port (4400) is the daemon-to-SDK channel and defaults correctly.
Then read what it gives you back
⚠ lines and a non-zero exit are a to-do list, not a failed install. The command names the cause and prints the REMAINING steps from wherever it stopped, and it will not tell you to redo a phase that already worked. Do those, and re-run; re-running is safe.
It is not finished until a verdict exists. A session listed means the SDK reached the page. Setup is finished when the first run returns a verdict. Writing files is not an install. If it exits non-zero, the app is wired and something is still outstanding; say so plainly rather than reporting success.
If the user gave you a license key, see License key below.
If that command could not run it
Do not choose this path. It is not the thorough version of the one above; it is what you fall back to when the command physically could not do the work, and taking it by preference turns a one-command install into a long manual one. Use it only when ONE of these is true, and you can say which:initexited without ever printingstarting:orwatching for an app to connect, which means the CLI on this machine predates the runtime phases and stopped after writing files.initprinted a to-do list, you did those things, re-ran it, and it stopped in the same place twice.- There is no Node 20.11 or newer on this machine, so nothing can run.
⚠ in the report, not a step you would rather do yourself, not a feeling that you should check its work. Re-run the command. It is idempotent, it reports what is already wired, and it names what is still outstanding.
When one of those three IS true, the whole manual procedure is one page:
- The SDK must load in a RUNNING page. Not wired in a config file: loaded, in a page a browser has open. This is the step the funnel dies on.
- A session must appear on that app’s own url.
reticle_session { action: "list" }returning an empty list has four causes with four different fixes, and itsnext_actionnames which one this is. - A verdict must exist.
reticle_act_and_waitorreticle_assert, and nothing else. A drive that ends without one has no result however many tools it used.
The dev server, whoever starts it
A dev server already running wheninit ran does not have Reticle in its bundle. It read vite.config.ts / next.config.js at boot; init edited that file afterwards. The process keeps serving the old bundle, the page loads without the SDK, no session appears, and every symptom points at the wiring you just correctly did. This fails every time, not intermittently, and it is a common reason an install finds an empty session list.
So, in this order:
- A dev server was already running? Restart it, then hard-reload the tab. “Something is listening” does not mean the right bundle is served.
- Nothing was running? Start it in the BACKGROUND and say so in one line.
reticle_session { action: "list" }gives you this project’s own dev command innext_action; use that, never compose one. Started afterinit, it needs no restart.reticle initmay start it for you, and stops it again if setup fails: a command somebody ran is attributable and stoppable where a daemon is not.
- Never run two at once. One dev server on the app’s port. Restarting a stale one means stopping it first, not starting a second alongside it.
- Never guess the command. It comes from
package.jsonscripts. No recognisable dev script means say so and stop, not invent one. - Never kill anything you did not start, and never a daemon or a port holder. The one exception is the restart above, and say in one line that you did it.
- The permission prompt belongs to your host. Never bypass, suppress or auto-approve it, and take a refusal as the answer. You have no business editing a permissions file yourself.
initwrites one rule, for thereticleserver alone, and prints that it did.
License key
Enterprise features are unlocked by a signed key, verified locally with Ed25519 and no network call. If the user hands you one, during setup or at any later point:RETICLE_LICENSE_KEY to the project’s .env and adds .env to .gitignore if nothing there covers it. Do not do those two by hand: a key committed to git is a leaked credential, and it stays leaked after the file is removed. Confirm with npx @reticlehq/server license, which prints active, eval, missing, invalid or expired.
Never echo the key back in your reply, and never put it in a commit, a code comment, or a feedback report. The rest: curl https://docs.reticle.sh/enterprise.md.