> For the complete documentation index, see [llms.txt](https://docs.tryterra.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tryterra.co/developer-tools/terra-cli/authentication.md).

# Authentication

Log in to the Terra CLI interactively, from CI, or without a browser, and manage the token it stores.

The CLI authenticates with an admin token for your Terra account. There are three ways to supply one.

| Situation                                    | Use                                                  |
| -------------------------------------------- | ---------------------------------------------------- |
| Your own machine                             | `terra login`                                        |
| CI, or any other non-interactive environment | The `TERRA_ADMIN_TOKEN` environment variable         |
| A machine with no browser, or a coding agent | `terra login --start`, then `terra login --complete` |

## Interactive login

```bash
terra login
```

The CLI prints a pairing code and opens the dashboard to approve it. Once approved, the token is stored in your OS keyring. Only non-secret metadata, such as the token id, scopes, and expiry, goes in the config file.

By default the token receives every non-dangerous admin scope. Scopes that expose credentials or change billing and team membership, such as `keys:read`, `tokens:admin`, `billing:write`, and `team:write`, are excluded unless you ask for them:

```bash
terra login --scope keys:read --scope providers:write
```

`--scope` requests a specific set of admin scopes, rather than adding to the default set. Data API scopes cannot be granted by `terra login`; use `terra data-tokens create` for those. `terra login --help` lists grantable scopes and marks dangerous ones.

Restrict a token to one environment with `--env`:

```bash
terra login --env dev-prod
```

Pass `--no-browser` to print the verification URL instead of opening it.

## CI

Set `TERRA_ADMIN_TOKEN` and skip `terra login`. Every command uses the variable, and nothing is written to the config file or the keyring.

```bash
export TERRA_ADMIN_TOKEN=terra_at_...
terra environments list
```

## Without a browser

When the process cannot stay open while a human approves in a browser, split the login in two.

```bash
terra login --start
```

```json
{
  "user_code": "TERRA-K7MP-4WX2",
  "verification_uri": "https://dashboard.tryterra.co/cli/verify",
  "verification_uri_complete": "https://dashboard.tryterra.co/cli/verify?code=TERRA-K7MP-4WX2",
  "device_code": "1a2b3c4d",
  "expires_in": 900,
  "interval": 5,
  "next_step": "terra login --complete 1a2b3c4d"
}
```

Open `verification_uri_complete` in any browser and approve the pairing. Then run the `next_step` command. It waits for the approval and stores the token.

`--start` stores nothing. There is no token until the pairing is approved.

## Token lifetime

Admin tokens expire after 30 days. Extend one with `terra tokens rotate`. Rotation works until the 90-day grant window closes, and after that you log in again.

Rotation invalidates the current token and prints its replacement once. Save that `token` value and supply it through `TERRA_ADMIN_TOKEN`. The rotation command does not update the CLI's stored credential. To replace the stored credential through the login flow, run `terra login` again.

The API sets both windows, not the CLI. `terra whoami` reports the expiry the server issued.

For unattended access to the data API, mint a data token rather than scripting a login:

```bash
terra data-tokens create --env dev-prod --name ci --scopes auth:write
```

## Where the token is stored

In the OS keyring, keyed by profile. When no keyring is available, the CLI falls back to a file with mode 0600 in the config directory and says so. Set `TERRA_KEYRING=file` to force the file.

`terra config --list` shows the token metadata and which backend is in use. The config file never holds a token.

## Check who you are

```bash
terra whoami
terra whoami --format json
```

`terra whoami` runs the same operation as `terra account retrieve`. The response includes the token's `token_id`, `kind`, `customer_id`, `scopes`, `dev_ids`, and `expires_at`. The `user` object requires `account:read`; without that scope it is `null`. Missing or rejected credentials exit with code 2.

## Log out

```bash
terra logout
```

This revokes the stored token server-side and removes it locally. If the revocation fails, the local credential is still removed, and the CLI says so.

A token supplied through `TERRA_ADMIN_TOKEN` is not stored, so `terra logout` does not revoke it. Unset the variable instead.
