Files
nucleic-remote-ios/NucleicRemote
NucleicandClaude Opus 4.8 d8fc4696a8 iOS pairing scanner: handle no-camera / denied gracefully
The QR scanner sat on a silent black screen when the camera couldn't
start: it called AVCaptureDevice.default(for: .video), got nil (e.g. on
the Simulator, which has no camera), and bailed via an early guard with
no UI feedback. It also never requested camera permission (a denied
device stayed black with no recovery) and sized the preview layer only
once in viewDidLoad.

Now it gates on AVCaptureDevice authorization (requesting access when
undetermined, surfacing a Settings link when denied), reports an
"unavailable" state when there's no camera so the UI explains the black
screen, and updates the preview frame in viewDidLayoutSubviews. Camera
runs work on a background queue.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 04:45:18 -07:00
..

NucleicRemote (iPhone client)

The thin iOS remote client for Nucleic (PLAN milestone M4). It's a pure projection of the Mac host over LAN: monitor sessions, read transcripts/diffs, answer approvals, and send follow-up input — scope approve. No local git or CLI; the Mac is the single authority (see docs/UX_IOS.md and docs/SYNC_PROTOCOL.md).

Architecture

All wire/crypto logic is shared with the Mac via the NucleicProtocol SwiftPM library (this Xcode project links it as a local package at ../..):

  • Transport — NWFrameChannel (NWConnection) + LANDiscovery (Bonjour _nucleic._tcp).
  • Engine — NucleicProtocol.SyncClient runs the Noise handshake (XXpsk0 to pair, IK to reconnect), exchanges hello/welcome, and turns HostMsgs into a SyncClient.Event stream.
  • State — RemoteStore (ObservableObject) is the single on-device UI state, a pure projection of the host. Identity + pinned host live in IdentityStore (Keychain + UserDefaults).
  • UI — SwiftUI: SessionsView (attention-first list), SessionDetailView (transcript/diff + status-driven action area), ApprovalCardView (Face ID gate on high-risk), PairingScannerView (QR), SettingsView.

Build & run

# Resolves the local NucleicProtocol package automatically.
xcodebuild -project ios/NucleicRemote/NucleicRemote.xcodeproj \
  -scheme NucleicRemote \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro' build

Or open NucleicRemote.xcodeproj in Xcode and run. To pair, start the sync server on the Mac (Nucleic ▸ Settings ▸ Add iPhone shows the QR), then scan it. On a real device, both must be on the same Wi‑Fi.

Status

The full pair → list → subscribe → approve → reconnect path is implemented and the protocol/ server side is covered by tests in Tests/NucleicProtocolTests and Tests/NucleicCoreTests. Push notifications / Live Activity (UX_IOS §5.1/§5.3) are the M5 follow-up (needs the relay).