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

# Authentication and contexts

> How the orca CLI signs in, where it keeps credentials, how contexts switch between tenants, and how to run it in CI.

> **Last updated: 2026-09-06**

The CLI authenticates with a tenant API key (an `ao_` token, see [API keys](/concepts/api-keys)). The tenant and role come from the key; there is no separate tenant flag. `orca login` mints a key for you through the dashboard and stores it locally. In CI you skip the login and supply a key through the environment.

## Signing in

```bash theme={"dark"}
orca login
```

`orca login` and `orca auth login` are the same command. It picks one of three flows:

<Tabs>
  <Tab title="Browser (default)">
    In an interactive terminal on a machine with a browser, the CLI binds a loopback port on `127.0.0.1`, opens `https://app.orcapods.ai/cli-auth` with a one-time state value, and waits for the dashboard to post the minted key back. Sign in, confirm the request, and the key lands in the CLI without ever appearing on screen.

    If the callback does not arrive within five minutes, the CLI falls back to a masked paste prompt so you can copy the key from the dashboard by hand. Ctrl-C exits with code 130.
  </Tab>

  <Tab title="Device code">
    ```bash theme={"dark"}
    orca login --headless
    ```

    The CLI asks the conductor for a device code and prints it with a verification URL:

    ```text theme={"dark"}
    First, copy your one-time code: BCDF-GHJK
    Then open: https://app.orcapods.ai/cli-auth?code=BCDF-GHJK
    Waiting for approval... (expires in 15 minutes, Ctrl-C to cancel)
    ```

    Open the URL on any device, sign in, check that the code matches, and approve. The CLI polls until the key is issued. Codes are single-use and expire after 15 minutes.

    This flow is selected automatically, without `--headless`, whenever the terminal is not interactive or the CLI detects a coding agent, CI, or SSH session (`CLAUDECODE`, `CURSOR_TRACE_ID`, `CI`, `SSH_CONNECTION`, or `SSH_TTY` in the environment). `--browserless` and `--no-browser` are accepted as synonyms.

    With `--json`, the first stdout line is an NDJSON event carrying the code, the verification URL, and the expiry, so a script or agent can relay it; the final login record follows once approved.
  </Tab>

  <Tab title="Token">
    ```bash theme={"dark"}
    orca login --with-token ao_live_...
    ```

    No browser, no prompt. The CLI verifies the key against the API and stores it. Use this when you already have a key, for example one minted in the dashboard under Settings, then API Keys, or by `orca keys create` on another machine.
  </Tab>
</Tabs>

Every flow verifies the key against the API before saving it, and every flow accepts these flags:

| Flag                                          | Description                                                                                                                                                             |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--label <label>`                             | Name for the minted key as shown in the dashboard. Defaults to `cli-<user>@<host>`, or `claude-code-<user>@<host>` and similar when a coding agent is driving the login |
| `--api-url <url>`                             | Conductor API base URL. Defaults to `https://api.orcapods.ai`                                                                                                           |
| `--dashboard-url <url>`                       | Dashboard base URL for the browser flow. Defaults to `https://app.orcapods.ai`                                                                                          |
| `--gateway-url <url>`                         | Public chat gateway base URL used by `orca chat`                                                                                                                        |
| `--with-token <token>`                        | Supply a key directly and skip the login flow                                                                                                                           |
| `--headless`, `--browserless`, `--no-browser` | Force the device-code flow                                                                                                                                              |

The minted key inherits the role of the user who approved it. The approval screen shows the key label, so you can see which terminal or agent asked.

## Checking who you are

```bash theme={"dark"}
orca whoami
orca auth status
orca doctor
```

`whoami` asks the server which tenant, role, and key the stored credential resolves to. `auth status` shows the local view: the active context, its URLs, and a masked key, and verifies the key against the API. `doctor` runs a full set of connectivity and configuration checks and prints a fix for each problem it finds.

## Where credentials live

Credentials and contexts are stored in one JSON file:

```text theme={"dark"}
~/.config/orca/config.json
```

The directory is created with mode `0700` and the file with `0600`; the CLI re-applies `0600` on every save and warns on load if the file is readable by other users. The location follows `ORCA_CONFIG_DIR` if set, otherwise `$XDG_CONFIG_HOME/orca`, otherwise `~/.config/orca`.

