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

# Sign in: setup, login, and logout

> Sign the released CLI in with one command and a browser approval, and understand the session file and 12-hour token it leaves behind.

Signing in takes one command and one browser approval. Run `receipt setup`, approve the CLI in the page that opens, and every other command — `receipt workspace`, `receipt tools`, `receipt mcp`, `receipt connect` — has an identity to work with. It stays signed in for 12 hours.

## Three commands, one session

| Command          | What it does                                                                                                                                            |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `receipt setup`  | Signs you in, installs the Claude observer when the companion binary is present, then prints your account, the connector catalog and the observer state |
| `receipt login`  | The sign-in step alone — no connector summary, no observer install                                                                                      |
| `receipt logout` | Deletes the saved session for the target you are signed in to                                                                                           |

All three also work with a leading `connect`, so `receipt connect setup` and `receipt setup` are the same command. The similarly named `receipt connect doctor` and `receipt connect check` do **not** run setup — they run the read-only [`receipt doctor`](/cli/doctor), which resolves your endpoint and reports the saved session without ever opening a browser.

For the hosted app there is nothing to configure — the binary resolves `app.kentron.ai` on its own, so a plain `receipt setup` on a fresh machine signs you straight in. You only pass a host when you are pointing at a dev or self-hosted origin; see [Install the CLI](/cli/install).

## What setup actually does

Exactly two things, in order:

1. **Signs you in.** It resolves which host to talk to, reuses a saved session if one matches and is still valid, and otherwise runs the browser device login below and writes a new session file.
2. **Installs the Claude observer**, but only when the companion binary can be found. The current release does not ship that companion, so on a freshly installed CLI the step reports itself as not installed and names the reason. That is not an error and it does not stop sign-in — see [Observing and importing Claude Code activity](/cli/observe-claude-code).

<Warning>
  `receipt setup` does **not** start provider onboarding. It signs you in and installs the observer, nothing more. Onboarding a provider is [`receipt connect`](/cli/connect).
</Warning>

## Flags

`setup` and `login` take the same endpoint and sign-in flags.

<ParamField path="--target" type="prod | dev | local | http(s) URL" default="prod">
  Which endpoint to use. An `http://` or `https://` value, like `--server-url`, produces a `custom` target. Anything else fails with `receipt connect target must be prod, dev, local, or an http(s) URL` — and it fails even when you also passed `--server-url`, because the target word is validated before the override is applied.
</ParamField>

<ParamField path="--server-url" type="url">
  The Receipt Connect gateway to use, overriding the target. Setting it always produces a `custom` session.
</ParamField>

<ParamField path="--auth-url" type="url">
  The web origin that hosts the browser sign-in page, when it is not the same host as the gateway.
</ParamField>

<ParamField path="--fresh-login" type="boolean" default="false">
  Ignore any saved session and run the device login again. `setup` now detects an expired token on its own and re-runs the login for you, so you mainly need this to force a re-login while a token is still technically valid — for example when the gateway has rejected it.
</ParamField>

<ParamField path="--no-login" type="boolean" default="false">
  Skip sign-in entirely; the account line then reads `Receipt account: not connected (disabled by setup flag)`. Aliases: `--skip-login`, `--local-only`.
</ParamField>

<ParamField path="--no-claude" type="boolean" default="false">
  Skip the Claude observer install. `setup` only. Aliases: `--no-observer`, `--no-background`, `--skip-claude`.
</ParamField>

<ParamField path="--no-open" type="boolean">
  Print the sign-in URL instead of opening a browser. `--open=false` does the same, and so does setting `RECEIPT_CONNECT_OPEN_BROWSER=0` in the environment.
</ParamField>

<ParamField path="--json" type="boolean" default="false">
  Return a structured envelope instead of the status lines. It also suppresses the `Step 1 of 2` progress lines.
</ParamField>

Observer flags such as `--proxy-bin <path>`, `--mode` and `--event-log` are passed through to the observer install step.

<Note>
  `--no-open` is a boolean, and this binary's flag parser lets a boolean swallow the next word. `receipt setup --no-open --json` is fine; `receipt setup --no-open` followed by another bare word is not. Use `--open=false` if you need the flag anywhere but last. See [the parsing rules](/cli/overview).
</Note>

## Session reuse

`setup` reuses the saved session for the target — no browser opens — only when **all three** of these hold:

