# Run Ubriot from CI or an AI agent

Use the ubriot CLI without a password prompt, with API keys, JSON output and exit codes for GitHub Actions, scripts and AI agents on macOS, Linux or Windows.

`ubriot login` asks for a password in an interactive terminal, so it does not work in CI or for an AI agent. Use an API key in the `UBRIOT_TOKEN` environment variable instead.

Until ubriot 1.4.0 is on npm, the published CLI ignores `UBRIOT_TOKEN`. An agent can use the [MCP server](https://docs.ubriot.dev/mcp.md) or the [HTTP API](https://docs.ubriot.dev/api.md) with the same API key today.

## Prerequisites

- A Ubriot account with an active trial or plan. A person creates it at [ubriot.dev/signup](https://ubriot.dev/signup) and verifies a card at [ubriot.dev/dashboard/billing](https://ubriot.dev/dashboard/billing). An agent cannot sign up or pay on someone's behalf.
- Node.js 18 or newer, and the CLI: `npm install -g ubriot`.
- An app already set up in Ubriot, with its signing credentials uploaded by a signed-in person (see [Quickstart](https://docs.ubriot.dev/quickstart.md) and [Credentials](https://docs.ubriot.dev/credentials.md)). API keys cannot upload credentials.
- For iOS, one successful `ubriot ship ios` run by a signed-in person, so the provisioning profile exists. With an API key, the CLI skips provisioning and uses that stored profile.

## 1. Create an API key

A signed-in person opens [ubriot.dev/dashboard/api-keys](https://ubriot.dev/dashboard/api-keys), enters a key name such as `GitHub Actions` and clicks **Create key**.

Expected result: a panel headed "Copy your new key now" shows a key starting with `ubk_`. It is shown once. Copy it into your secret store before dismissing the panel. Later visits show only the first characters of each key.

## 2. Set UBRIOT_TOKEN

macOS and Linux (bash or zsh):

```bash
export UBRIOT_TOKEN="ubk_..."
```

Windows PowerShell:

```powershell
$env:UBRIOT_TOKEN = "ubk_..."
```

Windows Command Prompt:

```bat
set UBRIOT_TOKEN=ubk_...
```

GitHub Actions: add the key as a repository secret named `UBRIOT_TOKEN`. This workflow builds the tagged commit for Android and submits it to the internal track whenever a tag starting with `v` is pushed:

```yaml
name: Release
on:
  push:
    tags: ["v*"]
jobs:
  android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm install -g ubriot
      - run: ubriot builds create --app myapp --platform android --branch "${{ github.ref_name }}" --wait --submit-google-play --track internal
        env:
          UBRIOT_TOKEN: ${{ secrets.UBRIOT_TOKEN }}
```

`--branch` accepts a branch or a tag name; Ubriot clones that ref from the app's repository. The step fails (exit code 1) if the build or the Google Play upload fails, and its log shows the reason.

`UBRIOT_TOKEN` overrides any saved `ubriot login` session and is never written to `~/.ubriot/config.json`.

## 3. Confirm access

```bash
ubriot whoami
ubriot --json apps list
```

Expected result: `whoami` prints `Using UBRIOT_TOKEN from the environment.` and `apps list` prints a JSON array of your apps with `id`, `slug` and `name`. An empty array means the key works but the account has no apps yet.

## 4. Run release commands

Read-only commands are safe to run at any time:

```bash
ubriot --json builds list --app myapp
ubriot builds show 123
ubriot builds logs 123
ubriot --json builds last-good --app myapp
```

These act on real apps and real users. Run them only when the person you work for asks:

```bash
ubriot ship ios --app myapp
ubriot builds create --app myapp --platform android --wait --submit-google-play --track internal
ubriot update --app myapp --channel production
```

Without a terminal, the CLI prints toolchain and runtime warnings and continues without asking. In an interactive terminal, ubriot 1.4.0 or later accepts `--yes` to skip those questions. `--no-submit` builds without submitting to a store. `ubriot migrate eas` and `ubriot migrate codepush` print a plan and change nothing until you add `--apply`.

With an API key, `ubriot ship ios` skips iOS auto-provisioning and uses the provisioning profile already stored for the app. If the app has never been provisioned, run `ubriot ship ios` once after `ubriot login` on a machine with a terminal.

## Exit codes

| Code | Meaning |
|---|---|
| `0` | Success. |
| `1` | The command failed: a build failed, a store rejected the upload, an option was missing or the API returned an error. The reason is on stderr. |
| `2` | Not logged in, or the token was rejected. |

## What an API key cannot do

These need a signed-in session (`ubriot login` or the dashboard) and return `401` with "This action needs a signed-in session and does not accept API keys":

- Upload, list, copy or delete credentials, and `credentials setup-testflight`.
- Create, list or revoke push server keys.
- `channels list`, `channels create` and `channels point`. To roll back with an API key, use the MCP tool `ubriot_release_health` with `action: "rollback"`.
- `builds retry-upload`, `builds reset-testflight` and `builds reset-google-play`.
- Create or revoke API keys, rotate the git webhook secret, billing and team management.

## Common errors

| Message | What to do |
|---|---|
| `ubriot login needs an interactive terminal.` | Set `UBRIOT_TOKEN` to an API key as above. |
| `Not logged in. Run: ubriot login ... or set UBRIOT_TOKEN` (exit 2) | `UBRIOT_TOKEN` is empty or not exported to this process. In GitHub Actions, check the `env:` block on the step. |
| `Authentication failed: Invalid API key.` (exit 2) | The key was revoked, mistyped or belongs to a deleted account. Create a new key. |
| `Authentication failed: This action needs a signed-in session and does not accept API keys.` (exit 2) | The command is in the list above. Run it after `ubriot login`, or in the dashboard. |
| `could not reach the Ubriot API at ...` | Check the network, and that `UBRIOT_API_BASE` is unset or correct. |
| `Verify a payment card at ubriot.dev/dashboard/billing to start your 14-day trial.`, `Your 14-day trial has ended.` or `No active subscription.` | Builds, OTA publishes and push need a running trial or a paid plan. A person must fix this at [ubriot.dev/dashboard/billing](https://ubriot.dev/dashboard/billing). |
| `Verify this account's email address before starting builds or store submissions. ...` (`email_not_verified`) | The account owner verifies the email from the banner at [ubriot.dev/dashboard](https://ubriot.dev/dashboard). The API key keeps working afterwards. See [Verify your email](https://docs.ubriot.dev/quickstart.md#verify-email). |

See [Quickstart](https://docs.ubriot.dev/quickstart.md#errors) and [Builds](https://docs.ubriot.dev/builds.md#recover) for build and submission errors.

## Revoke a key

Open [ubriot.dev/dashboard/api-keys](https://ubriot.dev/dashboard/api-keys) and revoke it. Requests with that key fail with `Invalid API key` straight away. Deleting your account revokes all of its keys.
