> For the complete documentation index, see [llms.txt](https://mercure-technologies.gitbook.io/xprem/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mercure-technologies.gitbook.io/xprem/eoas/publish-an-update.md).

# Publish an update

Publishing is one command. Two things decide whether it reaches users: the runtime version and authentication. Everything else is flags.

### Runtime version

The runtime version connects an update to a compatible native build. It must match exactly. Otherwise, the update is not delivered.

Neither side reports an error. This makes mismatches easy to miss.

[Expo's runtime versions guide](https://docs.expo.dev/eas-update/runtime-versions/) covers the concept in full.

#### Recommended: a fixed version

Set a fixed runtime version in `app.config.ts`:

```ts
runtimeVersion: '1.0.0',
```

Bump it before every build that changes native code. This includes native dependencies, config plugins, and files under `ios/` or `android/`.

JavaScript-only changes do not need a new runtime version. They keep matching installed builds, so you can publish them as updates.

#### The fingerprint policy

Expo also offers a fingerprint policy. It derives the runtime version from a hash of your native configuration:

```ts
runtimeVersion: { policy: 'fingerprint' },
```

The hash stays identical while native properties remain unchanged. You never need to bump a version manually.

{% hint style="warning" %}
We do not recommend the fingerprint policy unless you fully understand it. CI and local environments can produce different fingerprints for one commit. The only symptom is an update that never arrives.

Use it only when you can diagnose and control fingerprint mismatches.
{% endhint %}

Official documentation: <https://docs.expo.dev/versions/latest/sdk/fingerprint/>

### Authentication

EOAS authenticates with `EOO_TOKEN`, the app-scoped API key created in the dashboard. Set it in the environment that runs the publish command; see [EOAS overview](/xprem/eoas/overview.md) for how keys are created and scoped.

{% hint style="warning" %}
Without `EOO_TOKEN`, EOAS silently falls back to Expo authentication and the server rejects the request. A missing token therefore shows up as a rejected publish, not as a clear "token not set" error.
{% endhint %}

### Publish an update

Run this in your Expo project:

```bash
npx eoas publish --branch <branch-name>
```

EOAS resolves the runtime version, exports the bundle with `expo export`, uploads assets, and points the branch at the new update.

#### Flags

| Flag                             | Default                   | Purpose                                                                                                                                                    |
| -------------------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--branch <name>`                | Required                  | Branch that receives the update                                                                                                                            |
| `--platform <ios\|android\|all>` | `all`                     | Platforms to export and publish                                                                                                                            |
| `--message`, `-m <text>`         | Latest Git commit message | Description shown in the dashboard                                                                                                                         |
| `--rollout-percentage <1-99>`    | None                      | Stages the update as a progressive rollout served to that share of devices, the rest keep the previous update                                              |
| `--outputDir <dir>`              | `dist`                    | Directory for the export                                                                                                                                   |
| `--packageRunner <bin>`          | Auto-detected             | Runner for `expo export` and `expo config`                                                                                                                 |
| `--nonInteractive`               | `false`                   | Skips prompts; required in CI                                                                                                                              |
| `--dumpSourcemap`                | `false`                   | Emits Hermes source maps alongside the bundle (passes `--dump-sourcemap` to `expo export`) so the published artifact can be symbolicated (Sentry, PostHog) |

To stage an update on a fraction of your devices before delivering it to everyone, pass `--rollout-percentage`. How devices are selected, and how you progress, finish or revert the rollout from the dashboard, is covered in [Progressive rollouts](/xprem/eoas/progressive-rollouts.md).

#### Environment variables

| Variable                          | Purpose                                                                                                                                                                                                                                     |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EOO_TOKEN`                       | App-scoped API key created in the dashboard. Required.                                                                                                                                                                                      |
| `RELEASE_CHANNEL`                 | Passed to your app config and bundle export.                                                                                                                                                                                                |
| `EOAS_PACKAGE_RUNNER`             | Overrides the package runner.                                                                                                                                                                                                               |
| `DEBUG`                           | Enables verbose logging.                                                                                                                                                                                                                    |
| `EOAS_ALLOW_INSECURE_UPLOAD_URLS` | The CLI accepts upload URLs over HTTPS only, and allows plain HTTP on loopback addresses. Set it to `1` or `true` to accept a non-loopback plain-HTTP endpoint, such as a self-hosted MinIO. Your update artifacts then travel unencrypted. |

{% hint style="warning" %}
EOAS does not load `.env` files. It runs `expo export` with `EXPO_NO_DOTENV=1`, disabling Expo CLI dotenv loading.

Every variable must exist in the process environment.
{% endhint %}

```bash
EOO_TOKEN=your_token RELEASE_CHANNEL=staging \
  npx eoas publish --branch staging
```

Or load a file explicitly with `dotenv`:

```bash
dotenv -e .env.local -- npx eoas publish --branch staging
```

#### Why set `RELEASE_CHANNEL`?

`RELEASE_CHANNEL` does not select the branch. Only `--branch` does.

EOAS builds your JavaScript bundle before publishing it. Set `RELEASE_CHANNEL` to build the app for the intended release channel.

This selects the channel-specific environment variables, configuration, and screens used in the bundle.

### Update message

Attach a short description with `--message` or `-m`:

```bash
npx eoas publish --branch production -m "Fix login crash on Android"
```

If omitted, EOAS uses the latest Git commit message. This matches EAS Update. The message appears in the dashboard updates table.

### Package runner

EOAS uses `npx` by default to run Expo CLI commands. These include `expo export` and `expo config`. Override it for another package manager.

Resolution priority:

1. `--packageRunner` CLI flag
2. `EOAS_PACKAGE_RUNNER` environment variable
3. `packageManager` in the nearest `package.json`
4. `npx`

| `packageManager` value | Resolved runner |
| ---------------------- | --------------- |
| `bun@x.x.x`            | `bunx`          |
| `pnpm@x.x.x`           | `pnpm exec`     |
| `yarn@x.x.x`           | `npx`           |
| `npm@x.x.x`            | `npx`           |

```bash
# Auto-detected from package.json
npx eoas publish --branch production

# Explicit flag
npx eoas publish --branch production --packageRunner bunx

# Environment variable
EOAS_PACKAGE_RUNNER=bunx eoas publish --branch production
```

### CI/CD

Automate publishing with `npx eoas publish --nonInteractive`.

Set `EOO_TOKEN` as a CI secret and keep `--nonInteractive` so the command never waits for a prompt.

```bash
EOO_TOKEN=$EOO_TOKEN RELEASE_CHANNEL=production \
  npx eoas publish --branch production --nonInteractive
```

#### A clean working tree is required

`eoas publish` refuses to run when the git working tree is dirty, and untracked files count as changes. With `--nonInteractive` it prints the files that still need to be committed and aborts with `Commit all changes. Aborting...`. Run interactively, it offers to commit everything for you before continuing.

Build environments that generate files as part of the pipeline have two escape hatches. Pass `--disableRepositoryCheck` to skip the check for that run, or set the `EAS_NO_VCS` environment variable to run the command without version control at all.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://mercure-technologies.gitbook.io/xprem/eoas/publish-an-update.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
