---
title: Brilliant Labs (preview)
seoTitle: Brilliant Labs Halo and Frame — Extentos support status
description: "Brilliant Labs support in Extentos: the BLE transport, on-device Lua bundle, display translation, still capture and microphone ship inside the SDK on both platforms — nothing to add on Android, TransportChoice.brilliant on iOS — but no hardware has run any of it and there is no emulator either. Video is unsupported permanently. Halo and Frame are selectable in the simulator today with their real panel geometry and input."
type: reference
platform: all
vendor: brilliant
related:
  - /docs/vendors
  - /docs/vendors/android-xr
  - /docs/ecosystem/platforms/brilliant-labs
  - /docs/concepts/capabilities
  - /docs/concepts/display
  - /docs/getting-started/choose-your-path
---

Brilliant Labs is the third vendor Extentos targets, and it is the **inverse of Android XR**. Where Android XR has an emulator and no purchasable glasses, Brilliant has purchasable glasses and no emulator — so the transport is shippable, and nothing has run it against a device, real or simulated.

This page is the honest status: what runs today, what is unverified, and what Brilliant breaks that a Meta-shaped app quietly assumes.

## TL;DR

- **Built**: the BLE transport, the on-device Lua bundle, the connect handshake, the display translation, **still capture** and the microphone (`audioChunks`, `transcriptions`, `recordDiscrete`) — the protocol half in the shared Rust core, so both platforms run the same code.
- **Verified as far as it can be without hardware**: the wire protocol is checked **byte-for-byte against Brilliant's own implementation**, and the layout is mutation-tested.
- **Ships with the SDK on both platforms**: inside `com.extentos:glasses` on Android and `GlassesCore` on iOS — **no vendor dependency to add on either.** Brilliant charges nothing for access (no SDK, no account, no credentials, just BLE), so Extentos charges nothing either. You *can* build against it — you just cannot yet know it works.
- **No hardware verification, and no emulator either.** This is a weaker claim than Android XR's, and it is stated separately for that reason.
- **Testable today**: both devices are selectable in the simulator with their real panel geometry and input hardware.
- **Meta is unaffected.** A Meta-only app never inherits any of it.

## Extentos support

The same eleven rows appear on every vendor page, in the same order, so vendors can be
compared directly rather than by reading three differently-shaped tables. Depth
specific to this vendor follows below.

| | State | Detail |
|---|---|---|
| **Hardware you can buy** | 🟡 Orderable | Halo, $399 — but Brilliant says the first units ship **early August 2026**, so ordering today is a pre-order rather than a device in hand. Frame is no longer sold. |
| **Distribution** | ✅ Open | The most open in the category: no Brilliant store, no review, no allowlist, no invite waitlist. Your app is an ordinary phone app that talks BLE, so it ships through the App Store and Play on their usual terms and Brilliant gates nothing. The constraint is the other end of the funnel — hardware ships early August 2026, so there is nobody to ship it to yet. |
| **Transport** | ✅ Both platforms | `BrilliantCore` in the shared Rust core; each platform shell is a socket and nothing else. |
| **Published** | ✅ Ships with the SDK | Inside `com.extentos:glasses` on Android and `GlassesCore` on iOS — nothing to add on either platform. The former `com.extentos:glasses-brilliant` artifact still resolves as an empty deprecated stub so an existing build does not break on a version bump; drop the line at your convenience. |
| **Verified on hardware** | ⛔ None on Brilliant hardware | No Brilliant device has run any of this, and unlike Android XR there is no emulator standing in either. The iOS *audio* path was separately verified on a real iPhone — see below. |
| **Camera** | 🟡 Stills built | `capturePhoto()` is implemented end to end — the request goes out, the device streams the JPEG back in chunks, and you get a `Photo`. Unverified on hardware like everything else here. **Video is a separate answer** — see the row below, and note the resolution split: Frame takes any even 100–720, while Halo has exactly ONE legal resolution, so on a Halo the requested `Resolution` is advisory and `Photo.width` reports what actually arrived. |
| **Display** | ✅ Built | Halo's **256×256 circle** and Frame's 640×400 rectangle. Your `glasses.display.show { … }` tree lays out for whichever panel is connected. |
| **Microphone** | ✅ Works | `audioChunks()`, `transcriptions()` and `recordDiscrete()`. Brilliant streams microphone audio over its own BLE link rather than pairing as a Bluetooth headset, so reaching it is the transport's job rather than the phone's. `recordDiscrete` is bounded by the recogniser's own endpointing — the same division of labour the Meta path uses, where silence detection belongs to the platform rather than the core — so `silenceTimeoutSeconds` selects silence-bounded behaviour rather than setting an exact threshold. |
| **Speaker** | 🟡 Halo only | Halo has bone-conduction speakers and the audio path to them is built; phone-side synthesis is not wired yet, so `speak()` returns a typed refusal. **Frame has no speaker at all** — guard on the speaker capability, not on whether a display exists. |
| **Simulator** | ✅ Both devices | Real panel geometry and input, including the circle. |
| **Integration** | ✅ Nothing to add | Not scaffolded, and does not need to be. Android: nothing — it ships in the SDK and self-registers. iOS: one transport choice plus `NSBluetoothAlwaysUsageDescription`. Handler code is identical to Meta's either way. |

