# Quickstart

Install the Ubriot CLI, create your app, add Apple credentials and ship your first build to TestFlight.

From an empty terminal to a build processing in TestFlight. The first app takes about five minutes; every app after that is two commands.

## Before you start

- A Ubriot account with a verified email address (see [Create and verify your account](#account)). Create one at [ubriot.dev/signup](https://ubriot.dev/signup), then verify a payment card at [ubriot.dev/dashboard/billing](https://ubriot.dev/dashboard/billing) to start the 14-day trial. There is no free tier; the $1 card check is refunded straight away. Builds, OTA updates and push are blocked until the trial starts.
- An Apple Developer Program membership, and for Android a Google Play developer account.
- A React Native or Expo app in a Git repository. macOS, Linux and Windows all work: builds run on Ubriot's machines, not yours.
- Node.js 18 or newer.

Running from CI or as an AI agent? Use an API key instead of `ubriot login`: see [Run Ubriot from CI or an AI agent](https://docs.ubriot.dev/automation.md).

## Create and verify your account

A person creates the account at [ubriot.dev/signup](https://ubriot.dev/signup). The form includes a short human check. New accounts cannot be created from Tor exit addresses, and sign-up attempts are limited per network each hour; existing accounts sign in from anywhere. The same limits apply to creating an account with an emailed code in Ubriot Console. Sign-up errors carry a `code`:

| `code` | What to do |
|---|---|
| `captcha_required`, `captcha_failed` | Reload the sign-up page, complete the human check and submit again. |
| `captcha_unavailable` | The check could not be confirmed. Wait a minute and try again. |
| `signup_network_blocked` | Create the account from a regular connection instead of Tor. |
| `signup_rate_limited` | Try again in an hour. |
| `account_paused` (on sign-in) | The account was paused. Sign up again with the same email at [ubriot.dev/signup](https://ubriot.dev/signup); the new account starts empty. Or contact [support@ubriot.dev](mailto:support@ubriot.dev). |

### Verify your email

Builds and store submissions need a verified email address. An account created with an emailed code is verified already. After signing up with a password, open [ubriot.dev/dashboard](https://ubriot.dev/dashboard), choose "Send code" on the "Verify your email to start builds" banner and enter the 6-digit code from the email. Your password and API keys keep working, and other signed-in devices renew their session automatically.

Until then, starting a build or a store submission returns `403` with `"code": "email_not_verified"`, by session, API key, CLI or MCP alike. An agent cannot verify on someone's behalf: ask the account owner to do it, then retry.

## 1. Install and log in

```bash
npm install -g ubriot
ubriot login
```

`ubriot login` asks for the email and password of your Ubriot account in the terminal. If you signed up with an emailed code and have no password, set one with "Forgot password" on [ubriot.dev/login](https://ubriot.dev/login) first.

Expected result: `Logged in as you@example.com`. `ubriot whoami` shows who is logged in and `ubriot logout` clears the saved session.

## 2. Create your app

The examples split long commands with `\` for macOS and Linux shells. In Windows PowerShell, use a backtick (`` ` ``) instead, or put the command on one line.

```bash
ubriot apps create \
  --name "My App" --slug myapp \
  --repo https://github.com/you/yourrepo.git --branch main \
  --ios-bundle com.you.myapp
```

Expected result: the CLI prints the new app's id and slug. In a monorepo, point Ubriot at the app folder with `--expo-project-root apps/mobile`. Add `--android-id com.you.myapp` for Android. For a private repository, upload a GitHub token as described in [Credentials](https://docs.ubriot.dev/credentials.md#github).

## 3. Add Apple credentials (first app only)

Two uploads, once per Apple developer account. Every future app reuses them.

Upload the App Store Connect API key (.p8) from App Store Connect, under Users and Access, Integrations:

```bash
ubriot credentials upload-asc-key --app myapp --name "ASC Key" \
  --key-p8 AuthKey_XXXX.p8 --key-id XXXX --issuer-id YYYY
```

Upload the distribution certificate (.p12) exported from Keychain or the Apple Developer portal:

```bash
ubriot credentials upload-ios-cert --app myapp --name "Distribution Cert" \
  --p12 dist.p12 --p12-password <password> --team-id ZZZZ
```

## 4. Ship

```bash
ubriot ship ios
```

Run it from the app folder: without `--app`, Ubriot uses the app whose slug matches `expo.slug` in that folder's app.json. Anywhere else, pass `--app myapp`.

Signing is provisioned automatically: Ubriot registers your bundle ID with Apple and creates the App Store provisioning profile from your stored credentials. No Apple portal visit and no profile downloads. The command builds the binary, uploads it, and tracks App Store Connect until TestFlight marks the build valid.

Android is the same shape: upload your keystore and Google Play service account (see [Credentials](https://docs.ubriot.dev/credentials.md#android)), then run `ubriot ship android`.

## Every app after the first

```bash
ubriot apps create --name "Next App" --slug nextapp --ios-bundle com.you.nextapp --repo <url>
ubriot ship ios
```

Credentials are account-level and signing is auto-provisioned, so it is two commands end to end.

## Confirm success

`ubriot ship ios` exits with code 0 once App Store Connect accepts the build. The build then appears in App Store Connect under TestFlight, and `ubriot builds list --app myapp` shows it as succeeded with its TestFlight state. If the command was interrupted, follow the build with `ubriot builds watch <buildId>`.

## Common errors

| Message | What to do |
|---|---|
| `Verify a payment card at ubriot.dev/dashboard/billing to start your 14-day trial.` | Start the trial at [ubriot.dev/dashboard/billing](https://ubriot.dev/dashboard/billing). |
| `Verify this account's email address before starting builds or store submissions. ...` | Verify the email from the dashboard banner. See [Verify your email](#verify-email). |
| `No app specified. Pass --app <appSlug> or run from an Expo app with expo.slug in app.json.` | Pass `--app myapp`, or run from the folder with app.json. |
| `No App Store Connect API key found. Upload one with: ubriot credentials upload-asc-key` | Do step 3. |
| `No ios-distribution-certificate found. Upload one with: ubriot credentials upload-ios-cert` | Do step 3. |
| `Not logged in.` | Run `ubriot login`, or set `UBRIOT_TOKEN`. |
| A failed build | Read `ubriot builds logs <buildId>`, or, on ubriot 1.3.0 or later, `ubriot ask "why did build <buildId> fail?"`. See [Builds](https://docs.ubriot.dev/builds.md#recover). |

## Next steps

- [Builds](https://docs.ubriot.dev/builds.md): profiles, store tracks, watching builds and retrying submissions.
- [OTA updates](https://docs.ubriot.dev/ota-updates.md): ship JavaScript changes without a new build.
- [CLI reference](https://docs.ubriot.dev/cli.md): every command and option.
