Skip to content

perf(server): speed up large terminal clipboard sequences - #23819

Merged
juliusmarminge merged 3 commits into
pingdotgg:mainfrom
AksharP5:perf/server-terminal-control-scans
Oct 23, 2026
Merged

juliusmarminge merged 3 commits into
pingdotgg:mainfrom
AksharP5:perf/server-terminal-control-scans

Conversation

@AksharP5

@AksharP5 AksharP5 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Large terminal clipboard writes repeatedly scan the accumulated pending control string before publishing each PTY output chunk. Emitting a 256 KiB OSC 52 clipboard sequence in 4 KiB writes reproduces the extra work on Linux.

Change

Resume string-terminator searches at the new data, retaining the previous character for a split ESC/backslash terminator. Preserve the existing strip rules and exact saved history. The regression bounds character reads and checks large OSC 52/C1 DCS strings, split termination, later controls, persistence, and reopen.

Scope and approval

Fixes #23817
Fixes https://git.cafe/pingdotgg/t3code/issues/23817

Triaged bug via the automated issue flow. Reuses the existing fix PR and merges current main. No product setting, contract, or client behavior changes.

Verification

  • Deterministic regression fails on main: 1,368,175 character reads exceed the 262,242 bound. With the fix: 123,066 reads.
  • vp test run src/terminal/Manager.test.ts in apps/server: 43 passed after merging main.
  • Server typecheck passed. Scoped lint passed with one existing warning at unchanged Manager.test.ts line 731. Diff whitespace check passed.
  • Real dev server and node-pty, driven through the authenticated browser terminal RPC: a 349,536-byte OSC 52 sequence produced 24,417,215 parser character visits before and about 349,700 after. Both persisted histories retain the exact sequence. These counts do not measure UI latency; PTY chunk boundaries vary.
  • Runtime transcript. Server-only change; fixture matrix is empty and no render paths change. Browser/native rendering captures do not apply.

Implemented and verified with GPT-6.1 Sol and Claude Opus 5.5 through Codex and Claude Agent SDK in T3 Code; original implementation by GPT-6.1 Sol and GPT-6 Astra through Codex.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Oct 22, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 9d2e612

Macroscope's review found this PR approvable — This localized optimization reduces repeated scanning of large chunked terminal control sequences and includes regression coverage for persistence across reopen. It does not change product defaults, APIs, workflows, or static-analysis configuration.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 9d2e612 and 12cf2c9.

📒 Files selected for processing: 1
  • apps/server/src/terminal/Manager.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

The terminal history scanner now limits terminator searches for pending string control sequences. A regression test checks large chunked OSC 52 and DCS sequences, persisted history, and reopened history.

Changes: Terminal history sanitization

Layer / File(s) Summary
Bounded terminator scanning and history validation
apps/server/src/terminal/Manager.ts, apps/server/src/terminal/Manager.test.ts
The scanner starts terminator searches at the later of the sequence body start and the pending-prefix scan bound for ESC- and C1-prefixed sequences. The test checks large chunked OSC 52 and DCS output, persisted history, and reopened history.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor · Severity of issue fixed: Low

Suggested reviewers: juliusmarminge, t3dotgg

Merge Risk: ⚪ Minimal · up to 12cf2

The terminal history change is ready to merge after normal checks; no actionable risk remains identified.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title "perf(server): speed up large terminal clipboard sequences" states the main change: the server sanitizer now resumes terminator searches at new data, so large OSC 52 clipboard sequences are …
Linked Issues check Passed Issue #23817 requires that sanitizeTerminalHistoryChunk scan only new bytes for a string terminator. It also requires that split terminators and exact saved history stay correct. The whole-PR summar…
Out of Scope Changes check Passed The whole-PR summary lists two changed files: apps/server/src/terminal/Manager.ts (+10/-2) and apps/server/src/terminal/Manager.test.ts (+56/-0). The production change limits terminator searches i…
Description check Passed The pull request description includes all required sections. It clearly states the problem, change, linked issue and approval context, focused verification results, limitations, and agent attribution.
Full details: Title check

