Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/web, apps/server, apps/desktop
Summary
Settling a thread doesn't close its preview browser tabs. Each preview tab is a <webview> with its own Chromium renderer process, so every thread that ever opened a preview keeps a renderer alive until T3 Code restarts. On an agent-heavy workflow these pile up fast.
On my machine after ~3 days of normal use: 35 orphaned preview renderers using ~8.4 GB of RAM. All of them belonged to threads I had already settled or closed, and all sat at 0% CPU. The dev servers they had pointed at were long gone. The machine had pushed 6.5 of 8 GB into swap. The only fix was to quit T3 Code, which interrupts any running threads.
Steps to reproduce
- In the desktop app, have an agent open a preview in a thread (e.g. the
preview_openMCP tool against a local dev server). - Let the turn finish, then settle the thread.
- Check Activity Monitor or
ps -axo pid,rss,etime,command | grep 'T3 Code.*Renderer'. - Repeat across a few threads.
Expected behavior
Settling a thread releases what it was holding. Settlement already does this for idle shells (ThreadSettlementService → terminals.closeIdle), so its preview tabs should close too, along with their renderer processes.
Actual behavior
The renderer for every preview tab in every settled thread stays alive indefinitely. One renderer accumulates per thread that ever used a preview, and memory only grows until the app restarts. Nothing in the UI shows these tabs still exist: t3_preview_list from a new thread reports no sessions, and the settled threads are out of the sidebar, so there's no obvious way to find or close them.
What I observed (renderer client IDs climbing from 119 to 234 over ~2 days, every one idle):
PID RSS ELAPSED TYPE CLIENT ID
27541 1167MB 02-21:56 renderer 4 <- main window
16426 94MB 01-21:55 renderer 119 <- preview webview
34161 290MB 01-21:54 renderer 130
52613 293MB 01-21:00 renderer 132
... (31 more, 128–347 MB each, all 0.0% CPU)
41623 303MB 16:49 renderer 234
Every leaked renderer has --disable-blink-features, which the main window renderer lacks, i.e. they're preview guests.
Root cause (from reading main @ 0ecb78e)
apps/web/src/browser/ElectronBrowserHost.tsxis mounted app-wide and renders aHostedBrowserWebviewfor every preview session of every thread inuseActivePreviewSessions()(previewStateStore.ts). That includes threads that aren't visible, settled ones included.- A webview is only released when its server-side session closes (
desktopTabLifetime.ts→previewBridge.closeTabon unmount). apps/server/src/orchestration-v2/ThreadSettlementService.tshandlesthread.settledby calling onlycloseIdleTerminals(threadId). It never closes the thread's preview sessions. The comment there ("Settling closes the thread's shells that sit at an idle prompt, so they stop holding the worktree") shows settlement is already meant to release per-thread resources. Previews were just left out.
So nothing ever closes a settled thread's preview sessions, and the host keeps rendering them.
Suggested fix
PreviewManager.close (apps/server/src/preview/Manager.ts) already takes { threadId, tabId? }, and omitting tabId closes every tab for the thread. Calling it from the thread.settled handler next to closeIdleTerminals should be a small change. The same handler is probably the right place to close the thread's Device panel sessions (deviceService.close) too.
If some users want previews to survive settlement, put this behind a setting ("Close preview browsers when a thread is settled", on by default). The default matters more than the toggle: the current behavior leaks memory without limit and gives no sign that it's happening.
Impact
Major degradation or frequent failure
This gets worse the more you use the product as intended. Agent workflows that verify UI open previews in many threads, so memory grows with every thread, invisibly, until the machine swaps or the user restarts the app mid-work. Users will blame "T3 Code is a memory hog" rather than a leak. It should be fixed soon.
Version or commit
0.0.46-nightly.20261003.2610 (desktop). Root cause read from main @ 0ecb78e.
Environment
macOS 26.7.1, Apple Silicon, 48 GB RAM, T3 Code (Nightly) desktop
Workaround
Quit and reopen T3 Code. This interrupts any running threads.
Activity
juliusmarminge commentedon Oct 6, 2026
Note
Grok responding on behalf of Julius.
Thanks for the detailed write-up and the renderer measurements, @niko-itswld. This is the same leak tracked in #15579:
ElectronBrowserHostkeeps a liveHostedBrowserWebviewfor every preview session in every thread, and nothing (settlement included) ever closes those sessions, so hidden preview renderers pile up until restart. The triage there already lists closing a thread's previews on idle/settlement, next tocloseIdleTerminals, as a fix option.Closing this as a duplicate so the discussion stays in one place. Your macOS numbers (35 renderers, ~8.4 GB) and the
PreviewManager.close({ threadId })suggestion would be really useful as a comment on #15579. If you think settlement needs separate tracking, say so and we can reopen.