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

# Local quickstart

> Run Patch on your laptop, connect your own app, or try the optional on-device OTA demo.

:::note
These docs cover React Native and Capacitor. Use the selector at the top of the sidebar to switch between them.
:::

Evaluate the full Codemagic Patch service on your machine before provisioning domains or OAuth. The **local evaluation stack** runs the real server, worker, Postgres, MinIO, and dashboard, with sign-in replaced by a local one-click login. If you want to see an OTA update before integrating your own app, try the optional [on-device demo](https://github.com/codemagic-ci-cd/codemagic-patch/tree/main/examples/on-device-demo) to watch an OTA update apply on a simulator or emulator.

## What you need

- macOS, Linux, or WSL 2 on Windows — the command runs a bash script, so a native Windows shell is not supported
- Node.js `20.19+` or `22.12+` for the `cmpatch` CLI, plus `git` and `curl` (the CLI downloads its copy of the repository and runs its bootstrap script)
- [Docker](https://docs.docker.com/get-docker/) with Compose v2 — if it is missing or not running, the CLI offers to install or start it
- Only if you want to run the demo app: an **iOS Simulator** (macOS, Xcode, and CocoaPods or the Bundler version required by the demo lockfile) and/or an **Android emulator** (Android SDK, Java, and `adb` on `PATH`), plus Node.js `≥ 22.20` and Yarn via [Corepack](https://nodejs.org/api/corepack.html)

## 1. Start the stack

```bash
npm install -g @codemagic/patch-cli
cmpatch selfhost local-eval
```

The command checks Docker first (offering to install or start it), prepares the source it needs, builds and starts the stack, seeds demo apps, and points `cmpatch` at it. The first run can take a few minutes while images build. Running it again is safe: an already-running stack is just re-checked.

When it finishes you get:

- **Dashboard** — [http://localhost:8080](http://localhost:8080) (sign in as `local-admin@example.com`, prefilled, one click; the CLI offers to open it)
- **API** — [http://localhost:3000](http://localhost:3000); the CLI makes it the default when no higher-precedence project or environment setting overrides it
- Seeded `demo-app-ios` / `demo-app-android` for the on-device demo, plus **Example Data** (Staging / Production releases and metrics) so the dashboard looks populated before you publish

You can now [connect your own app](#5-try-it-with-your-own-app), [explore the dashboard](#4-confirm-in-the-dashboard-optional), or [try the demo](#3-watch-an-update-apply-on-device-demo) if you want to see an OTA update on a ready-made app first.

`cmpatch selfhost local-eval status` prints everything else about the stack whenever you need it: the services and their state, the MinIO console, the seeded API token, and a sample publish command.

<details>
<summary>From a clone instead</summary>

If you would rather work from your own clone of the repository, the script the CLI wraps does the same thing (it also needs Node.js `≥ 22.20` and Yarn, and installs `cmpatch` globally itself):

```bash
git clone https://github.com/codemagic-ci-cd/codemagic-patch.git
cd codemagic-patch
./scripts/local-eval/up.sh
```

</details>

:::warning
Evaluation only, not a production install. Authentication is disabled and all ports bind to localhost. To deploy with your own domains, follow [Install](/docs/install).
:::

## 2. Try it with your own app {#5-try-it-with-your-own-app}

You can start here as soon as the stack is running; the demo is optional. To use Patch in your project, wire the SDK against localhost.

  <TabItem value="react-native" label="React Native">

| Config key | Local value |
| --- | --- |
| `CodemagicPatchApiUrl` | `http://localhost:3000` |
| `CodemagicPatchDownloadBaseUrl` | `http://localhost:9100/codemagic-patch` |
| `CodemagicPatchDeploymentKey` | from `cmpatch deployment list` for your app |

Run `cmpatch init --server-url http://localhost:3000` from your project root. The command creates one app per platform (do not reuse `demo-app-*` unless you only need the bundled demo) and links the project. The iOS Simulator can use these localhost URLs directly. For an Android emulator or a USB-connected Android device, keep both URLs above and forward the API and download ports with `adb` (use `-s <serial>` if multiple devices are connected):

```bash
adb reverse tcp:3000 tcp:3000
adb reverse tcp:9100 tcp:9100
```

Repeat the forwarding after restarting the device or adb server. The guided demo handles it automatically. The evaluation stack binds only to your laptop's loopback interface, so replacing localhost with a LAN IP does not make it reachable from an iPhone or another machine. For those devices, use a reachable server from the [Install guide](/docs/install).

:::warning
Android release builds block plain HTTP by default, and OTA updates apply only to release builds. For local evaluation only, add `android:usesCleartextTraffic="true"` to the `<application>` element in `android/app/src/main/AndroidManifest.xml`. Remove it before building for the store.
:::

- [Native setup](/docs/setup/native-setup) for bare React Native or the Expo config plugin
- Coming from Expo Updates: [Migrating from Expo Updates](/docs/migration/migrating-from-expo-updates) (local PoC path first)
- Coming from a CodePush fork: [Migrating from CodePush](/docs/migration/migrating-from-codepush)

  </TabItem>
  <TabItem value="capacitor" label="Capacitor">

Install the Capacitor CLI with `npm install -g @codemagic/capacitor-patch-cli` and the SDK with `npm install @codemagic/capacitor-patch`; see [Native setup](/docs/setup/native-setup-capacitor#install-the-cli-and-the-sdk). Both are 0.x releases, so their API and flags may still change.

Create one app per platform on the local stack and copy each app's `Staging` deployment key. Do not use the `demo-app-*` apps; they belong to the React Native demo.

```bash
cmpatch-capacitor login --server-url http://localhost:3000
cmpatch-capacitor app create --name MyApp-iOS --server-url http://localhost:3000
cmpatch-capacitor app create --name MyApp-Android --server-url http://localhost:3000
cmpatch-capacitor deployment list --app MyApp-iOS --server-url http://localhost:3000
cmpatch-capacitor deployment list --app MyApp-Android --server-url http://localhost:3000
```

To skip `--server-url` in later commands, run `cmpatch-capacitor config set --server-url http://localhost:3000`.

Add the local URLs to `capacitor.config.ts`, with a separate deployment key for each platform:

```ts
plugins: {
  CodemagicPatch: {
    ios: {
      deploymentKey: "<ios-deployment-key>",
      apiUrl: "http://localhost:3000",
      downloadBaseUrl: "http://localhost:9100/codemagic-patch",
    },
    android: {
      deploymentKey: "<android-deployment-key>",
      apiUrl: "http://localhost:3000",
      downloadBaseUrl: "http://localhost:9100/codemagic-patch",
    },
  },
},
```

Run `npx cap sync`. The iOS Simulator can reach these localhost URLs directly. For an Android emulator or a USB-connected device, keep the same URLs and forward the API and download ports with `adb` (add `-s <serial>` if more than one device is connected):

```bash
adb reverse tcp:3000 tcp:3000
adb reverse tcp:9100 tcp:9100
```

Repeat the forwarding after restarting the device or adb server. The evaluation stack binds only to your laptop's loopback interface, so a LAN IP does not make it reachable from an iPhone or another machine. For those devices, use a server set up with the [Install guide](/docs/install).

:::warning
Android blocks plain HTTP by default. For local evaluation only, add `android:usesCleartextTraffic="true"` to the `<application>` element in `android/app/src/main/AndroidManifest.xml`. Remove it before building for the store.
:::

Next, follow [Native setup](/docs/setup/native-setup-capacitor) and [Checking for updates](/docs/setup/checking-for-updates). If you use Appflow Live Updates, see [Migrating from Appflow](/docs/migration/migrating-from-appflow).

  </TabItem>
</SdkTabs>

## Optional: watch an update apply (on-device demo) {#3-watch-an-update-apply-on-device-demo}

  <TabItem value="react-native" label="React Native">

If you would like to try Patch with a ready-made app, run the guided walkthrough:

```bash
cmpatch demo
```

It uses the evaluation checkout, so you do not need a separate clone, a prior `cmpatch login`, or manual dependency installation. If you started the stack from your own clone, run the command inside that clone or pass `--checkout /path/to/codemagic-patch`. Use `--platform ios` or `--platform android` to choose a platform explicitly.

The command checks the demo prerequisites, signs you in to the local stack if needed, installs dependencies, and builds and launches a **Release** app. The first native build can take several minutes. This build boots from its embedded JavaScript bundle, which the OTA update will replace.

1. Look at the running storefront: its product cards should show *"Couldn't load product"* / *"Invalid product response"*.
2. The CLI shows the one-line fix it will make automatically and asks whether to publish it. Approve after you have seen the error. You do not need to edit any source files.
3. The CLI publishes the JavaScript fix, waits for publication, then backgrounds and returns to the same app. On iOS, Settings briefly appears; on Android, the Home screen appears. The app downloads the update and reloads automatically, without rebuilding or reinstalling the native app.
4. Confirm that the product cards now load and **Add to cart** confirms the order. The CLI then offers to open the release in the dashboard.

If automatic app switching fails, follow the CLI's instructions to background the app and bring it back manually. A published release alone does not confirm that the device applied it; check the storefront after it reloads.

For prerequisites, troubleshooting, or the optional walkthrough by hand, see the [on-device demo README](https://github.com/codemagic-ci-cd/codemagic-patch/tree/main/examples/on-device-demo).

  </TabItem>
  <TabItem value="capacitor" label="Capacitor">

`cmpatch demo` runs a React Native app. For Capacitor, use the [example app](https://github.com/codemagic-ci-cd/codemagic-patch/tree/main/client-capacitor/example-app) in the repository, an Ionic + Angular app that uses the SDK. Its README covers checking, downloading, installing, restarting, and crash rollback against the local stack. You can also [connect your own app](#5-try-it-with-your-own-app) and [publish a release](/docs/setup/first-release).

  </TabItem>
</SdkTabs>

## Optional: explore the dashboard {#4-confirm-in-the-dashboard-optional}

Open [http://localhost:8080](http://localhost:8080) and sign in as `local-admin@example.com` to browse **Example Data**, including sample releases and metrics. These sample releases are not downloadable. If you ran the demo, open **demo-app-ios** or **demo-app-android** and its `staging` deployment to see the release you published.

If you have an editable repository clone, you can also sign in with `cmpatch login --server-url http://localhost:3000` and publish the bundled fixture from its root (it uses the seeded `cli-smoke-test` deployment so it does not collide with the on-device demo):

```bash
cmpatch release create \
  --server-url http://localhost:3000 \
  --app demo-app-ios \
  --deployment cli-smoke-test \
  --bundle-path examples/local-dev/bundles/ios-hermes-v1.zip \
  --target-binary-version 1.0.0 \
  --fingerprint local-dev-fingerprint \
  --release-notes "Local quickstart" \
  --yes
```

## Tear down

```bash
cmpatch selfhost local-eval down
```

The stack's data (database and stored bundles) is kept for the next start; add `--delete-data` to remove it too. From a clone, the equivalent is `docker compose -f docker-compose.dev.yml down -v`.

## What you just ran

| Piece | Local value |
| --- | --- |
| Dashboard | `http://localhost:8080` |
| API | `http://localhost:3000` |
| Artifact downloads | `http://localhost:9100/codemagic-patch` |
| Demo apps | `demo-app-ios` / `demo-app-android` (each with `staging`) |
| Demo deployment keys | `dev_local_ios_deployment_key` / `dev_local_android_deployment_key` |
| Fixture publish | `demo-app-ios` / `cli-smoke-test` (`dev_local_deployment_key`) |

:::warning
The seeded API token (`cm_pat_local-dev-token-change-me-00000001`) is for local scripting only. Do not reuse it in production.
:::

## Where to go next

  <TabItem value="react-native" label="React Native">

| Goal | Page |
| --- | --- |
| Install and configure the app SDK | [Native setup](/docs/setup/native-setup) |
| Confirm update behavior on your app | [Verify a test release](/docs/using-patch/verify-test-release) |
| Coming from Expo Updates | [Migrating from Expo Updates](/docs/migration/migrating-from-expo-updates) |
| Coming from a CodePush fork | [Migrating from CodePush](/docs/migration/migrating-from-codepush) |
| Deploy with your own domains | [Install](/docs/install) |

  </TabItem>
  <TabItem value="capacitor" label="Capacitor">

| Goal | Page |
| --- | --- |
| Install and configure the app SDK | [Native setup](/docs/setup/native-setup-capacitor) |
| Confirm update behavior on your app | [Verify a test release](/docs/using-patch/verify-test-release) |
| Coming from Appflow Live Updates | [Migrating from Appflow](/docs/migration/migrating-from-appflow) |
| Deploy with your own domains | [Install](/docs/install) |

  </TabItem>
</SdkTabs>
