---
title: "Create a Patch"
description: "Ship a Dart change to users of an existing release, and list, promote and roll back patches."
---

Once you have published a release of your app, you can push updates using one of the `shorebird patch` commands.

Pre-Patch Checklist

Before running a patch command, review this checklist to ensure your patch compiles and applies cleanly:

* **No Native Code Changes**: Ensure your updates do not touch native platform code (e.g. Kotlin, Swift, or build configurations in `android/` or `ios/`). Native updates cannot be patched.
* **No Asset Changes**: Check that no new images, fonts, or other files have been added or removed in `pubspec.yaml` (asset patching is not yet supported).
* **Flutter Version**: No action needed. `shorebird patch` builds with the Flutter revision the release used, automatically.

**What Shorebird checks automatically:** Before creating a patch, Shorebird compares your local build against the stored release artifacts and warns you (or blocks the upload by default) if it detects native code or asset differences. You can bypass these checks with `--allow-native-diffs` or `--allow-asset-diffs`. If you find yourself needing these flags, it is likely a Shorebird bug or you may be running an old version of `shorebird` — please [reach out](mailto:contact@shorebird.dev) for help.

* Android

  Android

  ```
  shorebird patch android --track=stable
  ```

* iOS

  iOS

  ```
  shorebird patch ios --track=stable
  ```

* Linux

  Linux

  ```
  shorebird patch linux --track=stable
  ```

* macOS

  macOS

  ```
  shorebird patch macos --track=stable
  ```

* Windows

  Windows

  ```
  shorebird patch windows --track=stable
  ```

### Patching multiple platforms simultaneously

If your app supports multiple platforms, you can build and publish patches for them in a single command using the `--platforms` (or `-p`) option:

```
shorebird patch --platforms=android,ios --track=stable
```

This will build and promote the patches for the specified platforms to their respective releases in one step.

This will do several things:

