Start here
What's new
What changed recently, and what changes when you upgrade. Published releases come first. After them are the changes already in the SDK repositories that ship with the next SDK and CLI releases. Read those before you upgrade, because several of them change defaults.
Published
2 November 2026
- Flutter adapter packages are on pub.dev.
bug_capsule_firebase,bug_capsule_geolocator,bug_capsule_google_maps,bug_capsule_stripeandbug_capsule_shorebirdare published as0.1.0-dev.1. They needbug_capsule ^0.4.1-beta.10. See adapter packages and the Shorebird adapter. - Dashboard: verdict v2 results on runs. Runs show Fixed (qualified) and Unsafe badges and say why such a run doesn't count as fixed. A v2 Fixed run shows the baseline behind it, for example "Baseline 3/3 reproduced on abc1234". A Fixed run judged with the old rules says so. See verdict v2.
1 November 2026
- Flutter
0.4.1-beta.10, the standalone CLI0.4.1-beta.10(npm installer@bugcapsule/cli 0.4.0-beta.5), Flutterbug_capsule_patch 0.1.0-dev.1and iOS0.4.1-beta.5: signed patch runtime and patch CLI commands (signed patch engine), guard decisions recorded into capsules (emergency recovery).
Coming in the next SDK and CLI releases
Not published yet. Everything in this section is in the SDK repositories but not in any release on pub.dev, Maven Central, Swift Package Manager or npm. The current releases are Flutter 0.4.1-beta.10, Android 0.4.1-beta.6, iOS 0.4.1-beta.5 and web 0.4.0-beta.4, and they behave as the rest of these docs describe. The Flutter, Android, iOS and web releases share test fixtures and the capsule and verdict specs, so upgrade the SDK, the CLI and @bugcapsule/web-replay together.
Stricter verdicts (verdict v2)
verify, regress run and gate report FIXED only when the capsule's own commit reproduced the failure every time (the baseline), enough attempts on your build ran cleanly, and each clean attempt shows the failing path ran. Two new verdicts appear: FIXED (QUALIFIED) (exit 4) and UNSAFE (exit 5). Add BugCapsule.expect(…) postconditions to flows whose capsules come from exceptions. The full rules are under verdict v2.
Privacy defaults
- No request or response bodies in production by default. Production mode keeps method, URL, status, headers and timing. Debug and QA modes still record (redacted) bodies. Set
captureNetworkBodies: trueto keep bodies in production. An explicit value always wins over the mode, and your project's capture settings can turn bodies off but never on. On Android and iOS the option becomes optional (Boolean?/Bool?), which breaks code that reads it as a plain boolean. - Binary bodies are recorded as size and content type only, in every mode, unless you opt in: Flutter
maxBinaryByteson the Dio or http integration, AndroidBugCapsuleOkHttp(captureBinaryBodies = true), iOScaptureBinaryBodies: true, webnetworkIntegration({ captureBinaryBodies: true }). - A capsule without bodies still replays. Responses come back with their recorded status, headers and latency and an empty body, the attempt reports
network.noBody, and eligibility listsnetwork.bodies. - Android SQLite spans replace SQL literals with
?. - Redaction removes every BugCapsule credential format from free text, including SDK tokens, CLI tokens and keys, wherever they appear in logs, messages or bodies. The web SDK also redacts more key names (
pwd,pass,csrf,refresh,access) and headers (X-Session,Authentication). Form-encoded bodies follow the URL parameter rules, which changes request keys for form posts with fields such ascodeorsession.
Consent and local data
Flutter, Android and web add collectionEnabled in the config, a persisted setCollectionEnabled(…) consent switch and clearLocalData(). Saved captures expire after 7 days. Android keeps its files out of Auto Backup, and Flutter on iOS can exclude them from backups with bug_capsule_native. The iOS SDK follows in a later release. See consent and local data.
Project settings can only narrow capture
- Trace propagation targets from your project's settings can only remove destinations from the list in your app. They are matched as plain substrings, never as regular expressions. If you set trace targets only in the dashboard, list those destinations in
tracePropagationTargetsin the app. - The capsule size limit from project settings is capped at 50 MiB. Android also caps a server
Retry-Afterat 24 hours. - Plain
http://is refused in SDK tokens and explicit backend settings, except tolocalhost,127.0.0.0/8,[::1]and the Android emulator's10.0.2.2. A project secret key (bcs_…) in an app is refused. A refused setup never crashes the app: it runs without capture or uploads, and the status API says why (iOS:invalid_backend). For a backend on your LAN, use https,adb reverseor a tunnel.
Storage restore follows the capture policy
Capsules record which storage keys their capture allowed (manifest.storagePolicy). Replay writes only those keys, further narrowed by the replayed build's own allowlist, and reports every other key as the material divergence restore.disallowed. Android also validates SharedPreferences and DataStore names and refuses paths outside the app's storage directories. Capsules recorded by older SDKs have no policy and replay without storage restoration.
Replay safety
- Web: replay network is deny by default. From the app's origin the page may only load static resources with
GET/HEAD. Every other request, real WebSocket, beacon,EventSource, form post or worker request is blocked and reported asnetwork.escaped. A dev server's live-reload socket is blocked too, so replay against a production-style build.--allow-live <url substring>lets matching requests through for debugging and makes the run UNSAFE. Release@bugcapsule/web-replaywith the matching@bugcapsule/web. - Flutter: replay fails closed. When replay can't start (fetch, schema or preflight failure), the app shows a short screen with the reason instead of running live. Replay runs only in debug builds, or in profile builds compiled with
--dart-define=BUGCAPSULE_ALLOW_PROFILE_REPLAY=true. - A result printed on stdout counts only when it carries the armed attempt's random id, so logged text can't complete an attempt.
Startup and memory
- Android
initdoes no disk I/O on the calling thread.BugCapsule.isRecordingturns true shortly afterinit. Events, logs and scope changes made in between are kept (up to 256 of each) and applied once ready.captureExceptionandcaptureMessagereturnnullduring startup and send the event afterwards. Transactions started during startup aren't traced. - The in-memory recorder has a byte budget: Android
maxRetainedBytesand webmaxRecorderBytes, both 8 MiB. Over it, the oldest HTTP bodies and interaction payloads are dropped first, then the oldest events, and capsules listcapture.truncated.
CLI
verifybuilds the capsule's commit first (--baseline-runs, default 3) and raises--runsto what the baseline requires. New flags:--accept-qualified,--verdict-v1, andgate --fail-on unverified.- The CLI no longer writes, runs or opens anything a capsule or server chose. Capsule file names are validated. Pinned worktrees live under
~/.bugcapsule/pins(owner-only) and are reused only for the same commit. Downloads are capped at 256 MiB, with a 60-second stall limit. Saved credentials are written owner-only. Browser login opens only an https page on your BugCapsule site. - Web
sourcemaps inject/uploadfollow only.mapfiles inside the input directory, and warn when the secret key is passed as--key. UseBUGCAPSULE_SECRET_KEYinstead.
Upgrade checklist
- Decide whether production needs bodies, and set
captureNetworkBodiesexplicitly if it does. On Android and iOS, update code that reads it as a boolean. - Move trace propagation targets you set only in the dashboard into the app config.
- Replace plain-http LAN backends with https,
adb reverseor a tunnel. - Add
BugCapsule.expect(…)postconditions for key flows, so fixes can reach FIXED instead of FIXED (QUALIFIED) or INCONCLUSIVE. - Update CI: treat exit codes 4 and 5, decide on
--accept-qualifiedand--fail-on unverified, and make sure CI can check out the capsule's commit for the baseline. - Wire your consent screen to
setCollectionEnabledand your "delete my data" action toclearLocalData(). - Web: replay against a production-style build, and upgrade
@bugcapsule/weband@bugcapsule/web-replaytogether. - Flutter: add the profile replay dart-define if you replay profile builds.