feat(ios): add experimental SwiftUI client - #5178
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review Diff is too large for automated approval analysis. A human reviewer should evaluate this PR. You can customize Macroscope's approvability policy. Learn more. |
Mobile interaction polishThis pass replaces the generic home-row sparkle with the resolved harness mark, keeps the latest transcript content visible when the software keyboard changes the viewport, makes keyboard dismissal immediate, constrains long thread headers, and reduces mobile prompt controls to model + reasoning in the composer and Automatic / Full access in the thread menu.
Verification:
Commits: |
| let resolvedURL = try await resolver.workspaceAssetURL( | ||
| threadID: threadID, | ||
| path: entry.path | ||
| ) |
There was a problem hiding this comment.
Image preview resolver never wired
High Severity
Image file previews cast the client to FeatureWorkspaceAssetResolving, but NativeFeatureClient never conforms to that protocol or implements workspaceAssetURL. Opening any workspace image hits the capability-unavailable path every time, even though T3Client.resolvedAssetURL and AssetResource.workspaceFile already exist for this route.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0096041. Configure here.
| var index = 2 | ||
| while occupied.contains("term-\(index)") { index += 1 } | ||
| return "term-\(index)" | ||
| } |
There was a problem hiding this comment.
Wrong primary terminal ID scheme
High Severity
TerminalSessionList treats "default" as the primary shell and allocates new IDs as term-2, term-3, …, skipping term-1. Shared contracts and other clients use term-1 via DEFAULT_TERMINAL_ID / nextTerminalId, so this client opens a separate shell, can label both as Terminal 1, and fails to share the primary session with web or React Native.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit ff13ebd. Configure here.
| cwd: context.cwd, | ||
| worktreePath: context.worktreePath, | ||
| columns: 80, | ||
| rows: 24 |
There was a problem hiding this comment.
Attach forces 80×24 resize
Medium Severity
terminalEvents always calls attachTerminal with hardcoded columns: 80 and rows: 24. Server attach resizes a running PTY when those fields are present, so opening the view or switching sessions can shrink the shell away from the Ghostty-measured grid until a later resize catches up, and newly created attach sessions start at the wrong size.
Reviewed by Cursor Bugbot for commit ff13ebd. Configure here.
|
|
||
| private func authenticationDidFinish() { | ||
| Task { _ = await onAuthenticationChanged() } | ||
| } |
There was a problem hiding this comment.
Auth cover lingers after email sign-in
Medium Severity
After email sign-in, AuthView only dismisses the inner sheet. authenticationDidFinish then runs onAuthenticationChanged in a detached Task that awaits a full controller.refresh(), including every environment status fetch, before clearing isAuthPresented. Users briefly land back on the custom provider screen while already signed in, and the same full refresh also keeps the OAuth button spinner up after a successful social sign-in.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 32318ec. Configure here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
There are 21 total unresolved issues (including 20 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b25ca74. Configure here.
| } | ||
| .frame(minWidth: proxy.size.width, alignment: .leading) | ||
| .padding(.vertical, 10) | ||
| .padding(.trailing, 14) |
There was a problem hiding this comment.
Source view always scrolls horizontally
Medium Severity
FeatureSourceTextView sets the stack minWidth to the viewport width, then adds trailing padding outside that frame. Scrollable content is therefore always wider than the viewport, so even short files get horizontal overflow. That fights vertical scrolling in the bidirectional ScrollView. The review diff path avoids this by keeping horizontal padding inside each row’s intrinsic width before applying minWidth.
Reviewed by Cursor Bugbot for commit b25ca74. Configure here.
|
hey jarvis merge this |
| .toolbarBackground(.hidden, for: .navigationBar) | ||
| } | ||
| .task { | ||
| if clerk.environment == nil { |
There was a problem hiding this comment.
🟠 High Connection/T3ConnectView.swift:347
refreshEnvironment() errors are discarded with try?, so if the environment request fails, clerk.environment stays nil and providerButtons shows "Loading sign-in options…" forever. OAuth providers never become usable and no error or retry is surfaced. Consider storing the error in errorMessage so the existing alert can display it, and offering a retry path.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/swift-ios/Features/Connection/T3ConnectView.swift around line 347:
`refreshEnvironment()` errors are discarded with `try?`, so if the environment request fails, `clerk.environment` stays `nil` and `providerButtons` shows "Loading sign-in options…" forever. OAuth providers never become usable and no error or retry is surfaced. Consider storing the error in `errorMessage` so the existing alert can display it, and offering a retry path.
| <dict> | ||
| <key>destination</key> | ||
| <string>upload</string> | ||
| <key>manageAppVersionAndBuildNumber</key> |
There was a problem hiding this comment.
🟡 Medium workflows/mobile-eas-production.yml:179
The archive export sets manageAppVersionAndBuildNumber to false while the build number is hard-coded to 12 throughout the workflow. If the upload succeeds but a later step (TestFlight group assignment or beta review submission) fails and the job is rerun, xcodebuild -exportArchive re-uploads the same CFBundleVersion 12, which App Store Connect rejects as a duplicate — the job fails before reaching the idempotent post-upload logic that could have resumed safely. Consider either incrementing CURRENT_PROJECT_VERSION per run or skipping the upload step when build 12 already exists in App Store Connect, so reruns resume at the assignment/review steps instead of re-attempting the upload.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @.github/workflows/mobile-eas-production.yml around line 179:
The archive export sets `manageAppVersionAndBuildNumber` to `false` while the build number is hard-coded to 12 throughout the workflow. If the upload succeeds but a later step (TestFlight group assignment or beta review submission) fails and the job is rerun, `xcodebuild -exportArchive` re-uploads the same `CFBundleVersion` 12, which App Store Connect rejects as a duplicate — the job fails before reaching the idempotent post-upload logic that could have resumed safely. Consider either incrementing `CURRENT_PROJECT_VERSION` per run or skipping the upload step when build 12 already exists in App Store Connect, so reruns resume at the assignment/review steps instead of re-attempting the upload.
This reverts commit bf7047d.






T3 Code's shipped mobile client is React Native. This experiment adds a standalone native SwiftUI client so the team can try its feel, performance, and connection workflows without replacing any existing surface.
The app lives entirely in
apps/swift-ios, speaks the existing server contracts directly, and installs side by side as T3 Code (SwiftUI) with bundle IDcom.t3tools.t3code.swiftui.Try it
apps/swift-ios/T3Code.xcodeprojin Xcode.T3Codescheme and an iOS 17+ simulator or device.See
apps/swift-ios/README.mdfor architecture, included functionality, and known gaps.What to test
Preview
Verification
245 native simulator tests passed, 0 failed, 1 skipped
Repeated A to B to C to A long-thread navigation verified against an isolated real-data snapshot
Latest build compiled, installed, and launched on an iPhone 17 Pro simulator
Signed latest build installed on Big O and DevPhone15; automatic launch deferred because both devices were locked
Remove
DO NOT MERGEonly after explicit maintainer approvalThis PR was built by GPT-5.6-sol using the Codex harness in T3 Code.
Note
High Risk
Large new iOS surface with Clerk, DPoP, relay token exchange, and Keychain-backed crypto on security-critical connection paths; experimental and parallel to the shipped React Native client.
Overview
Introduces an experimental native SwiftUI iOS client under
apps/swift-iosthat installs side by side with the existing React Native app and talks to T3 servers directly (not viapackages/client-runtime).The diff adds a T3 Connect stack for managed environments: Clerk session + relay JWT (
T3ConnectClerkSession), P-256 DPoP proofs with a device-bound Keychain identity (T3ConnectDPoPSigner), relay HTTP APIs (T3ConnectRelayClient), bootstrap-to-access-token exchange and WebSocket ticketing (T3ConnectManagedEnvironmentAuthorizer), and aT3ConnectController/T3ConnectRuntimeAuthorizationbridge into the app’s environment credential model. Build-time Connect settings are resolved from Info.plist keys inT3ConnectConfiguration.Contributor and agent docs are updated so mobile is two clients: React Native (
apps/mobile, Metro/Expo) vs SwiftUI (apps/swift-ios, XcodeT3Codescheme,t3code-swiftui-devdeep links).AGENTS.md,test-t3-mobile,test-t3-app, andios-debugger-agentnow require picking the affected client before verification.Reviewed by Cursor Bugbot for commit 7b8bb94. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add experimental native SwiftUI iOS client with full workspace, terminal, and T3 Connect support
WebSocketRPCClientactor andT3Clientthat handle WebSocket connections, HTTP polling fallback, RPC request/response framing, and credential management via Keychain.T3ConnectManagedEnvironmentAuthorizerfor token exchange and WebSocket ticketing.Macroscope summarized 7b8bb94.