Skip to main content
From your app directory, reticle connect --project "My App" wires the app, opens browser sign-in approval if needed, links the named cloud project, and syncs the local history already on this machine. Run the installer once on the machine first. connect is the one command for signing in, linking and choosing a project.
If your daemon is not on the default port 4400, run npx @reticlehq/server init --port <N> first: connect takes no --port, and the init it runs for an unwired app uses the default. Use --url https://your-cloud-origin for a self-hosted cloud. connect checks a saved sign-in against that exact host before reuse; if it has expired, the browser approval opens again. It mints or reuses a project-scoped key, so there is no key to paste. The browser asks you to sign in, or to create a free account at app.reticle.sh. A new account gets free credits to try Harness; adding a card starts a 14-day trial with 500 credits, and the paid plan includes 1,000 credits per seat each month. Harness drives and chat checks spend credits; storing and syncing runs is free. What syncs, and how to switch each part off, is in What is recorded. A newly wired app may have no run to sync yet: ask your agent to verify one flow and the linked daemon will sync the result. Run reticle status to check who is signed in and whether this folder is linked, and reticle sync to send anything still pending. The other cloud commands are thin clients over the /v1 API. Their logic is server-side.

Where credentials live

Auth for any command is RETICLE_API_KEY from the environment (the agent path) if set, otherwise the login token. RETICLE_CLOUD_URL (or its short form RETICLE_URL) overrides the endpoint; without it, a command uses the saved session’s host, and otherwise the hosted service, https://app.reticle.sh.

In CI

CI needs RETICLE_API_KEY and nothing else: no connect. Commit .reticle/cloud.json, store the key as a secret, and the daemon and reticle sync sync to the project the binding names. A key stored in credentials.json wins over the environment when both exist. The environment key is only sent to the host it belongs to: RETICLE_CLOUD_URL when set, otherwise the hosted service. A repo linked to a self-hosted install therefore also needs RETICLE_CLOUD_URL set to that install in CI. A repo with no cloud.json and a key in the environment syncs to the hosted service, or to RETICLE_CLOUD_URL.

The commands

reticle connect

Signs in if needed (a browser device flow like gh auth login: approve in the browser, the CLI polls until confirmed), then binds this repository to a cloud project and sends local history. It mints a project-scoped key, so there is nothing to paste; with RETICLE_API_KEY already set, it resolves that key’s project instead. --project accepts a slug id or a display name, and creates the project when no project has that name. Omitted, the project is named after the projectId in .reticle.json, else after this folder. --workspace picks the workspace to link in when you belong to more than one. --no-install is passed to the init it runs for an unwired app. Writes cloud.json and the key. reticle login, reticle link and reticle project were removed. Each prints that it was removed, names connect, and exits 1. Sign-in is with Google or GitHub, in the browser. Email sign-in is gone. Without a browser (CI, an agent, a server), set RETICLE_API_KEY to a key from Settings > API keys.

reticle logout

Signs out of ONE host. Which host: --url, else RETICLE_CLOUD_URL, else the active session. Every other host stays signed in, and per-project keys in credentials.json stay. Prints { "loggedOut": true, "url": "…" }, naming the host it signed out of.

Who am I: reticle status

reticle status says who you are signed in as and whether this folder is linked to a cloud project, beside the daemon and session facts. The account half reads local files only and makes no call to the cloud. reticle whoami is the old spelling; it still works for one release and prints one line naming status.

reticle config

Edits .reticle/cloud.json in place. Any value other than on or off (or local or server for --verify) exits 2. --harness on|off switches the Harness for this project on the platform, not in cloud.json. Each drive spends the workspace’s credits. It exits 1 when the platform did not switch it (locked, no access, or offline). Requires the repo to be linked; run in an unlinked repo it exits 2 before it looks at the flags at all:

reticle sync

Sends local run artifacts from .reticle to the linked project, honoring the sync policy, and collects decisions made on the dashboard. Each switch removes only its own part: with sync.runs off no runs are sent, but flows and records still go unless they are off too. sync.screenshots sends the screenshot of each step, and follows sync.runs when unset. sync.video sends the frames that Reticle takes about once a second between steps while it drives a tab, and follows sync.screenshots when unset. Set "video": false under sync to keep the frames on this machine and still send the step screenshots. Prints { ok, project, sent, pulled }, where sent carries the accepted counts and, when the server refused anything, a rejected array naming each run’s index and reason and a refused array for flows, capsules and derived records. sent.records lists only the records the server accepted. Runs go up in batches, so a large backlog is never one oversized request. reticle push was removed: use reticle sync. Add --watch to keep syncing: it runs one cycle, waits, and runs the next, until you stop it with Ctrl+C. The wait is 60 seconds by default; set RETICLE_SYNC_INTERVAL_MS to change it. Add --move-history to also send the runs, flows and records made under this folder’s previous link, after it was linked to another workspace.
What the platform cannot read is not sent at all, and a notSent array says why: a record kind an older platform does not know yet (this one alone leaves ok true), or a flow or run in a file version it does not read. Sending those would only be refused again on every cycle. A rejection is a failed sync. If the server refuses any artifact, ok is false and the command exits 1, even when other artifacts in the same bundle landed. The reason is kept as the last sync error, which reticle status reports, and the background daemon logs it once, until a cycle refuses nothing. A refused run, flow set or capsule set is not offered again until its file changes, the platform reports that it reads more, the CLI version changes, or seven days pass. Each of these offers it once more. Until then it is listed under notRetried, and the summary reads refused, not retried: N run(s) (reason). A refused artifact never reaches the dashboard and is re-offered on every cycle, so partial loss is still loss. ok: true and exit 0 mean everything offered was accepted, which includes the common case of a repo that was already up to date. The accepted counts still report what did land, so a partial sync is visible as one.

reticle runs

The linked project’s recent run artifacts. The key scopes the query server-side. reticle runs <runId> reads one run, which is how to get back a Harness drive whose local .reticle/runs/<runId>.drive.json is gone. It exits 1 with “not synced yet, or not found” when the platform does not have it.

reticle runs regression

Which flows broke relative to before. Exits 3 when any flow regressed. reticle gate checks the same thing in a linked repo and exits 3 too, so CI needs only the gate.

reticle runs share

Mints a public proof link for one run. A missing runId exits 2.

reticle runs issues

The triage queue from the dashboard. --fix <fingerprint> prints that one issue’s fix prompt as bare text on stdout, so it can be piped straight into an agent. An unknown fingerprint exits 2; an issue with no suggested fix prints nothing on stdout and exits 4.

reticle runs memory

What the linked project has learned, scoped to the project this folder is linked to. --subject <name> narrows it to one area. If the response cannot be shown to be about this project, it prints nothing on stdout and exits 1. reticle regression, reticle share, reticle issues and reticle memory were removed. Each prints the runs form to use and exits 1.

When the repo is not attached

sync and every runs command need a project to talk to. Without one they exit 1 with the same line on stderr, measured:

Exit codes

Output is pretty-printed JSON on stdout. Errors and next-step nudges go to stderr, so an agent parsing stdout is unaffected.

Worked example

Last modified on November 4, 2026