fix(terminal): settling a thread closes its idle shells - #13673
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR changes production terminal lifecycles by closing idle shells during settlement and successful setup completion, using new process-tree detection and race-handling logic in shared terminal infrastructure. The behavior is intentionally narrow and tested, but its observable side effects and cross-component runtime impact merit human review. No code changes detected at You can add or adjust custom eligibility rules. Learn more. |
Settled threads kept their terminal shells open forever. The worktree setup shell stayed at a prompt after its script ended, and zsh prompt themes fork a helper copy of the shell, so every idle shell reported a running command. That kept the sidebar terminal icon pulsing on settled threads and blocked worktree cleanup. - Idle detection ignores a child that is a copy of the shell with no children of its own. - TerminalManager.closeIdle closes a thread's terminals that wait at an idle prompt, after a fresh process check. Busy terminals stay open. - thread.settled closes the thread's idle terminals. - A setup script that exits 0 closes its idle setup shell. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The settle hook skips a thread that was un-settled before its event ran. - closeIdle keeps a terminal that printed output during the process check, because typing echoes output before the command's process appears in the snapshot. - closeIdle logs the bounded error message, not the error object. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
write does not advance the event sequence, so a keystroke whose echo arrives after the process check could still let closeIdle kill the terminal. Sessions now count writes, and closeIdle skips a terminal when its output sequence or input count changed during the check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
702a95a to
25bd7cd
Compare
## What's Changed * feat(usage): read cursor, opencode, and antigravity history by @maria-rcks in pingdotgg/t3code#10409 * fix(sqlite): retry failed statement preparations by @yashranaway in pingdotgg/t3code#10584 * fix(mobile): scale Android controls with appearance text size by @none23 in pingdotgg/t3code#13356 * fix(web): return focus to the composer after saving a citation note by @mackinleysmith in pingdotgg/t3code#13450 * feat(observability): honor the standard OTLP endpoint, headers, and protocol variables by @yordis in pingdotgg/t3code#13492 * fix(terminal): settling a thread closes its idle shells by @t3dotgg in pingdotgg/t3code#13673 * fix(server): load Cursor keyring with createRequire by @Yash-Singh1 in pingdotgg/t3code#13678 * perf(server): avoid rereading unchanged files in review previews by @shivamhwp in pingdotgg/t3code#13395 **Full Changelog**: pingdotgg/t3code@v0.0.43-nightly.20260925.2251...v0.0.43-nightly.20260925.2269 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.43-nightly.20260925.2269
Settled threads kept their terminal shells open forever. The worktree setup shell stays at a prompt after its script ends. Also, zsh prompt themes (zsh-async and similar) fork a helper copy of the shell, and the terminal manager counted that copy as a running command. So every idle zsh shell showed the pulsing terminal icon in the sidebar, even on settled threads. A live terminal also blocks worktree cleanup for its checkout.
Earlier attempts stopped at "never close terminals on settle" (#5774, #4684) because closing every terminal can kill a dev server or an editor. This change closes only shells that wait at an idle prompt:
TerminalManager.closeIdle: closes a thread's terminals that wait at an idle prompt. It runs a fresh process check and does not use the last poll. A terminal that runs a command stays open. If the check fails, all terminals stay open.thread.settledhook in the provider command reactor callscloseIdle. That covers manual settle and auto-settle.Closed terminals keep their output in the terminal history. A reopened terminal starts a new shell. No wire contract changed, so web, desktop, and mobile all get this from the server.
Proof: I ran the real
TerminalManagerwith real node-pty zsh shells andps. Onmain, an idle shell reportedrunning: true (zsh)because of its prompt worker. On this branch, it reportsfalse.closeIdleclosed the idle shell and kept the shell that ransleep 60. Focused tests cover detection,closeIdle, the settle hook, and the setup runner.Made with Claude Opus 5.5 (1M context) in Claude Code, running in T3 Code.
🤖 Generated with Claude Code
Summary by CodeRabbit