[codex] Add Android mobile support - #3579
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 Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
| public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { | ||
| // A direct gesture takes ownership from any interrupted programmatic jump. | ||
| // Resume visible-file events immediately so the inspector follows the finger. | ||
| isProgrammaticScrollActive = false | ||
| contentView.isVerticalScrollActive = true | ||
| } |
There was a problem hiding this comment.
🟡 Medium ios/T3ReviewDiffView.swift:394
scrollViewWillBeginDragging clears isProgrammaticScrollActive but leaves pendingScrollFileId and pendingScrollAnimated set. If scrollToFile was queued before the target header existed (e.g. rows still decoding), a later setRowsJson calls applyPendingScrollIfNeeded() and jumps to the old target, overriding the user's manual scroll. Clear the pending scroll request when the user takes control.
| public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { | |
| // A direct gesture takes ownership from any interrupted programmatic jump. | |
| // Resume visible-file events immediately so the inspector follows the finger. | |
| isProgrammaticScrollActive = false | |
| contentView.isVerticalScrollActive = true | |
| } | |
| public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { | |
| // A direct gesture takes ownership from any interrupted programmatic jump. | |
| // Resume visible-file events immediately so the inspector follows the finger. | |
| isProgrammaticScrollActive = false | |
| pendingScrollFileId = nil | |
| pendingScrollAnimated = false | |
| contentView.isVerticalScrollActive = true | |
| } |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/modules/t3-review-diff/ios/T3ReviewDiffView.swift around lines 394-399:
`scrollViewWillBeginDragging` clears `isProgrammaticScrollActive` but leaves `pendingScrollFileId` and `pendingScrollAnimated` set. If `scrollToFile` was queued before the target header existed (e.g. rows still decoding), a later `setRowsJson` calls `applyPendingScrollIfNeeded()` and jumps to the old target, overriding the user's manual scroll. Clear the pending scroll request when the user takes control.
| paddingTop: 8, | ||
| paddingBottom: target ? 0 : Math.max(insets.bottom, 18), | ||
| paddingTop: isAndroid ? insets.top + 8 : 8, | ||
| paddingBottom: target ? (isAndroid ? 72 : 0) : Math.max(insets.bottom, 18), |
There was a problem hiding this comment.
🟡 Medium review/ReviewCommentComposerSheet.tsx:174
The hard-coded 72 px paddingBottom on Android assumes the KeyboardStickyView footer is always 72 px tall, but the footer height is actually 44 (button) + 8 (pt-2) + Math.max(insets.bottom, 10). On devices where insets.bottom exceeds ~20 (e.g. iPhones with a home indicator, where it can be ~34), the footer is taller than 72 px and overlaps the bottom of the comment input and attachment strip, hiding them from view and making them untappable. The padding should be computed from the actual footer height instead of hard-coded.
- paddingBottom: target ? (isAndroid ? 72 : 0) : Math.max(insets.bottom, 18),
+ paddingBottom: target ? (isAndroid ? Math.max(insets.bottom, 10) + 52 : 0) : Math.max(insets.bottom, 18),🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/src/features/review/ReviewCommentComposerSheet.tsx around line 174:
The hard-coded `72` px `paddingBottom` on Android assumes the `KeyboardStickyView` footer is always 72 px tall, but the footer height is actually `44` (button) + `8` (`pt-2`) + `Math.max(insets.bottom, 10)`. On devices where `insets.bottom` exceeds ~20 (e.g. iPhones with a home indicator, where it can be ~34), the footer is taller than 72 px and overlaps the bottom of the comment input and attachment strip, hiding them from view and making them untappable. The padding should be computed from the actual footer height instead of hard-coded.
927d43b to
212ac28
Compare
| view.setSpellCheck(spellCheck) | ||
| } | ||
|
|
||
| Events( |
There was a problem hiding this comment.
🟡 Medium t3composereditor/T3ComposerEditorModule.kt:48
The Events(...) declaration omits onComposerSubmit, and T3ComposerEditorView defines no corresponding EventDispatcher or hardware-keyboard handler. As a result, the onSubmit prop exposed by ComposerEditorProps is never invoked on Android — hardware-keyboard submit that works on iOS silently does nothing here. Consider adding "onComposerSubmit" to the Events list, wiring up an onComposerSubmit dispatcher in the view, and detecting the submit key combination (e.g., Enter without Shift) to fire it.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorModule.kt around line 48:
The `Events(...)` declaration omits `onComposerSubmit`, and `T3ComposerEditorView` defines no corresponding `EventDispatcher` or hardware-keyboard handler. As a result, the `onSubmit` prop exposed by `ComposerEditorProps` is never invoked on Android — hardware-keyboard submit that works on iOS silently does nothing here. Consider adding `"onComposerSubmit"` to the `Events` list, wiring up an `onComposerSubmit` dispatcher in the view, and detecting the submit key combination (e.g., Enter without Shift) to fire it.
| backgroundColorValue, | ||
| cursorColorValue, | ||
| paletteColors, | ||
| ) |
There was a problem hiding this comment.
🟡 Medium t3terminal/T3TerminalView.kt:252
createTerminal() assigns the result of GhosttyBridge.nativeCreate() directly to terminalHandle without checking for a 0 return value, which indicates native session creation failed. When this happens, terminalHandle stays 0L and emitResize() proceeds to fire onResize and call feedPendingBuffer()/renderSnapshot() as if the terminal were live, so the JS layer never learns creation failed and the view stays blank. Consider checking the return value and emitting an error event when it is 0.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/modules/t3-terminal/android/src/main/java/expo/modules/t3terminal/T3TerminalView.kt around line 252:
`createTerminal()` assigns the result of `GhosttyBridge.nativeCreate()` directly to `terminalHandle` without checking for a `0` return value, which indicates native session creation failed. When this happens, `terminalHandle` stays `0L` and `emitResize()` proceeds to fire `onResize` and call `feedPendingBuffer()`/`renderSnapshot()` as if the terminal were live, so the JS layer never learns creation failed and the view stays blank. Consider checking the return value and emitting an error event when it is `0`.
| ``` | ||
|
|
||
| The script downloads Zig 0.15.2 when needed, checks out the pinned upstream Ghostty revision, and | ||
| rebuilds all four Android ABIs with 16 KB page-size support. |
There was a problem hiding this comment.
🟡 Medium t3-terminal/README.md:50
The new README section states the script rebuilds "all four Android ABIs with 16 KB page-size support," but build-libghostty-android.sh never passes -Wl,-z,max-page-size=16384 and -Wl,-z,common-page-size=16384 to the linker. A developer following these instructions will rebuild and vendor .so files that are not 16 KB-page compatible while the docs claim otherwise. Add the required linker flags to the script so the rebuilt libraries match the documented behavior.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/modules/t3-terminal/README.md around line 50:
The new README section states the script rebuilds "all four Android ABIs with 16 KB page-size support," but `build-libghostty-android.sh` never passes `-Wl,-z,max-page-size=16384` and `-Wl,-z,common-page-size=16384` to the linker. A developer following these instructions will rebuild and vendor `.so` files that are not 16 KB-page compatible while the docs claim otherwise. Add the required linker flags to the script so the rebuilt libraries match the documented behavior.
| Prop("editable") { view: T3ComposerEditorView, editable: Boolean -> | ||
| view.setEditable(editable) | ||
| } | ||
| Prop("scrollEnabled") { view: T3ComposerEditorView, scrollEnabled: Boolean -> |
There was a problem hiding this comment.
🟡 Medium t3composereditor/T3ComposerEditorModule.kt:35
The scrollEnabled prop does not actually disable scrolling. setScrollEnabled only toggles editor.isVerticalScrollBarEnabled, which controls whether the scrollbar is drawn — not whether the view scrolls. When scrollEnabled={false} is passed from JS, the editor remains scrollable and only the scrollbar disappears, so the prop silently does not work. Consider disabling touch interception or overriding onTouchEvent to actually prevent scrolling when scrollEnabled is false.
Also found in 1 other location(s)
apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt:199
setScrollEnabled()at line199only assignseditor.isVerticalScrollBarEnabled. Android'ssetVerticalScrollBarEnabled()controls whether the scrollbar is drawn, not whether anEditTextcan actually scroll. When callers passscrollEnabled=false, long composer contents can still be vertically scrolled; only the scrollbar disappears, so the exposed prop does not work on Android.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorModule.kt around line 35:
The `scrollEnabled` prop does not actually disable scrolling. `setScrollEnabled` only toggles `editor.isVerticalScrollBarEnabled`, which controls whether the scrollbar is drawn — not whether the view scrolls. When `scrollEnabled={false}` is passed from JS, the editor remains scrollable and only the scrollbar disappears, so the prop silently does not work. Consider disabling touch interception or overriding `onTouchEvent` to actually prevent scrolling when `scrollEnabled` is false.
Also found in 1 other location(s):
- apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt:199 -- `setScrollEnabled()` at line `199` only assigns `editor.isVerticalScrollBarEnabled`. Android's `setVerticalScrollBarEnabled()` controls whether the scrollbar is drawn, not whether an `EditText` can actually scroll. When callers pass `scrollEnabled=false`, long composer contents can still be vertically scrolled; only the scrollbar disappears, so the exposed prop does not work on Android.
| </> | ||
| )} | ||
|
|
||
| <GitActionProgressOverlay progress={gitActionProgress} onDismiss={dismissGitActionResult} /> |
There was a problem hiding this comment.
🟡 Medium threads/ThreadRouteScreen.tsx:725
GitActionProgressOverlay positions itself at insets.top + 48, which was calibrated for the native iOS header. On Android, the new AndroidScreenHeader is Math.max(insets.top, 12) + 58 tall, so the overlay renders ~10px inside the header and overlaps the title and action buttons while a git action is running or after it completes. Consider passing a platform-aware top offset to GitActionProgressOverlay so it clears the Android header.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/src/features/threads/ThreadRouteScreen.tsx around line 725:
`GitActionProgressOverlay` positions itself at `insets.top + 48`, which was calibrated for the native iOS header. On Android, the new `AndroidScreenHeader` is `Math.max(insets.top, 12) + 58` tall, so the overlay renders ~10px inside the header and overlaps the title and action buttons while a git action is running or after it completes. Consider passing a platform-aware top offset to `GitActionProgressOverlay` so it clears the Android header.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 6 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for all 6 issues found in the latest run.
- ✅ Fixed: iOS associated domains removed
- Restored the associatedDomains array with applinks and webcredentials entries for clerk.t3.codes, which was inadvertently dropped when relyingParty was removed from the variant config.
- ✅ Fixed: Composer scroll flag ignored
- Added a scrollEnabled property to SelectionAwareEditText with a scrollTo override that blocks scrolling when disabled, so setScrollEnabled now controls actual scroll behavior, not just the scroll bar.
- ✅ Fixed: Collapsed files skew highlight indices
- Added a visibleToOriginalIndex mapping array built during rebuildVisibleRows, and the onVisibleRowsChanged callback now translates filtered indices back to original row indices before emitting the visible-range event.
- ✅ Fixed: Stale rows after content reset
- setContentResetKey now increments rowsDecodeGeneration and clears rows, visibleRows, visibleToOriginalIndex, and canvasView.rows so in-flight decodes from the previous section are rejected and stale content is immediately cleared.
- ✅ Fixed: Top scroll never clears file
- emitVisibleFile now checks if verticalOffset is at zero and emits onVisibleFileChange with a null fileId in that case, matching the iOS behavior that selects the "All files" navigator destination.
- ✅ Fixed: Collapsed comments stay tall
- Added collapsedCommentIds to DiffCanvasView and updated rowHeight to return 44dp for collapsed comments (matching iOS's 44pt) instead of the full expanded height.
Or push these changes by commenting:
@cursor push a991bbde89
Preview (a991bbde89)
diff --git a/apps/mobile/app.config.ts b/apps/mobile/app.config.ts
--- a/apps/mobile/app.config.ts
+++ b/apps/mobile/app.config.ts
@@ -107,6 +107,7 @@
icon: variant.iosIcon,
supportsTablet: true,
bundleIdentifier: iosBundleIdentifier,
+ associatedDomains: ["applinks:clerk.t3.codes", "webcredentials:clerk.t3.codes"],
infoPlist: {
NSAppTransportSecurity: {
NSAllowsArbitraryLoads: true,
diff --git a/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt b/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
--- a/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
+++ b/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
@@ -197,6 +197,7 @@
fun setScrollEnabled(scrollEnabled: Boolean) {
editor.isVerticalScrollBarEnabled = scrollEnabled
+ editor.scrollEnabled = scrollEnabled
}
fun setAutoFocus(autoFocus: Boolean) {
@@ -424,7 +425,12 @@
private class SelectionAwareEditText(context: Context) : EditText(context) {
var selectionListener: ((Int, Int) -> Unit)? = null
var pasteImagesListener: ((List<String>) -> Unit)? = null
+ var scrollEnabled = true
+ override fun scrollTo(x: Int, y: Int) {
+ if (scrollEnabled) super.scrollTo(x, y)
+ }
+
override fun onSelectionChanged(selStart: Int, selEnd: Int) {
super.onSelectionChanged(selStart, selEnd)
selectionListener?.invoke(selStart, selEnd)
diff --git a/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt b/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
--- a/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
+++ b/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
@@ -32,6 +32,7 @@
private val onToggleComment by EventDispatcher()
private var rows: List<DiffRow> = emptyList()
private var visibleRows: List<DiffRow> = emptyList()
+ private var visibleToOriginalIndex: IntArray = intArrayOf()
private var collapsedFileIds: Set<String> = emptySet()
private var viewedFileIds: Set<String> = emptySet()
private var selectedRowIds: Set<String> = emptySet()
@@ -56,11 +57,13 @@
init {
canvasView.onRowTap = { row, gesture -> handleRowTap(row, gesture) }
canvasView.onVisibleRowsChanged = { first, last ->
+ val originalFirst = if (first in visibleToOriginalIndex.indices) visibleToOriginalIndex[first] else first
+ val originalLast = if (last in visibleToOriginalIndex.indices) visibleToOriginalIndex[last] else last
onDebug(
mapOf(
"message" to "visible-range",
- "firstRowIndex" to first,
- "lastRowIndex" to last,
+ "firstRowIndex" to originalFirst,
+ "lastRowIndex" to originalLast,
),
)
emitVisibleFile(first)
@@ -81,7 +84,12 @@
fun setContentResetKey(value: String) {
if (contentResetKey == value) return
contentResetKey = value
+ rowsDecodeGeneration += 1
tokensDecodeGeneration += 1
+ rows = emptyList()
+ visibleRows = emptyList()
+ visibleToOriginalIndex = intArrayOf()
+ canvasView.rows = emptyList()
canvasView.tokensByRowId = emptyMap()
lastVisibleFileId = null
pendingInitialScroll = true
@@ -314,21 +322,27 @@
private fun rebuildVisibleRows() {
val filtered = ArrayList<DiffRow>(rows.size)
+ val indexMapping = ArrayList<Int>(rows.size)
var currentFileCollapsed = false
- rows.forEach { row ->
+ rows.forEachIndexed { originalIndex, row ->
if (row.kind == "file") {
currentFileCollapsed = collapsedFileIds.contains(row.resolvedFileId)
filtered.add(row)
+ indexMapping.add(originalIndex)
} else if (!currentFileCollapsed) {
if (row.kind != "comment" || !collapsedCommentIds.contains(row.id)) {
filtered.add(row)
+ indexMapping.add(originalIndex)
} else {
filtered.add(row.copy(commentText = "Comment collapsed"))
+ indexMapping.add(originalIndex)
}
}
}
visibleRows = filtered
+ visibleToOriginalIndex = indexMapping.toIntArray()
canvasView.rows = filtered
+ canvasView.collapsedCommentIds = collapsedCommentIds
canvasView.viewedFileIds = viewedFileIds
canvasView.selectedRowIds = selectedRowIds
applyPendingInitialScroll()
@@ -360,6 +374,13 @@
private fun emitVisibleFile(firstVisibleIndex: Int) {
if (visibleRows.isEmpty()) return
+ if (canvasView.verticalOffset() <= 0) {
+ if (lastVisibleFileId != null) {
+ lastVisibleFileId = null
+ onVisibleFileChange(mapOf("fileId" to null))
+ }
+ return
+ }
val start = firstVisibleIndex.coerceIn(0, visibleRows.lastIndex)
val fileId = (start downTo 0)
.asSequence()
@@ -590,6 +611,11 @@
field = value
invalidate()
}
+ var collapsedCommentIds: Set<String> = emptySet()
+ set(value) {
+ field = value
+ rebuildOffsets()
+ }
var theme: DiffTheme = DiffTheme.fallback("light")
set(value) {
field = value
@@ -691,7 +717,11 @@
private fun rowHeight(row: DiffRow): Int = when (row.kind) {
"file" -> style.fileHeaderHeightPx.toInt()
- "comment" -> max((style.rowHeightPx * 3.2f).toInt(), (56 * density).toInt())
+ "comment" -> if (collapsedCommentIds.contains(row.id)) {
+ (44 * density).toInt()
+ } else {
+ max((style.rowHeightPx * 3.2f).toInt(), (56 * density).toInt())
+ }
else -> style.rowHeightPx.toInt()
}.coerceAtLeast(1)You can send follow-ups to the cloud agent here.
| canvasView.setVerticalOffset(0) | ||
| canvasView.setHorizontalOffset(0) | ||
| applyPendingInitialScroll() | ||
| } |
There was a problem hiding this comment.
Stale rows after content reset
Medium Severity
When contentResetKey changes, the view clears tokens and scroll but does not bump rowsDecodeGeneration or clear rows. An in-flight setRowsJson decode from the previous review section can still post after the reset and repopulate the canvas with the old diff.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 276b453. Configure here.
| if (fileId == lastVisibleFileId) return | ||
| lastVisibleFileId = fileId | ||
| onVisibleFileChange(mapOf("fileId" to fileId)) | ||
| } |
There was a problem hiding this comment.
Top scroll never clears file
Medium Severity
Android never emits onVisibleFileChange with a null fileId when the diff is scrolled to the top. The navigator keeps highlighting the first file instead of the shared “all files” destination that iOS reports at offset zero.
Reviewed by Cursor Bugbot for commit 276b453. Configure here.
ApprovabilityVerdict: Needs human review 29 blocking correctness issues found. Diff is too large for automated approval analysis. A human reviewer should evaluate this PR. You can customize Macroscope's approvability policy. Learn more. |
770c781 to
9f54b06
Compare
1053338 to
2ae9365
Compare
| } | ||
| } catch (_: Exception) { | ||
| } | ||
| } |
There was a problem hiding this comment.
Stale token patches after reset
High Severity
The setTokensPatchJson function asynchronously applies token patches. It only checks tokensResetKey for relevance, missing a crucial check against contentResetKey. This can cause token patches from a previous diff to be applied to the current view, resulting in incorrect highlighting.
Reviewed by Cursor Bugbot for commit 2ae9365. Configure here.
| token.fontStyle and 1 != 0 -> Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC) | ||
| token.fontStyle and 2 != 0 -> Typeface.create(Typeface.MONOSPACE, Typeface.BOLD) | ||
| else -> Typeface.MONOSPACE | ||
| } |
There was a problem hiding this comment.
Bold italic tokens render wrong
Low Severity
The when statement for textPaint.typeface in drawLineRow applies fontStyle bits sequentially, causing tokens with both italic and bold flags to render only as italic. This results in bold styling being lost and diverges from the intended combined styling.
Reviewed by Cursor Bugbot for commit 2ae9365. Configure here.
| if (imageUris.isNotEmpty()) { | ||
| pasteImagesListener?.invoke(imageUris) | ||
| return true | ||
| } |
There was a problem hiding this comment.
Paste skips text when images present
Medium Severity
On paste, if any clipboard item exposes an image URI, Android invokes onComposerPasteImages and returns true without calling super.onTextContextMenuItem. Plain-text paste from the same or another clip item never runs, so mixed or text-first paste silently fails.
Reviewed by Cursor Bugbot for commit 2ae9365. Configure here.
| "onToggleViewedFile", | ||
| "onPressLine", | ||
| "onToggleComment", | ||
| ) |
There was a problem hiding this comment.
Review diff pull refresh missing
Medium Severity
The Android T3ReviewDiffSurface module does not define the refreshing prop or onPullToRefresh event that exist on iOS. SourceFileSurface passes both when refresh is enabled, so pull-to-refresh on the native source file view does nothing on Android.
Reviewed by Cursor Bugbot for commit 2ae9365. Configure here.
| const { layout, panes, togglePrimarySidebar } = useAdaptiveWorkspaceLayout(); | ||
|
|
||
| if (!layout.usesSplitView) { | ||
| if (Platform.OS === "android" || !layout.usesSplitView) { |
There was a problem hiding this comment.
🟡 Medium layout/workspace-sidebar-toolbar.tsx:15
WorkspaceSidebarToolbar returns null on Android regardless of layout.usesSplitView, so split-view Android routes lose the sidebar toggle and New task/Return to chat buttons. The Android exclusion should be removed unless Android genuinely lacks split-view support.
| if (Platform.OS === "android" || !layout.usesSplitView) { | |
| if (!layout.usesSplitView) { |
Also found in 1 other location(s)
apps/mobile/src/features/review/ReviewSheet.tsx:663
On Android the new
!isAndroidguard atReviewSheetline 663 removes the entire right-side toolbar, which is the only placeThreadGitMenuis rendered. The replacementAndroidScreenHeaderonly shows the section selector, so opening review on Android no longer exposes the commit/push/"More" git actions that this screen previously provided. Users must leave review to perform those actions, which is a regression in core review functionality.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/src/features/layout/workspace-sidebar-toolbar.tsx around line 15:
`WorkspaceSidebarToolbar` returns `null` on Android regardless of `layout.usesSplitView`, so split-view Android routes lose the sidebar toggle and `New task`/`Return to chat` buttons. The Android exclusion should be removed unless Android genuinely lacks split-view support.
Also found in 1 other location(s):
- apps/mobile/src/features/review/ReviewSheet.tsx:663 -- On Android the new `!isAndroid` guard at `ReviewSheet` line 663 removes the entire right-side toolbar, which is the only place `ThreadGitMenu` is rendered. The replacement `AndroidScreenHeader` only shows the section selector, so opening review on Android no longer exposes the commit/push/"More" git actions that this screen previously provided. Users must leave review to perform those actions, which is a regression in core review functionality.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
There are 11 total unresolved issues (including 8 from previous reviews).
Autofix Details
Bugbot Autofix prepared fixes for all 3 issues found in the latest run.
- ✅ Fixed: Shared horizontal scroll across files
- Replaced the single horizontalOffset field with a per-file HashMap<String, Int> so each file maintains its own horizontal scroll position, matching iOS's horizontalOffsetsByFileId behavior.
- ✅ Fixed: Paste sends unreadable content URIs
- Added copyToLocalFile() that copies content:// clipboard images into app cache (t3-composer-paste/*.png) and emits file:// URIs that convertPastedImagesToAttachments can read, matching the iOS writeTemporaryImage pattern.
- ✅ Fixed: Word diff highlights missing Android
- Added wordDiffRanges field to DiffRow, parsing from row JSON, and implemented drawWordDiffRanges() to render intra-line add/delete highlights matching iOS's behavior.
Or push these changes by commenting:
@cursor push 5664a9a0e6
Preview (5664a9a0e6)
diff --git a/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt b/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
--- a/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
+++ b/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
@@ -7,6 +7,7 @@
import android.graphics.Paint
import android.graphics.RectF
import android.graphics.Typeface
+import android.net.Uri
import android.text.Editable
import android.text.InputType
import android.text.Spanned
@@ -20,6 +21,8 @@
import expo.modules.kotlin.viewevent.EventDispatcher
import expo.modules.kotlin.views.ExpoView
import org.json.JSONObject
+import java.io.File
+import java.util.UUID
import kotlin.math.max
class T3ComposerEditorView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
@@ -434,21 +437,39 @@
if (id == android.R.id.paste || id == android.R.id.pasteAsPlainText) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
val clip = clipboard?.primaryClip
- val imageUris = buildList {
+ val fileUris = buildList {
if (clip != null) {
for (index in 0 until clip.itemCount) {
clip.getItemAt(index).uri?.let { uri ->
val mimeType = context.contentResolver.getType(uri)
- if (mimeType?.startsWith("image/") == true) add(uri.toString())
+ if (mimeType?.startsWith("image/") == true) {
+ copyToLocalFile(uri)?.let { add(it) }
+ }
}
}
}
}
- if (imageUris.isNotEmpty()) {
- pasteImagesListener?.invoke(imageUris)
+ if (fileUris.isNotEmpty()) {
+ pasteImagesListener?.invoke(fileUris)
return true
}
}
return super.onTextContextMenuItem(id)
}
+
+ private fun copyToLocalFile(contentUri: Uri): String? {
+ return try {
+ val pasteDir = File(context.cacheDir, "t3-composer-paste")
+ pasteDir.mkdirs()
+ val destFile = File(pasteDir, "${UUID.randomUUID()}.png")
+ context.contentResolver.openInputStream(contentUri)?.use { input ->
+ destFile.outputStream().use { output ->
+ input.copyTo(output)
+ }
+ }
+ Uri.fromFile(destFile).toString()
+ } catch (_: Exception) {
+ null
+ }
+ }
}
diff --git a/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt b/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
--- a/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
+++ b/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
@@ -86,7 +86,7 @@
lastVisibleFileId = null
pendingInitialScroll = true
canvasView.setVerticalOffset(0)
- canvasView.setHorizontalOffset(0)
+ canvasView.resetHorizontalOffsets()
applyPendingInitialScroll()
}
@@ -416,6 +416,7 @@
val change: String,
val oldLineNumber: Int?,
val newLineNumber: Int?,
+ val wordDiffRanges: List<DiffWordDiffRange>?,
val commentText: String,
val commentRangeLabel: String,
val commentSectionTitle: String,
@@ -423,6 +424,11 @@
val resolvedFileId: String get() = fileId.ifEmpty { id }
}
+private data class DiffWordDiffRange(
+ val start: Int,
+ val end: Int,
+)
+
private data class DiffToken(
val content: String,
val color: Int?,
@@ -567,12 +573,13 @@
)
private var rowOffsets = intArrayOf(0)
private var verticalOffset = 0
- private var horizontalOffset = 0
+ private var horizontalOffsetsByFileId = HashMap<String, Int>()
private var lastVisibleRange: Pair<Int, Int>? = null
var rows: List<DiffRow> = emptyList()
set(value) {
field = value
+ horizontalOffsetsByFileId.clear()
rebuildOffsets()
}
var tokensByRowId: Map<String, List<DiffToken>> = emptyMap()
@@ -603,7 +610,7 @@
var contentWidthPx: Int = (1200 * density).toInt()
set(value) {
field = max(value, suggestedMinimumWidth)
- setHorizontalOffset(horizontalOffset)
+ clampHorizontalOffsets()
invalidate()
}
var onRowTap: ((DiffRow, String) -> Unit)? = null
@@ -619,7 +626,7 @@
override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
super.onSizeChanged(width, height, oldWidth, oldHeight)
setVerticalOffset(verticalOffset)
- setHorizontalOffset(horizontalOffset)
+ clampHorizontalOffsets()
}
override fun onDraw(canvas: Canvas) {
@@ -665,20 +672,58 @@
fun maxVerticalOffset(): Int = max(0, (rowOffsets.lastOrNull() ?: 0) - height)
fun setHorizontalOffset(value: Int) {
+ val fileId = fileIdAtVerticalCenter() ?: return
val nextOffset = value.coerceIn(0, maxHorizontalOffset())
- if (horizontalOffset == nextOffset) return
- horizontalOffset = nextOffset
+ val current = horizontalOffsetsByFileId[fileId] ?: 0
+ if (current == nextOffset) return
+ horizontalOffsetsByFileId[fileId] = nextOffset
invalidate()
}
fun scrollByHorizontal(delta: Int) {
- setHorizontalOffset(horizontalOffset + delta)
+ val fileId = fileIdAtVerticalCenter() ?: return
+ val current = horizontalOffsetsByFileId[fileId] ?: 0
+ setHorizontalOffsetForFile(fileId, current + delta)
}
- fun horizontalOffset(): Int = horizontalOffset
+ fun horizontalOffset(): Int {
+ val fileId = fileIdAtVerticalCenter() ?: return 0
+ return horizontalOffsetsByFileId[fileId] ?: 0
+ }
fun maxHorizontalOffset(): Int = max(0, contentWidthPx - width)
+ fun resetHorizontalOffsets() {
+ horizontalOffsetsByFileId.clear()
+ }
+
+ private fun setHorizontalOffsetForFile(fileId: String, value: Int) {
+ val nextOffset = value.coerceIn(0, maxHorizontalOffset())
+ val current = horizontalOffsetsByFileId[fileId] ?: 0
+ if (current == nextOffset) return
+ horizontalOffsetsByFileId[fileId] = nextOffset
+ invalidate()
+ }
+
+ private fun clampHorizontalOffsets() {
+ val maxOffset = maxHorizontalOffset()
+ val iterator = horizontalOffsetsByFileId.entries.iterator()
+ while (iterator.hasNext()) {
+ val entry = iterator.next()
+ entry.setValue(entry.value.coerceIn(0, maxOffset))
+ }
+ }
+
+ private fun fileIdAtVerticalCenter(): String? {
+ if (rows.isEmpty()) return null
+ val centerY = verticalOffset + height / 2
+ val index = rowIndexAt(centerY).coerceIn(0, rows.lastIndex)
+ return (index downTo 0)
+ .asSequence()
+ .map { rows[it].resolvedFileId }
+ .firstOrNull { it.isNotEmpty() }
+ }
+
private fun rebuildOffsets() {
rowOffsets = IntArray(rows.size + 1)
rows.forEachIndexed { index, row ->
@@ -760,7 +805,7 @@
fill(canvas, theme.hunkBackground, 0f, top.toFloat(), width.toFloat(), bottom.toFloat())
textPaint.color = theme.hunkText
textPaint.textSize = style.codeFontSizePx
- drawScrollableCode(canvas, top, bottom) { codeX ->
+ drawScrollableCode(canvas, top, bottom, row.resolvedFileId) { codeX ->
canvas.drawText(
row.text.ifEmpty { row.content },
codeX,
@@ -773,7 +818,7 @@
private fun drawNoticeRow(canvas: Canvas, row: DiffRow, top: Int, bottom: Int) {
textPaint.color = theme.mutedText
textPaint.textSize = style.codeFontSizePx
- drawScrollableCode(canvas, top, bottom) { codeX ->
+ drawScrollableCode(canvas, top, bottom, row.resolvedFileId) { codeX ->
canvas.drawText(row.text, codeX, centeredBaseline(top, bottom, textPaint), textPaint)
}
}
@@ -782,7 +827,7 @@
fill(canvas, theme.headerBackground, style.gutterWidthPx, top.toFloat(), width.toFloat(), bottom.toFloat())
boldTextPaint.color = theme.text
boldTextPaint.textSize = 12f * density
- drawScrollableCode(canvas, top, bottom) { codeX ->
+ drawScrollableCode(canvas, top, bottom, row.resolvedFileId) { codeX ->
canvas.drawText(
row.commentSectionTitle.ifEmpty { row.commentRangeLabel.ifEmpty { "Comment" } },
codeX,
@@ -824,7 +869,8 @@
}
val tokens = tokensByRowId[row.id]
- drawScrollableCode(canvas, top, bottom) { codeX ->
+ drawScrollableCode(canvas, top, bottom, row.resolvedFileId) { codeX ->
+ drawWordDiffRanges(canvas, row, codeX, top, bottom)
if (tokens.isNullOrEmpty()) {
textPaint.textSize = style.codeFontSizePx
textPaint.color = when (row.change) {
@@ -859,16 +905,40 @@
canvas.drawText(newNumber, style.changeBarWidthPx + style.gutterWidthPx / 2f, baseline, textPaint)
}
+ private fun drawWordDiffRanges(canvas: Canvas, row: DiffRow, codeX: Float, top: Int, bottom: Int) {
+ val ranges = row.wordDiffRanges
+ if (ranges.isNullOrEmpty()) return
+ val change = row.change
+ if (change != "add" && change != "delete") return
+
+ val fillColor = if (change == "add") withAlpha(theme.addBar, 71) else withAlpha(theme.deleteBar, 71)
+ textPaint.textSize = style.codeFontSizePx
+ val charWidth = textPaint.measureText("m")
+ val highlightHeight = max(4f * density, min((bottom - top).toFloat() - 4f * density, textPaint.fontMetrics.let { -it.ascent + it.descent }))
+ val highlightY = (top + bottom) / 2f - highlightHeight / 2f
+ val cornerRadius = 3f * density
+
+ for (range in ranges) {
+ if (range.end <= range.start) continue
+ val startX = codeX + range.start * charWidth
+ val rangeWidth = max(2f * density, (range.end - range.start) * charWidth)
+ backgroundPaint.color = fillColor
+ canvas.drawRoundRect(startX, highlightY, startX + rangeWidth, highlightY + highlightHeight, cornerRadius, cornerRadius, backgroundPaint)
+ }
+ }
+
private fun drawScrollableCode(
canvas: Canvas,
top: Int,
bottom: Int,
+ fileId: String,
draw: (Float) -> Unit,
) {
val gutterEnd = style.changeBarWidthPx + style.gutterWidthPx
+ val offset = horizontalOffsetsByFileId[fileId] ?: 0
canvas.save()
canvas.clipRect(gutterEnd, top.toFloat(), width.toFloat(), bottom.toFloat())
- draw(gutterEnd + style.codePaddingPx - horizontalOffset)
+ draw(gutterEnd + style.codePaddingPx - offset)
canvas.restore()
}
@@ -895,10 +965,12 @@
private fun drawHorizontalScrollIndicator(canvas: Canvas) {
val maxOffset = maxHorizontalOffset()
if (maxOffset <= 0 || width <= 0) return
+ val currentOffset = horizontalOffset()
+ if (currentOffset <= 0) return
val trackWidth = width.toFloat()
val thumbWidth = max(24f * density, trackWidth * trackWidth / contentWidthPx)
val thumbTravel = trackWidth - thumbWidth
- val left = thumbTravel * horizontalOffset / maxOffset
+ val left = thumbTravel * currentOffset / maxOffset
fill(
canvas,
withAlpha(theme.mutedText, 110),
@@ -962,6 +1034,15 @@
change = row.optString("change", "context"),
oldLineNumber = row.optNullableInt("oldLineNumber"),
newLineNumber = row.optNullableInt("newLineNumber"),
+ wordDiffRanges = row.optJSONArray("wordDiffRanges")?.let { rangesArray ->
+ List(rangesArray.length()) { rangeIndex ->
+ val rangeObj = rangesArray.getJSONObject(rangeIndex)
+ DiffWordDiffRange(
+ start = rangeObj.optInt("start"),
+ end = rangeObj.optInt("end"),
+ )
+ }
+ },
commentText = row.optString("commentText"),
commentRangeLabel = row.optString("commentRangeLabel"),
commentSectionTitle = row.optString("commentSectionTitle"),You can send follow-ups to the cloud agent here.
|
|
||
| fun horizontalOffset(): Int = horizontalOffset | ||
|
|
||
| fun maxHorizontalOffset(): Int = max(0, contentWidthPx - width) |
There was a problem hiding this comment.
Shared horizontal scroll across files
Medium Severity
The T3ReviewDiffView on Android uses a single horizontal scroll offset for the entire diff. This differs from iOS's per-file tracking and can cause files to display with incorrect horizontal alignment if another file was previously scrolled.
Reviewed by Cursor Bugbot for commit 2b34778. Configure here.
|
Bugbot Autofix prepared fixes for all 4 issues found in the latest run.
Or push these changes by commenting: Preview (969f425c0b)diff --git a/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt b/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
--- a/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
+++ b/apps/mobile/modules/t3-composer-editor/android/src/main/java/expo/modules/t3composereditor/T3ComposerEditorView.kt
@@ -437,7 +437,9 @@
val imageUris = buildList {
if (clip != null) {
for (index in 0 until clip.itemCount) {
- clip.getItemAt(index).uri?.let { uri ->
+ val item = clip.getItemAt(index)
+ if (!item.text.isNullOrEmpty()) continue
+ item.uri?.let { uri ->
val mimeType = context.contentResolver.getType(uri)
if (mimeType?.startsWith("image/") == true) add(uri.toString())
}
diff --git a/apps/mobile/modules/t3-review-diff/android/build.gradle b/apps/mobile/modules/t3-review-diff/android/build.gradle
--- a/apps/mobile/modules/t3-review-diff/android/build.gradle
+++ b/apps/mobile/modules/t3-review-diff/android/build.gradle
@@ -16,4 +16,5 @@
dependencies {
implementation project(':expo-modules-core')
+ implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
}
diff --git a/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffModule.kt b/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffModule.kt
--- a/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffModule.kt
+++ b/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffModule.kt
@@ -44,6 +44,9 @@
Prop("initialRowIndex") { view: T3ReviewDiffView, initialRowIndex: Double ->
view.setInitialRowIndex(initialRowIndex)
}
+ Prop("refreshing") { view: T3ReviewDiffView, refreshing: Boolean ->
+ view.setRefreshing(refreshing)
+ }
Events(
"onDebug",
@@ -52,6 +55,7 @@
"onToggleViewedFile",
"onPressLine",
"onToggleComment",
+ "onPullToRefresh",
)
AsyncFunction("scrollToFile") { view: T3ReviewDiffView, fileId: String, animated: Boolean ->
diff --git a/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt b/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
--- a/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
+++ b/apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt
@@ -12,6 +12,7 @@
import android.view.ViewGroup
import android.view.ViewConfiguration
import android.widget.OverScroller
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import expo.modules.kotlin.AppContext
import expo.modules.kotlin.viewevent.EventDispatcher
import expo.modules.kotlin.views.ExpoView
@@ -24,12 +25,16 @@
class T3ReviewDiffView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
private val canvasView = DiffCanvasView(context)
+ private val swipeRefreshLayout = object : SwipeRefreshLayout(context) {
+ override fun canChildScrollUp(): Boolean = canvasView.verticalOffset() > 0
+ }
private val onDebug by EventDispatcher()
private val onVisibleFileChange by EventDispatcher()
private val onToggleFile by EventDispatcher()
private val onToggleViewedFile by EventDispatcher()
private val onPressLine by EventDispatcher()
private val onToggleComment by EventDispatcher()
+ private val onPullToRefresh by EventDispatcher()
private var rows: List<DiffRow> = emptyList()
private var visibleRows: List<DiffRow> = emptyList()
private var collapsedFileIds: Set<String> = emptySet()
@@ -66,12 +71,21 @@
emitVisibleFile(first)
}
- addView(
+ swipeRefreshLayout.addView(
canvasView,
LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT),
)
+ swipeRefreshLayout.setOnRefreshListener { onPullToRefresh(emptyMap()) }
+ addView(
+ swipeRefreshLayout,
+ LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT),
+ )
}
+ fun setRefreshing(value: Boolean) {
+ swipeRefreshLayout.isRefreshing = value
+ }
+
fun setTokensResetKey(value: String) {
if (tokensResetKey == value) return
tokensResetKey = value
@@ -163,6 +177,7 @@
}
fun setTokensPatchJson(value: String) {
+ val capturedContentResetKey = contentResetKey
payloadDecodeExecutor.execute {
try {
val payload = JSONObject(value)
@@ -171,6 +186,7 @@
payload.optJSONObject("tokensByRowId") ?: JSONObject(),
)
post {
+ if (capturedContentResetKey != contentResetKey) return@post
if (resetKey.isNotEmpty() && resetKey != tokensResetKey) return@post
if (decodedTokens.isNotEmpty()) {
canvasView.tokensByRowId = canvasView.tokensByRowId + decodedTokens
@@ -211,7 +227,14 @@
val deltaX = event.x - lastTouchX
val deltaY = event.y - lastTouchY
if (max(abs(deltaX), abs(deltaY)) > touchSlop) {
- dragAxis = if (abs(deltaY) >= abs(deltaX)) DragAxis.VERTICAL else DragAxis.HORIZONTAL
+ if (abs(deltaY) >= abs(deltaX)) {
+ if (deltaY > 0 && canvasView.verticalOffset() == 0) {
+ return false
+ }
+ dragAxis = DragAxis.VERTICAL
+ } else {
+ dragAxis = DragAxis.HORIZONTAL
+ }
}
}
return dragAxis != null
@@ -839,6 +862,7 @@
textPaint.textSize = style.codeFontSizePx
textPaint.color = token.color ?: theme.text
textPaint.typeface = when {
+ token.fontStyle and 3 == 3 -> Typeface.create(Typeface.MONOSPACE, Typeface.BOLD_ITALIC)
token.fontStyle and 1 != 0 -> Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC)
token.fontStyle and 2 != 0 -> Typeface.create(Typeface.MONOSPACE, Typeface.BOLD)
else -> Typeface.MONOSPACEYou can send follow-ups to the cloud agent here. |
There was a problem hiding this comment.
🟡 Medium threads/ThreadComposer.tsx:208
ComposerConnectionStatusPill renders as a pressable that calls props.onPress for every status kind, including the new "syncing" state. In ThreadComposer, onPress is wired to onReconnectEnvironment, so tapping the pill during normal message loading/syncing triggers retryEnvironment and interrupts the in-progress sync instead of acting as a passive progress indicator. Consider rendering the pill as a non-interactive View (or disabling the Pressable) when status.kind === "syncing".
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/src/features/threads/ThreadComposer.tsx around line 208:
`ComposerConnectionStatusPill` renders as a pressable that calls `props.onPress` for every status kind, including the new `"syncing"` state. In `ThreadComposer`, `onPress` is wired to `onReconnectEnvironment`, so tapping the pill during normal message loading/syncing triggers `retryEnvironment` and interrupts the in-progress sync instead of acting as a passive progress indicator. Consider rendering the pill as a non-interactive `View` (or disabling the `Pressable`) when `status.kind === "syncing"`.
| fun setContentResetKey(value: String) { | ||
| if (contentResetKey == value) return | ||
| contentResetKey = value | ||
| tokensDecodeGeneration += 1 | ||
| canvasView.tokensByRowId = emptyMap() |
There was a problem hiding this comment.
🟡 Medium t3reviewdiff/T3ReviewDiffView.kt:81
setContentResetKey clears tokens and scroll position but never clears rows, visibleRows, or canvasView.rows. Since new rowsJson is decoded asynchronously on a background thread, the previous file's rows remain rendered and tappable until the new rows finish decoding and are posted back. Users can see and interact with the wrong file's lines and comments after navigating to a different file. Consider clearing the rows in setContentResetKey so the view is blanked immediately while the new payload is in flight.
fun setContentResetKey(value: String) {
if (contentResetKey == value) return
contentResetKey = value
- tokensDecodeGeneration += 1
- canvasView.tokensByRowId = emptyMap()
+ rowsDecodeGeneration += 1
+ rows = emptyList()
+ visibleRows = emptyList()
+ canvasView.rows = emptyList()
+ canvasView.tokensByRowId = emptyMap()
lastVisibleFileId = null🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/modules/t3-review-diff/android/src/main/java/expo/modules/t3reviewdiff/T3ReviewDiffView.kt around lines 81-85:
`setContentResetKey` clears tokens and scroll position but never clears `rows`, `visibleRows`, or `canvasView.rows`. Since new `rowsJson` is decoded asynchronously on a background thread, the previous file's rows remain rendered and tappable until the new rows finish decoding and are posted back. Users can see and interact with the wrong file's lines and comments after navigating to a different file. Consider clearing the rows in `setContentResetKey` so the view is blanked immediately while the new payload is in flight.
| container.addView( | ||
| inputView, | ||
| LinearLayout.LayoutParams(1, 1), | ||
| inputView.addTextChangedListener( |
There was a problem hiding this comment.
🟠 High t3terminal/T3TerminalView.kt:200
TextWatcher.onTextChanged only forwards the inserted substring (s.subSequence(start, end)) and then clears the EditText in afterTextChanged. For replacement edits where before > 0 and count > 0—such as IME autocorrect replacing teh with the—Android reports only the replacement text, so this code emits the without first emitting a backspace to delete the previously sent teh. The terminal receives duplicated or mangled input instead of the final committed string.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/modules/t3-terminal/android/src/main/java/expo/modules/t3terminal/T3TerminalView.kt around line 200:
`TextWatcher.onTextChanged` only forwards the inserted substring (`s.subSequence(start, end)`) and then clears the `EditText` in `afterTextChanged`. For replacement edits where `before > 0` and `count > 0`—such as IME autocorrect replacing `teh` with `the`—Android reports only the replacement text, so this code emits `the` without first emitting a backspace to delete the previously sent `teh`. The terminal receives duplicated or mangled input instead of the final committed string.
Co-authored-by: codex <codex@users.noreply.github.com>
…ead work log The wrapper already re-exports expo-symbols' name type as AppSymbolName for exactly this use; drop the direct expo-symbols type import. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Long-pressing the app icon now offers a static "New task" shortcut plus the 2-3 most recently opened threads. Shortcut items carry in-app hrefs (same paths as agent notifications), so taps route through linkTo — on cold start the target is pushed over the initial Home route, keeping back-navigation sane (sheet back -> home, not app exit). Thread opens are derived from the root navigation state in the stack layout (no changes to the thread screens); titles come from the thread-shell atom and update the shortcut label once they load. Recents persist in secure storage so the launcher list survives restarts. Runtime updates are gated to Android; the config plugin generates the adaptive shortcut icon resource. Requires expo prebuild + a dev-client rebuild (new native module). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Flips predictiveBackGestureEnabled on (manifest android:enableOnBackInvokedCallback="true"), which retires legacy KEYCODE_BACK/onBackPressed() delivery on Android 13+. react-native 0.85 keeps JS back handling alive under that mode only on Android 16 + targetSdk 36 (ReactActivity registers an always-enabled OnBackPressedCallback there). On Android 13-15 nothing registers, so every back gesture would background the app and React Navigation/BackHandler would never hear it. withAndroidPredictiveBackCompat mirrors the same shim into MainActivity for API 33-35, wrapping invokeDefaultOnBackPressed so the exit path cannot re-enter the dispatcher and loop. Audit notes: - AndroidAnchoredMenu's BackHandler dismiss stays correct: back reaches JS via the registered dispatcher callbacks on every API level, and a registered callback also means the system never plays a "leave app" preview while the menu merely closes. Comment documents the invariant. - react-native-screens 4.25.2 is both the SDK 56 pin and the latest release; v4 has no predictive-back progress animations (upstream: software-mansion/react-native-screens#2540), so in-app pops keep the standard screens transition. - Android form sheets (Git sheets etc.) are Material BottomSheetDialog fragments that own their dialog-scoped back dispatch; NewTaskSheet and Settings present as cards on Android and pop via React Navigation. Requires expo prebuild + a dev-client rebuild (manifest + MainActivity). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Uniwind conversion moved the thread composer's pill stretch from
style={{maxWidth:'100%', width:'100%'}} to className="w-full max-w-full",
but ComposerToolbarButton's default cap (maxWidth: 172) still lived in the
inline style, which beats className-derived styles — so the model and
reasoning pills stopped filling their flex share and left dead space at the
row's end. Move the default cap into the class chain where tailwind-merge
lets callers lift it with max-w-full; the numeric maxWidth prop keeps
winning via the inline style.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| // Presents the T3 Connect onboarding sheet after an in-session sign-in. | ||
| useConnectOnboardingNavigation(); | ||
| // Launcher app shortcuts: routes shortcut taps and tracks opened threads. | ||
| useAppShortcuts(props.state); |
There was a problem hiding this comment.
🟠 High src/Stack.tsx:269
useAppShortcuts can crash the root layout on a malformed thread deep link. If a shortcut, notification, or external link resolves to the Thread route with invalid environmentId or threadId params, EnvironmentId.make() / ThreadId.make() inside the hook throw during render, bringing down the entire navigation tree instead of ignoring the bad link. The same constructors are wrapped in try/catch elsewhere (e.g. AdaptiveWorkspaceLayout), so guard the route-param parsing inside useAppShortcuts the same way.
Also found in 1 other location(s)
apps/mobile/src/features/shortcuts/appShortcuts.ts:32
shortcutHrefonly checks whetheraction.params?.hrefstarts with/, so any persisted shortcut carrying an arbitrary in-app path like/settingsor an obsolete route is treated as valid.useShortcutNavigationthen passes that value straight tolinkTo, which makes the app navigate on stale/foreign shortcuts even though this helper's contract says those must be rejected.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/src/Stack.tsx around line 269:
`useAppShortcuts` can crash the root layout on a malformed thread deep link. If a shortcut, notification, or external link resolves to the `Thread` route with invalid `environmentId` or `threadId` params, `EnvironmentId.make()` / `ThreadId.make()` inside the hook throw during render, bringing down the entire navigation tree instead of ignoring the bad link. The same constructors are wrapped in `try/catch` elsewhere (e.g. `AdaptiveWorkspaceLayout`), so guard the route-param parsing inside `useAppShortcuts` the same way.
Also found in 1 other location(s):
- apps/mobile/src/features/shortcuts/appShortcuts.ts:32 -- `shortcutHref` only checks whether `action.params?.href` starts with `/`, so any persisted shortcut carrying an arbitrary in-app path like `/settings` or an obsolete route is treated as valid. `useShortcutNavigation` then passes that value straight to `linkTo`, which makes the app navigate on stale/foreign shortcuts even though this helper's contract says those must be rejected.
Addresses the review-bot findings on the shortcuts module: - activeThreadRef (moved to the pure module) no longer trusts route params: trims, type-guards, and catches the branded id constructors' schema throws, returning null for malformed input. It runs during render of the root stack layout, so a crafted deep link like t3code-dev://threads/%20/x previously threw and took down the whole navigation tree. - A failed recents load no longer erases history: the empty in-memory fallback still syncs the launcher, but storage writes are gated until a successful load or a real thread open. Saves are also chained so an older write cannot land after (and overwrite) a newer one. - shortcutHref allowlists exactly /new and /threads/<seg>/<seg> instead of accepting any path-shaped string from launcher-persisted actions. - Launcher ids reuse the URI-encoded href, so distinct env/thread pairs can no longer collide on a plain '-' join. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hardware/gesture back inside a drilled-in submenu now pops one level (matching the tappable parent-title header) instead of dismissing the whole menu; a further back at the top level still closes it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ons, Nerd Font (#3775) Co-authored-by: Julius Marminge <julius@mac.lan> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
There are 15 total unresolved issues (including 13 from previous reviews).
Bugbot Autofix is ON, but a cloud agent failed to start.
Reviewed by Cursor Bugbot for commit 80cf687. Configure here.
| if (result._tag === "Failure" && reopenedStaleTerminalKeyRef.current === terminalKey) { | ||
| reopenedStaleTerminalKeyRef.current = null; | ||
| } | ||
| }); |
There was a problem hiding this comment.
Duplicate terminal open on launch
Medium Severity
The new useEffect designed to re-open stale or exited terminals can issue an openTerminal RPC concurrently with an existing pending terminal launch for the same session, leading to redundant openTerminal requests.
Reviewed by Cursor Bugbot for commit 80cf687. Configure here.
| const sessionEnded = terminal.status === "exited" || terminal.status === "closed"; | ||
| if (!sessionEnded || runningTerminalKeyRef.current !== terminalKey) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Exit missed after attach detach
Medium Severity
When terminalAttachInput becomes null (for example during a brief disconnect), the exit handler clears runningTerminalKeyRef but still requires that ref to match before treating exit/closed as a session the user ended on this screen. If the shell exits while attach is detached, reattach can show an exited session without navigating away, and the stale-reopen effect may spawn a new shell instead of mirroring the web drawer exit flow.
Reviewed by Cursor Bugbot for commit 80cf687. Configure here.
mrpunyetaz-cloud
left a comment
There was a problem hiding this comment.
I need to solve this before merged
…apping The CTM squash auto-merged upstream/main's Android mobile support (pingdotgg#3579) into CTM-shaped mobile sources, leaving hybrids: main's persistence/ and state/preferences.ts import an environment-cache-store written against pre-V2 contracts, and CTM's connection/storage.ts calls a makeCatalogStore export the main-shaped catalog-store no longer has. Restore the whole apps/mobile/src tree to codex-turn-mapping shape; mobile builds are not produced from this tree.
* Add middle-click close for right panel tabs (#3161) Co-authored-by: Julius Marminge <jmarminge@gmail.com> * fix: warm WSL before preflight in WSL-only backend mode (#3588) * Add Claude Sonnet 5 as the default Claude model (#3620) * Restore the ultrathink frame border effect (#3625) * fix(dev): Fix electron dev launch and add test (#3662) * Add adaptive split-view layout for iPad/mobile workspace (#3514) Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(mobile): compile patched native pods from source on EAS (#3667) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Make the thread composer read as elevated liquid glass (#3668) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Upgrade Vite Plus and enable bundled dev opt-in (#3679) * Surface pending tasks in mobile home and draft flow (#3670) * fix(mobile): combined test branch — scroll, back-swipe, thread lists, computer switching (#3687) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * Add repo-root favicon.svg so t3 code shows its own icon (#3683) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Load thread snapshots over HTTP before live sync (#3719) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * Fix mobile legend anchor under automatic iOS insets (#3684) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Improve live activity routing and diagnostics (#3685) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * Prevent Add Project sheet from collapsing on relayout (#3759) * Use variant-specific splash icons in mobile app (#3762) * Fix Expo widget asset wiring order (#3763) * Extend Done display to 15 minutes and show up to 5 Live Activity banner rows (#3761) * Clear VCS presentation state on finish (#3764) * Lead with the outcome when no agents are active in the Live Activity (#3768) * Add T3 Connect onboarding for mobile and web (#3765) * Revert "Add T3 Connect onboarding for mobile and web" (#3776) * Expose Clerk Google sign-in env vars to Expo (#3772) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Set up Cursor Cloud dev environment (web + Android toolchain) (#3755) Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Theo Browne <t3dotgg@users.noreply.github.com> * Revert "Revert "Add T3 Connect onboarding for mobile and web"" (#3777) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Use rounded depth logo for production splash screen (#3780) Co-authored-by: Cursor Agent <cursoragent@cursor.com> * fix(release): stage pnpm 11 allowBuilds for desktop installs (#3781) Co-authored-by: Cursor Agent <cursoragent@cursor.com> * Upgrade Clerk toolchain to latest versions (#3785) * fix(release): bump electron-builder so pnpm 11 deduped deps land in the asar (#3790) * Fix desktop native optional dependency packaging (#3816) * [codex] Upgrade Clerk stack (#3821) Co-authored-by: codex <codex@users.noreply.github.com> * [codex] Preserve worktree metadata during branch sync (#3822) Co-authored-by: codex <codex@users.noreply.github.com> * feat(client): persist offline environment data and mobile preferences (#3795) Co-authored-by: Julius Marminge <julius@mac.lan> Co-authored-by: codex <codex@users.noreply.github.com> * [codex] Label max and ultra reasoning (#3824) Co-authored-by: codex <codex@users.noreply.github.com> * fix(mobile): embed fonts and render project favicons reliably (#3823) Co-authored-by: codex <codex@users.noreply.github.com> * Show compact PR number badges in mobile thread rows (#3827) Co-authored-by: codex <codex@users.noreply.github.com> * Expose mobile PR indicator labels to accessibility (#3828) Co-authored-by: codex <codex@users.noreply.github.com> * Fix truncated chat error alert layout (#3899) * fix(marketing): show platform-appropriate commit shortcut on the website (#3644) * [codex] Add Android mobile support (#3579) Co-authored-by: Horus Lugo <horusgoul@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan> --------- Co-authored-by: Hugo Blom <6117705+huxcrux@users.noreply.github.com> Co-authored-by: Julius Marminge <jmarminge@gmail.com> Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Theo Browne <me@t3.gg> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Theo Browne <t3dotgg@users.noreply.github.com> Co-authored-by: Rowan <rowan@cardow.co> Co-authored-by: Patricio Gómez Meneses <107218376+Prgm-code@users.noreply.github.com> Co-authored-by: Jake Leventhal <jakeleventhal@me.com> Co-authored-by: Vedank Purohit <VedankPurohit2@gmail.com> Co-authored-by: Horus Lugo <horusgoul@gmail.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc>
Resolves apps/mobile/app.config.ts: keep fork's buildConfig(base) wrapper for self-hosted OTA updates while adopting upstream's extracted widgetsPlugin const and expo-asset plugin (Android support, pingdotgg#3579). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Merge upstream/main through [codex] Add Android mobile support (pingdotgg#3579) into the personal fork. Resolve the mobile configuration conflict by retaining upstream conditional widget installation for Android and personal-team builds while preserving the fork-configurable iOS bundle identifier for widget and app-group IDs. Remove the stale native-header theming fragment from ThreadRouteScreen while preserving upstream Android in-flow header behavior. Verification: - vp check (passes with 10 pre-existing warnings; output redirected around a Vite+ stdout panic) - vp run typecheck - vp run lint:mobile (passes; Linux host skips unavailable SwiftLint, ktlint, and detekt) No feature work is included in this sync merge.
* Fix truncated chat error alert layout (pingdotgg#3899) * fix(marketing): show platform-appropriate commit shortcut on the website (pingdotgg#3644) * [codex] Add Android mobile support (pingdotgg#3579) Co-authored-by: Horus Lugo <horusgoul@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan> --------- Co-authored-by: Jake Leventhal <jakeleventhal@me.com> Co-authored-by: Vedank Purohit <VedankPurohit2@gmail.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Horus Lugo <horusgoul@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan>
* Use rounded depth logo for production splash screen (pingdotgg#3780) Co-authored-by: Cursor Agent <cursoragent@cursor.com> * fix(release): stage pnpm 11 allowBuilds for desktop installs (pingdotgg#3781) Co-authored-by: Cursor Agent <cursoragent@cursor.com> * Upgrade Clerk toolchain to latest versions (pingdotgg#3785) * fix(release): bump electron-builder so pnpm 11 deduped deps land in the asar (pingdotgg#3790) * Fix desktop native optional dependency packaging (pingdotgg#3816) * [codex] Upgrade Clerk stack (pingdotgg#3821) Co-authored-by: codex <codex@users.noreply.github.com> * [codex] Preserve worktree metadata during branch sync (pingdotgg#3822) Co-authored-by: codex <codex@users.noreply.github.com> * feat(client): persist offline environment data and mobile preferences (pingdotgg#3795) Co-authored-by: Julius Marminge <julius@mac.lan> Co-authored-by: codex <codex@users.noreply.github.com> * [codex] Label max and ultra reasoning (pingdotgg#3824) Co-authored-by: codex <codex@users.noreply.github.com> * fix(mobile): embed fonts and render project favicons reliably (pingdotgg#3823) Co-authored-by: codex <codex@users.noreply.github.com> * Show compact PR number badges in mobile thread rows (pingdotgg#3827) Co-authored-by: codex <codex@users.noreply.github.com> * Expose mobile PR indicator labels to accessibility (pingdotgg#3828) Co-authored-by: codex <codex@users.noreply.github.com> * Fix truncated chat error alert layout (pingdotgg#3899) * fix(marketing): show platform-appropriate commit shortcut on the website (pingdotgg#3644) * [codex] Add Android mobile support (pingdotgg#3579) Co-authored-by: Horus Lugo <horusgoul@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan> * Use client-side fallbacks for missing project favicons (pingdotgg#3959) * Skip stale working-task notifications (pingdotgg#3961) * Prepare Android beta branding and review diff UI (pingdotgg#3967) * perf(web): duty-cycle status animations and remove fixed noise overlay (pingdotgg#3978) * fix(docs): correct CI task-runner commands in ci.md (pingdotgg#3990) * fix(docs): repair broken source links in architecture overview (pingdotgg#3991) * fix(docs): replace stale codething-mvp absolute paths with repo-relative links (pingdotgg#3992) * docs: Add T3 Code Legal Docs (pingdotgg#3972) Co-authored-by: codex <codex@users.noreply.github.com> * Fix Legal modal header crash (pingdotgg#4000) Co-authored-by: codex <codex@users.noreply.github.com> * [codex] Fix onboarding connection status (pingdotgg#4001) Co-authored-by: codex <codex@users.noreply.github.com> * Isolate native diff highlight grammar state (pingdotgg#4029) * Fix macOS fullscreen titlebar spacing (pingdotgg#4019) * Prevent duplicate project workspace roots (pingdotgg#3829) Co-authored-by: codex <codex@users.noreply.github.com> * Normalize over-indented markdown list items (pingdotgg#4020) Co-authored-by: codex <codex@users.noreply.github.com> * Resolve localhost preview URLs for remote environments (pingdotgg#4011) Co-authored-by: codex <codex@users.noreply.github.com> * fix(mobile): Send composer images in upload wire format (pingdotgg#4035) * Fix iOS terminal Enter input encoding (pingdotgg#4043) * Add native mobile share target support (pingdotgg#4021) Co-authored-by: codex <codex@users.noreply.github.com> * [codex] Expand real-route app store screenshot harness (pingdotgg#4014) Co-authored-by: codex <codex@users.noreply.github.com> * fix(server): use CLAUDE_CONFIG_DIR instead of HOME for Claude instanc… (pingdotgg#4017) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * Fix dropped events during initial thread snapshot (pingdotgg#4079) * feat: show nightly update changelog tooltip (pingdotgg#3832) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(git): treat selected commit paths literally (pingdotgg#3998) * fix(server): stabilize non-repository Git diagnostics (pingdotgg#4077) * Refresh app icons across release variants (pingdotgg#4080) Co-authored-by: codex <codex@users.noreply.github.com> * Update marketing GitHub star count (pingdotgg#4088) * fix(marketing): correct Cursor icon color (pingdotgg#4090) * Normalize protocol-relative remote host input as https (pingdotgg#3971) * fix(cursor): default binary path to cursor-agent (avoid path conflict w/ grok) (pingdotgg#4094) * Fix documented task-runner commands (bun run -> vp) (pingdotgg#3965) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Allow preview panel to grow on wide displays (pingdotgg#4044) * fix: prevent initial right-click from selecting a context menu item (pingdotgg#3877) * Fix duplicate keybinding rule when replacing with an existing rule (pingdotgg#3969) Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(server): image upload crashed dispatchCommand with a stack overflow (pingdotgg#3952) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * Remove unused code parameter from describePreviewError (pingdotgg#3970) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Julius Marminge <jmarminge@gmail.com> * [codex] prevent ACP assistant ID collisions after restarts (pingdotgg#3932) Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(web): inset Windows desktop scrollbars from resize edge (pingdotgg#4097) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Julius Marminge <jmarminge@gmail.com> * [codex] fix mobile composer Enter behavior (pingdotgg#3930) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> * feat(server): include runtime model and effort in Codex developer instructions (pingdotgg#3948) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(ux): spamming cmd + , no longer stack opening settings (pingdotgg#2757) Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(terminal): strip AppImage runtime env from spawned terminals (pingdotgg#3108) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> * fix(server): thread cwd through Claude capability probe (pingdotgg#2048) (pingdotgg#2124) Co-authored-by: Julius Marminge <julius0216@outlook.com> * [codex] fix: guard invalid web timestamps (pingdotgg#3515) Co-authored-by: Codex <codex@openai.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * [codex] fix: tolerate invalid latest user message timestamps (pingdotgg#3521) Co-authored-by: Codex <codex@openai.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * [codex] Fix provider update checks restore defaults (pingdotgg#3531) Co-authored-by: Codex <codex@openai.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(server): skip undecodable provider runtime rows when listing sessions (pingdotgg#3951) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Julius Marminge <jmarminge@gmail.com> Co-authored-by: codex <codex@users.noreply.github.com> * Share MCP OAuth locks across Codex shadow homes (pingdotgg#4104) * Preserve T3 Code identity in macOS development launcher (pingdotgg#4102) * fix(web): increase contrast of question option descriptions (pingdotgg#3867) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * feat: draft hero landing on the index route (pingdotgg#4055) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com> * feat: file explorer mention actions and zoom-aware context menus (pingdotgg#4054) Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(web): avoid duplicate mention text on paste Co-authored-by: codex <codex@users.noreply.github.com> * fix(mobile): restore iOS home screen branding (pingdotgg#4025) Co-authored-by: Julius Marminge <julius0216@outlook.com> * perf(client): defer active thread cache writes (pingdotgg#4006) * Default diffs to working changes (pingdotgg#3974) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Add Grok to marketing site provider list (pingdotgg#3484) * Fix reopening existing Diff tab (pingdotgg#3973) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Fix sending messages during active turns (pingdotgg#3919) Co-authored-by: Julius Marminge <julius0216@outlook.com> * [codex] Route OpenCode missing-session errors through Effect (pingdotgg#3608) Co-authored-by: Codex <codex@openai.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * [fix/feat:ui] Show default option badge (pingdotgg#3232) Co-authored-by: Julius Marminge <julius0216@outlook.com> * [fix/feat:ui] Preserve open-in editor brand colors (pingdotgg#3225) Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(web): handle macOS Home and End in composer (pingdotgg#2508) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Allow failed remote environments to be removed (pingdotgg#4084) Co-authored-by: Julius Marminge <julius0216@outlook.com> * [codex] canonicalize client timestamps (pingdotgg#4112) * [fix/feat:ui] Make selected menu checks blue (pingdotgg#3234) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> * fix(desktop): Validate WSL node version against engine range after probe success (pingdotgg#3621) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Refresh splash screen and favicon branding (pingdotgg#4120) * Add terminal selection copy action (pingdotgg#2904) * Add isolated app testing workflow (pingdotgg#4121) Co-authored-by: codex <codex@users.noreply.github.com> * feat(web): themed sidebar header art for nightly and dev builds (pingdotgg#4130) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Julius Marminge <jmarminge@gmail.com> * feat: add headless `t3 connect` setup for SSH hosts (pingdotgg#3749) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> * Refine T3 Connect authorization surfaces (pingdotgg#4159) Co-authored-by: codex <codex@users.noreply.github.com> * fix: increase OpenCode server startup timeout from 5s to 30s (pingdotgg#4132) * fix(shared): delete unused agentAwareness phase predicates (pingdotgg#4134) * fix(mobile): Stabilize native stack option updates (pingdotgg#4037) Co-authored-by: codex <codex@users.noreply.github.com> * Make test-t3-app skill discoverable by Claude Code (pingdotgg#4162) Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> * fix(web): improve dev sidebar backdrop contrast & remove version pills (pingdotgg#4166) * Fix draft banner stack overlap (pingdotgg#4164) Co-authored-by: codex <codex@users.noreply.github.com> * Add portable mobile app testing guidance (pingdotgg#4165) Co-authored-by: codex <codex@users.noreply.github.com> * fix(client): use lightweight connection probe (pingdotgg#4137) * fix(server): resolve Claude SDK executable path on Windows npm installs (pingdotgg#3740) * Fix project action preview settings persistence (pingdotgg#3842) * fix(desktop): allow clipboard writes in the preview browser (pingdotgg#3889) * fix(web): handle sidebar shortcut before editors (pingdotgg#3921) * fix(server): recognize Bedrock-backed Claude as authenticated (pingdotgg#3931) * Fix incorrect pluralization of “entry” (pingdotgg#3933) * feat(server): title background-task work-log rows with the task name (pingdotgg#3751) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix: delegate OpenCode session titles to provider (pingdotgg#3720) * Archive selected threads from the context menu (pingdotgg#3895) * fix(cli): support force removing projects (pingdotgg#3922) * fix: allow sidebar to be shrunk when wider than viewport (pingdotgg#2456) Co-authored-by: Shoaib Ansari <shoaibansari@Shoaibs-Mac-mini.local> Co-authored-by: Julius Marminge <julius0216@outlook.com> * fix(codex): show web search query and url in tool call details (pingdotgg#2093) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Add Codex launch arguments setting (pingdotgg#2892) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Julius Marminge <jmarminge@gmail.com> Co-authored-by: root <root@localhost.localdomain> * [orchestration] Clear stale active turn when session becomes inactive (pingdotgg#3159) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Regenerate Codex reset credit protocol bindings (pingdotgg#4173) Co-authored-by: codex <codex@users.noreply.github.com> * fix(preview): preserve direct localhost navigation (pingdotgg#3939) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> * Synchronize mobile threads with authoritative shell snapshots (pingdotgg#4163) Co-authored-by: codex <codex@users.noreply.github.com> * Gate iOS glass layout on native support (pingdotgg#4032) Co-authored-by: codex <codex@users.noreply.github.com> * fix(opencode): resume the OpenCode session on follow-ups instead of starting an empty one (pingdotgg#3617) Co-authored-by: codex <codex@users.noreply.github.com> * fix(server): use CLI for OpenCode health check instead of spawning server (pingdotgg#4153) * fix(web): scope timeline minimap hover target to the side gutter (pingdotgg#3869) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * [codex] show complete approval details (pingdotgg#4111) * fix(web): paint text selection over composer chips (pingdotgg#4139) Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com> * [codex] preserve custom model slugs (pingdotgg#4168) * fix(web): preview workspace images in the file panel (pingdotgg#3996) Co-authored-by: Rhiz3K <rhiz3k@protonmail.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * feat(web): drag files from the explorer into the chat composer (pingdotgg#4140) Co-authored-by: Julius Marminge <julius0216@outlook.com> Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com> * fix(desktop): preserve main window bounds (pingdotgg#3851) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> * perf(orchestration): speed up new-chat propagation and offline catch-up (pingdotgg#4177) Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * Finale: upgrade changed files card to fix various UI issues (pingdotgg#4113) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Pass CLI OAuth config to hosted web deploy (pingdotgg#4186) Co-authored-by: codex <codex@users.noreply.github.com> * fix(web): always show environment chip for remote projects (pingdotgg#4217) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(web): keep composer editable while disconnected (pingdotgg#4241) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix: better defaults — Claude 1M context, Codex gpt-5.6, worktrees from origin main (pingdotgg#4240) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(claude): handle all SDK stream messages; stop spurious work-log warning rows (pingdotgg#4244) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> --------- Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Rowan <rowan@cardow.co> Co-authored-by: Patricio Gómez Meneses <107218376+Prgm-code@users.noreply.github.com> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan> Co-authored-by: Jake Leventhal <jakeleventhal@me.com> Co-authored-by: Vedank Purohit <VedankPurohit2@gmail.com> Co-authored-by: Horus Lugo <horusgoul@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: Theo Browne <me@t3.gg> Co-authored-by: Kriday Dave <technocratix902@gmail.com> Co-authored-by: Ishan <ishansachu1@gmail.com> Co-authored-by: Dimitar Stoykov <mitkostoikov1988@gmail.com> Co-authored-by: Hugo Vizcaino Santana <42343504+HugoVizcainoSantana@users.noreply.github.com> Co-authored-by: Eric Tsai <52527831+EricTsai83@users.noreply.github.com> Co-authored-by: Manuel De Ceglie <80224270+AmoonPod@users.noreply.github.com> Co-authored-by: BunnyGamezsc <146652788+BunnyGamezsc@users.noreply.github.com> Co-authored-by: Olivier Melcher <olivier.melcher@gmail.com> Co-authored-by: Fazal Kadivar <fazalkadivar7@gmail.com> Co-authored-by: Julius Marminge <jmarminge@gmail.com> Co-authored-by: Maxwell Young <maxtheyoung@gmail.com> Co-authored-by: Yukun Shan <92423096+nateEc@users.noreply.github.com> Co-authored-by: James <105842516+jamesx0416@users.noreply.github.com> Co-authored-by: Leonel Rivas <herial_vi@icloud.com> Co-authored-by: Matt Van Horn <mvanhorn@users.noreply.github.com> Co-authored-by: Wout Stiens <71498452+StiensWout@users.noreply.github.com> Co-authored-by: Codex <codex@openai.com> Co-authored-by: xxashxx-svg <xxanshxx9@gmail.com> Co-authored-by: Yordis Prieto <yordis.prieto@gmail.com> Co-authored-by: Chris Michael Guzman <67719167+Chrrxs@users.noreply.github.com> Co-authored-by: Aditya Mer <101453576+Aditya190803@users.noreply.github.com> Co-authored-by: ss <69873514+sandersonstabo@users.noreply.github.com> Co-authored-by: Guilherme Vieira <46866023+GuilhermeVieiraDev@users.noreply.github.com> Co-authored-by: Noah Zepner <noah@zepner.dev> Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com> Co-authored-by: Taras <Taras.Fomin@gmail.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: eeinarsson <128746408+eeinarsson@users.noreply.github.com> Co-authored-by: David Whatley <nsxdavid@gmail.com> Co-authored-by: coach007 <6238600+keeperxy@users.noreply.github.com> Co-authored-by: Carlos Rico-Ospina <carlosricojr@gmail.com> Co-authored-by: Andrew Barnes <bortstheboat@gmail.com> Co-authored-by: Pieter van Zyl <20579513+PieterVanZyl-Dev@users.noreply.github.com> Co-authored-by: mel <mcmelon@nodiumhosting.com> Co-authored-by: Tristan Knight <tris203@gmail.com> Co-authored-by: Christoph Herzog <a.github@omega-id.com> Co-authored-by: Shoaib <shoaib050326@gmail.com> Co-authored-by: Shoaib Ansari <shoaibansari@Shoaibs-Mac-mini.local> Co-authored-by: root <root@localhost.localdomain> Co-authored-by: Andrew Forster <76947376+Andrew-Forster@users.noreply.github.com> Co-authored-by: Vadym Kotai <vdmkotai@gmail.com> Co-authored-by: Rhiz3K <33246262+Rhiz3K@users.noreply.github.com> Co-authored-by: Rhiz3K <rhiz3k@protonmail.com> Co-authored-by: Anirudh Coontoor <me@anirudhs.net> Co-authored-by: Rusiru Sadathana <rusirusadathana@gmail.com>
## What's Changed * Add middle-click close for right panel tabs by @huxcrux in https://github.com/pingdotgg/t3code/pull/3161 * fix: warm WSL before preflight in WSL-only backend mode by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/3588 * Add Claude Sonnet 5 as the default Claude model by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3620 * Restore the ultrathink frame border effect by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3625 * fix(dev): Fix electron dev launch and add test by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3662 * Add adaptive split-view layout for iPad/mobile workspace by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3514 * fix(mobile): compile patched native pods from source on EAS by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3667 * Make the thread composer read as elevated liquid glass by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3668 * Upgrade Vite Plus and enable bundled dev opt-in by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3679 * Surface pending tasks in mobile home and draft flow by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3670 * fix(mobile): combined test branch — scroll, back-swipe, thread lists, computer switching by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3687 * Add repo-root favicon.svg so t3 code shows its own icon by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3683 * Load thread snapshots over HTTP before live sync by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3719 * Fix mobile legend anchor under automatic iOS insets by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3684 * Improve live activity routing and diagnostics by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3685 * Prevent Add Project sheet from collapsing on relayout by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3759 * Use variant-specific splash icons in mobile app by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3762 * Fix Expo widget asset wiring order by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3763 * Extend Done display to 15 minutes and show up to 5 Live Activity banner rows by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3761 * Clear VCS presentation state on finish by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3764 * Lead with the outcome when no agents are active in the Live Activity by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3768 * Add T3 Connect onboarding for mobile and web by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3765 * Revert "Add T3 Connect onboarding for mobile and web" by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3776 * Expose Clerk Google sign-in env vars to Expo by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3772 * Set up Cursor Cloud dev environment (web + Android toolchain) by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3755 * Revert "Revert "Add T3 Connect onboarding for mobile and web"" by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3777 * Use rounded depth logo for production splash screen by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3780 * fix(release): stage pnpm 11 allowBuilds for desktop installs by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3781 * Upgrade Clerk toolchain to latest versions by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3785 * fix(release): bump electron-builder so pnpm 11 deduped deps land in the asar by @avocardow in https://github.com/pingdotgg/t3code/pull/3790 * Fix desktop native optional dependency packaging by @Prgm-code in https://github.com/pingdotgg/t3code/pull/3816 * [codex] Upgrade Clerk stack by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3821 * [codex] Preserve worktree metadata during branch sync by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3822 * feat(client): persist offline environment data and mobile preferences by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3795 * [codex] Label max and ultra reasoning by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3824 * fix(mobile): embed fonts and render project favicons reliably by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3823 * Show compact PR number badges in mobile thread rows by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3827 * Expose mobile PR indicator labels to accessibility by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3828 * Fix truncated chat error alert layout by @jakeleventhal in https://github.com/pingdotgg/t3code/pull/3899 * fix(marketing): show platform-appropriate commit shortcut on the website by @VedankPurohit in https://github.com/pingdotgg/t3code/pull/3644 * [codex] Add Android mobile support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3579 * Use client-side fallbacks for missing project favicons by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3959 * Skip stale working-task notifications by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3961 * Prepare Android beta branding and review diff UI by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3967 * perf(web): duty-cycle status animations and remove fixed noise overlay by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3978 * fix(docs): correct CI task-runner commands in ci.md by @kridaydave in https://github.com/pingdotgg/t3code/pull/3990 * fix(docs): repair broken source links in architecture overview by @kridaydave in https://github.com/pingdotgg/t3code/pull/3991 * fix(docs): replace stale codething-mvp absolute paths with repo-relative links by @kridaydave in https://github.com/pingdotgg/t3code/pull/3992 * docs: Add T3 Code Legal Docs by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3972 * Fix Legal modal header crash by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4000 * [codex] Fix onboarding connection status by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4001 * Isolate native diff highlight grammar state by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4029 * Fix macOS fullscreen titlebar spacing by @D3OXY in https://github.com/pingdotgg/t3code/pull/4019 * Prevent duplicate project workspace roots by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3829 * Normalize over-indented markdown list items by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4020 * Resolve localhost preview URLs for remote environments by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4011 * fix(mobile): Send composer images in upload wire format by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4035 * Fix iOS terminal Enter input encoding by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4043 * Add native mobile share target support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4021 * [codex] Expand real-route app store screenshot harness by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4014 * fix(server): use CLAUDE_CONFIG_DIR instead of HOME for Claude instanc… by @dmstoykov in https://github.com/pingdotgg/t3code/pull/4017 * Fix dropped events during initial thread snapshot by @D3OXY in https://github.com/pingdotgg/t3code/pull/4079 * feat: show nightly update changelog tooltip by @HugoVizcainoSantana in https://github.com/pingdotgg/t3code/pull/3832 * fix(git): treat selected commit paths literally by @EricTsai83 in https://github.com/pingdotgg/t3code/pull/3998 * fix(server): stabilize non-repository Git diagnostics by @EricTsai83 in https://github.com/pingdotgg/t3code/pull/4077 * Refresh app icons across release variants by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4080 * Update marketing GitHub star count by @AmoonPod in https://github.com/pingdotgg/t3code/pull/4088 * fix(marketing): correct Cursor icon color by @AmoonPod in https://github.com/pingdotgg/t3code/pull/4090 * Normalize protocol-relative remote host input as https by @kridaydave in https://github.com/pingdotgg/t3code/pull/3971 * fix(cursor): default binary path to cursor-agent (avoid path conflict w/ grok) by @BunnyGamezsc in https://github.com/pingdotgg/t3code/pull/4094 * Fix documented task-runner commands (bun run -> vp) by @kridaydave in https://github.com/pingdotgg/t3code/pull/3965 * Allow preview panel to grow on wide displays by @olivoil in https://github.com/pingdotgg/t3code/pull/4044 * fix: prevent initial right-click from selecting a context menu item by @Fazalkadivar21 in https://github.com/pingdotgg/t3code/pull/3877 * Fix duplicate keybinding rule when replacing with an existing rule by @kridaydave in https://github.com/pingdotgg/t3code/pull/3969 * fix(server): image upload crashed dispatchCommand with a stack overflow by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3952 * Remove unused code parameter from describePreviewError by @kridaydave in https://github.com/pingdotgg/t3code/pull/3970 * [codex] prevent ACP assistant ID collisions after restarts by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/3932 * fix(web): inset Windows desktop scrollbars from resize edge by @nateEc in https://github.com/pingdotgg/t3code/pull/4097 * [codex] fix mobile composer Enter behavior by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/3930 * feat(server): include runtime model and effort in Codex developer instructions by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3948 * fix(ux): spamming cmd + , no longer stack opening settings by @jamesx0416 in https://github.com/pingdotgg/t3code/pull/2757 * fix(terminal): strip AppImage runtime env from spawned terminals by @leorivastech in https://github.com/pingdotgg/t3code/pull/3108 * fix(server): thread cwd through Claude capability probe (#2048) by @mvanhorn in https://github.com/pingdotgg/t3code/pull/2124 * [codex] fix: guard invalid web timestamps by @StiensWout in https://github.com/pingdotgg/t3code/pull/3515 * [codex] fix: tolerate invalid latest user message timestamps by @StiensWout in https://github.com/pingdotgg/t3code/pull/3521 * [codex] Fix provider update checks restore defaults by @StiensWout in https://github.com/pingdotgg/t3code/pull/3531 * fix(server): skip undecodable provider runtime rows when listing sessions by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3951 * Share MCP OAuth locks across Codex shadow homes by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4104 * Preserve T3 Code identity in macOS development launcher by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4102 * fix(web): increase contrast of question option descriptions by @xxashxx-svg in https://github.com/pingdotgg/t3code/pull/3867 * feat: draft hero landing on the index route by @yordis in https://github.com/pingdotgg/t3code/pull/4055 * feat: file explorer mention actions and zoom-aware context menus by @yordis in https://github.com/pingdotgg/t3code/pull/4054 * fix(mobile): restore iOS home screen branding by @PixPMusic in https://github.com/pingdotgg/t3code/pull/4025 * perf(client): defer active thread cache writes by @Chrrxs in https://github.com/pingdotgg/t3code/pull/4006 * Default diffs to working changes by @jakeleventhal in https://github.com/pingdotgg/t3code/pull/3974 * Add Grok to marketing site provider list by @Aditya190803 in https://github.com/pingdotgg/t3code/pull/3484 * Fix reopening existing Diff tab by @jakeleventhal in https://github.com/pingdotgg/t3code/pull/3973 * Fix sending messages during active turns by @jakeleventhal in https://github.com/pingdotgg/t3code/pull/3919 * [codex] Route OpenCode missing-session errors through Effect by @StiensWout in https://github.com/pingdotgg/t3code/pull/3608 * [fix/feat:ui] Show default option badge by @sandersonstabo in https://github.com/pingdotgg/t3code/pull/3232 * [fix/feat:ui] Preserve open-in editor brand colors by @sandersonstabo in https://github.com/pingdotgg/t3code/pull/3225 * fix(web): handle macOS Home and End in composer by @GuilhermeVieiraDev in https://github.com/pingdotgg/t3code/pull/2508 * Allow failed remote environments to be removed by @zepi2509 in https://github.com/pingdotgg/t3code/pull/4084 * [codex] canonicalize client timestamps by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/4112 * [fix/feat:ui] Make selected menu checks blue by @sandersonstabo in https://github.com/pingdotgg/t3code/pull/3234 * fix(desktop): Validate WSL node version against engine range after probe success by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/3621 * Refresh splash screen and favicon branding by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4120 * Add terminal selection copy action by @tarik02 in https://github.com/pingdotgg/t3code/pull/2904 * Add isolated app testing workflow by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4121 * feat(web): themed sidebar header art for nightly and dev builds by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4130 * feat: add headless `t3 connect` setup for SSH hosts by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3749 * Refine T3 Connect authorization surfaces by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4159 * fix: increase OpenCode server startup timeout from 5s to 30s by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4132 * fix(shared): delete unused agentAwareness phase predicates by @kridaydave in https://github.com/pingdotgg/t3code/pull/4134 * fix(mobile): Stabilize native stack option updates by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4037 * Make test-t3-app skill discoverable by Claude Code by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4162 * fix(web): improve dev sidebar backdrop contrast & remove version pills by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4166 * Fix draft banner stack overlap by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4164 * Add portable mobile app testing guidance by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4165 * fix(client): use lightweight connection probe by @eeinarsson in https://github.com/pingdotgg/t3code/pull/4137 * fix(server): resolve Claude SDK executable path on Windows npm installs by @nsxdavid in https://github.com/pingdotgg/t3code/pull/3740 * Fix project action preview settings persistence by @keeperxy in https://github.com/pingdotgg/t3code/pull/3842 * fix(desktop): allow clipboard writes in the preview browser by @carlosricojr in https://github.com/pingdotgg/t3code/pull/3889 * fix(web): handle sidebar shortcut before editors by @Bortlesboat in https://github.com/pingdotgg/t3code/pull/3921 * fix(server): recognize Bedrock-backed Claude as authenticated by @PieterVanZyl-Dev in https://github.com/pingdotgg/t3code/pull/3931 * Fix incorrect pluralization of “entry” by @McMelonTV in https://github.com/pingdotgg/t3code/pull/3933 * feat(server): title background-task work-log rows with the task name by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3751 * fix: delegate OpenCode session titles to provider by @tris203 in https://github.com/pingdotgg/t3code/pull/3720 * Archive selected threads from the context menu by @theduke in https://github.com/pingdotgg/t3code/pull/3895 * fix(cli): support force removing projects by @Bortlesboat in https://github.com/pingdotgg/t3code/pull/3922 * fix: allow sidebar to be shrunk when wider than viewport by @shoaib050326 in https://github.com/pingdotgg/t3code/pull/2456 * fix(codex): show web search query and url in tool call details by @GuilhermeVieiraDev in https://github.com/pingdotgg/t3code/pull/2093 * Add Codex launch arguments setting by @jamesx0416 in https://github.com/pingdotgg/t3code/pull/2892 * [orchestration] Clear stale active turn when session becomes inactive by @Andrew-Forster in https://github.com/pingdotgg/t3code/pull/3159 * Regenerate Codex reset credit protocol bindings by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4173 * fix(preview): preserve direct localhost navigation by @Chrrxs in https://github.com/pingdotgg/t3code/pull/3939 * Synchronize mobile threads with authoritative shell snapshots by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4163 * Gate iOS glass layout on native support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4032 * fix(opencode): resume the OpenCode session on follow-ups instead of starting an empty one by @vdmkotai in https://github.com/pingdotgg/t3code/pull/3617 * fix(server): use CLI for OpenCode health check instead of spawning server by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4153 * fix(web): scope timeline minimap hover target to the side gutter by @xxashxx-svg in https://github.com/pingdotgg/t3code/pull/3869 * [codex] show complete approval details by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/4111 * fix(web): paint text selection over composer chips by @yordis in https://github.com/pingdotgg/t3code/pull/4139 * [codex] preserve custom model slugs by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/4168 * fix(web): preview workspace images in the file panel by @Rhiz3K in https://github.com/pingdotgg/t3code/pull/3996 * feat(web): drag files from the explorer into the chat composer by @yordis in https://github.com/pingdotgg/t3code/pull/4140 * fix(desktop): preserve main window bounds by @anirudhsama in https://github.com/pingdotgg/t3code/pull/3851 * perf(orchestration): speed up new-chat propagation and offline catch-up by @RusiruSadathana in https://github.com/pingdotgg/t3code/pull/4177 * Finale: upgrade changed files card to fix various UI issues by @sandersonstabo in https://github.com/pingdotgg/t3code/pull/4113 * Pass CLI OAuth config to hosted web deploy by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4186 * fix(web): always show environment chip for remote projects by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4217 * fix(web): keep composer editable while disconnected by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4241 * fix: better defaults — Claude 1M context, Codex gpt-5.6, worktrees from origin main by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4240 * fix(claude): handle all SDK stream messages; stop spurious work-log warning rows by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4244 * Sidebar v2 beta: flat thread list with a server-backed settled lifecycle by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4026 * fix(settings): validate the add-provider wizard step before advancing (#2813) by @leorivastech in https://github.com/pingdotgg/t3code/pull/3100 * fix(claude): isolate capability probe from user MCP servers by @jbbottoms in https://github.com/pingdotgg/t3code/pull/4015 * Preserve connecting status while a turn starts by @D3OXY in https://github.com/pingdotgg/t3code/pull/4101 * fix(server): stop restoring stale OpenCode models by @nateEc in https://github.com/pingdotgg/t3code/pull/4095 * [codex] keep scoped package references as text by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/4167 * fix(web): default provider selection for users without Codex by @mfazekas in https://github.com/pingdotgg/t3code/pull/4117 * Unify temporary worktree branch naming by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4278 * fix(web): use message-square icon for settled icon-less project threads in sidebar v2 by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4279 * Stabilize sidebar settling animations by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4280 * Restore Copy Link in chat link context menu by @caezium in https://github.com/pingdotgg/t3code/pull/4161 * fix(desktop): handle EPIPE errors on stdout/stderr to prevent crash dialog by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4213 * Preserve draft thread highlighting during promotion by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4283 * Move mobile working timer into the thread timeline by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4285 * Stabilize PR status lookups and provider session lifecycle by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4281 * fix: open command palette instead of custom dialog for new thread picker in SidebarV2 by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4269 * fix(server): don't drop sticky PR fallback when remote URL can't be resolved by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4289 * feat(web): copy branch name via right-click in the branch selector by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4275 * Add remote server updates and standalone service management by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4286 * Refine light-mode sidebar surfaces by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4268 * fix(mobile): don't mark Android VPN/Tailscale as offline when connected by @Wraient in https://github.com/pingdotgg/t3code/pull/3949 * improve and prevent silent thread branch drift and PR fetching by @justsomelegs in https://github.com/pingdotgg/t3code/pull/2284 * Refresh web application surfaces and dark-mode dialogs by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4319 * fix(web): new-thread defaults ignored for remote environments by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4276 * feat: add "Auto" runtime mode — AI-reviewed approvals for Codex and Claude by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4272 * Add shared t3.json project configuration support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4317 * Unify dialog glass and fix composer overlays by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4365 * fix(web): warn before silent Windows updates by @nateEc in https://github.com/pingdotgg/t3code/pull/4350 * [codex] Move project grouping to General settings by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4313 * [codex] Group project scopes in mobile thread lists by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4314 * [codex] Move mobile project grouping to General settings by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4315 * [codex] Deduplicate connection failure messaging by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4367 * Restore grouped project filtering in Sidebar V2 by @shivamhwp in https://github.com/pingdotgg/t3code/pull/4282 * [codex] restore Sidebar V2 project actions by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4373 * [codex] Group projects in new-thread pickers by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4312 * fix(web): restore dark composer toolbar styling by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4375 * Fix thread tooltip folder icon color by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4383 * fix(server): parse CLI version in update preflight by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4389 * fix(web): sidebar v2 polish — jump hints, working duration, in-flight fade, settled sort by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4274 * Fix logical project grouping labels on mobile by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4391 * Add preview color scheme controls and simplify project grouping by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4385 * fix(cli): publish nightly branded favicons by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4372 * Fix thread loading flash by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4396 * fix(client-runtime): keep a warm thread un-settled despite a merged/closed PR by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4309 * Fix composer context strip alignment and glass shell by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4404 * Polish iOS git progress overlay with glass effects by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4387 * Improve composer glass fallbacks by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4406 * feat(web): collapse large git diffs by default to make chat more readable by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4409 * Stop new threads inheriting checkout/branch from viewed thread by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4411 * fix: tone down branch-mismatch banner by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4416 * fix: Claude Code skills discoverable for the composer $ picker by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4414 * fix(web): keep settled threads reachable when opened directly by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4413 * feat(sidebar-v2): thread snoozing by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4311 * Upgrade Clerk packages and Expo integration by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4440 * Increase light-mode contrast for user message bubbles by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4441 * Restore model picker layout and retain iterative test state by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4450 * Color settled PR labels on hover by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4451 * [codex] Fix glass hover compositing artifacts by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4446 * Add Claude Opus 5 model by @thomaslittle in https://github.com/pingdotgg/t3code/pull/4472 * feat(web): add collapse-all toggle to diff panel by @0x4bs3nt in https://github.com/pingdotgg/t3code/pull/4475 * feat(web): show fast mode as a bolt instead of a "Normal" label by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4488 * feat(dev): keep worktree dev state isolated on T3 Code dev servers by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4555 * feat(dev): Make t3 code dev instances shareable over Tailscale by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4556 * fix(dev): skip browser-blocked ports by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4608 * fix: cut websocket throughput in half by pruning activity payloads by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4622 * perf(mobile): defer work-log detail serialization by @saphid in https://github.com/pingdotgg/t3code/pull/4607 * test: account for lazy thread feed details by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4628 * feat(relay): limit managed tunnels per user by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4530 * Add managed tunnel limits migration by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4635 * Add background preview capture and picture-in-picture support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4397 * feat(web): prompt stash — cmd+S saves the composer to a per-provider queue by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4453 * [codex] Upgrade Effect and Alchemy betas by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4643 * feat: allow new thread creation through project breadcrumbs by @0x4bs3nt in https://github.com/pingdotgg/t3code/pull/4638 * fix(web): scope PR state to the thread branch by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4460 * Drop redundant Relay user indexes by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4648 * feat(connect): release the Cloudflare tunnel when the environment shuts down by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4531 * Fix Relay Worker RuntimeContext wiring by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4653 * Fix live sidebar resize limits and defer Alchemy runtime context by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4655 * fix(web): constrain branch toolbar context by @maxktz in https://github.com/pingdotgg/t3code/pull/4657 * Keep MCP credentials alive across provider turns by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4659 * fix: close actions dropdown when editing by @0x4bs3nt in https://github.com/pingdotgg/t3code/pull/4660 * fix(preview): stabilize PiP viewport identity by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4661 * Add glass styling for thread tooltips and simplify preview tab handling by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4665 * Use tarball archiving for hosted web deploys by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4669 * fix(server): bound editor discovery during config loading by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4291 * Prevent draft thread detail polling before shell registration by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4670 * feat: add configurable source control writing settings by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4204 * feat(diff-panel): show total line additions and deletions by @0x4bs3nt in https://github.com/pingdotgg/t3code/pull/4674 * Clear provider update actions while updating by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4676 * Fix sidebar highlighting for draft threads by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4679 * Use glass surfaces for web toasts by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4681 * Show origin ref in branch trigger label by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4680 * fix(mobile): match react version to react-native 0.85.3 vendored renderer (19.2.3) by @KrzysztofMoch in https://github.com/pingdotgg/t3code/pull/4675 ## New Contributors * @avocardow made their first contribution in https://github.com/pingdotgg/t3code/pull/3790 * @Prgm-code made their first contribution in https://github.com/pingdotgg/t3code/pull/3816 * @jakeleventhal made their first contribution in https://github.com/pingdotgg/t3code/pull/3899 * @VedankPurohit made their first contribution in https://github.com/pingdotgg/t3code/pull/3644 * @kridaydave made their first contribution in https://github.com/pingdotgg/t3code/pull/3990 * @dmstoykov made their first contribution in https://github.com/pingdotgg/t3code/pull/4017 * @HugoVizcainoSantana made their first contribution in https://github.com/pingdotgg/t3code/pull/3832 * @EricTsai83 made their first contribution in https://github.com/pingdotgg/t3code/pull/3998 * @AmoonPod made their first contribution in https://github.com/pingdotgg/t3code/pull/4088 * @BunnyGamezsc made their first contribution in https://github.com/pingdotgg/t3code/pull/4094 * @olivoil made their first contribution in https://github.com/pingdotgg/t3code/pull/4044 * @Fazalkadivar21 made their first contribution in https://github.com/pingdotgg/t3code/pull/3877 * @maxwellyoung made their first contribution in https://github.com/pingdotgg/t3code/pull/3932 * @nateEc made their first contribution in https://github.com/pingdotgg/t3code/pull/4097 * @leorivastech made their first contribution in https://github.com/pingdotgg/t3code/pull/3108 * @xxashxx-svg made their first contribution in https://github.com/pingdotgg/t3code/pull/3867 * @yordis made their first contribution in https://github.com/pingdotgg/t3code/pull/4055 * @Chrrxs made their first contribution in https://github.com/pingdotgg/t3code/pull/4006 * @Aditya190803 made their first contribution in https://github.com/pingdotgg/t3code/pull/3484 * @zepi2509 made their first contribution in https://github.com/pingdotgg/t3code/pull/4084 * @eeinarsson made their first contribution in https://github.com/pingdotgg/t3code/pull/4137 * @keeperxy made their first contribution in https://github.com/pingdotgg/t3code/pull/3842 * @carlosricojr made their first contribution in https://github.com/pingdotgg/t3code/pull/3889 * @Bortlesboat made their first contribution in https://github.com/pingdotgg/t3code/pull/3921 * @PieterVanZyl-Dev made their first contribution in https://github.com/pingdotgg/t3code/pull/3931 * @McMelonTV made their first contribution in https://github.com/pingdotgg/t3code/pull/3933 * @tris203 made their first contribution in https://github.com/pingdotgg/t3code/pull/3720 * @theduke made their first contribution in https://github.com/pingdotgg/t3code/pull/3895 * @shoaib050326 made their first contribution in https://github.com/pingdotgg/t3code/pull/2456 * @vdmkotai made their first contribution in https://github.com/pingdotgg/t3code/pull/3617 * @Rhiz3K made their first contribution in https://github.com/pingdotgg/t3code/pull/3996 * @anirudhsama made their first contribution in https://github.com/pingdotgg/t3code/pull/3851 * @RusiruSadathana made their first contribution in https://github.com/pingdotgg/t3code/pull/4177 * @jbbottoms made their first contribution in https://github.com/pingdotgg/t3code/pull/4015 * @mfazekas made their first contribution in https://github.com/pingdotgg/t3code/pull/4117 * @caezium made their first contribution in https://github.com/pingdotgg/t3code/pull/4161 * @Wraient made their first contribution in https://github.com/pingdotgg/t3code/pull/3949 * @thomaslittle made their first contribution in https://github.com/pingdotgg/t3code/pull/4472 * @0x4bs3nt made their first contribution in https://github.com/pingdotgg/t3code/pull/4475 * @saphid made their first contribution in https://github.com/pingdotgg/t3code/pull/4607 * @maxktz made their first contribution in https://github.com/pingdotgg/t3code/pull/4657 * @KrzysztofMoch made their first contribution in https://github.com/pingdotgg/t3code/pull/4675 **Full Changelog**: https://github.com/pingdotgg/t3code/compare/v0.0.28...v0.0.29 ## What's Changed * Add middle-click close for right panel tabs by @huxcrux in https://github.com/pingdotgg/t3code/pull/3161 * fix: warm WSL before preflight in WSL-only backend mode by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/3588 * Add Claude Sonnet 5 as the default Claude model by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3620 * Restore the ultrathink frame border effect by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3625 * fix(dev): Fix electron dev launch and add test by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3662 * Add adaptive split-view layout for iPad/mobile workspace by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3514 * fix(mobile): compile patched native pods from source on EAS by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3667 * Make the thread composer read as elevated liquid glass by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3668 * Upgrade Vite Plus and enable bundled dev opt-in by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3679 * Surface pending tasks in mobile home and draft flow by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3670 * fix(mobile): combined test branch — scroll, back-swipe, thread lists, computer switching by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3687 * Add repo-root favicon.svg so t3 code shows its own icon by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3683 * Load thread snapshots over HTTP before live sync by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3719 * Fix mobile legend anchor under automatic iOS insets by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3684 * Improve live activity routing and diagnostics by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3685 * Prevent Add Project sheet from collapsing on relayout by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3759 * Use variant-specific splash icons in mobile app by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3762 * Fix Expo widget asset wiring order by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3763 * Extend Done display to 15 minutes and show up to 5 Live Activity banner rows by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3761 * Clear VCS presentation state on finish by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3764 * Lead with the outcome when no agents are active in the Live Activity by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3768 * Add T3 Connect onboarding for mobile and web by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3765 * Revert "Add T3 Connect onboarding for mobile and web" by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3776 * Expose Clerk Google sign-in env vars to Expo by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3772 * Set up Cursor Cloud dev environment (web + Android toolchain) by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3755 * Revert "Revert "Add T3 Connect onboarding for mobile and web"" by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3777 * Use rounded depth logo for production splash screen by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3780 * fix(release): stage pnpm 11 allowBuilds for desktop installs by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3781 * Upgrade Clerk toolchain to latest versions by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3785 * fix(release): bump electron-builder so pnpm 11 deduped deps land in the asar by @avocardow in https://github.com/pingdotgg/t3code/pull/3790 * Fix desktop native optional dependency packaging by @Prgm-code in https://github.com/pingdotgg/t3code/pull/3816 * [codex] Upgrade Clerk stack by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3821 * [codex] Preserve worktree metadata during branch sync by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3822 * feat(client): persist offline environment data and mobile preferences by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3795 * [codex] Label max and ultra reasoning by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3824 * fix(mobile): embed fonts and render project favicons reliably by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3823 * Show compact PR number badges in mobile thread rows by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3827 * Expose mobile PR indicator labels to accessibility by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3828 * Fix truncated chat error alert layout by @jakeleventhal in https://github.com/pingdotgg/t3code/pull/3899 * fix(marketing): show platform-appropriate commit shortcut on the website by @VedankPurohit in https://github.com/pingdotgg/t3code/pull/3644 * [codex] Add Android mobile support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3579 * Use client-side fallbacks for missing project favicons by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3959 * Skip stale working-task notifications by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3961 * Prepare Android beta branding and review diff UI by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3967 * perf(web): duty-cycle status animations and remove fixed noise overlay by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3978 * fix(docs): correct CI task-runner commands in ci.md by @kridaydave in https://github.com/pingdotgg/t3code/pull/3990 * fix(docs): repair broken source links in architecture overview by @kridaydave in https://github.com/pingdotgg/t3code/pull/3991 * fix(docs): replace stale codething-mvp absolute paths with repo-relative links by @kridaydave in https://github.com/pingdotgg/t3code/pull/3992 * docs: Add T3 Code Legal Docs by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3972 * Fix Legal modal header crash by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4000 * [codex] Fix onboarding connection status by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4001 * Isolate native diff highlight grammar state by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4029 * Fix macOS fullscreen titlebar spacing by @D3OXY in https://github.com/pingdotgg/t3code/pull/4019 * Prevent duplicate project workspace roots by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/3829 * Normalize over-indented markdown list items by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4020 * Resolve localhost preview URLs for remote environments by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4011 * fix(mobile): Send composer images in upload wire format by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4035 * Fix iOS terminal Enter input encoding by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4043 * Add native mobile share target support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4021 * [codex] Expand real-route app store screenshot harness by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4014 * fix(server): use CLAUDE_CONFIG_DIR instead of HOME for Claude instanc… by @dmstoykov in https://github.com/pingdotgg/t3code/pull/4017 * Fix dropped events during initial thread snapshot by @D3OXY in https://github.com/pingdotgg/t3code/pull/4079 * feat: show nightly update changelog tooltip by @HugoVizcainoSantana in https://github.com/pingdotgg/t3code/pull/3832 * fix(git): treat selected commit paths literally by @EricTsai83 in https://github.com/pingdotgg/t3code/pull/3998 * fix(server): stabilize non-repository Git diagnostics by @EricTsai83 in https://github.com/pingdotgg/t3code/pull/4077 * Refresh app icons across release variants by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4080 * Update marketing GitHub star count by @AmoonPod in https://github.com/pingdotgg/t3code/pull/4088 * fix(marketing): correct Cursor icon color by @AmoonPod in https://github.com/pingdotgg/t3code/pull/4090 * Normalize protocol-relative remote host input as https by @kridaydave in https://github.com/pingdotgg/t3code/pull/3971 * fix(cursor): default binary path to cursor-agent (avoid path conflict w/ grok) by @BunnyGamezsc in https://github.com/pingdotgg/t3code/pull/4094 * Fix documented task-runner commands (bun run -> vp) by @kridaydave in https://github.com/pingdotgg/t3code/pull/3965 * Allow preview panel to grow on wide displays by @olivoil in https://github.com/pingdotgg/t3code/pull/4044 * fix: prevent initial right-click from selecting a context menu item by @Fazalkadivar21 in https://github.com/pingdotgg/t3code/pull/3877 * Fix duplicate keybinding rule when replacing with an existing rule by @kridaydave in https://github.com/pingdotgg/t3code/pull/3969 * fix(server): image upload crashed dispatchCommand with a stack overflow by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3952 * Remove unused code parameter from describePreviewError by @kridaydave in https://github.com/pingdotgg/t3code/pull/3970 * [codex] prevent ACP assistant ID collisions after restarts by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/3932 * fix(web): inset Windows desktop scrollbars from resize edge by @nateEc in https://github.com/pingdotgg/t3code/pull/4097 * [codex] fix mobile composer Enter behavior by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/3930 * feat(server): include runtime model and effort in Codex developer instructions by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3948 * fix(ux): spamming cmd + , no longer stack opening settings by @jamesx0416 in https://github.com/pingdotgg/t3code/pull/2757 * fix(terminal): strip AppImage runtime env from spawned terminals by @leorivastech in https://github.com/pingdotgg/t3code/pull/3108 * fix(server): thread cwd through Claude capability probe (#2048) by @mvanhorn in https://github.com/pingdotgg/t3code/pull/2124 * [codex] fix: guard invalid web timestamps by @StiensWout in https://github.com/pingdotgg/t3code/pull/3515 * [codex] fix: tolerate invalid latest user message timestamps by @StiensWout in https://github.com/pingdotgg/t3code/pull/3521 * [codex] Fix provider update checks restore defaults by @StiensWout in https://github.com/pingdotgg/t3code/pull/3531 * fix(server): skip undecodable provider runtime rows when listing sessions by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3951 * Share MCP OAuth locks across Codex shadow homes by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4104 * Preserve T3 Code identity in macOS development launcher by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4102 * fix(web): increase contrast of question option descriptions by @xxashxx-svg in https://github.com/pingdotgg/t3code/pull/3867 * feat: draft hero landing on the index route by @yordis in https://github.com/pingdotgg/t3code/pull/4055 * feat: file explorer mention actions and zoom-aware context menus by @yordis in https://github.com/pingdotgg/t3code/pull/4054 * fix(mobile): restore iOS home screen branding by @PixPMusic in https://github.com/pingdotgg/t3code/pull/4025 * perf(client): defer active thread cache writes by @Chrrxs in https://github.com/pingdotgg/t3code/pull/4006 * Default diffs to working changes by @jakeleventhal in https://github.com/pingdotgg/t3code/pull/3974 * Add Grok to marketing site provider list by @Aditya190803 in https://github.com/pingdotgg/t3code/pull/3484 * Fix reopening existing Diff tab by @jakeleventhal in https://github.com/pingdotgg/t3code/pull/3973 * Fix sending messages during active turns by @jakeleventhal in https://github.com/pingdotgg/t3code/pull/3919 * [codex] Route OpenCode missing-session errors through Effect by @StiensWout in https://github.com/pingdotgg/t3code/pull/3608 * [fix/feat:ui] Show default option badge by @sandersonstabo in https://github.com/pingdotgg/t3code/pull/3232 * [fix/feat:ui] Preserve open-in editor brand colors by @sandersonstabo in https://github.com/pingdotgg/t3code/pull/3225 * fix(web): handle macOS Home and End in composer by @GuilhermeVieiraDev in https://github.com/pingdotgg/t3code/pull/2508 * Allow failed remote environments to be removed by @zepi2509 in https://github.com/pingdotgg/t3code/pull/4084 * [codex] canonicalize client timestamps by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/4112 * [fix/feat:ui] Make selected menu checks blue by @sandersonstabo in https://github.com/pingdotgg/t3code/pull/3234 * fix(desktop): Validate WSL node version against engine range after probe success by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/3621 * Refresh splash screen and favicon branding by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4120 * Add terminal selection copy action by @tarik02 in https://github.com/pingdotgg/t3code/pull/2904 * Add isolated app testing workflow by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4121 * feat(web): themed sidebar header art for nightly and dev builds by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4130 * feat: add headless `t3 connect` setup for SSH hosts by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3749 * Refine T3 Connect authorization surfaces by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4159 * fix: increase OpenCode server startup timeout from 5s to 30s by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4132 * fix(shared): delete unused agentAwareness phase predicates by @kridaydave in https://github.com/pingdotgg/t3code/pull/4134 * fix(mobile): Stabilize native stack option updates by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4037 * Make test-t3-app skill discoverable by Claude Code by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4162 * fix(web): improve dev sidebar backdrop contrast & remove version pills by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4166 * Fix draft banner stack overlap by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4164 * Add portable mobile app testing guidance by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4165 * fix(client): use lightweight connection probe by @eeinarsson in https://github.com/pingdotgg/t3code/pull/4137 * fix(server): resolve Claude SDK executable path on Windows npm installs by @nsxdavid in https://github.com/pingdotgg/t3code/pull/3740 * Fix project action preview settings persistence by @keeperxy in https://github.com/pingdotgg/t3code/pull/3842 * fix(desktop): allow clipboard writes in the preview browser by @carlosricojr in https://github.com/pingdotgg/t3code/pull/3889 * fix(web): handle sidebar shortcut before editors by @Bortlesboat in https://github.com/pingdotgg/t3code/pull/3921 * fix(server): recognize Bedrock-backed Claude as authenticated by @PieterVanZyl-Dev in https://github.com/pingdotgg/t3code/pull/3931 * Fix incorrect pluralization of “entry” by @McMelonTV in https://github.com/pingdotgg/t3code/pull/3933 * feat(server): title background-task work-log rows with the task name by @t3dotgg in https://github.com/pingdotgg/t3code/pull/3751 * fix: delegate OpenCode session titles to provider by @tris203 in https://github.com/pingdotgg/t3code/pull/3720 * Archive selected threads from the context menu by @theduke in https://github.com/pingdotgg/t3code/pull/3895 * fix(cli): support force removing projects by @Bortlesboat in https://github.com/pingdotgg/t3code/pull/3922 * fix: allow sidebar to be shrunk when wider than viewport by @shoaib050326 in https://github.com/pingdotgg/t3code/pull/2456 * fix(codex): show web search query and url in tool call details by @GuilhermeVieiraDev in https://github.com/pingdotgg/t3code/pull/2093 * Add Codex launch arguments setting by @jamesx0416 in https://github.com/pingdotgg/t3code/pull/2892 * [orchestration] Clear stale active turn when session becomes inactive by @Andrew-Forster in https://github.com/pingdotgg/t3code/pull/3159 * Regenerate Codex reset credit protocol bindings by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4173 * fix(preview): preserve direct localhost navigation by @Chrrxs in https://github.com/pingdotgg/t3code/pull/3939 * Synchronize mobile threads with authoritative shell snapshots by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4163 * Gate iOS glass layout on native support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4032 * fix(opencode): resume the OpenCode session on follow-ups instead of starting an empty one by @vdmkotai in https://github.com/pingdotgg/t3code/pull/3617 * fix(server): use CLI for OpenCode health check instead of spawning server by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4153 * fix(web): scope timeline minimap hover target to the side gutter by @xxashxx-svg in https://github.com/pingdotgg/t3code/pull/3869 * [codex] show complete approval details by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/4111 * fix(web): paint text selection over composer chips by @yordis in https://github.com/pingdotgg/t3code/pull/4139 * [codex] preserve custom model slugs by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/4168 * fix(web): preview workspace images in the file panel by @Rhiz3K in https://github.com/pingdotgg/t3code/pull/3996 * feat(web): drag files from the explorer into the chat composer by @yordis in https://github.com/pingdotgg/t3code/pull/4140 * fix(desktop): preserve main window bounds by @anirudhsama in https://github.com/pingdotgg/t3code/pull/3851 * perf(orchestration): speed up new-chat propagation and offline catch-up by @RusiruSadathana in https://github.com/pingdotgg/t3code/pull/4177 * Finale: upgrade changed files card to fix various UI issues by @sandersonstabo in https://github.com/pingdotgg/t3code/pull/4113 * Pass CLI OAuth config to hosted web deploy by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4186 * fix(web): always show environment chip for remote projects by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4217 * fix(web): keep composer editable while disconnected by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4241 * fix: better defaults — Claude 1M context, Codex gpt-5.6, worktrees from origin main by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4240 * fix(claude): handle all SDK stream messages; stop spurious work-log warning rows by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4244 * Sidebar v2 beta: flat thread list with a server-backed settled lifecycle by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4026 * fix(settings): validate the add-provider wizard step before advancing (#2813) by @leorivastech in https://github.com/pingdotgg/t3code/pull/3100 * fix(claude): isolate capability probe from user MCP servers by @jbbottoms in https://github.com/pingdotgg/t3code/pull/4015 * Preserve connecting status while a turn starts by @D3OXY in https://github.com/pingdotgg/t3code/pull/4101 * fix(server): stop restoring stale OpenCode models by @nateEc in https://github.com/pingdotgg/t3code/pull/4095 * [codex] keep scoped package references as text by @maxwellyoung in https://github.com/pingdotgg/t3code/pull/4167 * fix(web): default provider selection for users without Codex by @mfazekas in https://github.com/pingdotgg/t3code/pull/4117 * Unify temporary worktree branch naming by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4278 * fix(web): use message-square icon for settled icon-less project threads in sidebar v2 by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4279 * Stabilize sidebar settling animations by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4280 * Restore Copy Link in chat link context menu by @caezium in https://github.com/pingdotgg/t3code/pull/4161 * fix(desktop): handle EPIPE errors on stdout/stderr to prevent crash dialog by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4213 * Preserve draft thread highlighting during promotion by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4283 * Move mobile working timer into the thread timeline by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4285 * Stabilize PR status lookups and provider session lifecycle by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4281 * fix: open command palette instead of custom dialog for new thread picker in SidebarV2 by @UtkarshUsername in https://github.com/pingdotgg/t3code/pull/4269 * fix(server): don't drop sticky PR fallback when remote URL can't be resolved by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4289 * feat(web): copy branch name via right-click in the branch selector by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4275 * Add remote server updates and standalone service management by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4286 * Refine light-mode sidebar surfaces by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4268 * fix(mobile): don't mark Android VPN/Tailscale as offline when connected by @Wraient in https://github.com/pingdotgg/t3code/pull/3949 * improve and prevent silent thread branch drift and PR fetching by @justsomelegs in https://github.com/pingdotgg/t3code/pull/2284 * Refresh web application surfaces and dark-mode dialogs by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4319 * fix(web): new-thread defaults ignored for remote environments by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4276 * feat: add "Auto" runtime mode — AI-reviewed approvals for Codex and Claude by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4272 * Add shared t3.json project configuration support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4317 * Unify dialog glass and fix composer overlays by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4365 * fix(web): warn before silent Windows updates by @nateEc in https://github.com/pingdotgg/t3code/pull/4350 * [codex] Move project grouping to General settings by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4313 * [codex] Group project scopes in mobile thread lists by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4314 * [codex] Move mobile project grouping to General settings by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4315 * [codex] Deduplicate connection failure messaging by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4367 * Restore grouped project filtering in Sidebar V2 by @shivamhwp in https://github.com/pingdotgg/t3code/pull/4282 * [codex] restore Sidebar V2 project actions by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4373 * [codex] Group projects in new-thread pickers by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4312 * fix(web): restore dark composer toolbar styling by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4375 * Fix thread tooltip folder icon color by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4383 * fix(server): parse CLI version in update preflight by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4389 * fix(web): sidebar v2 polish — jump hints, working duration, in-flight fade, settled sort by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4274 * Fix logical project grouping labels on mobile by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4391 * Add preview color scheme controls and simplify project grouping by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4385 * fix(cli): publish nightly branded favicons by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4372 * Fix thread loading flash by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4396 * fix(client-runtime): keep a warm thread un-settled despite a merged/closed PR by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4309 * Fix composer context strip alignment and glass shell by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4404 * Polish iOS git progress overlay with glass effects by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4387 * Improve composer glass fallbacks by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4406 * feat(web): collapse large git diffs by default to make chat more readable by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4409 * Stop new threads inheriting checkout/branch from viewed thread by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4411 * fix: tone down branch-mismatch banner by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4416 * fix: Claude Code skills discoverable for the composer $ picker by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4414 * fix(web): keep settled threads reachable when opened directly by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4413 * feat(sidebar-v2): thread snoozing by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4311 * Upgrade Clerk packages and Expo integration by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4440 * Increase light-mode contrast for user message bubbles by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4441 * Restore model picker layout and retain iterative test state by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4450 * Color settled PR labels on hover by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4451 * [codex] Fix glass hover compositing artifacts by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4446 * Add Claude Opus 5 model by @thomaslittle in https://github.com/pingdotgg/t3code/pull/4472 * feat(web): add collapse-all toggle to diff panel by @0x4bs3nt in https://github.com/pingdotgg/t3code/pull/4475 * feat(web): show fast mode as a bolt instead of a "Normal" label by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4488 * feat(dev): keep worktree dev state isolated on T3 Code dev servers by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4555 * feat(dev): Make t3 code dev instances shareable over Tailscale by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4556 * fix(dev): skip browser-blocked ports by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4608 * fix: cut websocket throughput in half by pruning activity payloads by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4622 * perf(mobile): defer work-log detail serialization by @saphid in https://github.com/pingdotgg/t3code/pull/4607 * test: account for lazy thread feed details by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4628 * feat(relay): limit managed tunnels per user by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4530 * Add managed tunnel limits migration by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4635 * Add background preview capture and picture-in-picture support by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4397 * feat(web): prompt stash — cmd+S saves the composer to a per-provider queue by @t3dotgg in https://github.com/pingdotgg/t3code/pull/4453 * [codex] Upgrade Effect and Alchemy betas by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4643 * feat: allow new thread creation through project breadcrumbs by @0x4bs3nt in https://github.com/pingdotgg/t3code/pull/4638 * fix(web): scope PR state to the thread branch by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4460 * Drop redundant Relay user indexes by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4648 * feat(connect): release the Cloudflare tunnel when the environment shuts down by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4531 * Fix Relay Worker RuntimeContext wiring by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4653 * Fix live sidebar resize limits and defer Alchemy runtime context by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4655 * fix(web): constrain branch toolbar context by @maxktz in https://github.com/pingdotgg/t3code/pull/4657 * Keep MCP credentials alive across provider turns by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4659 * fix: close actions dropdown when editing by @0x4bs3nt in https://github.com/pingdotgg/t3code/pull/4660 * fix(preview): stabilize PiP viewport identity by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4661 * Add glass styling for thread tooltips and simplify preview tab handling by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4665 * Use tarball archiving for hosted web deploys by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4669 * fix(server): bound editor discovery during config loading by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4291 * Prevent draft thread detail polling before shell registration by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4670 * feat: add configurable source control writing settings by @maria-rcks in https://github.com/pingdotgg/t3code/pull/4204 * feat(diff-panel): show total line additions and deletions by @0x4bs3nt in https://github.com/pingdotgg/t3code/pull/4674 * Clear provider update actions while updating by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4676 * Fix sidebar highlighting for draft threads by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4679 * Use glass surfaces for web toasts by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4681 * Show origin ref in branch trigger label by @juliusmarminge in https://github.com/pingdotgg/t3code/pull/4680 * fix(mobile): match react version to react-native 0.85.3 vendored renderer (19.2.3) by @KrzysztofMoch in https://github.com/pingdotgg/t3code/pull/4675 ## New Contributors * @avocardow made their first contribution in https://github.com/pingdotgg/t3code/pull/3790 * @Prgm-code made their first contribution in https://github.com/pingdotgg/t3code/pull/3816 * @jakeleventhal made their first contribution in https://github.com/pingdotgg/t3code/pull/3899 * @VedankPurohit made their first contribution in https://github.com/pingdotgg/t3code/pull/3644 * @kridaydave made their first contribution in https://github.com/pingdotgg/t3code/pull/3990 * @dmstoykov made their first contribution in https://github.com/pingdotgg/t3code/pull/4017 * @HugoVizcainoSantana made their first contribution in https://github.com/pingdotgg/t3code/pull/3832 * @EricTsai83 made their first contribution in https://github.com/pingdotgg/t3code/pull/3998 * @AmoonPod made their first contribution in https://github.com/pingdotgg/t3code/pull/4088 * @BunnyGamezsc made their first contribution in https://github.com/pingdotgg/t3code/pull/4094 * @olivoil made their first contribution in https://github.com/pingdotgg/t3code/pull/4044 * @Fazalkadivar21 made their first contribution in https://github.com/pingdotgg/t3code/pull/3877 * @maxwellyoung made their first contribution in https://github.com/pingdotgg/t3code/pull/3932 * @nateEc made their first contribution in https://github.com/pingdotgg/t3code/pull/4097 * @leorivastech made their first contribution in https://github.com/pingdotgg/t3code/pull/3108 * @xxashxx-svg made their first contribution in https://github.com/pingdotgg/t3code/pull/3867 * @yordis made their first contribution in https://github.com/pingdotgg/t3code/pull/4055 * @Chrrxs made their first contribution in https://github.com/pingdotgg/t3code/pull/4006 * @Aditya190803 made their first contribution in https://github.com/pingdotgg/t3code/pull/3484 * @zepi2509 made their first contribution …
Co-authored-by: Horus Lugo <horusgoul@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan>
Co-authored-by: Horus Lugo <horusgoul@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: maria-rcks <maria@kuuro.net> Co-authored-by: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com> Co-authored-by: Alex <me@pixp.cc> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@mac.lan>



Summary
Why
The mobile app inherited iOS-only native modules and navigation assumptions. Android could build only after filling those native module gaps, and several shared screens rendered with incorrect insets, missing icons, inaccessible controls, or desktop/iOS-oriented interaction patterns.
The review diff also scrolled its entire native canvas horizontally, which moved line gutters and file headers with the code. It now owns horizontal code offset internally so persistent chrome stays fixed.
Impact
Android now has a usable end-to-end thread, file, Git review, composer, and connection flow. The iOS implementation keeps using its existing native toolbar and form-sheet behavior through platform-specific branches.
Validation
vp checkvp run typecheckvp run lint:mobile./gradlew :t3tools-mobile-review-diff-native:compileDebugKotlin./gradlew :app:assembleDebugNote
Add Android support to the mobile app
libghostty-vtwith a custom canvas view (TerminalCanvasView.kt) for font metrics, styling, and cursor blinkingexpo-symbolsusage across the codebaseOverlayPortalto avoid keyboard focus loss, and wiresControlPillMenuto use it on Android.solibraries for four ABIs; any ABI mismatch or library loading failure will crash the terminal viewChanges since #3579 opened
📊 Macroscope summarized 80cf687. 10 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.
Note
High Risk
Large new native/Android surface (review diff, composer, terminal JNI and prebuilt libs) plus iOS entitlement gating; regressions or load failures would hit core editing, review, and terminal flows.
Overview
Adds Android Expo modules for the composer editor, header buttons, and review diff so JS can use the same view contracts as iOS, including a custom canvas diff surface with fixed gutters, sticky file headers, async JSON decoding, and scroll/tap events.
Build and platform config:
app.config.tsgains an opt-in iOS Personal Team mode (T3CODE_IOS_PERSONAL_TEAM+ bundle ID validation) that drops widgets, push, app groups, and native Sign in with Apple; Clerk’sappleSignInplugin flag follows that mode. Android picks up predictive back,expo-quick-actions,expo-asset, and several Gradle/UI config plugins. Docs add Personal Team andios:release(Metro-free Release) flows; Metro blocks the repo.t3directory from the bundle.Terminal: Android is documented and vendored with pinned
libghostty-vt(headers/libs) for VT parsing/rendering, separate from the existing iOS GhosttyKit fork.Minor UI tweak: lighter translucent card tokens in
global.css.Reviewed by Cursor Bugbot for commit 80cf687. Bugbot is set up for automated code reviews on this repo. Configure here.