Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1371 commits
Select commit Hold shift + click to select a range
c5b869f
fix(desktop): chat videos go fullscreen across the whole screen again…
Nov 9, 2026
062b332
fix(desktop): recording cursor stays above modal dialogs and popovers…
Nov 9, 2026
c1463af
perf(web): changing file counts no longer re-render the chat view (#2…
Nov 9, 2026
9c7750d
fix(desktop): a window saved 1px past a display edge reopens where it…
Nov 9, 2026
2b1db48
fix(web): open citation comments with the caret at the end (#28667)
Nov 9, 2026
0e65e63
fix(desktop): page redirects during loading no longer show a navigati…
Nov 9, 2026
50e176d
fix(web): banner button hover follows the banner's rounded corners (#…
Nov 9, 2026
739aba7
fix(web,mobile): per-thread auto-settle menu says what it does (#29025)
Nov 9, 2026
a0056dd
perf(web): switching threads no longer re-renders every sidebar row (…
Nov 9, 2026
a3cd0aa
fix(web): deleting an archived thread also clears its draft, staged u…
Nov 9, 2026
dca297c
perf(web): Appearance settings no longer re-probe fonts on every open…
Nov 9, 2026
220a743
fix(desktop): discover browser profiles in XDG config home (#29243)
Nov 9, 2026
e26decd
fix(desktop): annotating inside a page's dialog no longer closes it (…
Nov 9, 2026
a72481f
fix(desktop): preserve concurrent downloads with the same name (#29308)
Nov 9, 2026
ceed427
fix(web): removing a queued message's attachment counts as an edit wh…
Nov 9, 2026
e74b410
fix(web): keybinding settings recognize the previewOpen condition (#2…
Nov 9, 2026
75200f4
fix(web): thread navigation shortcuts honor previewFocus and previewO…
Nov 9, 2026
8395f20
fix(web): editing a scheduled task shows its saved time when the hour…
Nov 9, 2026
2dc0751
perf(web): long reasoning previews format in linear time (600 ms → 1.…
Nov 9, 2026
8913a4a
fix(web): keep typed unpublished variable rows across settings re-del…
Nov 9, 2026
915676e
fix(web): deleting the open thread no longer opens a side chat or sub…
Nov 9, 2026
daa6984
fix(web): review findings handed to a thread no longer end in a broke…
Nov 9, 2026
a4c2684
fix(web): project content search no longer opens a result on an IME E…
Nov 9, 2026
d3e0e8b
refactor(shared): simplify remote branch filtering (#30456)
Nov 9, 2026
69c217f
fix(web): an IME Escape no longer sends the file picker or content se…
Nov 9, 2026
cddfc8d
fix(composer): bound long path search requests on web and mobile (#30…
Nov 9, 2026
6647b0a
fix(web): rich text previews keep paragraphs that end with a backslas…
Nov 9, 2026
b8c2cfa
fix(web): deleting a thread clears its side chats' drafts (#29832)
Nov 9, 2026
7a328c4
fix(mobile): thread row timers no longer reflow the title every secon…
Nov 9, 2026
7b24834
fix(mobile): smooth expand/collapse when the feed is at the bottom (#…
Nov 9, 2026
33db45e
fix(mobile): keep project and environment pickers reachable with the …
Nov 9, 2026
4bfa2c1
chore(mobile): update Expo SDK 58 and React Native native modules (#3…
Nov 9, 2026
5067b88
ci: give Release Smoke 15 minutes (#33478)
Nov 9, 2026
d411110
chore(mobile): update gesture handler and keyboard controller (#33229)
Nov 9, 2026
dc72705
fix(source-control): nightly CLI builds again without Cursor Origin's…
Nov 9, 2026
d7c52f9
fix(mobile): the thread feed re-wraps once when an iOS column resizes…
Nov 9, 2026
6b02cbf
fix(speech): match reference benchmarks to transcription hardware (#3…
Nov 9, 2026
12f3244
feat(models): add Claude Fable 5.2 (#33500)
Nov 9, 2026
f6203ff
fix(mobile): the chat inset resets after the keyboard closes while fr…
Nov 9, 2026
7078dcb
fix(mobile): a full swipe on a thread row finishes even if the pan is…
Nov 9, 2026
077fd62
fix(client): finishing a long background thread no longer freezes the…
Nov 9, 2026
d0f7a50
feat(models): the model picker checks for new models when it opens (#…
Nov 9, 2026
206a8e6
fix(desktop): close focused DevTools with Cmd+W (#33518)
Nov 9, 2026
1676313
chore(mobile): update react-native-pdf-jsi to 6.1.0 and link it on An…
Nov 9, 2026
2da1b74
fix(mobile): the unfolded Duo sidebar no longer pops back in while re…
Nov 9, 2026
eb6e7fa
fix(models): new models also surface the CLI update that supports the…
Nov 9, 2026
6e4711d
fix(web): clicked workspace areas no longer show the focus ring after…
Nov 9, 2026
bf469bb
chore(server): update Claude Agent SDK to 0.3.321 (#33530)
Nov 9, 2026
e85e009
fix(web): checking for updates finds provider updates on every machin…
Nov 9, 2026
8ab427c
fix(web): settings say custom instructions cover pull request descrip…
Nov 9, 2026
ad9e871
feat(web): send messages while attachments upload (#33092)
Nov 9, 2026
ff7aa5a
fix(mobile): Android PDF preview double-tap zoom and easier link taps…
Nov 9, 2026
3e4d449
chore(release): prepare v0.1.8
Nov 9, 2026
dd0737d
feat: approve agent sign-ins with T3 Connect instead of a code (#33600)
Nov 9, 2026
ee59ab2
fix(mobile): the composer and search bars move with their iOS columns…
Nov 9, 2026
9110dc2
ci(mobile): build Android store releases on Blacksmith (#33565)
Nov 9, 2026
45e0143
fix(web): thread title menu opens without a half-second wait on deskt…
Nov 9, 2026
b10cdde
fix(web): a new side chat focuses its message input (#32929)
Nov 9, 2026
bbdc7dc
perf(opencode): bound usage reads to in-window messages (#33612)
Nov 10, 2026
d655e2c
chore(web): upgrade @pierre/diffs to 1.7 and use its built-in find (#…
Nov 10, 2026
e6fa2e3
fix(web): expanding hidden diff context works after a diff refresh (#…
Nov 10, 2026
9a0d027
feat: approve agent sign-ins on app.t3.codes with T3 Connect (#33632)
Nov 10, 2026
53bcb9a
perf(cursor): improve account usage scanning (#33636)
Nov 10, 2026
ad98905
fix(web): dropdown items over the desktop title bar respond to clicks…
Nov 10, 2026
eb381a7
fix: hosted agent approval no longer fails with "Your session cannot …
Nov 10, 2026
6f8c743
fix(web): new threads use the last used project
Nov 10, 2026
f6a8a63
fix(mobile): distinguish local ACP instances by name (#32467)
Nov 10, 2026
83862af
ci(mobile): dev clients build on Blacksmith, and mobile:install start…
Nov 10, 2026
9318fdb
fix(mobile): Android sidebar and composer transitions no longer reflo…
Nov 10, 2026
9a3f8db
fix(server): price Antigravity Gemini Flash effort variants (#13809)
Nov 10, 2026
5e59ece
fix(mobile): Android feed stays at its end after the keyboard or side…
Nov 10, 2026
12085f0
fix(server): Antigravity install no longer fails on a stale Windows C…
Nov 10, 2026
b78c04d
ci(mobile): Android PR preview clients build on Blacksmith (#33618)
Nov 10, 2026
046efd7
fix(web): scrolling pans expanded images and Mermaid diagrams (#26630)
Nov 10, 2026
5ae9578
fix(desktop): agents see visible:true while the desktop shows their t…
Nov 10, 2026
0c83258
fix(server): allow requested WebMCP writes (#26570)
Nov 10, 2026
e2aa223
fix(antigravity): resolve model names from usage metadata (#33661)
Nov 10, 2026
16a6c1c
fix(web): show details for background commands (#33647)
Nov 10, 2026
f728112
fix(ci): store-build checkouts drop credentials without submodule cle…
Nov 10, 2026
8226715
fix(web): "Use T3 Code in another app" opens the Grok Bot app (#33663)
Nov 10, 2026
73fb49d
ci(mobile): keep the Android store AAB as a workflow artifact (#33674)
Nov 10, 2026
331889a
fix(mobile): hide compose in the detail rail while starting a task (#…
Nov 10, 2026
d1909d6
chore(mobile): bump app version to 2.3.0
Nov 10, 2026
20bb685
ci(mobile): version bump commits no longer credit Codex (#33689)
Nov 10, 2026
f6a32db
fix(server): stop PR watch flapping while workflows await approval (#…
Nov 10, 2026
e89abad
fix(server): show idle paragraphs before the assistant turn ends (#28…
Nov 10, 2026
6c9adfb
fix(mobile): fit usage view selector beside the date range at large t…
Nov 10, 2026
934c7f8
fix(web): center short PR titles in thread details (#33724)
Nov 10, 2026
4c36119
fix(server): Claude threads can allow an MCP app for the session (#33…
Nov 10, 2026
25da7eb
fix(web): reclaim notice says the machine will be offline (#33730)
Nov 10, 2026
577c524
fix(server): detaching a session no longer strands its pending approv…
Nov 10, 2026
eff4566
fix(opencode): long command turns no longer fail when the command req…
Nov 10, 2026
4168c14
fix(server): a queued message that names no model keeps the model pic…
Nov 10, 2026
4d9caf1
fix(ssh): tunnel readiness no longer counts ssh's connection time (#3…
Nov 10, 2026
4f57044
fix(server): preview_evaluate accepts top-level await (#31925)
Nov 10, 2026
5636b56
fix(server): quitting no longer restarts the relay client mid-shutdow…
Nov 10, 2026
9e12eca
fix(shared): relative Windows file links open the file (#33643)
Nov 10, 2026
8d54c8b
fix(server): a steer that restarts a completion wake no longer strand…
Nov 10, 2026
5dcf69e
fix(server): provider status checks no longer make mise download miss…
Nov 10, 2026
b37c7f6
fix(forgejo): find merged pull requests whose head branch was deleted…
Nov 10, 2026
65ffcbf
perf(shared): speed up escaped Markdown in long PR descriptions (#33438)
Nov 10, 2026
cec8d73
fix(server): a background agent tab survives a desktop window reload …
Nov 10, 2026
ad91636
fix(server): Commit, push & PR no longer pushes the default branch in…
Nov 10, 2026
d47591f
fix(acp): OMP threads show html_render pages (#33677)
Nov 10, 2026
56064fc
fix(ssh): Intel Mac hosts no longer try to download a missing t3 arch…
Nov 10, 2026
a22068f
fix(server): opening the branch menu no longer wipes PR status (#33263)
Nov 10, 2026
633438d
fix(server): failed updates report download diagnostics (#33239)
Nov 10, 2026
e4d86ab
fix(web): remote Lineage rows keep their title when the environment n…
Nov 10, 2026
580503e
fix(web): custom snooze footer stays inside the dialog (#33759)
Nov 10, 2026
2922e8f
fix(desktop): right-clicking a mailto link offers Copy Email Address …
Nov 10, 2026
7171fdd
fix(acp-registry): commands past the 128th are no longer dropped (#33…
Nov 10, 2026
f8fbc19
fix(server): one finished turn looks up its branch's pull request onc…
Nov 10, 2026
ca796d5
fix(mobile): Android Files sheet scrolls its tree instead of dragging…
Nov 10, 2026
b48b8ea
fix(web): prompt suggestions show after a steered turn (#33706)
Nov 10, 2026
0ca73a1
fix(server): usage prices Claude Mythos 5.2 from its Bedrock rate (#3…
Nov 10, 2026
bcee0f5
fix(server): Claude turns whose CLI exits before its first frame fail…
Nov 10, 2026
fa2f4ff
fix(web): panel resize handles follow touch drags (#33066)
Nov 10, 2026
feb9c6b
fix(server): signed-out Claude instances with their own config dir na…
Nov 10, 2026
61cb845
perf(server): opening a long thread reads from its latest segments, n…
Nov 10, 2026
d1aeed2
fix(server): repos without a remote no longer record failed spans on …
Nov 10, 2026
5a9866d
fix(mobile): missing files in previews name the checked path instead …
Nov 10, 2026
f12bb62
fix(server): a restart that misses its turn starts as a new turn (#32…
Nov 10, 2026
4c924ff
fix(desktop): new browser tabs no longer lose waits, clicks and snaps…
Nov 10, 2026
46015ec
fix(web): Go to source on a side chat quote keeps you on its parent t…
Nov 10, 2026
6b96956
fix(server): removing a queued completion message keeps its siblings'…
Nov 10, 2026
0a9abdd
fix(server): dev database seed drops active pull request watches (#32…
Nov 10, 2026
41443e5
fix(server): capture iOS screenshots on Xcode 26's simctl (#28353)
Nov 10, 2026
ebb0240
fix(mobile): medium Android windows keep the rail's room and the side…
Nov 10, 2026
ac5e48c
fix(web): notify when a new request replaces the pending one in a run…
Nov 10, 2026
80e1e4d
fix(server): Codex first-request usage limits keep their reset time (…
Nov 10, 2026
57d5e98
fix(web): minimap next turn is disabled at the bottom of a thread (#3…
Nov 10, 2026
d313b2a
fix(cursor): a steer keeps the prompt it interrupted (#32583)
Nov 10, 2026
b718643
test: remove redundant short-string truncation test (#33867)
Nov 10, 2026
c7a0931
fix(pi): Pi models whose provider ID contains a slash can be selected…
Nov 10, 2026
9b352a0
perf(server): MCP tool calls no longer read the caller's whole thread…
Nov 10, 2026
20c3dd3
fix(ssh): concurrent launches on one remote home share one server (#3…
Nov 10, 2026
80e6261
fix(mobile): iOS 18 iPad sidebar and thread feed start below the head…
Nov 10, 2026
e509db3
fix(web): Tab reaches the add-project and new-project submit buttons …
Nov 10, 2026
7389423
fix(web): screen readers hear the add-project submit shortcut (#32576)
Nov 10, 2026
047d492
fix(server): Antigravity limits read the quota host the account is me…
Nov 10, 2026
30c11a3
fix(web): the thread menu works for an older settled thread the sideb…
Nov 10, 2026
151d5f8
fix(opencode): show questions asked while OpenCode wakes a session on…
Nov 10, 2026
e5b0718
fix(server): blank .gitignore lines no longer make checkpoints drop n…
Nov 10, 2026
8ee7183
test(web): minimap next-turn test no longer flakes after a resize (#3…
Nov 10, 2026
0e2841d
feat(opencode): mirror native goals across clients (#33758)
Nov 10, 2026
cfb7cae
feat(web): bindable shortcut to regenerate a thread's title (#33987)
Nov 10, 2026
3cdc504
fix(server): linked projects keep their repository identity while it …
Nov 10, 2026
524a531
fix(mobile): tool call commands are highlighted and monospaced like o…
Nov 10, 2026
20723d6
fix: Claude monitor wakes no longer fire a completion alert per line …
Nov 10, 2026
81c3da3
fix(server): removed thread worktrees keep their project's skills in …
Nov 10, 2026
f06bfa6
fix(web): drag command palette threads into the composer (#33990)
Nov 10, 2026
08af12d
fix(shared): show zero seconds in minute durations (#33994)
Nov 10, 2026
350ecd6
fix(web): closing the right panel returns focus to where it was (#32569)
Nov 10, 2026
1fed70c
fix(server): say why threads without a project are unavailable (#32342)
Nov 10, 2026
3051b32
fix: chat file links open the file agents cite (#33943)
Nov 10, 2026
283fa1f
fix(clients): scroll truncated command output notice with logs (#34011)
Nov 10, 2026
a11ad74
fix(web): show app bundle icons and open apps from markdown links
Nov 10, 2026
71a1c49
feat(opencode): project native todo updates into checklists
Nov 10, 2026
e8d3075
fix(antigravity): recognize Gemini 4 Carbon and its quota (#33991)
Nov 10, 2026
05020d6
perf(client): reopening a finished command row no longer refetches it…
Nov 10, 2026
5f2bb93
perf(server): user-only message reads use the user-message index for …
Nov 10, 2026
a88a0ad
fix(web): keep HTML previews anchored when accordions expand (#34003)
Nov 10, 2026
44e894f
fix(web): preserve search result titles in drag previews (#34017)
Nov 10, 2026
d256170
fix: file links with line ranges open at their first line (#34006)
Nov 10, 2026
5be6bc9
fix(codex): show image generation tool calls
Nov 10, 2026
871b009
fix(pi): a steer Pi has not read yet shows as waiting, not steered (#…
Nov 10, 2026
d756fed
fix(server): provider switches hand off started cancelled runs (#34016)
Nov 10, 2026
f86e21f
fix(web,mobile): replace sparkles icons and ban them with a lint rule…
Nov 10, 2026
d290c1f
fix(github): a proxy's 403 with Retry-After is no longer reported as …
Nov 10, 2026
9cd7a04
fix(web): sending from an empty citation comment clears the composer …
Nov 10, 2026
78201b0
fix(server): text generation fallback respects project provider setti…
Nov 10, 2026
44ebb2f
feat(usage): show Muse Code limits, and xAI and Antigravity accounts …
Nov 10, 2026
8fc6fd0
fix(web): preserve previews during attachment preparation (#33949)
Nov 10, 2026
3725817
fix(desktop): input during window teardown no longer throws in the ma…
Nov 10, 2026
d6d1763
fix(web): sent messages keep the numbers written on list items (#33820)
Nov 10, 2026
1a2a4a5
fix(server): quitting stops an agent-device daemon left by an earlier…
Nov 10, 2026
3cb99ce
fix(mobile): attaching larger images no longer crashes with a BigInt …
Nov 10, 2026
17a6a01
feat(mobile): pick a voice environment once, then its method (#34073)
Nov 10, 2026
d91915d
fix(server): a t3 thread send to a finished delegated child notifies …
Nov 10, 2026
43915a4
fix(web): question panel header text sits centered in its row (#34095)
Nov 10, 2026
ae14293
feat(scripts): scenarios prove a fix in the real app with e2e, on web…
Nov 10, 2026
9e1f81c
feat(claude): Fable resets are offered and redeemed apart from weekly…
Nov 10, 2026
04f6cfc
fix(desktop): desktop IPC only answers the main app window (#34094)
Nov 10, 2026
79bca43
feat(server): voice models reuse copies already on disk (#34096)
Nov 11, 2026
1d80047
fix(web): scroll project picker to top on first result (#34113)
Nov 11, 2026
3a8c250
feat(opencode): track native image job outcomes and previews (#34089)
Nov 11, 2026
b883156
fix(scripts): scenarios run where localhost resolves to IPv6 first (#…
Nov 11, 2026
768f17c
ci: browser secret helper apt step fetches fewer indexes (#33966)
Nov 11, 2026
d152d2c
fix(client-runtime): a search query pasted from github.com lists pull…
Nov 11, 2026
4ca1039
fix(web): tighter outdated-conversation cards in the PR code panel (#…
Nov 11, 2026
ccc7b2d
fix(web): MCP App cards no longer flash white in dark mode while the …
Nov 11, 2026
92f1b8e
fix(peer): link requests use the addresses the app already has for a …
Nov 11, 2026
c90b678
fix(server): Find frees searched thread text after one idle minute (#…
Nov 11, 2026
f7b81e1
fix(web): settings search shortcuts follow the physical key on non-US…
Nov 11, 2026
bbd51f7
fix(server): import Codex chats moved into a project from the scratch…
Nov 11, 2026
5c97ada
fix(desktop): clear stale GPU caches when the Electron version change…
Nov 11, 2026
b3fdf2b
fix(web): PR links jump to the comment, diff line, checks or commits …
Nov 11, 2026
fae2d20
fix(cli): installers retry transient GitHub errors (#32913)
Nov 11, 2026
facd190
fix(web): opening the terminal with Cmd+J no longer re-renders the wh…
Nov 11, 2026
0f13d2c
refactor(web): remove icon morphing (#33985)
Nov 11, 2026
ed52af3
feat(opencode): track native shell jobs across turns
Nov 11, 2026
631ea1b
fix(server): restart send stops a Claude turn and runs the message ne…
Nov 11, 2026
ba4d01c
fix(shared): login-shell environment probe ignores DEBUG trap output …
Nov 11, 2026
0815d98
fix(web): make Q&A option outlines visible across themes (#34178)
Nov 11, 2026
05adc16
fix(web): hide empty replies when renders show the result (#34182)
Nov 11, 2026
4363d0b
fix(web): mouse tilt wheel no longer switches threads on Windows and …
Nov 11, 2026
32fdad5
fix(web): timeline minimap preview no longer steals hover or jumps ar…
Nov 11, 2026
c192c67
fix(server): auto thread sends queue while a turn is stopping (#34163)
Nov 11, 2026
c03f84b
fix(server): stream the usage-scan cache to disk instead of one strin…
Nov 11, 2026
5b11efe
fix(clients): images the agent opens stay visible in the chat (#30473)
Nov 11, 2026
31bf2f7
fix(client-runtime): pasted repository page URLs clone the repository…
Nov 11, 2026
1161141
fix(web): trackpad flicks over the right panel tabs no longer navigat…
Nov 11, 2026
a0efdae
fix: new threads move from draft to Working in one step (#33783)
Nov 11, 2026
c82e1ba
fix(gitlab): review comments can cover a range of lines (#30535)
Nov 11, 2026
42185a6
test(web): right panel tab swipe test runs as macOS on any CI host (#…
Nov 11, 2026
1c17285
fix(shared): cite assistant messages with IDs over 512 characters (#2…
Nov 11, 2026
034f3ba
fix(server): updates copy the database while the server still runs wh…
Nov 11, 2026
a03d9bc
fix(mobile): file links in question cards open the file viewer (#29151)
Nov 11, 2026
37452ee
fix(server): cloning into a stranded clone project's empty folder reu…
Nov 11, 2026
492f711
fix(desktop): stable updates no longer show a nightly's release notes…
Nov 11, 2026
2163d41
fix(shared): Open in Zed ignores the OpenZFS zed daemon on Linux (#33…
Nov 11, 2026
7e45dcd
fix(mobile): chat code blocks colour diff, kotlin, sql and other lang…
Nov 11, 2026
543ee27
fix(server): fork Claude threads after project root changes (#22836)
Nov 11, 2026
8030067
fix(web): snooze times read naturally in context menus (#24945)
Nov 11, 2026
dea8472
feat(web): label chips show the label's description on hover (#28732)
Nov 11, 2026
b6d3097
feat(web): composer strip names the worktree folder (#28459)
Nov 11, 2026
362ef9a
feat(gitlab): revert a merged merge request (#30556)
Nov 11, 2026
399df48
fix(claude): version errors from a custom endpoint no longer say to r…
Nov 11, 2026
8cbc959
fix(web): files marked Viewed stay folded when a pull request's Code …
Nov 11, 2026
4e1be34
feat(server): watched GitHub pull requests react to host events, not …
Nov 11, 2026
5badea5
fix(server): hide passive Claude Stop-hook summaries (#22964)
Nov 11, 2026
75b22bf
fix(web): dismiss image path tooltips after preview and scroll (#30620)
Nov 11, 2026
b0f12e1
fix(server): PR sync and run-status checks stop reading whole thread …
Nov 11, 2026
950c342
fix(server): preview snapshots keep page text beside large accessibil…
Nov 11, 2026
40c3682
feat(web): screen readers can hear the agent's messages and steps dur…
Nov 11, 2026
a536ff7
fix(server): thread search finds phrases inside quotes and their comm…
Nov 11, 2026
f697d4d
fix(web): local server cards in the browser empty state take pointer …
Nov 11, 2026
fc5edd3
fix(server): worktrees cut from a non-default base no longer show the…
Nov 11, 2026
6e21f81
fix(desktop): wait for the local server to exit when quitting (#22996)
Nov 11, 2026
c50dd8e
fix(server): agent continuations preserve the working timer start (#2…
Nov 11, 2026
8c9af54
fix(web): disable the git actions menu when nothing in it is usable (…
Nov 11, 2026
94f54a5
fix(server): preserve active turns when switching provider instances …
Nov 11, 2026
46afd69
fix(server): scheduled task updates keep the saved workspace unless t…
Nov 11, 2026
5bb5d53
fix(web): full-screen HTML pages fit their content and zoom by reflow…
Nov 11, 2026
1bdf470
fix(web): project actions auto-open Preview in web clients (#34048)
Nov 11, 2026
24e7747
fix(server): a follow-up delegated task waits for a run its child que…
Nov 11, 2026
ba918d7
feat(fork): integrate upstream v0.1.9 preview
Nov 12, 2026
d4918cd
test(secrets): provide crypto to driver switch fixture
Nov 12, 2026
8d0d528
fix(fork): complete v0.1.9 settings and account integration
Nov 12, 2026
9efb22a
fix(ci): size large upstream integration diffs
Nov 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
17 changes: 11 additions & 6 deletions .agents/skills/test-t3-app/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ description: Test T3 Code's web and desktop UI through its built-in Browser pane

# Test T3 web and desktop

Use T3's built-in Browser panel for verification. If its tools are absent or
the panel reports unavailable, explain the blocker and stop verification.
Do not install or switch to another automation system. For native mobile
testing, use [test-t3-mobile](../test-t3-mobile/SKILL.md).
Use T3's built-in Browser panel for verification. Follow the recovery steps
below before declaring it unavailable. Do not install or switch to another
automation system. For native mobile testing, use
[test-t3-mobile](../test-t3-mobile/SKILL.md).

## Start the app

Expand Down Expand Up @@ -36,8 +36,13 @@ model, such as Haiku for Claude or Luna for Codex.

## Use the Browser panel

Call `preview_status`, then `preview_open` if the Browser panel is
closed. Navigate to the complete startup pairing URL once with
Call `preview_status`. If no tab can be automated, call `preview_open`, including
when status reports `available: false` or `tabId: null`. Status can report
unavailable simply because no tab exists yet; opening a tab needs no user action.
Stop verification and explain the blocker only if the tools are absent or
`preview_open` reports unavailable or fails.

Navigate to the complete startup pairing URL once with
`preview_navigate`, then use `preview_snapshot` and T3's interaction tools.
If the token was consumed or expired, run `node apps/server/src/bin.ts pair`
for a fresh one. Keep using the same tab.
Expand Down
5 changes: 3 additions & 2 deletions .agents/skills/test-t3-mobile/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ vp run mobile:install <ios|android> <device-id>

This installs the dev client for the checkout's native fingerprint: from the
device, the local cache, or the shared cache in seconds, building once only
when no machine has that fingerprint yet (5-15 minutes, logged to the file it
names). The device id may be omitted when exactly one device is booted. It
when no machine has that fingerprint yet: in the `Mobile Dev Client` workflow
on Blacksmith when HEAD is pushed and `gh` may dispatch it (the command waits),
otherwise here (5-15 minutes, logged to the file it names). The device id may be omitted when exactly one device is booted. It
prints one JSON line; on failure it names the next command. Mobile verification
includes that step unless the user prohibits it.

Expand Down
2 changes: 1 addition & 1 deletion .github/SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Security policy

Report security vulnerabilities affecting T3 Code or T3 Tools-operated infrastructure to
[security@ping.gg](mailto:security@ping.gg). Please do not disclose them publicly until we have had
[security@t3.codes](mailto:security@t3.codes). Please do not disclose them publicly until we have had
a reasonable opportunity to investigate and remediate them.

See the [full security policy](https://t3.codes/security-policy) for reporting details, scope,
Expand Down
2 changes: 2 additions & 0 deletions .github/actions/ci-changes/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ outputs:
value: ${{ steps.detect.outputs.typecheck }}
build:
value: ${{ steps.detect.outputs.build }}
desktop_launch:
value: ${{ steps.detect.outputs.desktop_launch }}
test:
value: ${{ steps.detect.outputs.test }}
test_packages:
Expand Down
12 changes: 10 additions & 2 deletions .github/actions/setup-ci-deps/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ inputs:
description: Arguments for `vp install`, such as filters. Empty installs the whole workspace.
required: false
default: ""
save-pnpm-store:
description: Set to "false" when a concurrent job with the same install args saves the pnpm store
required: false
default: "true"
runs:
using: composite
steps:
Expand Down Expand Up @@ -123,10 +127,14 @@ runs:
key: ${{ steps.pnpm_verified.outputs.cache-primary-key }}

# A filtered install that started from the current full store adds nothing
# worth a second copy of it.
# worth a second copy of it. A stacked PR, based on a branch other than the
# default, saves a ~1 GB store only its own reruns can read, so it only restores.
# Concurrent jobs with the same install args reserve one key, so the losers
# compress the store for nothing; all but one pass save-pnpm-store: false.
- name: Save pnpm store
if: >-
inputs.install == 'true' &&
inputs.install == 'true' && inputs.save-pnpm-store == 'true' &&
(github.event_name != 'pull_request' || github.base_ref == github.event.repository.default_branch) &&
steps.pnpm_cache.outputs.cache-hit != 'true' &&
(steps.pnpm_store.outputs.namespace == 'full' ||
steps.pnpm_cache.outputs.cache-matched-key != format('pnpm-full-v1-{0}-{1}-{2}', runner.os, runner.arch, hashFiles('pnpm-lock.yaml', 'pnpm-workspace.yaml', 'package.json')))
Expand Down
59 changes: 42 additions & 17 deletions .github/scripts/check-nightly-release.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,42 +40,67 @@ async function assertReleaseSource({ github, context, releaseChannel }) {

const isNightlyTag = (tag) => /^v.*-nightly\./.test(tag) || tag.startsWith("nightly-v");

async function findLatestNightly({ github, context }) {
const releases = await github.paginate(github.rest.repos.listReleases, {
...context.repo,
per_page: 100,
});
return releases
.filter((release) => !release.draft && release.published_at && isNightlyTag(release.tag_name))
.sort((a, b) => Date.parse(b.published_at) - Date.parse(a.published_at))[0];
// Only the three fields the gate reads. The REST list also returns every asset,
// which made a full scan tens of megabytes.
const RELEASES_QUERY = `
query ($owner: String!, $repo: String!, $cursor: String) {
repository(owner: $owner, name: $repo) {
releases(first: 100, after: $cursor, orderBy: { field: CREATED_AT, direction: DESC }) {
pageInfo { hasNextPage endCursor }
nodes { tagName isDraft publishedAt }
}
}
}
`;

// Returns the nightly with the newest publishedAt. Release order follows the
// tagged commit date, not publication, so every page is read unless `isSettled`
// says the newest nightly seen so far already decides the caller's answer.
async function findLatestNightly({ github, context, isSettled = () => false }) {
let latest;
let cursor = null;
do {
const { repository } = await github.graphql(RELEASES_QUERY, { ...context.repo, cursor });
const { nodes, pageInfo } = repository.releases;
for (const release of nodes) {
if (release.isDraft || !release.publishedAt || !isNightlyTag(release.tagName)) continue;
if (!latest || Date.parse(release.publishedAt) > Date.parse(latest.publishedAt)) {
latest = release;
}
}
if (latest && isSettled(latest)) return latest;
cursor = pageInfo.hasNextPage ? pageInfo.endCursor : null;
} while (cursor);
return latest;
}

async function shouldReleaseNightly({ github, context, core, now = Date.now() }) {
const lastNightly = await findLatestNightly({ github, context });
const isInGap = (release) => now - Date.parse(release.publishedAt) < MINIMUM_RELEASE_GAP_MS;
// Any nightly inside the gap means the newest one is too, so stop reading.
const lastNightly = await findLatestNightly({ github, context, isSettled: isInGap });

if (!lastNightly) {
core.info("No published nightly found. Proceeding with release.");
return true;
}

if (now - Date.parse(lastNightly.published_at) < MINIMUM_RELEASE_GAP_MS) {
core.info(`Nightly ${lastNightly.tag_name} was published less than six hours ago. Skipping.`);
const tag = lastNightly.tagName;
if (isInGap(lastNightly)) {
core.info(`Nightly ${tag} was published less than six hours ago. Skipping.`);
return false;
}

const { data: comparison } = await github.rest.repos.compareCommitsWithBasehead({
...context.repo,
basehead: `${lastNightly.tag_name}...${context.sha}`,
basehead: `${tag}...${context.sha}`,
per_page: 1,
});
if (comparison.status !== "ahead") {
core.info(
`Candidate commit is ${comparison.status} relative to ${lastNightly.tag_name}. Skipping.`,
);
core.info(`Candidate commit is ${comparison.status} relative to ${tag}. Skipping.`);
return false;
}

core.info(`New commits since ${lastNightly.tag_name}, and the six-hour gap has passed.`);
core.info(`New commits since ${tag}, and the six-hour gap has passed.`);
return true;
}

Expand All @@ -85,7 +110,7 @@ async function resolveLatestNightlyCommit({ github, context, core }) {
throw new Error("No published nightly found. Stable releases build the latest nightly commit.");
}

const tag = lastNightly.tag_name;
const tag = lastNightly.tagName;
const { data: commit } = await github.rest.repos.getCommit({ ...context.repo, ref: tag });
const version = /^(?:nightly-)?v(\d+\.\d+\.\d+)-nightly\./.exec(tag)?.[1];
if (!version) {
Expand Down
102 changes: 84 additions & 18 deletions .github/scripts/check-nightly-release.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ const {
const now = Date.parse("2026-09-05T12:00:00Z");
const hour = 60 * 60 * 1000;
const nightly = (hoursAgo, overrides = {}) => ({
tag_name: "v1.0.1-nightly.20260905.123",
draft: false,
published_at: new Date(now - hoursAgo * hour).toISOString(),
tagName: "v1.0.1-nightly.20260905.123",
isDraft: false,
publishedAt: new Date(now - hoursAgo * hour).toISOString(),
...overrides,
});

Expand Down Expand Up @@ -73,26 +73,39 @@ for (const comparisonStatus of ["behind", "diverged"]) {
});
}

function fixture({ releases = [nightly(7)], comparisonStatus = "ahead" } = {}) {
// `pages` holds the GraphQL release pages; `releases` is shorthand for one page.
function fixture({ releases = [nightly(7)], pages = [releases], comparisonStatus = "ahead" } = {}) {
const calls = [];
const cursors = [];
return {
calls,
cursors,
options: {
now,
context: { repo: { owner: "example", repo: "app" }, sha: "new" },
core: { info() {} },
github: {
rest: {
repos: {
listReleases() {},
async compareCommitsWithBasehead(params) {
calls.push(params);
return { data: { status: comparisonStatus } };
},
},
},
async paginate() {
return releases;
async graphql(_query, { owner, repo, cursor }) {
assert.deepEqual({ owner, repo }, { owner: "example", repo: "app" });
cursors.push(cursor);
const index = cursor === null ? 0 : Number(cursor);
const hasNextPage = index + 1 < pages.length;
return {
repository: {
releases: {
nodes: pages[index],
pageInfo: { hasNextPage, endCursor: hasNextPage ? String(index + 1) : null },
},
},
};
},
},
},
Expand All @@ -101,28 +114,65 @@ function fixture({ releases = [nightly(7)], comparisonStatus = "ahead" } = {}) {

test("releases the first nightly when no nightly is published", async () => {
const { options } = fixture({
releases: [nightly(0, { tag_name: "v1.0.0" }), nightly(0, { draft: true })],
releases: [nightly(0, { tagName: "v1.0.0" }), nightly(0, { isDraft: true })],
});
assert.equal(await shouldReleaseNightly(options), true);
});

test("uses publication time, not release order or the tagged commit date", async () => {
const { options } = fixture({
releases: [nightly(10), nightly(1), nightly(20, { tag_name: "nightly-v0.9.0" })],
releases: [nightly(10), nightly(1), nightly(20, { tagName: "nightly-v0.9.0" })],
});
assert.equal(await shouldReleaseNightly(options), false);
});

test("the six-hour gap ends exactly six hours after publication", async () => {
const atBoundary = fixture({ releases: [nightly(6)] });
assert.equal(await shouldReleaseNightly(atBoundary.options), true);
const justInside = fixture({ releases: [nightly(6 - 1 / 3_600_000)] });
assert.equal(await shouldReleaseNightly(justInside.options), false);
assert.equal(justInside.calls.length, 0);
});

test("stops reading releases once a nightly inside the gap is seen", async () => {
const { options, cursors } = fixture({ pages: [[nightly(10), nightly(2)], [nightly(30)]] });
assert.equal(await shouldReleaseNightly(options), false);
assert.deepEqual(cursors, [null]);
});

test("reads every page when no nightly seen so far settles the gap", async () => {
const { options, cursors, calls } = fixture({
pages: [
[nightly(10), nightly(0, { tagName: "v1.0.0" })],
[nightly(1, { tagName: "nightly-v0.9.0" })],
],
});
assert.equal(await shouldReleaseNightly(options), false);
assert.deepEqual(cursors, [null, "1"]);
assert.equal(calls.length, 0);
});

test("compares against the newest nightly across pages once the gap has passed", async () => {
const { options, calls } = fixture({
pages: [[nightly(10, { tagName: "v1.0.1-nightly.20260905.100" })], [nightly(8)]],
});
assert.equal(await shouldReleaseNightly(options), true);
assert.deepEqual(
calls.map((call) => call.basehead),
["v1.0.1-nightly.20260905.123...new"],
);
});

test("ignores stable releases and drafts when checking the gap", async () => {
const { options } = fixture({
releases: [nightly(0, { tag_name: "v1.0.0" }), nightly(0, { draft: true }), nightly(7)],
releases: [nightly(0, { tagName: "v1.0.0" }), nightly(0, { isDraft: true }), nightly(7)],
});
assert.equal(await shouldReleaseNightly(options), true);
});

test("fails instead of releasing when GitHub cannot supply release state", async () => {
const { options } = fixture();
options.github.paginate = async () => {
options.github.graphql = async () => {
throw new Error("GitHub unavailable");
};
await assert.rejects(shouldReleaseNightly(options), /GitHub unavailable/);
Expand All @@ -137,9 +187,9 @@ for (const status of ["behind", "diverged"]) {

const { resolveLatestNightlyCommit } = require("./check-nightly-release.cjs");

function nightlyCommitFixture({ releases, commitSha = "abc123" }) {
function nightlyCommitFixture({ releases, pages, commitSha = "abc123" }) {
const refs = [];
const { options } = fixture({ releases });
const { options } = fixture({ releases, pages });
options.github.rest.repos.getCommit = async ({ ref }) => {
refs.push(ref);
return { data: { sha: commitSha } };
Expand All @@ -150,10 +200,10 @@ function nightlyCommitFixture({ releases, commitSha = "abc123" }) {
test("stable releases resolve the commit of the newest published nightly", async () => {
const { options, refs } = nightlyCommitFixture({
releases: [
nightly(10, { tag_name: "v1.0.1-nightly.20260905.100" }),
nightly(1, { tag_name: "v1.0.1-nightly.20260905.123" }),
nightly(0, { tag_name: "v1.0.0" }),
nightly(0, { draft: true, tag_name: "v1.0.1-nightly.20260905.999" }),
nightly(10, { tagName: "v1.0.1-nightly.20260905.100" }),
nightly(1, { tagName: "v1.0.1-nightly.20260905.123" }),
nightly(0, { tagName: "v1.0.0" }),
nightly(0, { isDraft: true, tagName: "v1.0.1-nightly.20260905.999" }),
],
commitSha: "deadbeef",
});
Expand All @@ -167,7 +217,23 @@ test("stable releases resolve the commit of the newest published nightly", async

test("stable releases derive the version from legacy nightly tags", async () => {
const { options } = nightlyCommitFixture({
releases: [nightly(1, { tag_name: "nightly-v0.9.0-nightly.20260905.5" })],
releases: [nightly(1, { tagName: "nightly-v0.9.0-nightly.20260905.5" })],
});
assert.equal((await resolveLatestNightlyCommit(options)).version, "0.9.0");
});

test("stable releases read every page, even after a recent nightly", async () => {
const { options, refs } = nightlyCommitFixture({
pages: [
[nightly(2, { tagName: "v1.0.1-nightly.20260905.100" })],
[nightly(1, { tagName: "v1.0.1-nightly.20260905.123" })],
],
});
assert.equal((await resolveLatestNightlyCommit(options)).tag, "v1.0.1-nightly.20260905.123");
assert.deepEqual(refs, ["v1.0.1-nightly.20260905.123"]);
});

test("stable releases fail when no nightly is published", async () => {
const { options } = nightlyCommitFixture({ releases: [nightly(1, { tagName: "v1.0.0" })] });
await assert.rejects(resolveLatestNightlyCommit(options), /No published nightly found/);
});
Loading