# apps switch

```sh
scribase apps switch <org> <project> [--env production] [--format expo|dotenv|json] [--key anon|publishable]
```

`apps switch` reads the environment's client keys
(`GET .../environments/{env}/api-keys`) and prints the two values an app built
on `supabase-js` needs. Nothing else in the app has to change:
`createClient(url, key)` keeps working.

| Flag | Default | Meaning |
|---|---|---|
| `--env` | `production` | The environment to point at |
| `--format` | `expo` | `expo`: `EXPO_PUBLIC_SUPABASE_URL` / `EXPO_PUBLIC_SUPABASE_ANON_KEY` lines. `dotenv`: `SUPABASE_URL` / `SUPABASE_ANON_KEY`. `json`: one object for scripts |
| `--key` | `anon` | `anon` prints the legacy anon JWT, which every `supabase-js` version accepts. `publishable` prints the `sb_publishable_...` key |

## Example

```sh
scribase apps switch acme my-app > .env.production
```

```sh
# Scribase environment acme/my-app/production
# createClient(process.env.EXPO_PUBLIC_SUPABASE_URL, process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY) needs no other change.
EXPO_PUBLIC_SUPABASE_URL=https://<label>.<domain>
EXPO_PUBLIC_SUPABASE_ANON_KEY=eyJ...
#
# NEVER put the service_role or sb_secret_ key in an app: ...
#
# Native sign-in reads these environment auth settings ...
#   site_url (GOTRUE_SITE_URL): your app's scheme, e.g. myapp://
#   ...
```

Only the two assignments are real values. Everything else is comments.

## What it never prints

The `service_role` and `sb_secret_...` keys bypass row-level security, and
everything in an app bundle is public. `apps switch` never prints them. Server
code that needs them reads them from the console's API keys page or the API
(see [Environment API keys](https://docs.scribase.com/docs/api/environment-keys.md)).

## Auth settings for native sign-in

The output also names the environment auth settings that native Apple and
Google sign-in (`signInWithIdToken`) depend on. Set them on the environment's
**Auth** page in the console. They are environment settings, not app config:

| Setting | Variable | Value |
|---|---|---|
| `site_url` | `GOTRUE_SITE_URL` | The app's scheme, for example `myapp://` |
| `uri_allow_list` | `GOTRUE_URI_ALLOW_LIST` | Every `redirectTo` the app passes, for example `myapp://**`, plus `exp://**` for Expo Go |
| `external.apple.enabled` | `GOTRUE_EXTERNAL_APPLE_ENABLED` | `true` |
| `external.apple.client_id` | `GOTRUE_EXTERNAL_APPLE_CLIENT_ID` | The iOS bundle id, plus the Services ID if the web flow is used, comma-separated |
| `external.google.enabled` | `GOTRUE_EXTERNAL_GOOGLE_ENABLED` | `true` |
| `external.google.client_id` | `GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID` | The web, iOS and Android OAuth client ids, comma-separated |
| `external.google.skip_nonce_check` | `GOTRUE_EXTERNAL_GOOGLE_SKIP_NONCE_CHECK` | `true` only if the iOS Google SDK flow cannot pass a nonce |

## Errors

- **No public URL**: the control plane has no gateway base URL configured
  (`SCRIBASE_GATEWAY_BASE_URL` or `SCRIBASE_GATEWAY_BASE_URL_TEMPLATE`), so
  there is nothing an app could reach.
- **URL is not https**: only `https://` URLs, or `http://localhost` /
  `http://127.0.0.1` for local development, are accepted.
- **No publishable key**: use `--key anon`.

Moving an existing Supabase project first? See [import](https://docs.scribase.com/docs/cli/import.md),
which ends with the same switch.
