Skip to main content
receipt doctor is the read-only health check for the released CLI. It resolves which host you would talk to, probes the gateway and the sign-in endpoint, and reports the saved session and when it expires. It never opens a browser, never signs you in, and never prints your token — so it is safe to run any time something looks wrong. It is also reachable as receipt connect doctor and receipt connect check. All three run the same read-only check.
doctor never changes anything. It reads your session file and sends read-only GET probes to the gateway and the sign-in origin. To actually sign in, use receipt setup.

What it checks

A single receipt doctor run does four things:
  1. Resolves the endpoint — the gateway and sign-in origins for the target you ask for, which is prod unless you say otherwise. A --server-url/--auth-url override wins over the target; failing that the RECEIPT_CONNECT_* environment variables decide, and prod falls back to the hosted default https://app.kentron.ai that release builds carry. The full precedence is in environment and exit codes.
  2. Probes the gateway — a GET to /health. If that is not a 2xx it tries /healthz, and reports the fallback only when the fallback itself answers 2xx; otherwise the original /health result stands. The report names whichever path it used.
  3. Probes sign-in — a GET to the sign-in endpoint on the auth origin. Any HTTP status at all counts as reachable.
  4. Reports the saved session — the signed-in user and workspace, whether the token is expired and when it expires, or not signed in. It looks for the session saved for the target it is diagnosing, and falls back to the active session only when that session belongs to the same target — so doctor --target local reports your local sign-in even while prod is the active one. The token itself is never shown.
Every probe is a plain GET with a ten-second timeout, and none of them follows redirects: a host that answers /health with a 301 or 302 reads as unhealthy rather than as reachable.

Flags

boolean
default:"false"
Print the machine-readable envelope instead of the text report.
prod | dev | local | http(s) URL
default:"prod"
Which environment to diagnose. local defaults to gateway http://127.0.0.1:8787 and sign-in http://127.0.0.1:3000. A URL here behaves like --server-url and the report names the target custom. Only the flag counts: a bare positional, as in receipt doctor local, is ignored and you get prod.
url
Diagnose a specific Receipt Connect gateway. It takes precedence over --target and makes the target custom.
url
The web origin that hosts sign-in, when it is not the same host as the gateway.

The text report

On a fresh hosted install, before you sign in:
The first line is receipt doctor: ok or receipt doctor: attention needed. Then the target, the gateway URL with its probe result and which health path answered, the sign-in URL with its probe result, the MCP URL (the gateway plus /connect/mcp), and the session line. A Next steps list follows only when there is something to do.
The sign-in probe reports HTTP 400, and that is healthy. doctor sends a bare GET to the sign-in endpoint to check it is reachable; the endpoint answers 400 with user_code is required because the probe carries no user code. doctor only cares that the origin answered.
A signed-in machine with a healthy endpoint prints the session line and no next steps:
When a session is present but past its 12-hour lifetime, the session line carries an EXPIRED marker and the expiry time instead of expires ….

The next-step lines

Only the conditions that apply are printed, one per line, under Next steps:: When the endpoint cannot be resolved at all there is no report — just one line and exit 1, such as receipt doctor: receipt connect dev URL is not configured. Set RECEIPT_CONNECT_DEV_GATEWAY_URL or RECEIPT_CONNECT_DEV_URL. for --target dev on a machine with no dev host set.

The JSON shape

receipt doctor --json returns one envelope:
When a session is present, session carries the details instead:
sessionFile is printed as a full absolute path; ~/.receipt/session.json stands in for it here and everywhere else in this documentation. Each probe object is { url, status } when the origin answered or { url, error } when it could not be reached. If the endpoint cannot be resolved at all, the envelope is just { "ok": false, "error": "…", "nextSteps": ["…"] }.

Exit codes

doctor sets its exit code so you can gate scripts on it:
In CI or a health script, run receipt doctor --json and branch on the exit code: 0 means the endpoint is reachable and any session is valid; 1 means act — usually re-run receipt setup.

Common problems doctor surfaces

Every fix below is a receipt command; doctor itself only reports.
The target you last ran receipt setup against becomes the active session, but doctor diagnoses the target you hand it — prod when you hand it nothing. After setup --target local, a plain receipt doctor therefore checks the hosted endpoint and reports the prod session, or not signed in if you have never signed in there. Pass the same --target to doctor that you signed in with, and the session-vs-gateway check lines up.
A session file missing its gateway URL, token, or organization id — or one that will not parse — is treated as no saved session. doctor reports not signed in rather than an error, and the fix is the same: run receipt setup.
Messages from the other commands — sign-in failures, unauthorized, workspace and tool errors — are collected in troubleshooting. Next step: switch the workspace your session is bound to.