```json theme={"dark"}
{
  "currentContext": "default",
  "contexts": {
    "default": {
      "apiUrl": "https://api.orcapods.ai",
      "dashboardUrl": "https://app.orcapods.ai",
      "apiKey": "ao_live_...",
      "keyId": "key_01J..."
    }
  }
}
```

`keyId` is the server-side id of the minted key, recorded so `orca auth logout --revoke` can revoke it. It is absent when the key was pasted or passed with `--with-token`.

## Contexts

Contexts work like `kubectl` contexts: each holds a key and the URLs for one tenant or one deployment, and one of them is current. Use them to switch between organizations, or between the hosted platform and a self-hosted conductor.

```bash theme={"dark"}
orca login --context staging --api-url https://conductor.staging.example.com
orca context list
orca context use staging
orca context show
```

`orca login` writes into the context named by `--context` (or `ORCA_CONTEXT`), creating it if needed, and makes it current. `context use` switches the current context; `context show` prints the effective configuration after environment overrides, marking values that came from baked-in defaults. For one command at a time, pass `--context <name>` or set `ORCA_CONTEXT`.

## Precedence

Every setting resolves in the same order, per field:

1. A command-line flag (`--api-url`, `--context`)
2. An environment variable
3. The current context in the config file
4. The baked-in production default

| Variable               | Overrides                                                            |
| ---------------------- | -------------------------------------------------------------------- |
| `ORCA_API_KEY`         | The tenant API key                                                   |
| `ORCA_API_URL`         | Conductor API base URL                                               |
| `ORCA_CONTEXT`         | Which context is used                                                |
| `ORCA_DASHBOARD_URL`   | Dashboard URL for the browser login flow                             |
| `ORCA_GATEWAY_URL`     | Public chat gateway URL for `orca chat`                              |
| `ORCA_CHAT_KEY`        | Chat key for `orca chat` (a published-agent key, not a tenant key)   |
| `ORCA_TENANT`          | Tenant id (`org_...`) the agent was published under, for `orca chat` |
| `ORCA_CONFIG_DIR`      | Config directory                                                     |
| `ORCA_NO_UPDATE_CHECK` | Set to any value to disable the update hint on `orca --version`      |
| `ORCA_ASCII`           | Set to `1` to force ASCII glyphs in terminal output                  |
| `NO_COLOR`             | Disables color, per the no-color.org convention                      |
| `GITHUB_TOKEN`         | Used for GitHub API calls made by `orca update` and the update check |

Contexts that predate `cli-v0.5.0` may hold the old raw Railway hostname as `apiUrl`. The CLI transparently treats that exact value as `https://api.orcapods.ai` and rewrites it on the next login; custom URLs are never touched.

## CI and other headless environments

No config file is needed. Set the key in the environment and every command works:

```bash theme={"dark"}
export ORCA_API_KEY=ao_live_...
orca agents list --json
orca run deployer "Roll out build 4211" --json --detach
```

`ORCA_API_URL` is only required for self-hosted or local conductors. When both `ORCA_API_KEY` and `ORCA_API_URL` are set, a `--context` name that does not exist in the config file is accepted rather than rejected, so the same script runs on a developer machine and in CI.

Mint a key for a pipeline from a machine that is already signed in:

```bash theme={"dark"}
orca keys create ci-deploy --expires 2027-01-01T00:00:00Z
```

The token is printed exactly once. When stdout is a pipe, only the token is written, so `CI_KEY=$(orca keys create ci-deploy)` captures it cleanly. See the [orca keys reference](/cli/reference/keys).

## Signing out

```bash theme={"dark"}
orca auth logout            # forget the key locally
orca auth logout --revoke   # revoke it on the server first, then forget it
```

`--revoke` asks for confirmation in a terminal; add `--yes` to skip the prompt in scripts. If the server-side revoke fails, the CLI warns and still clears the key locally.

Errors on a missing or rejected credential are consistent: no key configured exits `3` with the hint `Run: orca auth login` or `Or set ORCA_API_KEY`; a 401 or 403 from the API also exits `3`. See [exit codes](/cli/output-and-scripting#exit-codes).

<Note>
  For the agent-oriented summary of these flows, see [Headless authentication](/agents/headless-auth).
</Note>
