# Apple {#bundle-insights-apple}

Analyze an Apple bundle by pointing `tuist inspect bundle` at an archive, an installable, or a built app:

::: code-group
```bash [Analyze an .ipa]
tuist inspect bundle App.ipa
```
```bash [Analyze an .xcarchive]
tuist inspect bundle App.xcarchive
```
```bash [Analyze an app bundle]
tuist inspect bundle App.app
```
```bash [Analyze by app name]
tuist inspect bundle App --platforms ios --configuration Debug
```
<!-- -->
:::

When you pass an app name instead of a path on macOS, Tuist resolves the built `.app` from Xcode's build products (honoring `--derived-data-path` when set), the same way `tuist share` does.

The command uploads the bundle to Tuist and returns a link to a detailed overview, including a scan of the contents and a module breakdown:

![Analyzed bundle](/images/guides/features/bundle-size/analyzed-bundle.png)

## Comparing with App Store Connect {#app-store-connect}

Tuist measures the bundle exactly as you provide it and does not apply [app thinning](https://developer.apple.com/documentation/xcode/reducing-your-app-s-size). The reported sizes correspond to the **universal** (unthinned) variant — the row labeled "Universal" in App Store Connect's app file sizes report — not the per-device variants.

Expect the numbers to be in the same range as the Universal row, but not identical:

- **Install size** is close to the Universal install size. App Store Connect reports a slightly higher value because it includes on-device overhead, such as filesystem block allocation and Apple's own estimation, that a raw file-size measurement does not capture.
- **Download size** is lower than the Universal download size. Apple encrypts the app binary after upload, and encrypted data compresses less efficiently, so the App Store's compressed download ends up larger than the `.ipa` archive Tuist measures. This happens on Apple's side after upload, so it is not reflected in Tuist's number.

The per-device rows in App Store Connect are smaller again, because app thinning removes CPU architectures and asset variants that a specific device does not need. Tuist does not currently report per-device (thinned) sizes.

## Understanding bundle sizes {#understanding-sizes}

For every analyzed bundle, Tuist reports two values:

- **Install size**: the space the app takes up once installed on a device.
- **Download size**: the compressed size users download. For Apple bundles this is only reported for `.ipa` (the size of the archive); for `.xcarchive` or `.app` inputs it is not available.

Sizes are stored in bytes and displayed using the decimal convention, where 1 MB is 1,000,000 bytes and 1 GB is 1,000,000,000 bytes — the same convention Apple uses to report storage and app sizes (see [How storage capacity is measured on Apple devices](https://support.apple.com/en-us/102119)). An install size of 733,446,863 bytes shows as 733.4 MB.

## Continuous integration {#continuous-integration}

To track bundle size over time, analyze the bundle on CI. First, make sure your CI is <.localized_link href="/guides/integrations/continuous-integration#authentication">authenticated</.localized_link>.

Tuist also needs to know which project to report the bundle to. If you have not connected the project yet, run `tuist init`, or declare the handle yourself:

::: code-group
```swift [Tuist.swift]
let tuist = Tuist(fullHandle: "my-account/my-project")
```
```toml [tuist.toml]
project = "my-account/my-project"
```
<!-- -->
:::

Use <.localized_link href="/references/tuist-toml">`tuist.toml`</.localized_link> for projects without a Swift manifest, such as Gradle projects. When both files are present, `Tuist.swift` takes precedence.

An example GitHub Actions workflow:

::: code-group
```yaml [Apple]
name: Build

jobs:
  build:
    steps:
      - # Build your app
      - name: Analyze bundle
        run: tuist inspect bundle App.ipa
        env:
          TUIST_TOKEN: ${{ secrets.TUIST_TOKEN }}
```
```yaml [Android]
name: Build

jobs:
  build:
    steps:
      - # Build your app
      - name: Analyze bundle
        # .aab is recommended over .apk for more accurate size analysis
        run: tuist inspect bundle App.aab
        env:
          TUIST_TOKEN: ${{ secrets.TUIST_TOKEN }}
```
<!-- -->
:::

Once set up, you can see how your bundle size evolves over time:

![Bundle size graph](/images/guides/features/bundle-size/bundle-size-graph.png)

## Pull/merge request comments {#pullmerge-request-comments}

> [!WARNING]
> **Integration With Git Platform Required**
>
> To get automatic pull/merge request comments, integrate your <.localized_link href="/guides/server/accounts-and-projects">Tuist project</.localized_link> with a <.localized_link href="/guides/server/authentication">Git platform</.localized_link>.

Once your Tuist project is connected with your Git platform such as [GitHub](https://github.com), Tuist will post a comment directly in your pull/merge requests whenever you run `tuist inspect bundle`:

![GitHub app comment with inspected bundles](/images/guides/features/bundle-size/github-app-with-bundles.png)

## Size thresholds {#size-thresholds}

> [!WARNING]
> **Integration With Git Forge Required**
>
> To use size thresholds, connect the [Tuist GitHub App](https://github.com/apps/tuist) to your project. You can do this from your project's integrations page.

Size thresholds let you block pull requests when the bundle size increases beyond a configured percentage or absolute size compared to a baseline branch. When a threshold is violated, Tuist creates a GitHub Check Run on the PR commit, blocking the merge until the size increase is resolved:

![PR status check showing bundle size threshold exceeded](/images/guides/features/bundle-size/github-pr-check-status.png)

The check run shows the baseline size, current size, and change in the configured unit. If the increase is intentional, you can accept it directly from the GitHub UI by clicking the **Accept** button:

![GitHub check run showing threshold violation](/images/guides/features/bundle-size/github-check-run-threshold.png)

### Configuration {#size-thresholds-configuration}

To configure thresholds, go to your project's **Settings > Bundles** tab:

![Bundle size thresholds settings](/images/guides/features/bundle-size/bundle-size-thresholds.png)

Choose **Install size** or **Download size**, then select a **Threshold type**:

- **Percentage (%)**: limit growth relative to the baseline size. Fractional percentages such as `0.47` are supported. Existing percentage thresholds keep their configured values and behavior.
- **Absolute size (MB)**: limit growth by a fixed amount, independent of the baseline size. Enter `1.5` to allow up to 1.5 MB of growth. MB uses decimal units: 1 MB = 1,000,000 bytes. Values must resolve to a positive whole number of bytes.

![Absolute bundle size growth threshold configuration](/images/guides/features/bundle-size/absolute-size-threshold.png)

Both types compare against the latest matching bundle on the configured **Baseline branch**. The optional **Bundle name** restricts a rule to that bundle. A check fails only when growth is **more than** the limit; equal growth, unchanged sizes, and decreases pass. Without a matching baseline or a recorded size for the chosen metric, the rule is skipped. A zero-size baseline is supported for absolute limits; percentage limits keep skipping it because percentage growth is undefined.

### Restricting who can accept {#size-thresholds-approvals}

By default anyone with write access to the repository can accept a size increase, because that is who GitHub shows the button to. To narrow it, set **Who can accept** under **Settings > Bundles**:

- **Anyone**: the default. Anyone with write access to the repository.
- **Selected GitHub users**: only the GitHub usernames you add.

Someone not on the list leaves the check failing with an explanation, and the button stays for whoever can use it.


