Skip to content
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
671 commits
Select commit Hold shift + click to select a range
8569ce9
perf(web): avoid quadratic markdown link scans (#18387)
saphid Oct 12, 2026
499a53c
perf(server): expired PR diffs no longer stay in memory until restart…
tris203 Oct 12, 2026
7f02b84
perf(usage): the first usage scan skips decoding transcript lines tha…
tris203 Oct 12, 2026
aa2bfc6
fix(mobile): preserve browser prompt replies across control updates (…
saphid Oct 12, 2026
f570294
fix(web): closed popovers no longer stay on screen and click-through …
akbarakma Oct 12, 2026
821a6d7
fix(web): keybinding settings label Focus URL with a capitalized acro…
RakshithBhat03 Oct 12, 2026
0fd7d2d
fix(web): long commands no longer overflow the Add Action dialog (#18…
fixfon Oct 12, 2026
fded2ca
fix(web): provider Runtime controls follow the settings row layout (#…
ScottN-PV Oct 12, 2026
6bbb72c
perf(web): Thinking shimmer steps instead of drawing every frame (#18…
realhasanshoaib Oct 12, 2026
808bee7
chore(typecheck): typecheck with tsc-rs (#16704)
t3dotgg Oct 12, 2026
9b9792e
test(server): finish workflow reads before changing transcripts (#18192)
lastobelus Oct 12, 2026
6a99eb3
test(server): Claude sign-in message test passes on Windows hosts (#1…
AdEx-Partners-DE Oct 12, 2026
63eaa79
fix(web): context menus no longer scroll when they fit the window (#1…
kacigaya Oct 12, 2026
a5331e4
fix(server): checkpoint restore keeps a nested workspace on Windows (…
JonasFocus Oct 12, 2026
ee2763e
Reject unknown params in t3_thread_read (#17823)
mfazekas Oct 12, 2026
d45d1a1
fix(desktop): Option-click on a chat link opens the system browser (#…
whoisaldo Oct 12, 2026
b8d03ba
fix(mobile): new thread draft names its repo and says it is a new thr…
kaovilai Oct 12, 2026
4a90c1c
fix(web): keep queued threads subscribed (#15293)
ANSHSINGH050404 Oct 12, 2026
4ff8b07
test(server): Claude reset tests are skipped on Windows hosts, where …
AdEx-Partners-DE Oct 12, 2026
fd6d9dd
fix(web): hide stash menu behind maximized panel (#18115)
Saikrishna1876 Oct 12, 2026
df78114
fix(web): sidebar toggle no longer sits under the macOS window button…
realhasanshoaib Oct 12, 2026
f79f37a
fix(server): missing agent binaries report launch failure
Moinax Oct 12, 2026
397a461
feat(android): add Pull Requests tab (#18372)
PixPMusic Oct 12, 2026
12b34e8
fix(mobile): Forgejo change requests ask for the summary they require…
flamboh Oct 12, 2026
b9ad3da
fix(server): cap automatic thread continuations and turn them on by d…
t3dotgg Oct 12, 2026
c32ade4
feat(mobile): stock tab bar, glass filter pills, and saved list filte…
juliusmarminge Oct 12, 2026
52f9046
fix(mobile): keep PR surfaces and Android tab selection visible acros…
PixPMusic Oct 12, 2026
4ab4cdf
fix(mobile): keep preview count badges inside the working pill (#18449)
RVZO6 Oct 12, 2026
2e24ec4
fix(mobile): show rounded pull request selection in the sidebar (#18480)
PixPMusic Oct 12, 2026
e688034
feat(web): model options for source control writer and review guide m…
juliusmarminge Oct 12, 2026
19bef8c
ci(mobile): cut a store build when the native fingerprint has no buil…
juliusmarminge Oct 12, 2026
37e2acd
fix(web): terminal colors no longer look washed out (#17168)
psv2522 Oct 12, 2026
d514a8c
refactor(settings): centralize schema-declared secrets and inputs (#1…
juliusmarminge Oct 12, 2026
6f6197c
fix(mobile): restore native scroll-edge effects on forms and PRs (#18…
juliusmarminge Oct 12, 2026
462e7f4
feat(mobile): native-sized pull request action bar (#18527)
juliusmarminge Oct 12, 2026
679b03e
fix(mobile): preserve theme contrast across surfaces and actions (#18…
juliusmarminge Oct 12, 2026
a39fd7b
refactor(mobile): share themed list rows and sections (#18510)
juliusmarminge Oct 12, 2026
9a2b9a2
refactor(mobile): share themed toggle rows in settings (#18511)
juliusmarminge Oct 12, 2026
abc80c8
refactor(mobile): share themed choice rows in settings (#18516)
juliusmarminge Oct 12, 2026
48595c7
fix(server): consolidate browser credential handling (#18509)
juliusmarminge Oct 12, 2026
5fe7568
feat: open T3 Code from a link with a prompt ready to send (#18454)
t3dotgg Oct 12, 2026
8f25cf9
fix(release): drop placeholder allowBuilds entry that broke nightly b…
t3dotgg Oct 12, 2026
eac6ba5
ci: fail PRs on invalid allowBuilds entries in pnpm-workspace.yaml (#…
t3dotgg Oct 12, 2026
f498b35
fix(mobile): menu dismiss taps no longer press the view underneath (#…
juliusmarminge Oct 12, 2026
d83929a
feat(web): one sidebar click updates every machine and provider (#18053)
t3dotgg Oct 12, 2026
5d59e71
fix(release): avoid PowerShell crashes on Windows ARM (#18573)
t3dotgg Oct 12, 2026
b3871d5
fix(server): Forgejo pull requests report their head commit (#18463)
flamboh Oct 12, 2026
a27cf8a
test(provider-acp): terminal kill test passes on Windows hosts (#18450)
AdEx-Partners-DE Oct 12, 2026
58d2532
fix(web): context meter no longer reads 1000k just under a million to…
luke2x Oct 12, 2026
1be5c1f
Merge branch 'main' into feat/claude-prompt-ghost-text
danielyc Oct 12, 2026
4e76925
fix(mobile): Android tablets launched in landscape open full screen
SamarpitSantoki Oct 12, 2026
5753207
fix(desktop): avoid Hyprland 0.48–0.50 Wayland color-manager startup …
krankos Oct 12, 2026
7b6d907
fix(mobile): iPhones on iOS 27.2 beta no longer open to a black scree…
shivamhwp Oct 12, 2026
701fc83
fix(mobile): installs skip the Enriched math download again (#18679)
juliusmarminge Oct 12, 2026
9e55228
fix(web): setup wizards follow custom themes (#18725)
SunkenInTime Oct 12, 2026
b821fa0
fix(server): resolve configured PR bases to branch names (#18754)
Yash-Singh1 Oct 12, 2026
0e7346c
fix: expose running terminals and prevent setup install stalls (#18740)
Yash-Singh1 Oct 12, 2026
511d20c
fix(mobile): hide Claude Read image placeholders when previews exist …
Yash-Singh1 Oct 12, 2026
457acb4
fix(mobile): preserve chat history when opening pull requests
PixPMusic Oct 12, 2026
a3c4e9e
fix(gitlab): merge request details report their head commit (#18608)
ScottN-PV Oct 12, 2026
ffb4af8
feat(server): rename built-in models from settings (#18840)
t3dotgg Oct 12, 2026
b03534f
fix(web): Git actions follow the selected thread (#18862)
Yash-Singh1 Oct 13, 2026
979589d
fix(desktop): preserve updater failure causes in diagnostics (#18864)
Yash-Singh1 Oct 13, 2026
34f8458
fix(web): attach dropped threads to pending answers (#18789)
Yash-Singh1 Oct 13, 2026
0179552
fix(web): keep button text stable during press scaling (#18866)
Yash-Singh1 Oct 13, 2026
8110edf
fix(bitbucket): preserve PR head commits for review guides (#18402)
ahilles107 Oct 13, 2026
e2e95a3
fix(server): return null for unresolved optional commands (#18871)
Yash-Singh1 Oct 13, 2026
5d6e419
fix: show computer-use action titles and align app icons (#18865)
Yash-Singh1 Oct 13, 2026
265fb70
fix(server): apply confirmed Claude subagent outcomes (#18778)
Yash-Singh1 Oct 13, 2026
41d86c1
fix(mobile): Browser page no longer logs a duplicate key warning (#18…
tris203 Oct 13, 2026
df26ef9
fix(web): a numeric q in the pull requests URL no longer crashes the …
ScottN-PV Oct 13, 2026
a143fa3
fix(client): T3 Connect clients reconnect once a new tunnel is ready …
shivamhwp Oct 13, 2026
346247b
fix(web): leaving the home page while the app loads no longer bounces…
shivamhwp Oct 13, 2026
1af1386
fix(mobile): attachment images no longer re-download on every reconne…
shivamhwp Oct 13, 2026
e24ea1d
fix(server): a migration id clash stops startup with a clear error in…
shivamhwp Oct 13, 2026
5a65169
fix(server): a thread with an event type from a newer build can still…
shivamhwp Oct 13, 2026
dc19285
fix(server): Codex titles and branch names no longer start the user's…
brycedbjork Oct 13, 2026
06620fa
fix(server): Claude thinking before a tool call stays a collapsed Tho…
maria-rcks Oct 13, 2026
ae7bed6
perf(server): cached branch PR lookups no longer start git processes …
SunkenInTime Oct 13, 2026
80664d5
fix(web): compact merge buttons show when they need a second click (#…
TonybynMp4 Oct 13, 2026
5070a83
fix(mobile): pull requests load from another environment when theirs …
juliusmarminge Oct 13, 2026
540a3e8
perf(web): collect active tool calls without array shifts (#18853)
saphid Oct 13, 2026
e9221e4
fix(web): center the pace icon on the limit card's "left" label (#18580)
akash3444 Oct 13, 2026
6abccc1
fix(web): update everything includes npm-installed servers again (#18…
ScottN-PV Oct 13, 2026
bbd98a5
fix(server): review guides find Bitbucket heads reported by short has…
ahilles107 Oct 13, 2026
e82a1ce
fix(web): scheduled task model picker no longer shifts the dialog (#1…
flamboh Oct 13, 2026
6524a8d
fix(ci): CodeRabbit reviews no longer request changes (#18954)
Yash-Singh1 Oct 13, 2026
98a6246
fix(web): links in HTML renders open like chat links (#18897)
maria-rcks Oct 13, 2026
a47decf
fix(web): remember editor selections before opening folders (#19078)
Yash-Singh1 Oct 13, 2026
42160f2
fix(ci): retry Cursor webhook HTTP 400s on main (#19077)
Yash-Singh1 Oct 13, 2026
8d75232
fix(web): let context handoff details use the available width (#19098)
Yash-Singh1 Oct 13, 2026
05e4f88
fix(server): snoozed threads allow queued automatic wakes (#19099)
Yash-Singh1 Oct 13, 2026
6a68bee
fix(web): merge button fits its label and animates width changes (#18…
flamboh Oct 13, 2026
446be69
fix(web): Cmd+Enter creates the new project while an option is highli…
SunkenInTime Oct 13, 2026
9a9fd2e
fix(pi): queue turn-start prompts when native work is running (#18639)
StiensWout Oct 13, 2026
4d76835
fix(pi): load T3 tool schemas for completion gateways (#18643)
StiensWout Oct 13, 2026
4292720
fix(devices): report agent tool startup failures (#18502)
PixPMusic Oct 13, 2026
8ac4b97
fix(web): settings warn when an environment silently drops a setting …
flamboh Oct 13, 2026
380bba3
fix(desktop): stop unsolicited Messages code autofill (#19118)
StiensWout Oct 13, 2026
c616e16
feat(chat): show pending context handoff when selecting a model (#18369)
maria-rcks Oct 13, 2026
fb8d0fc
fix(server): collect SQLite planner statistics when the database open…
otavio Oct 13, 2026
84cb134
fix(server): failed threads no longer scan every tool item for errors…
realhasanshoaib Oct 13, 2026
6947f0d
fix(web): keep clone folder names readable in the setup project picke…
tachytelicdetonation Oct 13, 2026
a01c48f
fix(composer): allow slash skill search within messages (#19107)
Bil0000 Oct 13, 2026
8c02798
fix(claude): default background text generation to haiku 5.5 (#18781)
maria-rcks Oct 13, 2026
006c508
chore(typecheck): bump tsc-rs to 0.6.0 (#19187)
t3dotgg Oct 13, 2026
3feae3a
fix(server): keep OpenCode timeouts from crashing the error formatter…
tachytelicdetonation Oct 13, 2026
25629a7
feat(server): run delegated tasks in separate worktrees (#19102)
Bil0000 Oct 14, 2026
aef0e9c
fix(git): preserve whitespace in file paths (#12464) (#12465)
Defmon3 Oct 14, 2026
a74ce48
fix(server): stop fsyncing SQLite on every commit so slow disks no lo…
t3dotgg Oct 14, 2026
85272ee
fix(chat): make links in agent questions clickable (#19197)
t3dotgg Oct 14, 2026
91e93a2
fix(usage): show one Antigravity account once, not once per machine (…
t3dotgg Oct 14, 2026
a4e2539
fix(web): Android beta links point to the APK release, not the banned…
shivamhwp Oct 14, 2026
109aaae
fix(client): "Subagent needs input" no longer sticks after the subage…
shivamhwp Oct 14, 2026
dff750b
fix(web): stop question answers from resetting the editor caret (#11337)
shivamhwp Oct 14, 2026
573cec0
fix(web): app shortcuts keep working after clicking into an HTML rend…
maria-rcks Oct 14, 2026
5e5c52b
fix(source-control): keep distinct CI checks with overlapping names (…
Lucenx9 Oct 14, 2026
5e5abc9
fix(server): avoid excessive backtracking in webhook templates (#19160)
Lucenx9 Oct 14, 2026
9c9ae43
fix(web): auto-merge button fits its label and animates width changes…
flamboh Oct 14, 2026
1ce8089
fix(web): scroll terminal output with touch gestures (#11305)
shivamhwp Oct 14, 2026
aba3a6d
feat(web): view visual replies full screen with zoom (#17561)
Bil0000 Oct 14, 2026
11fd54f
fix(web): removing a project no longer opens a new thread for it (#15…
shivamhwp Oct 14, 2026
6002c5c
fix(server): usage hubs with a host-less URL no longer vanish from Li…
shivamhwp Oct 14, 2026
43e7cd0
fix(mobile): huge turn diffs no longer run Android out of memory
Pipyakas Oct 14, 2026
3d340da
fix(mobile): long commands no longer freeze Android work-log taps
Pipyakas Oct 14, 2026
107f602
fix(mobile): search bar animates in on iOS 26+ instead of popping (#1…
juliusmarminge Oct 14, 2026
cb65643
chore(deps): Effect 4.0.4 and OpenCode 2.0.28, dropping the patches t…
juliusmarminge Oct 14, 2026
d765d03
fix(server): a Claude 403 no longer tells you to log in again (#15872)
shivamhwp Oct 14, 2026
4d73e1d
fix(server): persist only changed pull request links (#19248)
juliusmarminge Oct 14, 2026
05a7252
feat: dictate into the composer with a local speech model
StiensWout Oct 14, 2026
a77b317
fix: address dictation review findings
StiensWout Oct 14, 2026
c983c52
fix(server): an unreadable dictation directory no longer stops server…
StiensWout Oct 14, 2026
8b460a3
fix(server): delegate_task explains that supervised runtime modes pau…
saphid Oct 14, 2026
30d1010
fix(server): Claude subagent progress no longer re-stores the unchang…
Gigioxx Oct 14, 2026
8659fcf
fix(server): thread list reads no longer freeze the server on large d…
t3dotgg Oct 14, 2026
3b2ebce
perf(server): streamed events no longer rewrite the whole thread row …
Baker-Harrison Oct 14, 2026
3bbfdc7
docs: close PRs written by Gemini or Muse Wonder (#19286)
t3dotgg Oct 14, 2026
46ce56e
fix(mobile): Android no longer freezes when you leave a running thread
Oct 14, 2026
eeaac49
fix: update all no longer runs agents twice or loses background work …
t3dotgg Oct 14, 2026
860ea9d
fix(mobile): hash Reanimated static flags in the native fingerprint
Oct 14, 2026
5705426
fix(server): enforce one database owner and guard update rollback (#1…
maria-rcks Oct 14, 2026
13a2dae
fix(mobile): run the running-thread shimmer on the native driver instead
Oct 14, 2026
8855a6d
perf(server): reuse stored turn item positions (#19230)
tannerpolley Oct 14, 2026
bac35a2
perf(server): avoid quadratic resource history replay (#18825)
saphid Oct 14, 2026
94ca023
fix(server): repair ownership UUID generation (#19298)
t3dotgg Oct 14, 2026
5bba764
fix(client-runtime): slow config snapshots no longer drop working con…
saphid Oct 14, 2026
173a970
fix(server): bound activity publishes so stalled responses release th…
saphid Oct 14, 2026
a61ce57
refactor(mobile): memoize the shimmer interpolations
Oct 14, 2026
4cd0076
perf(shared): cached SQLite statements no longer hold large parameter…
t3dotgg Oct 14, 2026
acb9027
fix(provider-cursor): Cursor text generation no longer leaks SQLite f…
t3dotgg Oct 14, 2026
614b432
fix(server): make SQLite checkpoints durable on macOS (#19304)
t3dotgg Oct 14, 2026
fd9cdae
perf(server): Codex plan streaming no longer commits every token (#19…
t3dotgg Oct 14, 2026
2d14185
fix(server): large file edits no longer store their full diff twice (…
t3dotgg Oct 14, 2026
4f909be
fix(web): settings save again after a stored value fails decode (#19312)
t3dotgg Oct 14, 2026
c8a6768
fix(server): HTML and Markdown attachments no longer fail OpenCode tu…
t3dotgg Oct 14, 2026
a0ea721
fix(server): worktree paths no longer vanish on git before 2.36 (#19315)
t3dotgg Oct 14, 2026
19a67ef
fix(acp): custom models now reach the agent instead of failing to ope…
t3dotgg Oct 14, 2026
233e70b
fix(server): Claude no longer shows unavailable when its health check…
t3dotgg Oct 14, 2026
f372c00
fix(server): stalled OAuth token requests no longer block credential …
t3dotgg Oct 14, 2026
8d11fe1
fix(server): steered Claude turns no longer undercount token usage (#…
t3dotgg Oct 14, 2026
3213a0c
fix(server): closing a Claude session no longer leaves plugin MCP ser…
t3dotgg Oct 14, 2026
e6626ee
fix(client-runtime): T3 Connect link timeouts explain the relay 504 (…
t3dotgg Oct 14, 2026
6edd44f
fix(web): settle shortcut moves to the next thread like the sidebar (…
t3dotgg Oct 14, 2026
3a6ab58
fix(acp): Copilot's default agent no longer disappears from the Agent…
t3dotgg Oct 14, 2026
5fc1c5c
perf(server): SQLite checkpoints no longer block the event loop (#19324)
t3dotgg Oct 14, 2026
d10621d
fix(mobile): incompatible environments now say whether to update the …
t3dotgg Oct 14, 2026
9a5dc75
fix(web): live reasoning stays scrolled to the newest text while it s…
t3dotgg Oct 14, 2026
cd45be3
fix(server): T3 Connect no longer stays down after a network change (…
t3dotgg Oct 14, 2026
4cf8243
fix(clients): host images say when the connection lacks file access (…
t3dotgg Oct 14, 2026
9a01524
fix(clients): a resumed subagent no longer moves the later turn's Wor…
t3dotgg Oct 14, 2026
7ee2839
fix: Claude and Codex no longer time out behind mise wrappers (#19340)
t3dotgg Oct 14, 2026
06a84de
perf(server): turns no longer re-read merged PRs from GitHub (#19344)
t3dotgg Oct 14, 2026
5240897
docs(settings): explain that provider update checks also gate the mod…
fixfon Oct 14, 2026
69497b0
test(mobile): cover the Android orientation plugin's launch-time output
SamarpitSantoki Oct 14, 2026
9fb4ddb
fix(web): an unsaved citation comment survives a question or approval…
t3dotgg Oct 14, 2026
bc95bbd
fix(server): changing Claude effort no longer fails while background …
t3dotgg Oct 14, 2026
3417bc3
fix(server): service updates no longer fail on full disks or large da…
t3dotgg Oct 14, 2026
6485555
test(mobile): check configChanges flags without depending on order
SamarpitSantoki Oct 14, 2026
0425c32
fix(clients): # suggestions include pull requests linked to the threa…
t3dotgg Oct 14, 2026
0ae1091
fix(clients): pairing a switched-off computer again turns it back on …
t3dotgg Oct 14, 2026
ffceb61
fix(cli): t3 triage reports the server's version, not its own, as the…
t3dotgg Oct 14, 2026
40d43a1
fix(client-runtime): a new WSL backend no longer shows Limited permis…
t3dotgg Oct 14, 2026
26c48bb
fix(web): action shortcuts recorded in the browser now save (#19365)
t3dotgg Oct 14, 2026
adb0420
fix(clients): large pasted images no longer break later Claude image …
t3dotgg Oct 14, 2026
519d64f
fix(server): settled and idle-released threads no longer stay Waiting…
t3dotgg Oct 14, 2026
21af72f
perf(client-runtime): merged pull requests are no longer re-read ever…
t3dotgg Oct 14, 2026
90ca6a7
fix(server): new Codex threads no longer miss slow MCP servers' tools…
t3dotgg Oct 14, 2026
6c14293
fix(github): requested teams now show in pull request reviewers (#19375)
t3dotgg Oct 14, 2026
9688e74
fix(ssh): SSH launch no longer picks a port another server answers on…
t3dotgg Oct 14, 2026
f5b5f9d
fix(server): a failed T3 Connect relink no longer leaves a stale mana…
t3dotgg Oct 14, 2026
c08093c
fix(shared): Windows .cmd shims no longer print DEP0190 on every spaw…
t3dotgg Oct 14, 2026
3062701
fix(server): commit and title generation use your custom model when n…
t3dotgg Oct 14, 2026
f99b202
fix(web): T3 Connect settings can repair a link that drifted to publi…
t3dotgg Oct 14, 2026
7fd2ba7
fix(server): failed Claude text generation shows the CLI's own error …
t3dotgg Oct 14, 2026
2cde3f7
fix(web): terminal tells the shell its new width as soon as you relea…
t3dotgg Oct 14, 2026
7c43155
fix(web): keybindings page says to connect an environment when none i…
t3dotgg Oct 14, 2026
0796638
fix(chat): Codex follow-up suggestions show their label instead of ra…
t3dotgg Oct 14, 2026
b037b9a
fix(server): open in editor works over Tailscale SSH without a local …
t3dotgg Oct 14, 2026
8e018ff
fix(server): a deregistered T3 Connect host shows it was removed and …
t3dotgg Oct 14, 2026
cdba9a0
perf(server): idle servers no longer scan every process every 5 secon…
t3dotgg Oct 14, 2026
7d5a429
chore(typecheck): bump tsc-rs to 0.7.0 (#19408)
t3dotgg Oct 14, 2026
ce7e86f
Merge branch 'main' into feat/claude-prompt-ghost-text
danielyc Oct 14, 2026
df8df0d
fix(server): bound Bitbucket API requests with 30s timeout (#14140)
kvnloo Oct 14, 2026
dd5c7bd
fix(server): new worktrees no longer fail when a background fetch run…
t3dotgg Oct 14, 2026
8414d16
perf(server): thread search runs on the SQLite reader worker (#19382)
bompus Oct 14, 2026
7d57de4
feat(mobile): Android foldables use the sidebar header instead of a rail
t3dotgg Oct 14, 2026
9e5e520
fix(mobile): one-row composer keeps removable attachments above the row
t3dotgg Oct 14, 2026
6953427
fix(mobile): Android review diff scrolls to the end of long lines
Oct 14, 2026
4befc86
perf(server): traces keep ~40% more history and no longer block the e…
t3dotgg Oct 14, 2026
f37f99c
fix(shared): SQLite checkpoints no longer fall back to the main threa…
t3dotgg Oct 14, 2026
d056f04
refactor(mobile): measure review diff scroll width in the drawing helper
Oct 14, 2026
7371925
perf(server): unchanged node updates no longer write to SQLite (#19429)
t3dotgg Oct 14, 2026
36f91c4
fix(ssh): reconnecting keeps the remote server and its agents running…
t3dotgg Oct 14, 2026
28732b4
feat(observability): SQL spans show lock wait and connection; stalls …
t3dotgg Oct 14, 2026
d0a73b5
fix(server): threads woken by notifications no longer load their whol…
t3dotgg Oct 14, 2026
7ac952c
fix(server): worktree cleanup no longer runs sweeps back to back (#19…
t3dotgg Oct 14, 2026
68880cb
chore(sync): merge upstream main through 7ac952c630
eyeveil Oct 14, 2026
f2d578d
merge: integrate upstream PR #17618 feat(claude): suggest the next pr…
eyeveil Oct 14, 2026
00da07f
merge: integrate upstream PR #19273 feat: dictate into the composer w…
eyeveil Oct 14, 2026
dee6ad0
Merge branch 'pr-19424' into integrate/android
eyeveil Oct 14, 2026
af9a54e
Merge branch 'pr-19292' into integrate/android
eyeveil Oct 14, 2026
e0e5992
Merge branch 'pr-19240' into integrate/android
eyeveil Oct 14, 2026
06ee00e
Merge branch 'pr-19238' into integrate/android
eyeveil Oct 14, 2026
3f797d9
merge: integrate upstream PR #17890 feat(android): configure subscrip…
eyeveil Oct 14, 2026
da5f114
Merge branch 'pr-19431' into integrate/android
eyeveil Oct 14, 2026
7653a2a
Merge branch 'pr-18634' into integrate/android
eyeveil Oct 14, 2026
efd881b
Merge branch 'pr-18839' into integrate/android
eyeveil Oct 14, 2026
9771179
Merge branch 'pr-17195' into integrate/android
eyeveil Oct 14, 2026
c5908ce
merge: integrate upstream PR #15030 fix(mobile): restore lost iOS rac…
eyeveil Oct 14, 2026
4214631
fix(mobile): port usage widget settings row to ListRowLayout; refresh…
eyeveil Oct 14, 2026
97ca29f
merge: integrate ten upstream Android PRs
eyeveil Oct 14, 2026
b5a2e32
fix(server): keep server layer types from widening to any after PR #1…
eyeveil Oct 14, 2026
12f8a5b
merge: integrate upstream PR #17618 Claude next-prompt ghost text
eyeveil Oct 14, 2026
86e1be6
fix(server): serve dictation RPCs from their own group
eyeveil Oct 14, 2026
0069a54
merge: sync main into integrate/19273
eyeveil Oct 14, 2026
394ef57
merge: integrate upstream PR #17930 task graphs for parallel agent work
eyeveil Oct 14, 2026
149f3ca
merge: integrate upstream PR #15975 feat(home): add Home, an agent th…
eyeveil Oct 14, 2026
d78cbfc
merge: bring main (server type fix, Android batch, #17618) into integ…
eyeveil Oct 14, 2026
8c134b9
Merge branch 'main' into integrate/15975
eyeveil Oct 14, 2026
eb0422c
fix(server): add DictationError to runServer's explicit error type; d…
eyeveil Oct 14, 2026
698518d
merge: integrate upstream PR #17930 task graphs
eyeveil Oct 14, 2026
7b63690
test(home): expect upstream thread links with an environmentId query
eyeveil Oct 14, 2026
a5784bc
merge: sync main into integrate/19273
eyeveil Oct 14, 2026
1c77e13
Merge branch 'main' into integrate/15975
eyeveil Oct 14, 2026
9ee6261
merge: integrate upstream PR #19273 local-model dictation
eyeveil Oct 14, 2026
1cd8a4f
merge: integrate upstream PR #15975 Home agent
eyeveil Oct 14, 2026
c0b908b
test(server): tolerate sampled planner stats in Sqlite optimize test
eyeveil Oct 14, 2026
1f71f65
test(server): Sqlite planner-statistics probe tolerates sampled ANALYZE
eyeveil Oct 14, 2026
e507e60
fix(server): stop task graph nodes cancelled mid-launch and replay cu…
eyeveil Oct 14, 2026
fa7831d
fix(mobile): build react-native-enriched-markdown with the app's AGP
eyeveil Oct 14, 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
  •  
  •  
  •  
5 changes: 2 additions & 3 deletions .coderabbit.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { defineConfig, type CodeRabbitContext } from "@coderabbitai/config";

// Org members and collaborators merge their own pull requests. On anyone else's, CodeRabbit
// requests changes until its comments are resolved, then approves.
// Org members and collaborators can approve their own pull requests.
const UNGATED_AUTHORS = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
const isGated = ({ pr }: CodeRabbitContext) => !UNGATED_AUTHORS.has(pr?.authorAssociation ?? "");

export default defineConfig((ctx) => ({
reviews: {
high_level_summary: false,
review_status: false,
request_changes_workflow: isGated(ctx),
request_changes_workflow: false,
allow_author_approval: !isGated(ctx),
auto_review: {
enabled: true,
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/via-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ body:
id: version
attributes:
label: Version
description: Installed t3 version or commit.
description: Version the bug happened on (not the `t3 triage` CLI version), or unknown.
placeholder: 0.0.33
validations:
required: true
Expand Down
189 changes: 189 additions & 0 deletions .github/scripts/mirror-play-apk.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// Mirrors the newest build on a Google Play track to a rolling GitHub
// prerelease as a universal APK. Play generates and signs that APK from the
// uploaded bundle with the app signing key, so it carries the same signature
// as the Play Store install. Run by .github/workflows/mobile-android-apk.yml.
const { execFileSync } = require("node:child_process");
const crypto = require("node:crypto");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const { Readable } = require("node:stream");
const { pipeline } = require("node:stream/promises");

const PLAY_API = "https://androidpublisher.googleapis.com/androidpublisher/v3/applications";

function requireEnv(name) {
const value = process.env[name];
if (!value) throw new Error(`${name} is required.`);
return value;
}

// Service account key -> OAuth access token via a self-signed JWT grant.
async function playAccessToken(key) {
const now = Math.floor(Date.now() / 1000);
const encode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
const unsigned = `${encode({ alg: "RS256", typ: "JWT" })}.${encode({
iss: key.client_email,
scope: "https://www.googleapis.com/auth/androidpublisher",
aud: key.token_uri,
iat: now,
exp: now + 600,
})}`;
const signature = crypto.sign("RSA-SHA256", Buffer.from(unsigned), key.private_key);
const response = await fetch(key.token_uri, {
method: "POST",
body: new URLSearchParams({
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: `${unsigned}.${signature.toString("base64url")}`,
}),
});
if (!response.ok) {
throw new Error(`Google token exchange failed: ${response.status} ${await response.text()}`);
}
return (await response.json()).access_token;
}

async function play(token, method, url) {
const response = await fetch(url, { method, headers: { authorization: `Bearer ${token}` } });
if (!response.ok) {
throw new Error(`${method} ${url} failed: ${response.status} ${await response.text()}`);
}
return response;
}

// Highest version code the track serves, with its release name. Play names a
// release after the bundle's versionName unless the uploader sets one. This
// endpoint reads without opening an edit; an edit would invalidate any open
// EAS Submit edit made with the same service account.
async function newestTrackBuild(token, appUrl, trackName) {
const { releases = [] } = await (
await play(token, "GET", `${appUrl}/tracks/${trackName}/releases`)
).json();
let newest;
for (const release of releases) {
if (release.releaseLifecycleState !== "RELEASE_LIFECYCLE_STATE_PUBLISHED") continue;
for (const { versionCode } of release.activeArtifacts ?? []) {
if (!newest || versionCode > newest.versionCode) {
newest = { versionCode, versionName: release.releaseName || String(versionCode) };
}
}
}
return newest;
}

function gh(...args) {
return execFileSync("gh", args, { encoding: "utf8", stdio: ["ignore", "pipe", "inherit"] });
}

function readRelease(tag) {
try {
return JSON.parse(gh("release", "view", tag, "--json", "assets,body"));
} catch {
return undefined;
}
}

// Downloads the build's universal APK and uploads it, creating the release on
// first use. Returns false when Play lists no universal APK, which happens
// while it is still processing a fresh upload.
async function uploadApk({ token, appUrl, build, tag, apkName, notes, release }) {
const generated = await (
await play(token, "GET", `${appUrl}/generatedApks/${build.versionCode}`)
).json();
// One entry per app signing key. More than one means a key rotation, so
// fail rather than guess which signature testers should get.
const universal = (generated.generatedApks ?? []).filter((entry) => entry.generatedUniversalApk);
if (universal.length === 0) return false;
if (universal.length > 1) {
throw new Error(`Play returned ${universal.length} universal APKs, one per signing key.`);
}
const { downloadId } = universal[0].generatedUniversalApk;

const apkPath = path.join(fs.mkdtempSync(path.join(os.tmpdir(), "apk-")), apkName);
const download = await play(
token,
"GET",
`${appUrl}/generatedApks/${build.versionCode}/downloads/${encodeURIComponent(downloadId)}:download?alt=media`,
);
await pipeline(Readable.fromWeb(download.body), fs.createWriteStream(apkPath));

if (!release) {
// Prerelease with a non-v tag: release.yml, the desktop updater, the CLI,
// and the marketing site's latest-release lookup all ignore it.
gh(
"release",
"create",
tag,
"--prerelease",
"--latest=false",
"--title",
"T3 Code for Android (nightly)",
"--notes",
notes,
);
}
// --clobber replaces an asset a failed upload left behind.
gh("release", "upload", tag, apkPath, "--clobber");
return true;
}

async function main() {
const packageName = requireEnv("PACKAGE_NAME");
const trackName = requireEnv("PLAY_TRACK");
const tag = requireEnv("RELEASE_TAG");
const key = JSON.parse(requireEnv("GOOGLE_PLAY_SERVICE_ACCOUNT_JSON"));
const summary = (line) =>
process.env.GITHUB_STEP_SUMMARY &&
fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, `${line}\n`);

const token = await playAccessToken(key);
const appUrl = `${PLAY_API}/${packageName}`;
const build = await newestTrackBuild(token, appUrl, trackName);
if (!build) {
console.log(`The ${trackName} track has no live release.`);
return;
}

const safeName = build.versionName.replace(/[^0-9A-Za-z.]+/g, "-").replace(/^-|-$/g, "");
const apkName = `t3code-android-${safeName}-${build.versionCode}.apk`;
const notes = [
`T3 Code for Android that works with nightly servers, mirrored from the Google Play ${trackName} track. Current build: ${build.versionName} (${build.versionCode}).`,
"",
"The Play Store release can't connect to a nightly server yet. Install this APK if you can't join the Play testing group. Only the newest build is kept here.",
].join("\n");

const release = readRelease(tag);
const assets = release?.assets ?? [];
// A failed upload can leave an empty asset under the final name.
const published = assets.some(
(asset) => asset.name === apkName && asset.state === "uploaded" && asset.size > 0,
);
if (published) {
console.log(`${apkName} is already published.`);
} else if (await uploadApk({ token, appUrl, build, tag, apkName, notes, release })) {
console.log(`Published ${apkName}.`);
summary(`:white_check_mark: Published \`${apkName}\` to the \`${tag}\` release.`);
} else {
// The next run retries.
console.log(`Play lists no universal APK for ${build.versionCode}.`);
summary(
`:hourglass: Play lists no universal APK for ${build.versionName} (${build.versionCode}).`,
);
return;
}

// Reconciled on every run so an interrupted cleanup finishes on the next one.
for (const stale of assets) {
if (stale.name.endsWith(".apk") && stale.name !== apkName) {
gh("release", "delete-asset", tag, stale.name, "--yes");
}
}
if (release && release.body.replace(/\r\n/g, "\n").trim() !== notes) {
gh("release", "edit", tag, "--notes", notes);
}
}

main().catch((error) => {
console.error(error);
process.exit(1);
});
32 changes: 24 additions & 8 deletions .github/triage/PLAYBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ crashes, auth failures, broken setups, slow launches, or anything else. Your job
find out what went wrong, unblock the user if you can, and turn what you learned into
a well written GitHub issue when one is warranted.

A triage context file with machine facts (version, OS, paths, server liveness) was
A triage context file with machine facts (versions, OS, paths, server liveness) was
provided alongside this playbook. Everything machine-specific lives there, not here.

## 1. Ask what went wrong
Expand All @@ -18,9 +18,15 @@ valuable thing you can extract from this conversation.

## 2. Read the machine facts

Read the triage context file before investigating. It tells you the installed
version, the OS, whether the server process is currently running, and the exact
paths for state, logs, and the database.
Read the triage context file before investigating. It tells you the OS, whether
the server process is currently running, and the exact paths for state, logs, and
the database.

Its triage CLI version (called "Installed version" in older context files) is only
the version of the `t3` that ran `t3 triage`. It is often not the build the bug
happened on: `npx t3 triage` runs whatever `t3` npm resolves, while the user may
run the desktop app, the background service, or a nightly. The server process line
gives the local server's version when the server recorded one.

## 3. Check for a newer playbook

Expand All @@ -30,8 +36,16 @@ instead of this one. The user may be on an old release with an old copy.

## 4. Get the source

Clone the repo at the tag matching the user's installed version, into the source
cache directory named in the context file, one subdirectory per commit hash:
Before cloning, ask the user which version, device, and surface the bug happened
on. The bug may have happened on another machine, a remote server, the mobile app,
or an older build they have since updated. Check their answer against local facts
where they apply: the server version in the context file, or `serverVersion` from
`<origin>/.well-known/t3/environment` when a local server is running. If neither
the user nor the machine can tell you the version, say it is unknown. Do not guess.

Clone the repo at the release tag for that version (`v` followed by the version,
such as `v0.0.42`), into the source cache directory named in the context file,
one subdirectory per commit hash:

git clone --depth 1 --filter=blob:none --branch <release-tag> \
https://github.com/pingdotgg/t3code <source-cache-dir>/<hash>
Expand Down Expand Up @@ -82,8 +96,8 @@ comes from this repo's `main` branch.

Search existing issues in pingdotgg/t3code (use `gh`, or the public GitHub search
API if `gh` is missing or not logged in). Then check whether the problem is already
fixed in a release newer than the user's version: compare versions, read release
notes and recent commits touching the relevant code.
fixed in a release newer than the version the bug happened on: compare versions,
read release notes and recent commits touching the relevant code.

If the user is behind and the fix likely shipped, say so plainly and give them the
exact update command for how they run the CLI (the context file records how it was
Expand All @@ -105,6 +119,8 @@ of `main` for that work, never the tag-pinned diagnosis clone.
- Match the structure of the `via-triage` issue template
(`.github/ISSUE_TEMPLATE/via-triage.yml` in the repo): what happened, diagnosis,
repro steps, environment, evidence, related issues.
- Under Version, give the version the bug happened on from step 4, or say it is
unknown. Name the triage CLI version only as the CLI's.
- Label it `via-triage`. Use a plain, specific title with no prefix.
- Show the user the complete final issue text and get an explicit yes before
posting. Never post without it.
Expand Down
26 changes: 20 additions & 6 deletions .github/workflows/cursor-hygiene-webhook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,23 @@ jobs:
echo "Missing CURSOR_T3CODE_WEBHOOK_URL or CURSOR_T3CODE_WEBHOOK_AUTH — skipping."
exit 0
fi
curl -fsS --max-time 60 -X POST "$URL" \
-H "Authorization: $AUTH" \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: ${{ github.event_name }}" \
-H "X-GitHub-Delivery: ${{ github.run_id }}-${{ github.run_attempt }}" \
--data-binary @"${{ github.event_path }}"
for attempt in 1 2 3; do
curl_status=0
http_status=$(curl -fsS --max-time 60 -X POST "$URL" \
--output /dev/null --write-out '%{http_code}' \
-H "Authorization: $AUTH" \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: ${{ github.event_name }}" \
-H "X-GitHub-Delivery: ${{ github.run_id }}-${{ github.run_attempt }}" \
--data-binary @"${{ github.event_path }}") || curl_status=$?
if [ "$curl_status" -eq 0 ]; then
exit 0
fi
if [ "$GITHUB_REF" != "refs/heads/main" ] || \
[ "$curl_status" -ne 22 ] || [ "$http_status" != "400" ] || \
[ "$attempt" -eq 3 ]; then
exit "$curl_status"
fi
echo "Cursor webhook returned HTTP 400; retrying in 5 seconds ($attempt/2)."
sleep 5
done
59 changes: 59 additions & 0 deletions .github/workflows/mobile-android-apk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Mobile Android APK

# Publishes the newest nightly-compatible Android build as a sideloadable APK
# on the rolling "android-nightly" prerelease, for nightly users who can't join
# the Play testing group. Play re-signs uploaded bundles with the app signing
# key, so its universal APK matches the Play Store install and needs no signing
# secrets here. EAS submits asynchronously (--no-wait), so this polls Play
# instead of chaining off mobile-eas-production.yml; runs with nothing new exit
# early.
on:
schedule:
# Avoid minute zero, when GitHub scheduled jobs are busiest.
- cron: "23 * * * *"
workflow_dispatch:

concurrency:
group: mobile-android-apk
cancel-in-progress: false

jobs:
mirror:
name: Mirror Play APK
runs-on: blacksmith-2vcpu-ubuntu-2404
timeout-minutes: 10
permissions:
contents: write
env:
PACKAGE_NAME: com.t3tools.t3code
# eas.json submits v2-preview builds to this closed testing track; they
# speak the orchestration protocol nightly servers use, which the Play
# Store release can't.
PLAY_TRACK: v2
RELEASE_TAG: android-nightly
steps:
- id: credentials
name: Check for Play credentials
env:
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
run: |
if [ -n "$GOOGLE_PLAY_SERVICE_ACCOUNT_JSON" ]; then
echo "present=true" >> "$GITHUB_OUTPUT"
else
echo "present=false" >> "$GITHUB_OUTPUT"
echo "GOOGLE_PLAY_SERVICE_ACCOUNT_JSON is not available; skipping APK mirror."
fi
- name: Checkout
if: steps.credentials.outputs.present == 'true'
uses: actions/checkout@v6
with:
sparse-checkout: .github/scripts

- name: Mirror the newest APK
if: steps.credentials.outputs.present == 'true'
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
run: node .github/scripts/mirror-play-apk.cjs
2 changes: 2 additions & 0 deletions .github/workflows/mobile-eas-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ jobs:
uses: expo/expo-github-action/continuous-deploy-fingerprint@main
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
# The Expo action otherwise suppresses the EAS command's failure output.
RUNNER_DEBUG: "1"
with:
profile: preview:dev
branch: pr-${{ github.event.pull_request.number }}
Expand Down
Loading