iOS SDK
The Snapbug iOS SDK is built with Kotlin Multiplatform and distributed as SnapbugSDK.xcframework with a Swift-friendly wrapper. One call installs the full default plugin set: debug feedback overlay, network, analytics, crash reporter, device info, and logs.
Connections work over the Chrome Extension room-code flow (WebRTC, auto-enabled in debug builds) or directly over the local network. Simulators connect to localhost out of the box; physical devices use your machine's LAN IP as serverHost or the room-code flow. Only Apple-silicon simulators are supported (x86_64 simulator slices are excluded).
Installation
Add both lines to your Podfile, then run pod install:
pod 'Snapbug', '~> 0.1.1', :configurations => ['Debug']
pod 'Snapbug-no-op', '~> 0.1.1', :configurations => ['Release']Snapbug-no-op is the release twin: same import Snapbug API, every call inert. Your App Store build then ships neither the inspector nor the overlay, and you never guard the call site. See Release builds.
Initialization
Import the module and call Snapbug.start() once at app startup:
import Snapbug
@main
struct MyApp: App {
// Optional — only needed for the Home Screen quick action (long-press the app icon
// to open the Snapbug menu). Everything else works without it.
@UIApplicationDelegateAdaptor(SnapbugAppDelegate.self) var snapbugDelegate
init() {
Snapbug.start()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}On CocoaPods you do not guard this call — the Release build links the no-op pod and Snapbug.start() does nothing there. If your app already has its own scene delegate, call Snapbug.handleShortcut(_:) from your own quick-action handler instead of adopting SnapbugAppDelegate.
Or with configuration:
import Snapbug
Snapbug.start(config: .init(
serverHost: "192.168.1.42", // LAN IP for physical devices; nil = localhost
screenNameProvider: { MyRouter.currentScreen },
appVersion: "1.0",
catchFatalErrors: true // default
))For UIKit-based apps:
import Snapbug
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
Snapbug.start()
return true
}
}Release builds
Android has always had a no-op twin (snapbug-no-op) that turns the SDK into empty calls in release. iOS now has the same thing: the Snapbug-no-op pod. Same Objective-C surface, same Swift wrapper, every call inert, and module_name is still Snapbug — so import Snapbug compiles in both configurations and your code stays identical.
Declared with :configurations as shown above, this is what an App Store build gets:
| Debug (live) | Release (no-op) | |
|---|---|---|
Snapbug.framework in the bundle | 31 MB | 6.7 MB |
| Overlay shown to end users | yes | no |
| Device registers with the inspector | yes | no |
The 31 MB is the Compose/Skia runtime the overlay is written in — not WebRTC. The published framework contains no WebRTC symbols at all; that transport is a separate snapbug-transport-webrtc module.
Both lines are required. Declaring only pod 'Snapbug', :configurations => ['Debug'] leaves the Release configuration without the Snapbug module, and the build fails to compile.
Supported Features
| Feature | Status | Notes |
|---|---|---|
| Debug Feedback | Supported | Overlay, screenshots, annotations, bug reports — included in the same framework |
| Network (Ktor) | Supported | Install the Snapbug Ktor plugin in your shared KMP HttpClient |
| Analytics | Supported | Forward analytics events from Swift |
| Crash Reporter | Supported | Fatal error capture on by default (catchFatalErrors) |
| Device Info | Supported | Device/OS metadata in the inspector |
| Logs | Supported | Real-time stdout/stderr capture — see below |
| Deep Links | Not installed by default | |
| Database / SharedPreferences / Tables / Files | Not available on iOS |
Logs
Snapbug.start() installs the logs plugin, which captures the process stdout/stderr (Swift print, NSLog), mirrors it back to the Xcode console, and streams every line into the Logs inspector:
print→ levelI, tagstdoutNSLog→ levelW, tagstderr(the standard NSLog date prefix is stripped)os_log/os.Loggerwrite past stdio and are not captured
Network Plugin (Ktor)
To capture network traffic from a Ktor client, install the plugin in your shared Kotlin Multiplatform code:
val client = HttpClient {
install(SnapbugKtorPlugin)
}Analytics
Forward analytics events from Swift:
import Snapbug
SnapbugAnalyticsHelper.shared.sendEvent(
trackerName: "firebase",
eventName: "screen_view",
properties: ["screen_name": "Home"]
)Limitations
- No release twin on SPM —
Snapbug-no-opis a CocoaPods-only pod, because SPM has no equivalent of:configurations. On the SPM path, guardSnapbug.start()with#if DEBUGyourself - KMP naming — the SDK is a Kotlin Multiplatform framework, so some low-level APIs use Kotlin-style naming conventions
- Apple-silicon simulators only —
x86_64simulator slices are excluded (EXCLUDED_ARCHS[sdk=iphonesimulator*] = i386 x86_64)
Sample Project
A complete Swift/SwiftUI sample app is available at sample-ios-swift/ in the repository:
- Build the XCFramework:
./scripts/build-xcframework.sh(runs:debug-feedback:assembleSnapbugSDKReleaseXCFrameworkand copies the result into the Swift package). - Open
sample-ios-swift/SampleApp.xcodeprojin Xcode. - Select an iOS Simulator target, build and run.
Next Steps
- Connect your device
- Troubleshooting for common issues