1. Downloads the corresponding release artifacts.
2. Builds the artifacts for the update.
3. Generates a patch using the diff between the release and the current changes.
4. Uploads the patch artifacts to the Shorebird backend.
5. Publishes the patch to the track you pass with `--track` or choose when asked. See [Tracks](/code-push/tracks#publishing-a-patch-to-a-track).

Example output:

```
$ shorebird patch android --release-version 0.1.0+1 --track=stable
✓ Fetching app (0.2s)
✓ Fetching releases (0.1s)
✓ Fetching release artifacts (0.3s)
✓ Fetching aab artifact (0.1s)
✓ Fetching android_supplement artifact (0.1s)
✓ Downloading aab (100%) (1.9s)
Building patch with Flutter 3.47.9 (8352242a91)

Running Gradle task 'bundleRelease'...                             41.2s
✓ Built build/app/outputs/bundle/release/app-release.aab (21.4MB)
✓ Verifying patch can be applied to release (0.4s)
✓ Downloading release artifact 1/3 (100%) (0.5s)
✓ Downloading release artifact 2/3 (100%) (0.5s)
✓ Downloading release artifact 3/3 (100%) (0.5s)
✓ Creating patch artifacts (2.1s)

🚀 Ready to publish a new patch!

📱 App: My App (61fc9c16-3c2b-4a6f-9d1e-2f8a7b5c4d3e)
📦 Release Version: 0.1.0+1
🕹️  Platform: Android [arm32 (161.78 KB), arm64 (166.20 KB), x86_64 (161.51 KB)]
🟢 Track: Stable

✓ Creating patch (93ms)
✓ Uploading artifacts (1.5s)
✓ Fetching channels (86ms)
✓ Promoting patch to stable (78ms)

✅ Published Patch 1!
```

Note

There is no limit on the number of patches you can publish. See [Is there a limit to how many patches you can ship?](/code-push/faq#is-there-a-limit-to-how-many-patches-i-can-ship-per-release) for more details.

Each patch is for one release version. See [Release versions](/code-push/release#release-versions) for how Shorebird uses your app’s version.

To choose the release, pass `--release-version`:

```
shorebird patch android --release-version 0.1.0+1 --track=stable
```

`--release-version latest` targets the most recently updated release for that platform:

```
shorebird patch android --release-version latest --track=stable
```

Without `--release-version`, `shorebird patch` asks you to pick a release when it runs in a terminal. When it can’t ask, as in CI, always pass `--release-version`. Without it, `shorebird patch` builds the app first and reads the release version from the build, and can reuse that build as the patch, without the release’s settings, such as obfuscation. An Android archive (`aar`) or iOS framework for add-to-app has no version to read, so pass the host app’s release version.

In CI, pass the exact version of the release your users have, such as `--release-version 1.0.0+1`, when you might have a newer release that hasn’t shipped yet. `latest` targets the most recently updated release, which may be that newer one.

A patch is built with the Flutter version of its release and can’t change it. Shorebird 1.6.135 and newer warn when that version has a known problem on the platform you’re patching, such as [the iOS crash in Flutter 3.44](/code-push/troubleshooting/#app-crashes-after-a-patch-installs).

If your application supports flavors or multiple release targets, you can specify the flavor and target using the `--flavor` and `--target` options:

```
shorebird patch android --target lib/main_development.dart --flavor development --track=stable
```

Note

`shorebird patch` wraps `flutter build` and can take any argument `flutter build` can. Pass common ones directly, as in `shorebird patch android --dart-define="foo=bar"` or `shorebird patch android --no-tree-shake-icons`. Put any other `flutter build` argument after a `--` separator, as in `shorebird patch android -- <flutter build arguments>`. Shorebird 1.6.136 or older needs the separator for `--no-tree-shake-icons` too. Use the same arguments the release was built with, so the patch builds the same app.

## Options

The options on this page cover most patches: `--release-version`, `--track`, `--platforms`, `--flavor` and `--target`. A few others come up often:

* `--dry-run` (`-n`) builds and checks the patch without uploading it, which is useful in CI.
* `--export-options-plist` points an iOS patch at the same `ExportOptions.plist` as its release.
* `--min-link-percentage` sets how much of an iOS patch’s Dart code must run natively rather than in the interpreter. Shorebird 1.6.135 and newer default to `20`; `0` accepts any patch. See [Link percentage and slow patches](/code-push/performance/#link-percentage-and-slow-patches).
* `--allow-native-diffs` and `--allow-asset-diffs` publish a patch even when Shorebird detects native or asset changes. They’re not recommended: a patch can’t change native code or assets.

Run `shorebird patch --help` for every option.

### Patch performance

#### Android, macOS, Linux and Windows

Patching an application on these platforms has no effect on performance. A patch replaces your app’s compiled Dart code with a newly compiled version, so all of it runs on the CPU as before.

#### iOS

Patching an application on iOS typically does not affect application performance. However, the patching mechanism on iOS is different from other platforms. Unchanged code runs as normal (on the CPU), changed (or added) code will run in a Dart interpreter (slower than the CPU). Typically this change is undetectable, but if you are changing particularly performance-sensitive Dart code (e.g., code for processing images, or large datasets), you may see a performance difference after patching.

You can always test your patches before sending them to users by [staging patches](/code-push/guides/staging-patches). For a detailed look at how iOS patching works, see [System Architecture](/code-push/system-architecture).

If you ever see unexpected performance changes when patching, please [reach out](mailto:contact@shorebird.dev) for help.

***

## Manage patches

You can manage your patches directly from the command line using the `shorebird patches` commands.

### List patches

To list all patches associated with a specific release version:

```
shorebird patches list --release-version 1.0.0+1
```

This will display a list of all patches published for that release, their patch numbers, active status, and tracks.

### View patch details

To view detailed information for a specific patch number:

```
shorebird patches info --release-version 1.0.0+1 --patch-number 1
```

This command shows the patch’s ID, track, whether it is rolled back, any notes, and the size of each platform and architecture artifact.

### Promote a patch

If you published a patch to a staging track (e.g., `staging`) and verified it works correctly, you can promote it directly to the `stable` track using:

```
shorebird patches promote --release-version 1.0.0+1 --patch-number 1
```

`promote` is `set-track` with the track defaulting to `stable`. Older CLIs run the same command but print a deprecation warning, and its `--track`, `--channel`, `--app-id`, and `--json` flags need Shorebird 1.6.130 or newer.

### Set patch track

To assign a patch directly to a specific deployment track (e.g., promoting or routing to a staging beta group):

```
shorebird patches set-track --release-version 1.0.0+1 --patch-number 1 --track staging
```

The `--release-version` and `--patch-number` flags of `set-track` need Shorebird 1.6.128 or newer. On an older CLI, use `--release` and `--patch` instead, or run `shorebird upgrade` first.

### Roll back or roll forward a patch

To stop serving a patch, roll it back. To serve it again later, roll it forward:

```
shorebird patches rollback --release-version 1.0.0+1 --patch-number 1
shorebird patches rollforward --release-version 1.0.0+1 --patch-number 1
```

See [Roll back a Patch](/code-push/rollback#roll-back-from-the-cli) for what happens on devices and the options these commands take.

### Delete a patch

Individual patches can’t be deleted. A patch is removed along with the release it belongs to, or the app that owns that release. Those deletions are permanent, and the console asks you to confirm before anything is removed.

Tip

To stop serving a patch, use [rollback](/code-push/rollback). It remotely uninstalls the patch from end users’ devices, and you can undo it later.

See [Delete Apps, Releases, and Patches](/code-push/delete) for details.
