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

# CLI Authentication

> Three auth flows — OAuth + keyring for local development, ROBOTICKS_API_KEY for CI, GitHub OIDC exchange for GitHub Actions. Project-scoped keys, rotation, revocation.

# Authentication

`rbtk` supports three auth flows. Use the one that fits your environment.

| Flow                            | Where it shines                 | What it stores                          |
| ------------------------------- | ------------------------------- | --------------------------------------- |
| **OAuth + system keyring**      | Local development               | Refresh token in the OS keyring         |
| **`ROBOTICKS_API_KEY` env var** | Any CI, scheduled jobs, scripts | Nothing — env-var only                  |
| **GitHub OIDC exchange**        | GitHub Actions                  | Ephemeral access token per workflow run |

You can mix them — for example, `rbtk auth login` on your laptop and `ROBOTICKS_API_KEY` on your home server. The CLI picks the highest-priority configured source per invocation.

## OAuth + keyring (local development)

The browser-based flow is the default for human use. It stores a refresh token in the OS keyring (macOS Keychain, GNOME Keyring, Windows Credential Manager) — never on disk.

```bash theme={null}
rbtk auth login

# 1. Browser opens to https://app.roboticks.io/cli/authorize?code=...
# 2. You approve the request
# 3. The CLI exchanges the code for an access + refresh token
# 4. Refresh token written to keyring

rbtk auth status
# Logged in as amir@roboticks.io
# Org:     acme (Team)
# Project: warehouse
# Token:   expires in 58m, auto-refreshing
```

If the browser cannot open (SSH session, headless), the CLI prints a URL and a one-time code:

```
Open this URL on a device with a browser:
  https://app.roboticks.io/cli/authorize?code=GZHF-QXAQ
Then return here.

[waiting for approval... 5m]
```

### Logout

```bash theme={null}
rbtk auth logout
# Cleared refresh token from keyring
```

## API key (CI generic)

For any CI system that isn't GitHub Actions, mint a project-scoped API key in the dashboard and inject it as an environment variable.

### Mint a key

1. **Settings → API keys → New key**
2. Name it for the consumer (e.g., `gitlab-ci-warehouse`)
3. Pick a scope:
   * **Project** — most common; key is bound to one project, cannot escape
   * **Org admin** — for org-wide automation; use sparingly
4. Optionally set an expiry. Default is **90 days**.
5. Copy the displayed `rbtk_sk_...` value once — it is never shown again.

### Use it

```bash theme={null}
export ROBOTICKS_API_KEY=rbtk_sk_xx...
rbtk test list
```

In CI:

<Tabs>
  <Tab title="GitLab CI">
    ```yaml theme={null}
    variables:
      ROBOTICKS_API_KEY: $ROBOTICKS_API_KEY   # set as a masked CI variable
    ```
  </Tab>

  <Tab title="Jenkins">
    ```groovy theme={null}
    environment {
      ROBOTICKS_API_KEY = credentials('roboticks-api-key')
    }
    ```
  </Tab>

  <Tab title="CircleCI">
    ```yaml theme={null}
    environment:
      ROBOTICKS_API_KEY: $ROBOTICKS_API_KEY
    ```
  </Tab>
</Tabs>

<Warning>
  Never commit an API key to version control. Use your CI's secret store. Revoke immediately if leaked.
</Warning>

### Rotate and revoke

```bash theme={null}
# List keys for the current project
rbtk auth keys list

# Revoke one
rbtk auth keys revoke rbtk_sk_xx... --confirm
```

Or **Settings → API keys → ⋯ → Revoke** in the dashboard.

## GitHub OIDC (GitHub Actions)

GitHub Actions can mint short-lived OIDC tokens that the platform accepts in exchange for an ephemeral CLI access token. **No long-lived secrets in your repo.**

### One-time setup

In the dashboard at **Settings → GitHub OIDC**, register your GitHub repo (or org) and set the **subject claim policy**:

```
repo:acme/warehouse:ref:refs/heads/main
repo:acme/warehouse:environment:production
```

The platform mints CLI tokens only for workflow runs whose `sub` claim matches a policy line.

### In your workflow

```yaml theme={null}
jobs:
  test:
    runs-on: ubuntu-latest
    permissions:
      id-token: write        # required for OIDC
      contents: read
    steps:
      - uses: actions/checkout@v4
      - run: pipx install roboticks-cli
      - run: rbtk auth oidc-from-github
      - run: rbtk test run --push ./
```

`rbtk auth oidc-from-github` reads `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN` (auto-injected by GitHub Actions), trades them for a CLI token via `/auth/oidc/exchange`, and caches the result in memory for the workflow's lifetime.

You get **no secret rotation work** and **least-privilege** out of the box.

## Auth precedence

Per invocation, the CLI checks in order:

1. `--api-key` flag (rare; mostly for one-off scripts)
2. `ROBOTICKS_API_KEY` env var
3. In-memory OIDC token from a prior `rbtk auth oidc-from-github` in the same process
4. OS keyring entry from a prior `rbtk auth login`

The first match wins. `rbtk auth status` shows which source the current invocation would use.

## Project-scoped vs org-admin

|                    | Project key | Org admin key |
| ------------------ | ----------- | ------------- |
| Sees test results  | One project | All projects  |
| Creates test runs  | One project | All projects  |
| Manages billing    | No          | Yes           |
| Manages members    | No          | Yes           |
| Rotates other keys | No          | Yes           |

**Default to project-scoped** for CI. Reserve org-admin for human operators and audit tooling.

## Troubleshooting

<AccordionGroup>
  <Accordion title="`401 Unauthorized` from every command">
    Run `rbtk auth status`. If the token is expired and there's no refresh token, run `rbtk auth login` again. In CI, the API key may have been revoked — check the dashboard.
  </Accordion>

  <Accordion title="OIDC exchange returns `subject does not match policy`">
    Your workflow ran on a ref that isn't allowed by the subject claim policy. Either tighten the workflow's run conditions or add the ref to the policy at **Settings → GitHub OIDC**.
  </Accordion>

  <Accordion title="Keyring backend not available (headless Linux)">
    Install `python3-secretstorage` and `gnome-keyring`, or set `ROBOTICKS_API_KEY` in the environment as an alternative.
  </Accordion>
</AccordionGroup>

## Next

<CardGroup cols={2}>
  <Card title="Context switching" icon="arrows-rotate" href="/cli/context-commands">
    Pick org and project per invocation.
  </Card>

  <Card title="CI/CD recipes" icon="code-branch" href="/cli/ci-cd">
    GitHub Actions, GitLab, Jenkins, CircleCI, BuildKite.
  </Card>
</CardGroup>
