CCT-31 paid-edition Android app for XREAL Air 2 Pro + Beam Pro. Companion to the public OSS codetalker daemon.
Status: Phases 5–7 + character integration + MJPEG decoder + Phase 10a foreground service + Phase 8 AR skeleton shipped. The Nebula SDK AAR drop translates the skeleton into real AR rendering — see "XREAL Nebula SDK" below.
Mockups + docs: see docs/mockups/index.html in the public repo.
# 1. Daemon side (public repo)
pip install --user claude-code-talker
claude-code-talker serve
# 2. Get the dashboard's pairing token
# → http://127.0.0.1:17832/ui-react/ → Preferences → AR Companion
# 3. Android side (this directory)
./gradlew installDebug # installs to connected adb device
adb shell am start -n dev.opencircuit.codetalker/.MainActivity
# 4. In the app: Pair (scan QR or paste token), see your sessionsThis directory is gitignored from the public codetalker repo. It runs as its own local git repo until the codetalker-pro private repo is created (see CCT-30 in the public repo's docs/superpowers/specs/).
- Android Studio Hedgehog (2023.1) or newer
- JDK 17 (bundled with recent Android Studio)
- A running codetalker daemon on your LAN — usually
pip install --user claude-code-talker && claude-code-talker serve - (For AR phases) XREAL Air 2 Pro + Beam Pro
- (Optional) Tailscale on phone + PC for remote-from-anywhere use
- Launch Android Studio
- File → Open → select this
companion-android/directory - Wait for Gradle sync. The
libs.versions.tomlresolves all deps from Maven Central + Google. - Build → Make Project (Ctrl+F9). First sync downloads ~200 MB of AndroidX + Compose.
The Nebula SDK is currently distributed as local AARs. Once you've downloaded it from the XREAL developer portal:
- Drop the
.aarintoapp/libs/ - Uncomment the corresponding
implementation(files(...))line inapp/build.gradle.kts - Re-sync
Until the SDK is dropped in, the project compiles and the LAN-client tests run, but AR rendering is stubbed.
- In the codetalker dashboard (
http://<pc-ip>:17832/ui-react/), open Preferences → AR Companion → Issue pairing token. - A QR code appears.
- On the phone, launch this app, tap Pair, scan the QR. (Manual entry of
daemon_url+pairing_tokenworks too.) - The token is stored in Android Keystore-backed
EncryptedSharedPreferences.
- Install Tailscale on both the PC and the Android phone (free tier covers personal use).
tailscale upon both.- Pair the phone with the daemon's Tailnet IP (
100.x.x.x:17832) instead of the LAN IP. - Now the app works anywhere with internet.
The daemon already binds to 0.0.0.0, so it's reachable on whatever network it happens to be on. There's no Tailscale-specific code in the daemon or this app.
The Beam Pro ships with Android 14. To install this app:
On the Beam Pro:
- Settings → About Beam Pro → Build number — tap 7 times until "You are now a developer" appears.
- Settings → System → Developer options — toggle USB debugging to ON.
- Connect Beam Pro to your PC via USB-C.
- On the Beam Pro, accept the "Allow USB debugging?" prompt and check Always allow from this computer.
On your PC:
adb devices -l
# Expected: your Beam Pro listed with "device" status
# E.g.: ABCD1234 device product:beam_pro model:Beam_ProIf nothing shows: try a different USB-C cable (data-rated, not power-only), reboot the Beam Pro, or run adb kill-server && adb start-server.
Beam Pro supports wireless debugging:
- Settings → System → Developer options → Wireless debugging → ON
- Tap Pair device with pairing code — note the IP/port + 6-digit code.
- On PC:
adb pair 192.168.1.42:34567(use the IP+port shown), enter code. - Then
adb connect 192.168.1.42:34567(the OTHER port shown on the main wireless-debugging screen). adb devices -lshould now list the Beam Pro over WiFi.
./gradlew installDebug
adb shell am start -n dev.opencircuit.codetalker/.MainActivity
# Tail logs while testing
adb logcat -s codetalker:V CompanionForegroundService:V ButtonRouter:VWith the app open, press the Beam Pro's side buttons and watch logcat. The HardwareKeys class catches KEYCODE_HEADSETHOOK / MEDIA_PLAY_PAUSE / CAMERA / VOLUME_UP/DOWN — adjust HardwareKeys.kt:53-56 if the actual keycode reported by your firmware is different.
# Tighter logcat during button tuning
adb logcat -s ViewRootImpl:* | grep -i "key"The Nebula SDK is currently distributed as local AARs. Once you've downloaded it from the XREAL developer portal:
- Drop the
.aarintoapp/libs/ - Uncomment the corresponding
implementation(files(...))line inapp/build.gradle.kts - Replace the
TODO(nebula)markers inAROverlayActivity.kt,HudLayer.kt, andMenuLayer.kt— typically 5–10 lines per file (see comments inline for each anchor type). - Re-sync, rebuild, redeploy.
Until the SDK is dropped in, the AR Compose layers render as flat overlays on the Beam Pro's primary screen — useful for layout iteration before glasses are connected.
After pairing:
// Connect to daemon, list sessions
val client = DaemonClient(daemonUrl, pairingToken)
val sessions = client.listSessions()
println(sessions.map { it.displayName })If the daemon is running and the token is valid, you'll see your codetalker session catalog.
./gradlew testPhase 5 tests cover DaemonClient (8 tests), PairingFlow (TBD), and RetryPolicy (3 tests). They use OkHttp's MockWebServer — no daemon required.
| Phase | Status | Verifiable without hardware? |
|---|---|---|
| 5a — Project scaffold | ✅ shipped | Yes — ./gradlew test cold-build verified |
| 5b — DaemonClient + PairingFlow + ConnectionGuard | ✅ shipped | Yes — 12 MockWebServer tests |
| 5c — Pairing UI: Choose ↔ QR ↔ Manual | ✅ shipped | Yes — emulator |
| 5c+ — CameraX + ZXing QR scanner | ✅ shipped | Yes — emulator with synthetic QR |
| 6 — ButtonRouter state machine + STTRecorder | ✅ shipped | Yes — 11 state-machine tests |
| 6+ — HardwareKeys + dispatchKeyEvent + Beam Pro pipeline | ✅ shipped | Partial — code wired; Beam Pro needs adb-logcat tuning to confirm exact keycode |
| 7 — TTSPlayer (ExoPlayer + auth-header HTTP source) | ✅ shipped | Yes — emulator with daemon WAV stream |
| 9-decode — MJPEG parser | ✅ shipped | Yes — 6 pure-bytes tests |
| char — CharacterChip + persona avatars + voice cloning surfaces | ✅ shipped | Yes — daemon resolves attached_character; chip renders |
| 10a — Foreground service (audio + SSE survive backgrounding) | ✅ shipped | Yes — declared in manifest, manageable from MainActivity |
| 8 — AR HUD + Menu layers (Nebula SDK) | ✅ skeleton shipped, 🔜 awaits AAR | Skeleton: yes (compiles, renders flat). Real AR: needs Nebula AAR + glasses |
| 9-AR — Screen mirror plane in AR composition | pending | Needs Phase 8 |
| 10b — Tailscale recipe + battery profile + branding | partial | This README has the recipe; battery/branding need device |
Test count: 32 unit tests passing across 4 suites: ButtonRouter (11) · DaemonClient (12) · RetryPolicy (3) · MjpegStream (6).
The reconnection cadence is yours to design — the function is stubbed at app/src/main/kotlin/dev/opencircuit/codetalker/net/ConnectionGuard.kt. The file's docblock describes the trade-offs (aggressive vs patient vs WiFi-aware). Replace the placeholder body with whatever cadence matches your taste; the unit tests pin the contract.
This directory is closed-source pending the CCT-30 open-core split. Once codetalker-pro exists, the license will land here. Do not copy this code into the public OSS repo.