Explanation

The title "perf(server): speed up large terminal clipboard sequences" states the main change: the server sanitizer now resumes terminator searches at new data, so large OSC 52 clipboard sequences are processed faster. It uses a conventional commit prefix and is concise and specific. The title does not mention the split-terminator handling, but that is a detail.

Full details: Linked Issues check

Explanation

Issue #23817 requires that sanitizeTerminalHistoryChunk scan only new bytes for a string terminator. It also requires that split terminators and exact saved history stay correct. The whole-PR summary (merge base to reviewed head) states that apps/server/src/terminal/Manager.ts now limits terminator searches to the sequence body or the pending prefix's final character. This covers ESC-prefixed and C1-prefixed sequences. The summary states that the regression test in apps/server/src/terminal/Manager.test.ts covers large chunked OSC 52 and DCS strings, split termination, stripped query strings, preserved sequences, persistence, and reopen. The PR description reports a deterministic failure on main (1,368,175 character reads against a 262,242 bound) and 123,066 reads with the fix. It also reports 43 passing manager tests. Limit: the sanitizer diff and the reviewed-head file could not be read directly. The file read was truncated before the sanitizer, and the diff read failed because changed blobs were missing. This verdict therefore rests on the whole-PR summary and the reported test results, not on direct inspection of the current code. The previous assessment at 9d2e612 also passed. Changes between that head and 12cf2c9 could not be inspected, so their effect on the verdict is not established.

Full details: Out of Scope Changes check

Explanation

The whole-PR summary lists two changed files: apps/server/src/terminal/Manager.ts (+10/-2) and apps/server/src/terminal/Manager.test.ts (+56/-0). The production change limits terminator searches in sanitizeTerminalHistoryChunk, which is the behavior requested by #23817. The test change adds a regression for that behavior. The PR description states that no product settings, contracts, or client behavior change. The summary reports no public declaration changes. Limit: the diff could not be read directly, so the absence of unrelated hunks rests on the summary and the PR description. The previous assessment also found no out-of-scope changes.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@juliusmarminge juliusmarminge added the bugfix Fix PR opened by an issue lead; enters the PR loop label Oct 23, 2026 — with GitCafe Production
@juliusmarminge juliusmarminge added pr:ready Every gate passed; waits for Julius's land label pr:in-progress A lead is working on this PR and removed pr:ready Every gate passed; waits for Julius's land label pr:in-progress A lead is working on this PR labels Oct 23, 2026
@juliusmarminge
juliusmarminge merged commit 9f660d3 into pingdotgg:main Oct 23, 2026
48 of 49 checks passed
@juliusmarminge juliusmarminge removed the pr:ready Every gate passed; waits for Julius's land label label Oct 23, 2026
Pipyakas pushed a commit to Pipyakas/t3code that referenced this pull request Oct 23, 2026
…23819)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
(cherry picked from commit 9f660d3)
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Oct 23, 2026
## What's Changed
* fix(web): size Usage header controls to the available width by @nateEc in pingdotgg/t3code#24123
* perf(server): speed up large terminal clipboard sequences by @AksharP5 in pingdotgg/t3code#23819
* fix(server): make stale CLI service recovery actionable by @juliusmarminge in pingdotgg/t3code#23541
* fix(web): pasted images show their upload tile instantly by @bmdavis419 in pingdotgg/t3code#23832
* fix(server): clean up deleted threads worktrees with subagents by @juliusmarminge in pingdotgg/t3code#23900
* fix(server): pause periodic PR discovery without foreground clients by @juliusmarminge in pingdotgg/t3code#23852
* fix(server): meter checkpoint git subprocess attempts by @juliusmarminge in pingdotgg/t3code#24218