* `--fresh-login` was not passed,
* the saved `gatewayUrl` matches the host you resolved to (`localhost` and `127.0.0.1` count as the same), and
* the saved token has **not** expired.

If the token has expired, `setup` does not reuse it. It runs the full device login and writes a fresh session — you no longer end up carrying a dead token forward. Any other mismatch (a different host, or no saved session at all) also runs the full login.

Whichever way it resolves, the session for the target you set up is promoted to the active `~/.receipt/session.json`. So the most recent `setup` wins: `receipt setup --target local` and then `receipt setup` flips which environment [`receipt mcp`](/cli/tools-and-mcp), [`receipt workspace`](/cli/workspaces) and [`receipt tools`](/cli/tools-and-mcp) talk to — even when the later setup reused a still-valid saved session rather than signing in again.

## The browser device login, step by step

<Steps>
  <Step title="The CLI asks for a code">
    It prints `Starting Receipt Connect sign-in at <authUrl>...` and posts a start request to `<authUrl>/api/receipt-connect/cli-login`, with a 15-second timeout.

    The server rate-limits this: at most 10 starts per 60 seconds per client IP, and at most 3 sign-ins pending at once. Over either limit it answers HTTP 429 with `{"ok":false,"error":"rate_limited","retryAfter":60}`, and the CLI reports `receipt connect device login failed to start: rate_limited`.
  </Step>

  <Step title="You get a code good for ten minutes">
    The server issues an eight-character user code in the form `XXXX-XXXX`, drawn from an alphabet that leaves out the characters people misread — no `I`, `O`, `0` or `1`. It expires after 10 minutes.
  </Step>

  <Step title="The CLI prints the code and opens a browser">
    ```
    Step 1 of 2: sign in to Receipt
      Open: https://<your-receipt-host>/api/receipt-connect/cli-login?user_code=ABCD-EFGH
      Code: ABCD-EFGH
      Approve the CLI from the workspace that should own these connections.
    ```

    It then opens that URL in your browser, unless you passed `--no-open` or set `RECEIPT_CONNECT_OPEN_BROWSER=0`. The URL carries only the short user code.
  </Step>

  <Step title="You approve it in the browser">
    Approval needs an existing signed-in Receipt session in that browser **and** an active organization. What you see depends on the state:

    * **Not signed in** — you are redirected to the sign-in page and returned to the approval page afterwards.
    * **Approved** — `Receipt Connect is approved`, with `You can return to the terminal. This page can be closed.`
    * **No active organization** — `Select a workspace first`, with `Receipt Connect credentials are stored at the workspace level. Open Receipt, select a workspace, then run the CLI command again.`
    * **Unknown or expired code** — `This Receipt Connect code is invalid or expired.`
    * **Code already used** — `This Receipt Connect code was already used. Run the CLI command again.` Each code is single-use.
  </Step>

  <Step title="The CLI polls until you approve">
    It polls every 2 seconds, for up to 10 minutes. While you have not approved yet, the server answers `authorization_pending` and the CLI keeps waiting. An expired code ends it with `receipt connect device login expired`; running out of time ends it with `receipt connect device login timed out`.

    On success the CLI prints `Receipt sign-in approved.` and writes the session file.
  </Step>
</Steps>

Other failures you may see from this step: `receipt connect device login request failed for <url>: <message>` for a network or timeout problem, `receipt connect device login failed to start: http_404` when the auth URL is not the web application, `receipt connect device login returned an empty token`, and `receipt connect login did not return a workspace; select a Receipt workspace and try again`. Every one of them, with its cause and fix, is in [CLI troubleshooting](/cli/troubleshooting).

## Signing in only, with receipt login

`receipt login` runs the sign-in step above and stops there: no connector catalog, no observer install. Use it when you are switching environments or refreshing an expired token and do not want the rest of setup's work.

It takes an optional positional target, so these are equivalent:

```bash theme={null}
receipt login local
receipt login --target local
receipt login https://<your-receipt-host>
```

Session reuse works exactly as it does for `setup`. On success it prints three lines:

```
receipt login: signed in <email> for workspace Default (<workspaceId>)
receipt login: gateway https://<your-receipt-host>
receipt login: saved ~/.receipt/session.json
```

The first line reads `already signed in` instead of `signed in` when it reused a saved session. With `--json` you get `ok`, `reused`, the target and gateway URL, the identity fields, and both session file paths.

<Note>
  `login` honours setup's skip flags. `receipt login --no-login` prints `receipt login: skipped (disabled by setup flag)` and exits 0 without signing you in.