### Beyond the spine

Detail that has no counterpart on other vendors, kept separate so the table above stays comparable.

| Thing | State | What it means |
|---|---|---|
| Wire protocol | ✅ Built + verified | Framing, chunking and reassembly, checked byte-for-byte against the vendor's own BSD-3 implementation rather than against documentation. |
| On-device Lua bundle | ✅ Built | Uploaded on connect. Until it runs, a connected device understands nothing — which is why `Connected` and `Ready` are separate states. |
| Video | ⛔ Unsupported, permanently | No video primitive and no codec on either device, and frame-by-frame bitmaps are not viable at BLE speed — so `captureVideo()` and `videoFrames()` both refuse with that reason, and `videoFrames` **throws** it rather than ending in silence. This is the one vendor where stills work and streaming cannot, which is why the SDK's transport seam is named `videoStreamUnavailable` rather than `cameraUnavailable`. Unlike the camera row, this is not pending work: no effort changes it. The **simulator reproduces it** — select a Brilliant device and `videoFrames` refuses there too, so an app cannot be built against a capability the hardware lacks. |
| iOS audio path, on a real iPhone | ✅ Verified | Everything downstream of "bytes arrived" ran on an iPhone (iOS 26.5.2): transport resolution, and synthesised speech through the same seam a Halo feeds — `BleAudioInput` → the recogniser → a transcript, 6/6 words. Resolution also never triggers a Bluetooth permission prompt. The CoreBluetooth **socket** — scan, connect, MTU — still needs a Halo. See `ios-library/DeviceVerify/`. |

## The two devices

**Brilliant Halo** — a **256×256 round** display, camera, dual mics, bone-conduction speakers, a physical button and an IMU tap. **$399, orderable now — the only product Brilliant currently sells.** Brilliant states the first units ship in **early August 2026** (checked 2026-07-29), so ordering today is a pre-order rather than a device in hand.

**Brilliant Frame** — the earlier model: a 640×400 display, camera, one microphone, one tap gesture, and **no speaker**. **No longer sold** (its product page 404s and it is absent from the store, checked 2026-07-29), but the vendor still documents it, people still own them, and the transport detects and supports it. If you are buying hardware to develop against, buy a Halo.

Frame is worth pausing on: it is the first shipping device with a **screen and no audio out**. If your app renders a display and falls back to `audio.speak` when something goes wrong, that fallback is silence on Frame. Branch on the speaker capability, not on whether a display exists.

## What Brilliant breaks that Meta does not

Four assumptions a Meta-shaped app makes quietly. All four are visible in the simulator, so you can design around them without owning either device.

**The panel is round, and it is the smallest in the catalog.** Halo's addressable canvas is 256×256 and circular — a full-width row laid out to the panel width loses both of its ends. The SDK handles this for you: content lays out inside the inscribed square automatically, so you write one tree and it is correct on a circle. What it cannot do is make your tree shorter. A layout that fits Meta's 600×600 shows roughly a third of its content here, and trees clip rather than scroll on every vendor.

**There is one font size.** Neither device's text primitive takes a size argument, so `HEADING`, `BODY` and `CAPTION` render identically. Colour still differentiates, which is why secondary text carries its own colour on the wire. If your hierarchy depends on type size, it will flatten.

**The hardware cannot move focus.** Halo has a button and an IMU tap but **no swipe of any kind**; Frame has only the tap. This is the first vendor where the four display actions do not all have a gesture. Build single-action screens, or screens where the one thing you can act on is the obvious one.

**Audio is not Bluetooth audio.** Brilliant's mic and speaker run over a **custom GATT characteristic**, not the phone's Bluetooth audio routing. A Halo never appears as a system headset — so the [vendorless voice path](/docs/getting-started/choose-your-path), which reaches most glasses with no vendor SDK at all, does not reach Brilliant. Voice on Brilliant needs this transport.

## Adding it

**Android** — nothing to add. The transport ships inside `com.extentos:glasses`
and registers itself at app start, so if you already have the SDK you already
have Brilliant. Your handler code does not change either: the same
`glasses.display.show { … }` you write for Meta is what renders on a Halo.

Why nothing, when Meta needs `glasses-meta`? Because a vendor should cost your
app what the **vendor** charges. Meta's artifacts live on a credentialed repo, so
reaching them means accepting Meta's terms and minting a token — that toll is
theirs and we cannot remove it. Brilliant charges nothing: no SDK, no account, no
credentials, just BLE. Charging you a dependency line anyway would have been our
own invention.

<Callout type="info">
If your build still carries `implementation("com.extentos:glasses-brilliant:…")`
it keeps working — that coordinate now publishes as an empty stub that depends on
the SDK, so a version bump cannot break you. Remove the line whenever convenient.
</Callout>

**iOS** — already in `GlassesCore`, so there is nothing to add. Pick the
transport:

