Skip to main content

Build size analysis (iOS)

Bugsee Build Size Analysis turns app size into a first-class CI signal alongside crashes, ANRs, and session replay. It ships in two layers, configured independently, and works on both iOS and Android — this page covers the iOS setup; see the Android counterpart for parity.

The whole flow runs inside the same BugseeAgent post-action that already uploads dSYMs. You don't need a second build phase; you just turn the right environment variables on.

Requires Bugsee iOS SDK 6.1.5 or newer

Build info, size analysis, the in-build size check, and chunked upload all ship together in 6.1.5 (release notes). Earlier versions only ship the dSYM upload half of the post-action and silently ignore the size-related env vars.

Two layers

Build infodefault ON, Release-only. Every Archive registers a small metadata record with Bugsee: bundle id, marketing version, build number, configuration, VCS context (commit, branch, base branch, PR, repo), build timings, machine label, Xcode + SDK versions, raw IPA byte count, and the main executable's Mach-O LC_UUID. No IPA bytes are sent on this path. The record unlocks crash-context enrichment, build-history navigation in the dashboard, and the baseline lookup the size-check feature uses.

The Mach-O LC_UUID is the same identifier the runtime SDK reports with every crash (see BGSCrashReport.m), so every crash report deterministically joins to the build that produced it without any Info.plist injection or pre-build phase.

Size analysisdefault OFF, sub-feature of build info. Opt in via one env var and the same post-action additionally uploads the IPA for server-side analysis: download vs install size, per-category breakdown (executable, embedded frameworks, resources, assets, Swift runtime), and per-file diffs against the prior build.

Quick start

If the BugseeAgent post-action is already wired up for dSYM upload, you're one env var away:

  1. Open Product → Scheme → Edit Scheme, select the Archive action on the left.
  2. Expand Arguments → Environment Variables.
  3. Click + and add BUGSEE_SIZE_ANALYSIS_ENABLED with value 1.
  4. Archive the app. The dashboard's Builds tab will show the size breakdown for the new archive.

If you don't yet have the post-action, follow the dSYM upload setup in Crash symbolication → Auto dSYM upload first — the same script handles size analysis once the env var is set.

AI-assisted setup

If you use a local AI coding assistant (Claude Code, Cursor, GitHub Copilot, Windsurf, …), paste the prompt below into it. The agent inspects your .xcodeproj, finds the right scheme, adds the post-action, and walks you through each optional tweak interactively — you say yes/no per option, the agent shows you the resulting <EnvironmentVariables> block after each change, and you can skip straight through if none apply. End-to-end takes about 90 seconds.

Hand the whole page to your AI agent

Use the View as markdown option in the drop-down menu at the top of this page to grab the raw markdown source. Paste that into your AI assistant and it has the prompt — plus the surrounding context — without any copy-paste from the code block below.

Don't paste the app token into the prompt

The prompt deliberately asks the agent to prompt you for the app token rather than guess. Don't substitute the literal token in the text you paste — agents that log conversations may surface it later in transcripts or shared training data.

Add a Bugsee post-action to my iOS project, then walk me through
optional tweaks.

PART 1 — required setup
========================

1. Find the active app scheme. Look under
`*.xcodeproj/xcshareddata/xcschemes/` or
`*.xcworkspace/xcshareddata/xcschemes/`. Pick the scheme that
archives the main app target.

2. In that scheme, add a Run Script post-action under the Archive
action. Set "Provide build settings from" to the main app target
(without that, the script has no `$ARCHIVE_PATH` /
`$CONFIGURATION` and silently skips). The script body:

SCRIPT_SRC=$(find "$PROJECT_DIR" -name 'BugseeAgent' | head -1)
if [ ! "$SCRIPT_SRC" ]; then
echo "Error: BugseeAgent not found"
exit 1
fi
python3 "$SCRIPT_SRC" <APP_TOKEN> >> /tmp/BugseeAgent.txt

For Swift Package Manager integrations, replace the `find` line
with:
`SCRIPT_SRC="$BUILD_DIR/../SourcePackages/checkouts/spm/Tools/BugseeAgent"`.

3. Ask me for my Bugsee app token before substituting
`<APP_TOKEN>` — do not guess. Don't ask me to paste the token into
our conversation if I have a more private channel; ask me to put
it in directly. The scheme file lives in
`xcshareddata/xcschemes/*.xcscheme`.

