CircleBox is a native flight recorder SDK for mobile apps.
It captures low-level runtime context into a fixed-size ring buffer and flushes crash-time context to .circlebox files that can be exported as JSON and CSV.
Crash stack traces tell you where a crash happened. CircleBox helps explain what happened before it.
CircleBox records environmental transitions such as memory pressure, thermal changes, connectivity changes, battery state, lifecycle events, and custom breadcrumbs, then preserves the latest timeline around a crash.
- Fixed-size in-memory ring buffer (default: 50 events)
- Crash pre-hook flush to local
.circleboxfile - iOS hard-crash marker capture for signal crashes (
SIGABRT,SIGSEGV,SIGBUS,SIGILL,SIGTRAP,SIGFPE) - Pending crash report detection on next launch
- JSON and CSV export APIs
- Compressed exports (
json_gzip,csv_gzip) and summary export (summary) - Schema v2 canonical export format (snake_case + provenance fields)
- Automatic system signal tracking on iOS and Android
- Binary pending/checkpoint persistence with legacy JSON fallback
- Flutter bridge and chaos sample app
- React Native bridge (bare + Expo prebuild) with automatic JS error hooks
- Companion Sentry/PostHog adapters for iOS, Android, and Flutter
- Companion cloud uploaders with persistent local retry queue + idempotent ingest headers
- Naming guard to enforce
CircleBoxnaming consistency
CircleBox captures these categories in v1:
- Thermal state transitions
- Memory pressure notifications
- Connectivity transitions
- Battery level and low-power mode
- Main-thread contention (jank > configured threshold)
- Permission changes (location/camera)
- Background/foreground lifecycle transitions
- Disk space samples
- Native exception pre-hook event
- Custom breadcrumb events
CircleBox uses a fixed-capacity circular buffer.
- New events append in O(1)
- When capacity is reached, the oldest event is overwritten
- Memory use stays bounded and predictable
On uncaught crash paths:
- CircleBox appends a final
native_exception_prehookevent - Snapshots in-memory events
- Performs atomic file write to
pending/latest.circlebox - Chains to previously installed crash handlers
exportLogs() writes report files to SDK-managed app storage:
- JSON: structured envelope + events
- CSV: flattened event rows for quick inspection/import
ios/CircleBoxSDK- Swift Package implementationandroid/circlebox-sdk- Android/Kotlin library implementationflutter/circlebox_flutter- Flutter bridge pluginflutter/circlebox_adapters- Flutter companion adapters for Sentry/PostHog forwardingreact-native/circlebox-react-native- React Native bridge packagereact-native/circlebox-cloud-react-native- React Native cloud companion uploaderintegrations/ios/CircleBoxIntegrations- iOS companion adaptersintegrations/android/circlebox-integrations- Android companion adaptersios/CircleBoxCloud- iOS cloud companion uploaderandroid/circlebox-cloud- Android cloud companion uploaderflutter/circlebox_cloud_flutter- Flutter cloud companion uploadercloud/circlebox-cloud- Cloud backend workspace (Cloudflare Worker ingest + Supabase metadata + jobs)cloud/dashboard- Cloud website (landing + docs + admin dashboard)samples/ios-chaos-app- iOS sample scaffoldsamples/android-chaos-app- Android sample appsamples/flutter_chaos_app- Flutter chaos validator appsamples/react-native-chaos-app- React Native (Expo prebuild) chaos sampledocs/schema-v1.md- legacy schema referencedocs/schema-v2.md- canonical schema referencedocs/integrations.md- adapter and forwarding integration guidedocs/phase1-closeout.md- Phase 1 acceptance and sign-off checklistdocs/cloud-cli.md- CLI usage for control-plane project/key managementscripts/check_naming.sh- naming guard scriptscripts/check_release_versions.sh- release version alignment guardscripts/check_schema_parity.py- fixture parity contract checkerscripts/decode_persistence.py- pending/checkpoint decoder utilityscripts/cli/circlebox.sh- control-plane CLI.github/workflows- CI workflows
- iOS 13+
- Android API 23+
- Flutter 3.22+ for bridge package
- React Native 0.73+ (bare or Expo prebuild) for RN bridge package
CircleBox release mode is git-tag + release artifacts:
- iOS: Swift Package products from git tag (
CircleBoxSDK,CircleBoxCloud,CircleBoxIntegrations) - Android: GitHub Release AAR assets (
circlebox-sdk,circlebox-cloud) - Flutter: Git dependency with monorepo
path - React Native: GitHub Release
.tgzpackages
See cloud/dashboard/content/docs/release-matrix.mdx for full install matrix.
CircleBox supports three production operating modes:
- Offline only (no network, no keys)
- Core + CircleBox cloud (managed ingest + dashboard)
- Core + self-host backend (optional aggregate usage beacon)
Control-plane onboarding:
- UI:
/signup,/app/onboarding,/app/projects/<project_id>/keys - CLI:
scripts/cli/circlebox.sh(seedocs/cloud-cli.md)
Add one package dependency (root URL):
.package(url: "https://github.com/jeremiahseun/circle-box.git", from: "0.3.1")Select CircleBoxSDK (and optionally CircleBoxCloud, CircleBoxIntegrations) from that single package reference.
Add CircleBoxSDK to your app, then call:
import CircleBoxSDK CircleBox.start(config: .default) CircleBox.breadcrumb("User started Checkout", attrs: ["flow": "checkout"]) if CircleBox.hasPendingCrashReport() { let files = try CircleBox.exportLogs(formats: [.json, .csv]) print(files) }Signal crash capture is enabled by default on iOS and can be disabled:
CircleBox.start(config: CircleBoxConfig(enableSignalCrashCapture: false))Include circlebox-sdk in your app build, then call:
import com.circlebox.sdk.CircleBox import com.circlebox.sdk.CircleBoxExportFormat CircleBox.start() CircleBox.breadcrumb("User started Checkout", mapOf("flow" to "checkout")) if (CircleBox.hasPendingCrashReport()) { val files = CircleBox.exportLogs(setOf(CircleBoxExportFormat.JSON, CircleBoxExportFormat.CSV)) println(files) }Use the bridge API:
import 'package:circlebox_flutter/circlebox_flutter.dart'; await CircleBox.start(); await CircleBox.breadcrumb('User started Checkout', attrs: {'flow': 'checkout'}); if (await CircleBox.hasPendingCrashReport()) { final files = await CircleBox.exportLogs( formats: { CircleBoxExportFormat.json, CircleBoxExportFormat.csv, CircleBoxExportFormat.jsonGzip, CircleBoxExportFormat.csvGzip, CircleBoxExportFormat.summary, }, ); print(files); }You can increase ring-buffer depth from Flutter:
await CircleBox.start(config: const CircleBoxConfig(bufferCapacity: 200));Use the React Native bridge package:
import { CircleBox } from 'circlebox-react-native'; await CircleBox.start({ bufferCapacity: 200, enableDebugViewer: true, installReactNativeErrorHooks: true, }); await CircleBox.breadcrumb('User started Checkout', { flow: 'checkout' }); if (await CircleBox.hasPendingCrashReport()) { const files = await CircleBox.exportLogs(['json', 'csv', 'summary']); console.log(files); }CircleBox.start(config:)CircleBox.breadcrumb(_:attrs:)CircleBox.exportLogs(formats:) -> [URL]CircleBox.hasPendingCrashReport() -> BoolCircleBox.clearPendingCrashReport()
CircleBox.start(config)CircleBox.breadcrumb(message, attrs)CircleBox.exportLogs(formats) -> List<File>CircleBox.hasPendingCrashReport() -> BooleanCircleBox.clearPendingCrashReport()
CircleBox.start(config)CircleBox.breadcrumb(message, attrs)CircleBox.exportLogs(formats) -> List<String>CircleBox.hasPendingCrashReport() -> boolCircleBox.clearPendingCrashReport()
CircleBox.start(config?)CircleBox.breadcrumb(message, attrs?)CircleBox.exportLogs(formats?) -> Promise<string[]>CircleBox.hasPendingCrashReport() -> Promise<boolean>CircleBox.clearPendingCrashReport() -> Promise<void>
See docs/schema-v2.md for canonical schema details and docs/schema-v1.md for legacy reference.
Key fields:
- Envelope:
schema_version,session_id,platform, app/device metadata,export_source,capture_reason,events[] - Event:
seq,timestamp_unix_ms,uptime_ms,type,thread,severity,attrs
CSV columns:
- Metadata row:
meta,schema_version,export_source,capture_reason,session_id,platform,generated_at_unix_ms - Event row:
seq,timestamp_unix_ms,uptime_ms,type,thread,severity,attrs_json
cd samples/android-chaos-app gradle :app:installDebugcd samples/ios-chaos-app xcodegen generate open CircleBoxChaosApp.xcodeprojWorker-first cloud deployment helpers:
scripts/check_data_plane_schema.shscripts/deploy_cloud_worker.shscripts/smoke_test_worker_ingest.shscripts/deploy_phase3_cloud.shscripts/release_check.sh
Release runbook:
docs/release/deploy-today.mddocs/usage-beacon-validation.md
Manual flow:
- Trigger multiple mock chaos events
- Trigger hard crash
- Relaunch app
- Detect pending report and export JSON/CSV
- Verify event sequence near crash
bash scripts/check_naming.shbash scripts/check_release_versions.sh 0.3.1cd ios/CircleBoxSDK swift testcd flutter/circlebox_flutter flutter analyze flutter testcd flutter/circlebox_adapters flutter analyze flutter testIf gradle is installed:
cd android/circlebox-sdk gradle test gradle assembleReleasepython3 scripts/check_schema_parity.pybash scripts/release_check.shPublic registry publish runbook:
docs/release/public-registries.md
Optional smoke flags for release check:
CIRCLEBOX_WORKER_BASE_URLCIRCLEBOX_SMOKE_INGEST_KEYDASHBOARD_WORKER_TOKEN(optional, enables download-flow validation)
python3 scripts/decode_persistence.py /absolute/path/to/latest.circleboxnaming.yml- naming policy enforcementios.yml- Swift build/test + artifact uploadandroid.yml- Gradle test/release assemble + AAR uploadflutter.yml- Flutter plugin + adapters + chaos sample analyze/testsreact-native.yml- React Native bridge and sample typecheckschema-parity.yml- schema-v2 fixture contract checkscloud.yml- Phase 3A cloud/backend/uploader checksrelease.yml- tag-driven multi-platform release assets + checksum manifest
- Attribute sanitization is enabled by default
- Common sensitive patterns are redacted
- Long attribute values are truncated
- No network transfer is performed by default
CircleBox naming is enforced repository-wide.
Run:
bash scripts/check_naming.shMigration notes live in docs/migration.md.
MIT