Get started

iOS quickstart

The by-hand iOS quickstart — add the Extentos Swift package, set the Info.plist keys, initialize, and make your first capability call.

The Extentos iOS SDK installs from github.com/extentos/swift-glasses via Swift Package Manager — .package(url: "https://github.com/extentos/swift-glasses", from: "2.1.2") (current version on the install page). This page is the by-hand path; the agent-driven flow automates every step below.

1. Add the package

In Xcode: File → Add Package Dependencies…https://github.com/extentos/swift-glasses → dependency rule Up to Next Major Version, starting at 2.0.0. Link GlassesCore; add GlassesUI only if you render the packaged connection page (a voice app doesn't). Other manifest forms: Install. Requirements: the Swift 6 toolchain, Meta DAT (meta-wearables-dat-ios) 0.8.0+ (resolved transitively), and deployment target iOS 16.0+ — or 17.0+ if you add GlassesLocal for on-device models. Pick 17 up front if that's anywhere in your plan.

2. Add the Info.plist keys

Which keys you need depends on your path — see choose your path.

Voice apps need the privacy strings your capabilities imply — NSMicrophoneUsageDescription and NSSpeechRecognitionUsageDescription — plus UIBackgroundModes: ["audio"] if the assistant must keep listening while your app is backgrounded, plus the two Extentos keys EXTENTOS_APP_ID and EXTENTOSProjectKey. No Meta keys and no Meta Developer account. The project key is not a Meta credential: it's how a debug build on a real iPhone authenticates to the managed gateway, and an assistant app without it fails at runtime with AssistantError.NoApiKey after a perfectly clean build.

Camera or display apps additionally need the Meta DAT set: the MWDAT dict (including an explicit DAMEnabled), CFBundleURLTypes (a custom scheme, not a universal link), LSApplicationQueriesSchemes: ["fb-viewapp"], UISupportedExternalAccessoryProtocols: ["com.meta.ar.wearable"], and the Bluetooth/external-accessory UIBackgroundModes.

Full set with values: Info.plist setup.

3. Initialize

Create the SDK entry point once, at your App entry point, and forward the Meta auth callback:

import GlassesCore

@main
struct MyApp: App {
    // usedCapabilities is load-bearing on iOS — it picks the transport.
    // A voice app declares [.microphone, .speaker]; add .camera / .display
    // if you use them. Leaving it empty resolves to real glasses.
    let glasses: any ExtentosGlasses = Extentos.create(config: ExtentosConfig(
        usedCapabilities: [.microphone, .speaker]
    ))
    // Leave `debug` at its false default for anything you run on a real phone.
    // `debug: true` opens a pending browser-simulator socket and waits for the
    // MCP bridge to bind it — which is what you want during the simulator dev
    // loop, and which strands the app on a phone with no bridge running.

    var body: some Scene {
        WindowGroup {
            ContentView(glasses: glasses)
                .onOpenURL { url in Task { _ = await glasses.handleUrl(url) } }
        }
    }
}

ExtentosConfig's full field list (transport choice, environment, consent flags, …) is in the iOS API reference; details: Initialization.

4. Make your first capability call

Every call is async and returns an ExtentosResult — pattern-match it (if case .success(let photo) = await glasses.camera.capturePhoto()); don't wrap in do/catch. See Threading.

5. Drop in the connection page — camera and display apps only

Skip this step if you're building a voice app: it renders no connection page, so it doesn't need GlassesUI at all. See choose your path.

import GlassesUI

ExtentosConnectionPage(glasses: glasses)   // status, capabilities, toggles — library-owned UI

6. Verify in the simulator

Run against the browser simulator — the same library code as production with only the transport swapped, so a green run here is meaningful. With debug: true, the SDK's Auto transport resolution picks the simulator transport during development.