Note: `BUGSEE_BUILD_INFO_ENABLED` is ON by default — do NOT set it
explicitly anywhere.

PART 2 — optional tweaks
========================

Now walk me through each option below ONE AT A TIME. For each option:

a. Read me the full description so I know what it does and why I
might want it. Don't summarise — read it as written.
b. Ask yes/no.
c. If no, move on without editing anything.
d. If yes, apply the change and show me the updated
`<EnvironmentVariables>` block from the scheme XML before
moving to the next option.

All env-var edits go to the same scheme, Archive → Arguments →
Environment Variables (each as a separate row in the
`<EnvironmentVariables>` element) — NOT to the script body. This
keeps them toggleable from Xcode's UI later. Leave any existing
rows untouched.

When all six options are done, summarise what changed (or say
"no changes" if I said no to everything).

----------------------------------------------------------------------
Option 1 — Also upload the IPA for size analysis

What it does: Without this, the post-action only registers a build
record (version, configuration, VCS context — "build info"). With
this, the IPA itself is uploaded and analysed for download size,
install size, category breakdown, and per-file diffs.

When you want it: You actually want size analysis on the Bugsee
dashboard. Almost certainly say yes here, unless you're just
registering builds for crash-context lookup and don't care about
size.

When you skip it: You only want build registration for
symbolication / crash-context lookup, not full size analysis.

If yes: add `BUGSEE_SIZE_ANALYSIS_ENABLED=1`.

----------------------------------------------------------------------
Option 2 — Register every Xcode action

What it does: By default the post-action only runs on the Archive
action. This makes it run on every action — Build & Run,
`xcodebuild build`, plain test runs — so every CI build registers
a build record.

When you want it: You want crash-context lookup to cover non-Archive
CI runs (e.g. integration tests against a Debug build), so any
crash report from any build can be matched to a known build record.

When you skip it: You only ever care about release builds, or CI
bandwidth/quota is a concern.

Caveat — make sure I understand BEFORE applying: Debug `.app`s are
unsigned and unthinned, so their `artifact_size` is NOT comparable
to a Release archive. If size analysis is also on (option 1),
Debug builds will look much larger and skew any size diffs. Tell me
this explicitly and let me reconsider.

If yes (after I confirm): add `BUGSEE_BUILD_INFO_ALL_ACTIONS=1`.

----------------------------------------------------------------------
Option 3 — Register non-Release configurations

What it does: By default only configurations matching `release*`
(case-insensitive) are registered. This includes Debug and any
custom configurations as well.

When you want it: You ship more than just `Release` (e.g. an
`AdHoc` or `Internal` configuration) and want those builds to show
up on the dashboard too.

When you skip it: Standard Release-only workflow, or you don't
want Debug noise in your build list.

If yes: add `BUGSEE_BUILD_INFO_ALL_CONFIGURATIONS=1`.

----------------------------------------------------------------------
Option 4 — In-build size regression check

What it does: Compares each build's `artifact_size` against the
most-recent prior build of the same configuration. Crossing the
warning threshold emits a `warning:` log line; crossing the fail
threshold emits an `error:` line AND exits the post-action
non-zero (which fails the build on CI). Either gate is
independently optional — `0` or omitting it disables that gate.

When you want it: You want a guardrail that catches size
regressions before they ship — especially on PR pipelines so
reviewers see "this PR adds +4% download size" alongside test
results.

When you skip it: You're still establishing a baseline (the very
first few builds), or you'd rather watch size on the dashboard than
block CI on it.

Caveat: the script runs as a detached daemon — its `error:` line
lands in `$PROJECT_TEMP_DIR/BugseeAgent.log`, NOT the
`xcodebuild` build log. CI runs that need hard gating need to grep
that file. Mention this when I say yes.

If yes: ask me for the warning percentage (default 5.0) and the
fail percentage (default 10.0) — either can be `0` to disable.
Then add:
BUGSEE_SIZE_CHECK_ENABLED=1
BUGSEE_SIZE_CHECK_WARNING_PCT=<value> (if non-zero)
BUGSEE_SIZE_CHECK_FAIL_PCT=<value> (if non-zero)