```swift
let glasses = Extentos.create(config: ExtentosConfig(transport: .brilliant))
```

Add `NSBluetoothAlwaysUsageDescription` to your Info.plist. Halo streams over
its own BLE link rather than pairing as a headset, so iOS asks for the Bluetooth
string even though what you are building is, from the wearer's side, a
microphone.

Brilliant lives in the core on iOS and in its own artifact on Android. That is
deliberate rather than drift: Android's `:glasses-core` is kept vendor-free, so
a vendor there must be a separate module; `GlassesCore` on iOS already depends
on Meta's Device Access Toolkit, so there is no such isolation to protect.

On Android, `TransportChoice.Auto` resolves to Brilliant only when a Brilliant
device is already **bonded** to the phone. On iOS, `.auto` consults the
`hasBrilliantDevice` closure you supply — the same shape as the existing
`hasBondedMetaDevice`, because iOS exposes no bonded-device list an app may
read. `ExtentosBrilliant.hasConnectedDevice` is a ready-made one; omit it and
`.auto` behaves exactly as it did before this transport existed. That gate matters — the alternative would be
scanning on every connect, which costs seconds of radio for every app whether or
not the hardware is anywhere nearby. The practical consequence: **first pairing
is an explicit act in your app** (scan, pick, connect), and every connect after
that resolves automatically. Meta works the same way, except bonding happens in
Meta's own app first.

## What you can do today

Test how your app behaves when the connected device reports as Halo or Frame,
without any hardware — the simulator carries the device identity independently
of the transport.

```ts
await setSimDevice({ sessionId, device: "brilliant_halo" });
```

The simulator draws the real 256×256 circle, not a square, and its control pad shows the real input: a button with press / double-press / long-press, and **disabled** controls for the gestures the hardware does not have. A flow you can drive in the simulator is a flow the device could perform.

Switch to `brilliant_frame` to exercise the display-but-no-speaker path, which no other device in the catalog can give you.

## What you cannot do today

- **Know that it works.** Built and unverified — and unlike Android XR, there is no emulator standing in for it either. If you have a Halo, you would be the first person to run this.
- **Capture photos, record a clip, or use the speaker.** Each refused with a typed error naming what is missing. Live microphone audio and transcription *do* work — that is the part a voice app needs.

## Why publish something unverified?

Because withholding it would not have made it safer, only slower to find out about.

Adding it is **additive** for anyone already integrated: on Android one dependency line, on iOS one transport choice, with no change to handler code — and the core already carries the Brilliant vocabulary on both platforms. Nobody who built against the simulator has anything to redo.

Meanwhile an unpublished module can only ever be tested by us. Halo shipped into a developer-heavy community; if you own one, you can find out in an afternoon what would otherwise wait on our hardware arriving.

What that costs you is honesty about the state, which is the point of this page. The protocol underneath is verified about as well as protocol code can be without a device — checked against the vendor's own working implementation, the connect handshake driven against a fake socket, the layout mutation-tested. That is enough to believe the design is right. It is not enough to claim it works.

The first things likely to move on real hardware are the **font metrics** — Brilliant publishes none, so every text measurement is currently an educated guess — and possibly the **input mapping**, since press-to-select and long-press-for-back is a judgement about ergonomics that wearing the device would settle in a minute. Both are cosmetic rather than structural.

## How this fits the capability model

Extentos does not model "a Brilliant app". Your code asks whether a capability is available and responds; the same handler runs on any vendor that provides it. That is why the transport could be built before the hardware arrived, and why Frame's missing speaker needs no special case — it is an absent capability, handled by the same policy as any other.

See [capabilities](/docs/concepts/capabilities) and [the display capability](/docs/concepts/display).

## Frequently asked questions

### Can I build a Brilliant app with Extentos today?

You can build one. Whether it runs is genuinely unknown — no device has executed this code. The display path, the microphone (including `recordDiscrete`) and still capture are all real; only video is refused, and it is refused permanently rather than pending. The simulator will show you the layout consequences — and the video refusal — without any hardware.

### Is this the same status as Android XR?

No, and the difference is worth stating. Android XR is **emulator-proven** — its transport has run end to end against Google's emulator, but the module is unpublished (alpha dependencies) and no hardware exists to buy. Brilliant is the mirror image: the module is published and the hardware is on sale, but the transport has run against nothing but tests. One has been executed against something device-like; the other you can actually install.

### Does supporting Brilliant affect my Meta app?

No. The transport now ships inside the SDK on both platforms, but shipping is not claiming: it only *claims* a session when a Brilliant device is already bonded to the phone, it reads the bonded list without ever scanning (a BLE scan on every connect would cost power for apps that will never see one), and `Auto` ranks it behind Meta. A Meta app resolves exactly as it did before the fold.

### Brilliant's SDK is open source. Why not use it directly?

You can — it is BSD-3 and genuinely good. What Extentos adds is that the same app code also runs on Meta smart glasses and Android XR, and that the display tree you write is not Brilliant-specific. See the [neutral ecosystem view](/docs/ecosystem/platforms/brilliant-labs) for the platform on its own terms.