**Full Changelog**: pingdotgg/t3code@v0.1.3-nightly.20261023.3579...v0.1.3-nightly.20261023.3592

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.3-nightly.20261023.3592
adampeterhiggins added a commit to adampeterhiggins/t3code that referenced this pull request Oct 24, 2026
* test: delete low-value tests and dead test-only exports (pingdotgg#24058)

* test(server): restore DST scheduling tests deleted in the test snap (pingdotgg#23991)

* test(web): restore project settings permission tests deleted in the test snap (pingdotgg#24011)

* test(mobile): restore clipboard secret-redaction test deleted in the test snap (pingdotgg#23980)

* fix(web): Cmd+B toggles the sidebar unless text is selected (pingdotgg#24063)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(server): agent-browser and Chrome no longer outlive the agent that started them (pingdotgg#21299)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Theo Browne <me@theo.li>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* test(client-runtime): restore render scheduler tests deleted in the test snap (pingdotgg#23977)

* fix(web): cmd+k search hides subagents and favors recent, whole-word matches (pingdotgg#24032)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* test(lint): new polling loops in tests now fail lint (pingdotgg#23983)

* ci: unused dependency patches fail in check:changed, not after push (pingdotgg#23988)

* fix(desktop): PDFs in the preview can be annotated (pingdotgg#24022)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): instructed compact runs without a bare compaction first (pingdotgg#24008)

Co-authored-by: fixfon <12512757+fixfon@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* fix(desktop): reduce app crashes when a preview tab's renderer dies during agent screenshots (pingdotgg#24056)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(server): Stop stops a thread's subagents again (pingdotgg#23886)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(desktop): a stuck quit no longer leaves the app unkillable (pingdotgg#23873)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): keep blockquote text readable in every theme (pingdotgg#24036)

* fix(bitbucket): stop the startup sweep from flooding Bitbucket with 429s (pingdotgg#23889)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): screen readers hear when the open thread starts, needs you or finishes (pingdotgg#23752)

Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* perf(web): reduce allocations in streaming timeline scans (pingdotgg#23739)

* perf(web): reuse a collator when sorting changed-file trees (pingdotgg#23776)

* perf(scripts): check:changed finishes in about 10 s (pingdotgg#23581)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): size Usage header controls to the available width (pingdotgg#24123)

* perf(server): speed up large terminal clipboard sequences (pingdotgg#23819)

Co-authored-by: Julius Marminge <julius0216@outlook.com>

* fix(server): make stale CLI service recovery actionable (pingdotgg#23541)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): pasted images show their upload tile instantly (pingdotgg#23832)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>

* fix(server): clean up deleted threads worktrees with subagents (pingdotgg#23900)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(server): pause periodic PR discovery without foreground clients (pingdotgg#23852)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(server): meter checkpoint git subprocess attempts (pingdotgg#24218)

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Co-authored-by: Yordis Prieto <yordis.prieto@gmail.com>

* fix(web): clear stale resource monitor errors after retry (pingdotgg#24229)

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Co-authored-by: Yordis Prieto <yordis.prieto@gmail.com>

* fix(mobile): align draft workspace controls with the composer (pingdotgg#24239)

* feat(mobile): thread header minimizes on the Duo while reading back through history (pingdotgg#24235)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): center pull request timeline actions (pingdotgg#24259)

* fix(server): find the resource monitor when the server runs from its build output (pingdotgg#23965)

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Co-authored-by: Theo Browne <me@t3.gg>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Victor Vogel <satsdev@only21mil.xyz>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
Co-authored-by: Joseph Vidal <135430578+josephv123@users.noreply.github.com>
Co-authored-by: Theo Browne <me@theo.li>
Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com>
Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: fixfon <12512757+fixfon@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Yukun Shan <92423096+nateEc@users.noreply.github.com>
Co-authored-by: Akshar Patel <123344143+AksharP5@users.noreply.github.com>
Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com>

* fix(pull-requests): list filters narrow on every host that can (pingdotgg#23922)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(pull-requests): a filtered list fills its page instead of waiting for a scroll (pingdotgg#23923)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(pull-requests): label and author filters search the host (pingdotgg#23924)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(mobile): chat and composer chips stay readable in light mode (pingdotgg#22585)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): review thread avatars no longer clip in collapsed activity rows (pingdotgg#23545)

* ci: close "needs more info" issues after 7 days without a reply (pingdotgg#22628)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* fix(server): Codex accounts show ChatGPT's current plan names (pingdotgg#24200)

* fix(observability): desktop dev version and web environment match the other services (pingdotgg#23975)

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>

* fix(observability): custom resource attributes use the t3code prefix (pingdotgg#23974)

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>

* fix(mobile): Home and pull request lists let UIKit own their top inset (pingdotgg#24284)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(mobile): keep the Duo's Home and pull request headers fixed (pingdotgg#24295)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(server): interrupts started by an agent no longer say "by user" in the timeline (pingdotgg#24299)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(relay): deploy on-demand preview stages for labeled PRs

Labeled same-repo PRs deploy stage pr-<n> behind the relay-preview environment reviewer gate. Unlabel or close tears the stage down, and a nightly job retries failed teardowns. Runtime-created managed endpoint tunnels and CNAMEs are swept by a PreviewTunnelSweep resource.

Known gaps, tracked as follow-ups: an interrupted preview deploy can leave runtime tunnels behind; repo-level relay secrets still bypass the environment gate until moved.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* fix(mobile): HTML links in pull request comments open when tapped (pingdotgg#22110)

* perf(client): avoid full ordering scans for streamed replacements (pingdotgg#24264)

* fix(server): a fork's first /compact compacts its inherited history (pingdotgg#24172)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(server): agent recordings honor the browser frame rate setting (pingdotgg#23895)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(client-runtime): Stop clears commands already finished on the server (pingdotgg#23814)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): SSH environments on an older reused remote server explain the version mismatch instead of reconnecting forever (pingdotgg#23647)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(web): keep usage-limit wake action visible (pingdotgg#23803)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(server): reject pairing with an incompatible server protocol (pingdotgg#23789)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(mobile): Live Activity stops shouting the running-agent count (pingdotgg#24329)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(usage): include Muse Code session history (pingdotgg#22443)

Co-authored-by: Theo Browne <me@theo.li>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(mobile): add Usage and Settings to workspace navigation (pingdotgg#23841)

* fix(mobile): keep iPad workspace columns aligned while resizing (pingdotgg#24182)

* fix(mobile): no-project threads show a chat bubble instead of a monogram (pingdotgg#21546)

* fix(mobile): stabilize Duo search and portrait navigation (pingdotgg#24206)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(mobile): the unfolded Duo keeps its header in portrait (pingdotgg#24339)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(client-runtime): avoid duplicate handoff previews during startup (pingdotgg#24349)

* fix(mobile): Usage and Settings use the glass header and the Duo rail (pingdotgg#24348)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* perf(server): coalesce superseded streaming text updates (pingdotgg#24267)

* fix(server): stop flooding analytics with successful MCP tool calls (pingdotgg#24287)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(search): Cmd+K finds the right thread first, with indexed message search (pingdotgg#24343)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Co-authored-by: Theo Browne <me@t3.gg>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Joseph Vidal <135430578+josephv123@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Theo Browne <me@theo.li>
Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com>
Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: fixfon <12512757+fixfon@users.noreply.github.com>
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Yukun Shan <92423096+nateEc@users.noreply.github.com>
Co-authored-by: Akshar Patel <123344143+AksharP5@users.noreply.github.com>
Co-authored-by: Ben Davis <45952064+bmdavis419@users.noreply.github.com>
Co-authored-by: Yordis Prieto <yordis.prieto@gmail.com>
Co-authored-by: Alex <me@pixp.cc>
Co-authored-by: Victor Vogel <satsdev@only21mil.xyz>
Co-authored-by: oliver <97427849+flamboh@users.noreply.github.com>
Co-authored-by: Wiktor Golicz <56449542+Wiktor102@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Fix PR opened by an issue lead; enters the PR loop size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Large terminal clipboard sequences repeatedly rescan pending history

2 participants