Absolute-byte variants (`BUGSEE_SIZE_CHECK_WARNING_BYTES`,
`BUGSEE_SIZE_CHECK_FAIL_BYTES`) exist as an alternative — do NOT
add those unless I explicitly ask for byte-based gating.

----------------------------------------------------------------------
Option 5 — Speed up CI with chunked upload

What it does: The IPA is split into 8 MiB content-addressed chunks
and only the chunks that actually changed since the prior build are
re-uploaded. The Bugsee server stitches them back into a complete
IPA — transparently to the rest of the pipeline.

When you want it: Your CI runs frequently and most builds are
incremental — typically cuts upload time by 70–90% on subsequent
builds. The big win is on long pipelines where upload bandwidth
dominates. Only meaningful with `BUGSEE_SIZE_ANALYSIS_ENABLED=1`
(option 1) — build-info-only has nothing to chunk.

When you skip it: One-off / infrequent builds, or you'd rather
stick with the simpler single-PUT path until you've validated
chunked end-to-end in your environment.

Safety: any failure in the chunked path falls back to single-PUT
on the same build, so enabling this can't break uploads.

If yes: add `BUGSEE_CHUNKED_UPLOAD=1`. Mention to me that the
feature only engages when size analysis is also on.

----------------------------------------------------------------------
Option 6 — Verbose logging

What it does: Echoes the metadata POST URL (with the app token
masked) and the full payload into
`$PROJECT_TEMP_DIR/BugseeAgent.log`.

When you want it: You're diagnosing "why didn't my build register?"
and want to see exactly what was sent.

When you skip it: Steady-state CI — the log is noisier than useful.

If yes: add `BUGSEE_SIZE_ANALYSIS_DEBUG=1`.

----------------------------------------------------------------------

Verify by running `xcodebuild archive` once after the change. You
should see a `Bugsee: build upload complete` line in
`$PROJECT_TEMP_DIR/BugseeAgent.log`. Don't run it yourself — I'll
do it when I'm ready.

In-build size check

A CI guardrail that prints an error: line and fails the post-action when the IPA grows beyond a configured threshold versus the previous archive for the same (package_id, format, build_configuration) tuple. Configured via env vars on the same scheme:

BUGSEE_SIZE_CHECK_ENABLED=1
BUGSEE_SIZE_CHECK_WARNING_PCT=5.0
BUGSEE_SIZE_CHECK_FAIL_PCT=10.0
# BUGSEE_SIZE_CHECK_WARNING_BYTES=500000
# BUGSEE_SIZE_CHECK_FAIL_BYTES=2000000

Rules the check follows:

  • Each gate (warn / fail, percent / bytes) is independently optional — 0 or unset disables it.
  • Negative deltas never trigger. An archive that shrunk vs the baseline always PASSes.
  • Fail wins over warn at the same severity; percent is checked before bytes when both fire at the same severity.
  • The baseline is scoped to the same build_configurationRelease is never compared to Debug.
iOS asymmetry — error visibility

Post-action error: lines surface in $PROJECT_TEMP_DIR/BugseeAgent.log, not the xcodebuild build log — Xcode doesn't retroactively fail an already-signed Archive from a post-action. CI runs that need hard gating on size growth should grep the daemon log for the error: Bugsee size check prefix and fail the pipeline explicitly.

Fast CI: chunked upload

When enabled, the agent splits the IPA into 8 MiB content-addressed chunks, asks the server which chunks it already has, and uploads only the missing ones — typically cutting upload time by 70–90% on incremental CI runs.

BUGSEE_CHUNKED_UPLOAD=1

BUGSEE_CHUNKED_UPLOAD has no effect when BUGSEE_SIZE_ANALYSIS_ENABLED is off — the build-info-only path carries no bytes to chunk. Any failure in the chunked path falls back to the single-PUT upload automatically, so flipping the switch can't break CI.

What you'll see in the dashboard

  • Per-app size history chart. Download vs install size over time, grouped by configuration.
  • PR-time size delta. When the build's VCS context resolves a PR number, the dashboard threads builds together so you can see "+4.2% download size since main" alongside the test results.
  • Per-file diff view. For each Archive, the breakdown of which files grew, which shrank, and by how much — both in absolute bytes and percentage.
  • Crash join. Each build's record carries the same LC_UUID the SDK reports with every crash, so the dashboard ties every report deterministically to the build that produced it.

See also