</Note>

## What gets written to disk

The active session is `~/.receipt/session.json`. The directory is created with mode `0700` and the file is written atomically — to a temporary file at mode `0600`, then renamed — so it stays readable only by you.

* `RECEIPT_CLI_CONFIG_DIR` moves the whole directory.
* `RECEIPT_CLI_SESSION_FILE` sets the exact path of the active session file, and suppresses the per-target files entirely.

Those two are the only variables that change where sign-in writes; the full set the binary reads is in [Environment and exit codes](/cli/environment-and-exit-codes).

Alongside the active file, `prod`, `dev` and `local` targets each get their own copy: `session.prod.json`, `session.dev.json`, `session.local.json`. A `custom` target — anything reached through a URL or `--server-url` — writes **no** per-target file, only the active one.

Each file contains:

| Field                          | What it holds                           |
| ------------------------------ | --------------------------------------- |
| `kind`, `schemaVersion`        | Fixed markers identifying the file      |
| `target`                       | `prod`, `dev`, `local` or `custom`      |
| `gatewayUrl`                   | The Receipt Connect gateway base URL    |
| `authUrl`                      | The web origin used for sign-in         |
| `token`                        | **The bearer token, in plaintext**      |
| `userId`, `userEmail`          | Who signed in                           |
| `organizationId`               | The organization the token is scoped to |
| `workspaceId`, `workspaceName` | The workspace the token is bound to     |
| `savedAt`                      | When it was written                     |

<Warning>
  The session file is not secret-free. It stores a live bearer token in the clear, protected only by its `0600` file mode. Do not copy it between machines, commit it, or include it in a bug report.
</Warning>

A file missing `gatewayUrl`, `token` or `organizationId`, or one that will not parse, is treated as no session at all rather than as an error.

## Signing out, with receipt logout

`receipt logout` reads the active session, deletes it and the per-target file for that same target, and prints:

```
receipt logout: signed out <email> from https://<your-receipt-host>
```

With nothing to remove it prints `receipt logout: not signed in` and still exits 0. It reads no flags — there is no `--target`, so it always acts on whichever session is currently active. Sessions for other targets are left in place, which is what makes `receipt setup --target local` a safe way to come back to a local stack without losing your hosted sign-in. Deleting the files by hand works too.

<Warning>
  Signing out is local. It removes the files; it does not revoke the token at the gateway, so a copy of that token stays usable until it expires. Treat a leaked session file as live credentials for up to 12 hours.
</Warning>

## The token: 12 hours, three scopes, one workspace

The token the login returns is a JWT that:

* **Expires after 12 hours.**
* Carries three scopes: `connect:credential`, `connect:read` and `connect:write`.
* Is bound at login to the organization's **Default** workspace — always. You cannot choose a different workspace during sign-in; approving in the browser picks the organization, not the workspace. Changing workspace afterwards is [`receipt workspace use`](/cli/workspaces).

<Warning>
  The token is good for 12 hours. Once it expires, gateway calls fail with `unauthorized` — but `setup` no longer papers over that: it detects the expired token and re-runs the browser login for you, so signing in again is just `receipt setup`. To force a re-login before expiry (for example if the gateway has already started rejecting the token), run `receipt setup --fresh-login`.
</Warning>

`setup` also exports the session's values — gateway URL, token, organization, workspace and user id — as environment variables into its own process, and only its own process. They are not exported to your shell.

## What setup prints

```
Receipt account: connected to workspace Default (<workspaceId>)
Receipt Connect connectors:
  aws: AWS via real 'aws' CLI
  gcp: Google Cloud via real 'gcloud' CLI
  ...
Claude observer: not installed (Unable to find the Claude observer companion binary. Install a Receipt CLI release that bundles receipt-claude-proxy, or pass --proxy-bin <path> / set RECEIPT_CLAUDE_PROXY_BIN.)
```

The connector list is the whole catalog — all 63 connectors — not the connectors you have connected. To see actual connections, use [`receipt connect status`](/cli/connect).

The observer line reads `Claude observer: installed (<platform> <serviceFile>)` when the companion binary was found and the background service installed.

With `--json` you get the same information as one envelope: `ok`, a `receiptAccount` object (including whether the session was `reused` or `skipped`, the target, gateway URL, identity fields, and the session file paths), the full `connectors` catalog, and `claudeObserver`.

Next step: [check your setup with receipt doctor](/cli/doctor).
